chiark / gitweb /
Merge branch 'arkkra' into shiny
authorMark Wooding <mdw@distorted.org.uk>
Mon, 22 Jan 2007 12:37:25 +0000 (12:37 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 22 Jan 2007 12:37:25 +0000 (12:37 +0000)
294 files changed:
mup/docs/README0 [new file with mode: 0644]
mup/docs/faq.txt [new file with mode: 0644]
mup/docs/license.txt [new file with mode: 0644]
mup/docs/mkmupfnt.1 [new file with mode: 0644]
mup/docs/mkmupfnt.ps [new file with mode: 0644]
mup/docs/mup.1 [new file with mode: 0644]
mup/docs/mup.ps [new file with mode: 0644]
mup/docs/mupdisp.1 [new file with mode: 0644]
mup/docs/mupdisp.ps [new file with mode: 0644]
mup/docs/mupfeat.txt [new file with mode: 0644]
mup/docs/mupmate.1 [new file with mode: 0644]
mup/docs/mupmate.ps [new file with mode: 0644]
mup/docs/mupprnt.1 [new file with mode: 0644]
mup/docs/mupprnt.ps [new file with mode: 0644]
mup/docs/mupqref.ps [new file with mode: 0644]
mup/docs/overview.txt [new file with mode: 0644]
mup/docs/register.txt [new file with mode: 0644]
mup/docs/sample.mup [new file with mode: 0644]
mup/docs/sample.ps [new file with mode: 0644]
mup/docs/star.mup [new file with mode: 0644]
mup/docs/star.ps [new file with mode: 0644]
mup/docs/template.mup [new file with mode: 0644]
mup/docs/uguide.ps [new file with mode: 0644]
mup/docs/uguide/adjust.html [new file with mode: 0644]
mup/docs/uguide/altinp.html [new file with mode: 0644]
mup/docs/uguide/bars.html [new file with mode: 0644]
mup/docs/uguide/basics.html [new file with mode: 0644]
mup/docs/uguide/brackmac.html [new file with mode: 0644]
mup/docs/uguide/breathmk.html [new file with mode: 0644]
mup/docs/uguide/cadenza.html [new file with mode: 0644]
mup/docs/uguide/chant.html [new file with mode: 0644]
mup/docs/uguide/chordinp.html [new file with mode: 0644]
mup/docs/uguide/chrdattr.html [new file with mode: 0644]
mup/docs/uguide/cmdargs.html [new file with mode: 0644]
mup/docs/uguide/contexts.html [new file with mode: 0644]
mup/docs/uguide/cres.html [new file with mode: 0644]
mup/docs/uguide/crossbar.html [new file with mode: 0644]
mup/docs/uguide/crossst.html [new file with mode: 0644]
mup/docs/uguide/debug.html [new file with mode: 0644]
mup/docs/uguide/fontfile.html [new file with mode: 0644]
mup/docs/uguide/gensyn.html [new file with mode: 0644]
mup/docs/uguide/headfoot.html [new file with mode: 0644]
mup/docs/uguide/heeltoe.html [new file with mode: 0644]
mup/docs/uguide/ichdattr.html [new file with mode: 0644]
mup/docs/uguide/ifclause.html [new file with mode: 0644]
mup/docs/uguide/include.html [new file with mode: 0644]
mup/docs/uguide/index.html [new file with mode: 0644]
mup/docs/uguide/intro.html [new file with mode: 0644]
mup/docs/uguide/invisbar.html [new file with mode: 0644]
mup/docs/uguide/linecurv.html [new file with mode: 0644]
mup/docs/uguide/lyrics.html [new file with mode: 0644]
mup/docs/uguide/macros.html [new file with mode: 0644]
mup/docs/uguide/mantup.html [new file with mode: 0644]
mup/docs/uguide/manual.html [new file with mode: 0644]
mup/docs/uguide/midi.html [new file with mode: 0644]
mup/docs/uguide/midmeas.html [new file with mode: 0644]
mup/docs/uguide/mixtsig.html [new file with mode: 0644]
mup/docs/uguide/mugex10.gif [new file with mode: 0644]
mup/docs/uguide/mugex100.gif [new file with mode: 0644]
mup/docs/uguide/mugex101.gif [new file with mode: 0644]
mup/docs/uguide/mugex11.gif [new file with mode: 0644]
mup/docs/uguide/mugex12.gif [new file with mode: 0644]
mup/docs/uguide/mugex13.gif [new file with mode: 0644]
mup/docs/uguide/mugex14.gif [new file with mode: 0644]
mup/docs/uguide/mugex15.gif [new file with mode: 0644]
mup/docs/uguide/mugex16.gif [new file with mode: 0644]
mup/docs/uguide/mugex17.gif [new file with mode: 0644]
mup/docs/uguide/mugex18.gif [new file with mode: 0644]
mup/docs/uguide/mugex19.gif [new file with mode: 0644]
mup/docs/uguide/mugex2.gif [new file with mode: 0644]
mup/docs/uguide/mugex20.gif [new file with mode: 0644]
mup/docs/uguide/mugex21.gif [new file with mode: 0644]
mup/docs/uguide/mugex22.gif [new file with mode: 0644]
mup/docs/uguide/mugex23.gif [new file with mode: 0644]
mup/docs/uguide/mugex24.gif [new file with mode: 0644]
mup/docs/uguide/mugex25.gif [new file with mode: 0644]
mup/docs/uguide/mugex26.gif [new file with mode: 0644]
mup/docs/uguide/mugex27.gif [new file with mode: 0644]
mup/docs/uguide/mugex28.gif [new file with mode: 0644]
mup/docs/uguide/mugex29.gif [new file with mode: 0644]
mup/docs/uguide/mugex3.gif [new file with mode: 0644]
mup/docs/uguide/mugex30.gif [new file with mode: 0644]
mup/docs/uguide/mugex31.gif [new file with mode: 0644]
mup/docs/uguide/mugex32.gif [new file with mode: 0644]
mup/docs/uguide/mugex33.gif [new file with mode: 0644]
mup/docs/uguide/mugex34.gif [new file with mode: 0644]
mup/docs/uguide/mugex35.gif [new file with mode: 0644]
mup/docs/uguide/mugex36.gif [new file with mode: 0644]
mup/docs/uguide/mugex37.gif [new file with mode: 0644]
mup/docs/uguide/mugex38.gif [new file with mode: 0644]
mup/docs/uguide/mugex39.gif [new file with mode: 0644]
mup/docs/uguide/mugex4.gif [new file with mode: 0644]
mup/docs/uguide/mugex40.gif [new file with mode: 0644]
mup/docs/uguide/mugex41.gif [new file with mode: 0644]
mup/docs/uguide/mugex42.gif [new file with mode: 0644]
mup/docs/uguide/mugex43.gif [new file with mode: 0644]
mup/docs/uguide/mugex44.gif [new file with mode: 0644]
mup/docs/uguide/mugex45.gif [new file with mode: 0644]
mup/docs/uguide/mugex46.gif [new file with mode: 0644]
mup/docs/uguide/mugex47.gif [new file with mode: 0644]
mup/docs/uguide/mugex48.gif [new file with mode: 0644]
mup/docs/uguide/mugex49.gif [new file with mode: 0644]
mup/docs/uguide/mugex5.gif [new file with mode: 0644]
mup/docs/uguide/mugex50.gif [new file with mode: 0644]
mup/docs/uguide/mugex51.gif [new file with mode: 0644]
mup/docs/uguide/mugex52.gif [new file with mode: 0644]
mup/docs/uguide/mugex53.gif [new file with mode: 0644]
mup/docs/uguide/mugex54.gif [new file with mode: 0644]
mup/docs/uguide/mugex55.gif [new file with mode: 0644]
mup/docs/uguide/mugex56.gif [new file with mode: 0644]
mup/docs/uguide/mugex57.gif [new file with mode: 0644]
mup/docs/uguide/mugex58.gif [new file with mode: 0644]
mup/docs/uguide/mugex59.gif [new file with mode: 0644]
mup/docs/uguide/mugex6.gif [new file with mode: 0644]
mup/docs/uguide/mugex60.gif [new file with mode: 0644]
mup/docs/uguide/mugex61.gif [new file with mode: 0644]
mup/docs/uguide/mugex62.gif [new file with mode: 0644]
mup/docs/uguide/mugex63.gif [new file with mode: 0644]
mup/docs/uguide/mugex64.gif [new file with mode: 0644]
mup/docs/uguide/mugex65.gif [new file with mode: 0644]
mup/docs/uguide/mugex66.gif [new file with mode: 0644]
mup/docs/uguide/mugex67.gif [new file with mode: 0644]
mup/docs/uguide/mugex68.gif [new file with mode: 0644]
mup/docs/uguide/mugex69.gif [new file with mode: 0644]
mup/docs/uguide/mugex7.gif [new file with mode: 0644]
mup/docs/uguide/mugex70.gif [new file with mode: 0644]
mup/docs/uguide/mugex71.gif [new file with mode: 0644]
mup/docs/uguide/mugex72.gif [new file with mode: 0644]
mup/docs/uguide/mugex73.gif [new file with mode: 0644]
mup/docs/uguide/mugex74.gif [new file with mode: 0644]
mup/docs/uguide/mugex75.gif [new file with mode: 0644]
mup/docs/uguide/mugex76.gif [new file with mode: 0644]
mup/docs/uguide/mugex77.gif [new file with mode: 0644]
mup/docs/uguide/mugex78.gif [new file with mode: 0644]
mup/docs/uguide/mugex79.gif [new file with mode: 0644]
mup/docs/uguide/mugex8.gif [new file with mode: 0644]
mup/docs/uguide/mugex80.gif [new file with mode: 0644]
mup/docs/uguide/mugex81.gif [new file with mode: 0644]
mup/docs/uguide/mugex82.gif [new file with mode: 0644]
mup/docs/uguide/mugex83.gif [new file with mode: 0644]
mup/docs/uguide/mugex84.gif [new file with mode: 0644]
mup/docs/uguide/mugex85.gif [new file with mode: 0644]
mup/docs/uguide/mugex86.gif [new file with mode: 0644]
mup/docs/uguide/mugex87.gif [new file with mode: 0644]
mup/docs/uguide/mugex88.gif [new file with mode: 0644]
mup/docs/uguide/mugex89.gif [new file with mode: 0644]
mup/docs/uguide/mugex9.gif [new file with mode: 0644]
mup/docs/uguide/mugex90.gif [new file with mode: 0644]
mup/docs/uguide/mugex91.gif [new file with mode: 0644]
mup/docs/uguide/mugex92.gif [new file with mode: 0644]
mup/docs/uguide/mugex93.gif [new file with mode: 0644]
mup/docs/uguide/mugex94.gif [new file with mode: 0644]
mup/docs/uguide/mugex95.gif [new file with mode: 0644]
mup/docs/uguide/mugex96.gif [new file with mode: 0644]
mup/docs/uguide/mugex97.gif [new file with mode: 0644]
mup/docs/uguide/mugex98.gif [new file with mode: 0644]
mup/docs/uguide/mugex99.gif [new file with mode: 0644]
mup/docs/uguide/multirst.html [new file with mode: 0644]
mup/docs/uguide/multsong.html [new file with mode: 0644]
mup/docs/uguide/muschar.gif [new file with mode: 0644]
mup/docs/uguide/music.html [new file with mode: 0644]
mup/docs/uguide/muspaper.html [new file with mode: 0644]
mup/docs/uguide/mussym.html [new file with mode: 0644]
mup/docs/uguide/newscore.html [new file with mode: 0644]
mup/docs/uguide/noteattr.html [new file with mode: 0644]
mup/docs/uguide/octave.html [new file with mode: 0644]
mup/docs/uguide/oddeven.html [new file with mode: 0644]
mup/docs/uguide/param.html [new file with mode: 0644]
mup/docs/uguide/pedal.html [new file with mode: 0644]
mup/docs/uguide/phrase.html [new file with mode: 0644]
mup/docs/uguide/pianored.html [new file with mode: 0644]
mup/docs/uguide/prnttext.html [new file with mode: 0644]
mup/docs/uguide/pstools.html [new file with mode: 0644]
mup/docs/uguide/register.html [new file with mode: 0644]
mup/docs/uguide/roll.html [new file with mode: 0644]
mup/docs/uguide/running.html [new file with mode: 0644]
mup/docs/uguide/shaped.html [new file with mode: 0644]
mup/docs/uguide/sharehd.html [new file with mode: 0644]
mup/docs/uguide/slashmrk.html [new file with mode: 0644]
mup/docs/uguide/stuff.html [new file with mode: 0644]
mup/docs/uguide/tabstaff.html [new file with mode: 0644]
mup/docs/uguide/tags.html [new file with mode: 0644]
mup/docs/uguide/tempochg.html [new file with mode: 0644]
mup/docs/uguide/textmark.html [new file with mode: 0644]
mup/docs/uguide/textstr.html [new file with mode: 0644]
mup/docs/uguide/trnspose.html [new file with mode: 0644]
mup/docs/uguide/tuplets.html [new file with mode: 0644]
mup/docs/uguide/utilpgms.html [new file with mode: 0644]
mup/docs/uguide/verses.html [new file with mode: 0644]
mup/docs/whatsnew.html [new file with mode: 0644]
mup/docs/whatsnew.txt [new file with mode: 0644]
mup/makefile [new file with mode: 0644]
mup/mkmupfnt/mkmupfnt.c [new file with mode: 0644]
mup/mup/abshorz.c [new file with mode: 0644]
mup/mup/absvert.c [new file with mode: 0644]
mup/mup/assign.c [new file with mode: 0644]
mup/mup/beaming.c [new file with mode: 0644]
mup/mup/beamstem.c [new file with mode: 0644]
mup/mup/brac.c [new file with mode: 0644]
mup/mup/charinfo.c [new file with mode: 0644]
mup/mup/check.c [new file with mode: 0644]
mup/mup/debug.c [new file with mode: 0644]
mup/mup/defines.h [new file with mode: 0644]
mup/mup/errors.c [new file with mode: 0644]
mup/mup/extchar.h [new file with mode: 0644]
mup/mup/extchtbl.c [new file with mode: 0644]
mup/mup/font.c [new file with mode: 0644]
mup/mup/fontdata.c [new file with mode: 0644]
mup/mup/globals.c [new file with mode: 0644]
mup/mup/globals.h [new file with mode: 0644]
mup/mup/grpsyl.c [new file with mode: 0644]
mup/mup/ifgram.c [new file with mode: 0644]
mup/mup/lex.c [new file with mode: 0644]
mup/mup/locvar.c [new file with mode: 0644]
mup/mup/lyrics.c [new file with mode: 0644]
mup/mup/macros.c [new file with mode: 0644]
mup/mup/main.c [new file with mode: 0644]
mup/mup/mainlist.c [new file with mode: 0644]
mup/mup/map.c [new file with mode: 0644]
mup/mup/midi.c [new file with mode: 0644]
mup/mup/midiutil.c [new file with mode: 0644]
mup/mup/mkchords.c [new file with mode: 0644]
mup/mup/muschar.h [new file with mode: 0644]
mup/mup/muschtbl.c [new file with mode: 0644]
mup/mup/nxtstrch.c [new file with mode: 0644]
mup/mup/parstssv.c [new file with mode: 0644]
mup/mup/parstuff.c [new file with mode: 0644]
mup/mup/phrase.c [new file with mode: 0644]
mup/mup/plutils.c [new file with mode: 0644]
mup/mup/print.c [new file with mode: 0644]
mup/mup/prntdata.c [new file with mode: 0644]
mup/mup/prntmisc.c [new file with mode: 0644]
mup/mup/prnttab.c [new file with mode: 0644]
mup/mup/prolog.c [new file with mode: 0644]
mup/mup/range.c [new file with mode: 0644]
mup/mup/rational.c [new file with mode: 0644]
mup/mup/rational.h [new file with mode: 0644]
mup/mup/relvert.c [new file with mode: 0644]
mup/mup/restsyl.c [new file with mode: 0644]
mup/mup/roll.c [new file with mode: 0644]
mup/mup/setgrps.c [new file with mode: 0644]
mup/mup/setnotes.c [new file with mode: 0644]
mup/mup/ssv.c [new file with mode: 0644]
mup/mup/ssvused.h [new file with mode: 0644]
mup/mup/structs.h [new file with mode: 0644]
mup/mup/stuff.c [new file with mode: 0644]
mup/mup/symtbl.c [new file with mode: 0644]
mup/mup/tie.c [new file with mode: 0644]
mup/mup/trantab.c [new file with mode: 0644]
mup/mup/trnspose.c [new file with mode: 0644]
mup/mup/undrscre.c [new file with mode: 0644]
mup/mup/utils.c [new file with mode: 0644]
mup/mup/ytab.c [new file with mode: 0644]
mup/mup/ytab.h [new file with mode: 0644]
mup/mupdisp/at386.c [new file with mode: 0644]
mup/mupdisp/dispttyp.h [new file with mode: 0644]
mup/mupdisp/do_cmd.c [new file with mode: 0644]
mup/mupdisp/dos.c [new file with mode: 0644]
mup/mupdisp/genfile.c [new file with mode: 0644]
mup/mupdisp/help.bm [new file with mode: 0644]
mup/mupdisp/init.c [new file with mode: 0644]
mup/mupdisp/linvga.c [new file with mode: 0644]
mup/mupdisp/mupdisp.c [new file with mode: 0644]
mup/mupdisp/mupdisp.h [new file with mode: 0644]
mup/mupdisp/waitmsg.bm [new file with mode: 0644]
mup/mupdisp/xterm.c [new file with mode: 0644]
mup/mupmate/Config.C [new file with mode: 0644]
mup/mupmate/Config.H [new file with mode: 0644]
mup/mupmate/Edit.C [new file with mode: 0644]
mup/mupmate/Edit.H [new file with mode: 0644]
mup/mupmate/File.C [new file with mode: 0644]
mup/mupmate/File.H [new file with mode: 0644]
mup/mupmate/Help.C [new file with mode: 0644]
mup/mupmate/Help.H [new file with mode: 0644]
mup/mupmate/Main.C [new file with mode: 0644]
mup/mupmate/Main.H [new file with mode: 0644]
mup/mupmate/Preferences.C [new file with mode: 0644]
mup/mupmate/Preferences.H [new file with mode: 0644]
mup/mupmate/Run.C [new file with mode: 0644]
mup/mupmate/Run.H [new file with mode: 0644]
mup/mupmate/globals.H [new file with mode: 0644]
mup/mupmate/license.C [new file with mode: 0644]
mup/mupmate/mup16.xpm [new file with mode: 0644]
mup/mupmate/mup32.xpm [new file with mode: 0644]
mup/mupmate/mup48.xpm [new file with mode: 0644]
mup/mupmate/mupicons.ico [new file with mode: 0644]
mup/mupmate/mupmate.rc [new file with mode: 0644]
mup/mupmate/regform.C [new file with mode: 0644]
mup/mupmate/resource.h [new file with mode: 0644]
mup/mupmate/template.C [new file with mode: 0644]
mup/mupmate/utils.C [new file with mode: 0644]
mup/mupmate/utils.H [new file with mode: 0644]
mup/mupprnt [new file with mode: 0755]
mup_5.3.orig.tar.gz [new file with mode: 0644]

diff --git a/mup/docs/README0 b/mup/docs/README0
new file mode 100644 (file)
index 0000000..81a78c3
--- /dev/null
@@ -0,0 +1,172 @@
+
+                          Compiling Mup for UNIX
+
+       1.  Compiling Mup for UNIX
+
+       Mup has been compiled successfully on a wide variety of
+       UNIX-type systems, including Linux, UNIX SV_R4, and Solaris.
+       We cannot guarantee that it will work on your system, but it
+       generally ports with no more than minimal changes.
+
+       Download the mup53src.tar.gz Mup source package file and
+       unpack it:
+          gunzip mup53src.tar.gz
+          tar xf mup53src.tar
+
+       Alternately, you can download the RPM format Mup source
+       package and install it as you would any RPM package:
+          rpm -i mup-5.3-0.src.rpm
+
+       Installing the source package will create a mup-5.3
+       directory.  Go to that directory.
+          cd mup-5.3
+       There is a simple makefile provided, which should work on
+       most systems, so all you need to do is:
+          make install
+       You can edit the makefile if necessary for your environment.
+       Comments at the top of the makefile describe suggested
+       modifications if it doesn't work for you as is.  Note that
+       if you want to install in a system directory (like the
+       default location /usr/bin) you will need to be root for the
+       installation step. Otherwise building Mup requires no
+       special privileges.
+
+       If for some reason the makefile doesn't work, you can
+       compile Mup and any of the optional utility programs
+       (mupdisp, mkmupfnt, and mupmate) manually.  For compling Mup
+       itself, generally, something like the following will work:
+          cd mup
+          cc -o mup *.c -lm
+       For most UNIX-like compilers, the "-o mup" will cause the
+       program to be put into a file called "mup," and the "-lm"
+       will cause the math library to be included (That's a lower-
+       case letter "el" not a one).  You may also want to use other
+       options. For example, for many compilers "-O" (that's a
+       capital letter "oh" not a zero) will run the optimizer, and
+       "-s" will strip the resulting program to save disk space.
+
+       Copy mup into your $HOME/bin or a similar directory in your
+       $PATH.
+          cp mup $HOME/bin/mup
+
+       If you already have a means of displaying PostScript files,
+       such as gv, ghostview, or pageview, you can simply pipe the
+       output of Mup into your display program.  Or you can use the
+       mupdisp program in connection with Ghostscript, which is
+       free. You can download Ghostscript from
+       http://www.cs.wisc.edu/~ghost, or
+       http://www.ghostscript.com/.  We've found that on some
+       systems, Ghostscript compiles with lots of warnings, but it
+       works okay anyway.
+
+       Once you have installed Ghostscript, compile the mupdisp
+       program for displaying Mup output on screen. See the comment
+       at the top of mupdisp.c for suggestions on compiler options
+       to try.
+
+       Copy mupdisp into your $HOME/bin or similar directory.
+          cp mupdisp $HOME/bin/mupdisp
+
+       The mupdisp program works on the AT386 $TERM type under UNIX
+       x86 or under X-windows. If you have a different display
+       type, you may need to write your own display functions. In
+       most cases, you'll only need to write 6 short functions, and
+       you can use the examples in at386.c, dos.c, or xterm.c for a
+       general template of the functions. You will also need to
+       update dispttyp.h and init.c appropriately.
+
+       If you want to supply your own fonts to override the
+       standard Mup fonts, you can compile the mkmupfnt program:
+          cd mkmupfnt cc -o mkmupfnt mkmupfnt.c
+
+       The Mupmate program provide a menu-driven interface on top
+       of Mup.  It is built on top of the FLTK library, so you will
+       need to have the FLTK development package. You can get this
+       from http://www.fltk.org Get the latest version in the 1.1.x
+       series (we built with 1.1.7); don't get from the 2.x series.
+       Mupmate is written in C++, so you will need a C++ compiler,
+       such as g++.  See the top level makefile for typical
+       compilation options. FLTK normally comes with its own copies
+       of libjpg, libpng, and libz (compression) libraries, but it
+       will usually work with the generic versions of those
+       libraries as well.  You will also need standard X-windows
+       libraries: libX11, libXext, and libXpm.
+
+       A shell script called "mupprnt" is included for printing Mup
+       files using Ghostscript.  Copy mupprnt to your $HOME/bin or
+       other appropriate directory.
+          cp mupprnt $HOME/bin/mupprnt
+       You will need to set the GS_DEVICE shell variable to the
+       proper value for your printer. If you don't know what to set
+       it to, the comment at the top of mupprnt may help, or check
+       your Ghostscript documentation.  You could also just use the
+       print option on your PostScript viewer such as gv.
+
+       Once you have everything installed, you can remove the .tar
+       file if you wish, to free up disk space.
+          rm mup53src.tar
+
+       Please let us know if you need any workarounds for compiling
+       on your system. We want to try to make Mup as portable as
+       possible.
+
+       2.  Getting Mup running for the first time
+
+       Once you get Mup to compile successfully, try running it.
+       The first time you run Mup, it should give you a message
+       indicating Mup is shareware, and asking you to read the Mup
+       license agreement. It will then tell you to create a
+       particular file.  By creating this file, you agree to abide
+       by the Mup license, and Mup will be turned on for normal
+       operation.
+
+       Try running Mup on the sample input files (sample.mup and
+       star.mup ).  Verify that the output you get matches the
+       corresponding sample output files (sample.ps and star.ps ).
+       You will find differences in some of the numbers, comments,
+       timestamp, filenames, etc, but otherwise, in general the
+       PostScript output you get should be similar to the sample
+       output files provided, and if you display them, the results
+       should look pretty much identical.
+
+       If Mup fails to run properly on the sample files, either
+       your system has uncovered a bug that we haven't seen yet or
+       your machine has some incompatibility. You can turn on
+       debugging, by running with the -dN option, where N is a
+       bitmap of debugging flags, to help pinpoint where bugs may
+       be. The Mup User's Guide explains the bits of the debugging
+       flags. If you get stuck, you may contact us at
+       support@arkkra.com and we will try to help.
+
+       If you need to make any changes in order to get Mup to
+       compile and run successfully, please let us know.  If you
+       find anything confusing, we'd like to know that too.  We
+       want Mup to be as solid, portable, useful, and easy to use
+       as possible.
+
+       Also, please let us know if there are ways we can improve
+       the Mup documentation.
+
+       If you receive messages beginning with "internal error" this
+       usually indicates a program bug, so we'd like to know about
+       them. An exception is when you get a message about being
+       unable to allocate memory when there really isn't any memory
+       left. If you get other internal errors, please send us a
+       copy of an input file and any other information that may
+       help us reproduce the problem, so we can try to fix it in
+       the next Mup release.
+
+       Mup is shareware. Once you get Mup up and running, you can
+       try it out for free to decide whether you want to use it or
+       not. If you like it, execute
+          mup -r
+       to get a copy of the shareware registration form.  The
+       registration fee is $29.  See the license file for license
+       details.
+
+       Provide feedback (bugs reports, comments, suggestions,
+       questions) to:  support@arkkra.com
+
+       --------------------------------------------------
+
+       Arkkra Enterprises
diff --git a/mup/docs/faq.txt b/mup/docs/faq.txt
new file mode 100644 (file)
index 0000000..fd7cff2
--- /dev/null
@@ -0,0 +1,307 @@
+
+                   Mup Frequently Asked Questions (FAQ)
+
+       1.  Frequent questions for those who have not yet used Mup
+
+       1.1  Q: What makes Mup unique? Why should I consider using
+            Mup?
+
+         1.  Mup provides high quality music output at very low
+             cost. You can download Mup and try it out for
+             yourself.
+
+         2.  Mup is available ready-to-run for several computer
+             operating systems, and is also available in source
+             form, so that it can be run on almost any kind of
+             computers, including Windows, Apple, Linux or Unix.
+
+         3.  If you prefer a command line interface, Mup provides
+             that, and doesn't require using a mouse or learning a
+             new editor; you can just create a Mup input file using
+             any text editor of your choice.  However, if you
+             prefer an interface with menus and integrated editor,
+             the companion Mupmate program provides that.
+
+         4.  Mup input can be easily generated or manipulated by
+             another program.  Input files are typically small, so
+             it doesn't take a long time to create them. Since they
+             are ordinary text they can easily be moved to other
+             systems, even if the other system uses a different
+             operating system. For example, it would be easy to
+             email a song in Mup format to a friend, and if they
+             had Mup, they could then print it out or play it via
+             MIDI.  Since Mup output is standard PostScript or
+             standard MIDI, output files are also portable to
+             almost any operating system.
+
+         5.  Mup handles page layout details, but provides ways to
+             alter the layout if you wish. It has the power to
+             handle complicated scores, and can produce
+             professional-quality output quickly.
+
+         6.  Mup's ability to produce MIDI output can be very
+             helpful for "proof listening" to your music, which is
+             usually a very effective way to spot errors that you
+             might miss by just looking at the score,
+
+       1.2  Q: Will Mup run on my computer?
+
+       We currently provide Mup in ready-to-run form for Windows
+       and Linux x86 systems. A port of Mup for the Macintosh is
+       available from
+       http://www.uni-paderborn.de/cs/Michael.Thies.html and a
+       version for OS/2 is available from http://homepages.tu-
+       darmstadt.de/~st002279/os2/html/mup.html
+
+       If you use a different operating system, Mup source code is
+       also available, so if you have a C compiler, you can
+       probably compile and run Mup. It has been run using several
+       versions of UNIX on x86, Sun, Digital, Silicon Graphics, and
+       other systems.  It has also been run under OS/2, as well as
+       on an Amiga.  An ANSI-C compiler is recommended, but not
+       required.  Under MS-DOS, you will need a memory extender,
+       and at least a 32-bit compiler is strongly recommended.  Mup
+       will run on a 386, but at least a 486 is recommended for
+       best performance.  If you try to compile Mup and have
+       problems, please let us know at support@arkkra.com We'd like
+       to make it portable to as many computer system types as
+       possible.  The companion Mupmate program requires a C++
+       compiler and the FLTK toolkit.
+
+       1.3  Q: How long will it take to learn how to use Mup?
+
+       This will vary from person to person. A person who has
+       experience with computer languages will probably pick up Mup
+       more quickly, but such knowledge is not necessary.  Mup has
+       a broad array of features, so if you want to learn how to
+       use every feature that Mup has to offer, this may take
+       several days. (The Mup User's Guide, which explains all the
+       features, and includes many examples, is about 150 pages
+       long.) However, once you get Mup installed, you can start
+       experimenting with Mup after reading the first few pages of
+       the User's Guide, and it should take no more than a few
+       hours to feel comfortable with the basics, enough to enter
+       simple songs and get professional-looking output.  The
+       User's Guide includes many examples, and is provided both as
+       a PostScript file that you can print out on paper, and as
+       HTML files with hundreds of hypertext links, that you can
+       view with your Web browser.  The Mup installation package
+       contains several sample files and a template file to help
+       you get started.  You can also download sample songs from
+       ftp://ftp.arkkra.com/pub/music
+
+       1.4  Q: How long will it take to enter music?
+
+       This will vary greatly, depending on a number of factors,
+       such as how complicated the music is, how much experience
+       you have had with using Mup, how fast you type, etc. An
+       experienced Mup user can typically enter simple music in
+       less than 15 minutes per page, but very complex music can
+       often take over an hour, especially if you like to make a
+       lot of adjustments to make things look just exactly the way
+       you want.
+
+       1.5  Q: How did Mup and Arkkra Enterprises come about?
+
+       We are musicians and computer programmers who wanted a music
+       publication program that would produce very high-quality
+       output with a minimum amount of fuss. We wrote the Mup
+       program for our own use, and continue to use it for all our
+       own compositions. When other people expressed an interest in
+       getting a copy of Mup, we formed Arkkra Enterprises to set
+       up a Web site to make Mup available as shareware to anyone
+       who wants it.  We rely on the shareware registration fee
+       that you pay to cover the cost of maintaining a Web site and
+       providing support to answer questions. We add new features
+       based on user suggestions, and once you register, we will
+       notify you of any future free upgrades.
+
+       1.6  Q: How do I pay for Mup?
+
+       Fill out the registration form and send the form and (US)
+       $29 in cash, check, or money order to the address given on
+       the form.  If you are writing a check from a bank outside
+       the United States, please make it out in the bank's local
+       currency in an amount equivalent to 29 U.S. dollars; our
+       bank will not accept US-dollar-denominated checks from non-
+       US banks.  If you wish to pay via credit card, we have an
+       arrangement with setSystems to handle paying for Mup with a
+       credit card.  They are able to handle transactions in many
+       different currencies.  setSystems is part of Digital River,
+       a well-known e-commerce company.  As soon as we receive your
+       payment, we will email the registration information to you.
+       Once you register, we will notify you via email of future
+       Mup versions, and you can upgrade to any future versions of
+       Mup for free.  Once you have registered, you also can join
+       the Mup users mailing list if you wish, at no additional
+       charge.  We only use your address to send you information
+       about Mup; it is our policy to not give out names, email, or
+       street addresses to anyone else.
+
+       --------------------------------------------------
+
+       2.  Frequent questions from Mup users
+
+       2.1  Q. Is there a mailing list for Mup users?
+
+       Yes. There is a "majordomo" mailing list available
+       exclusively to registered Mup users.  It provides a forum
+       where you can ask or answer questions, get tips on how other
+       people are using Mup, etc.
+
+       2.2  Q. Can I put Mup output into some other document?
+
+       There is a tool that comes with Ghostscript, called
+       "ps2epsi" that converts a PostScript file to an Encapsulated
+       PostScript file, which can then be imported into other
+       documents.
+
+       2.3  Q: Can Mup produce PDF files?
+
+       Not directly, but since Mup produces PostScript output, you
+       can easily convert the output to PDF format using the ps2pdf
+       utility that comes with Ghostscript.
+
+       2.4  Q. Why is the first score indented differently than the
+            others?
+
+       The first score of a piece of music is traditionally
+       indented somewhat more than subsequent scores, so that's
+       what Mup does by default.  It does that by setting the
+       default label parameter to a few spaces, whereas it sets the
+       default for the label2 parameter to an empty string.  If you
+       don't want the indentation, you can set
+            label=""
+
+       2.5  Q: Is is possible to specify a pickup measure?
+
+       Yes. You use "space" on all voices. For example,
+          1: 2.s; 4e;
+          2: 2.s; 4c;
+       will produce a pickup measure with just a quarter note in
+       it.
+
+       2.6  Q: Is it possible to display a tempo marking of the
+            form '(N = 120)' where N is a note symbol, like a
+            quarter note?
+
+       Yes. Try something like
+          rom above all: 1 "( \(sm4n) = 120 )";
+
+       2.7  Q: Can Mup take a MIDI file as input?
+
+       No. However, it is possible to write a program that reads a
+       MIDI file and outputs a file that can be input to Mup. Two
+       programs that do this, called "mtm" and "midi2mup" have been
+       donated by Mup users.  They are limited, and not supported
+       by Arkkra Enterprises, but may be useful for some people.
+       Check out the programs donated by Mup users.
+
+       2.8  Q: What are some of the shorthands that can be used to
+            reduce typing?
+
+       There are many shorthands available. Some of the most useful
+       are:
+
+          - When the time value of a chord is the same as that of
+            the previous chord in the measure, it can be omitted.
+            If all pitch values of a chord are the same as the
+            previous chord, they can be omitted. For example:
+               1: 4c; 4c; 4ceg; 4ceg;
+            is the same as
+               1: 4c; ; ceg; ;
+
+          - If several voices have the same music data, they can be
+            given on a single line.
+               1-3 1-2: mr;
+            is equivalent to
+               1 1: mr;
+               1 2: mr;
+               2 1: mr;
+               2 2: mr;
+               3 1: mr;
+               3 2: mr;
+            A similar shorthand works for text and music symbols:
+               rom above 1-4: 3 "mf";   // staffs 1 through 4
+               < below 2-3: 4 til 3m+2; // staffs 2 and 3
+               mussym 1-5: 1 "ferm";   // staffs 1 through 5
+
+          - If several chords in a row have the same items in
+            square brackets before the chords, only the first must
+            have everything included. By giving an ellipsis after
+            the ] the items in brackets will be repeated for the
+            rest of the measure or until cancelled.  Thus the
+            following lines are equivalent:
+               1: [with .] c; [with .] d; [with .] e;
+               1: [with .]... c; d; e;
+
+       2.9  Q: The Mupprnt command doesn't seem to work right. What
+            do I do?
+
+       You may need to edit the mupprnt file to make sure the
+       variables and paths are set to match where things are
+       installed on your system.  In particular,
+
+          - GS_DIR needs to be set to the directory which contains
+            the Ghostscript font files (*.gsf) and the other
+            Ghostscript setup files (gs_*.ps).
+
+          - GS_DEVICE needs to be set to the proper type to match
+            your printer type.
+
+          - The path to Mup must be correct
+
+          - The path to Ghostscript (gs or gs386 on MS-DOS/Windows
+            system) must be correct.
+
+          - On MS-DOS/Windows systems, dos4gw.exe must be in your
+            PATH.
+       If you are using a viewer such as GSview or gv, you may want
+       to use its print feature rather than using mupprnt.
+
+       2.10  Q: On MS-DOS, the Mupdisp command comes back with
+             ghostscript error 1. What do I do?
+
+       Check your config.sys file. You need to have a line like
+          files=10
+       where the number after the equals sign is greater than or
+       equal to 9.
+
+       Also, make sure gs386.exe exists and is in your PATH. If you
+       are running Mup from MS-DOS directly or from a DOS prompt
+       under Windows, make sure you installed the DOS version of
+       Ghostscript, not the Windows version.  If you are using
+       Mupmate, or Winmup, make sure you installed the Windows
+       version of Ghostscript, not the MS-DOS version.
+
+       2.11  Q: If I use Mup for a language other than English,
+             will it handle the letters that are not used in
+             English?
+
+       Mup handles most common non-ASCII characters.  If your
+       keyboard does not allow you to enter them directly, you can
+       enter them by name, such as \(a:) for an 'a' with 2 dots
+       over it. The User's Guide section on text strings gives a
+       complete list of supported non-ASCII characters.
+
+       2.12  Q: Under Linux, Mupdisp says it can't open
+             /dev/console. What do I do?
+
+       The svga library used by Mupdisp in non-X-windows mode
+       requires write permission to the console. To allow this:
+
+          - Make Mupdisp setuid to root:
+               chown root mupdisp
+               chmod 4755 mupdisp
+
+       2.13  Q: What if I have more questions about Mup?
+
+       Send us email at support@arkkra.com We welcome any comments
+       and questions about Mup. Normally, you should have no
+       problem contacting us this way. In the unlikely event you
+       get a "rejected" reply when sending email, this is because
+       excessive "spam" (junk mail) has been received from your
+       domain at some time in the past, and our Internet service
+       provider has installed a "spam blocker."  In this case, you
+       will have to send email from another address or send paper
+       mail.
diff --git a/mup/docs/license.txt b/mup/docs/license.txt
new file mode 100644 (file)
index 0000000..8aa2155
--- /dev/null
@@ -0,0 +1,82 @@
+
+                               Mup License
+
+       At Arkkra Enterprises, we'd like all our customers to be
+       delighted with our products. To ensure that Mup and any
+       other products or services we provide are readily available
+       at the lowest possible cost to you, we need to establish
+       licensing terms.
+
+       While there are other music publication programs on the
+       market, we believe Mup has unique features that you may find
+       very useful.  Since different people may want different
+       things in a music publication program, you do not have to
+       pay for Mup until after you've had a chance to try it out
+       and evaluate it for yourself.  If you have problems with
+       Mup, let us know and we will try to resolve them.  If you
+       have paid your registration fee and we cannot resolve
+       problems to your satisfaction, we will gladly refund your
+       money.
+
+       1.  Mup License
+
+       Arkkra Enterprises disclaims all warranties relating to this
+       software, whether expressed or implied, including but not
+       limited to any implied warranties of merchantability and
+       fitness for a particular purpose, and all such warranties
+       are expressly and specifically disclaimed.  Neither Arkkra
+       Enterprises nor anyone else who has been involved in the
+       creation, production, or delivery of this software shall be
+       liable for any indirect, consequential, or incidental
+       damages arising out of the use of or inability to use such
+       software even if Arkkra Enterprises has been advised of the
+       possibility of such damages of claims.  In no event shall
+       Arkkra Enterprises' liability for any damages ever exceed
+       the price paid for the license to use the software,
+       regardless of the form of the claim.  The person using the
+       software bears all risk as to the quality and performance of
+       the software.
+
+       Some states do not allow the exclusion of the limit of
+       liability for consequential damages, so the above limitation
+       may not apply to you.
+
+       This agreement shall be governed by the laws of the state of
+       Illinois and shall inure to the benefit of Arkkra
+       Enterprises, and any successors, administrators, heirs and
+       assigns. Any action or proceeding brought by either party
+       against the other arising out of or related to this
+       agreement shall be brought only in the state or federal
+       court of competent jurisdiction located in DuPage County,
+       Illinois. The parties hereby consent to in personam
+       jurisdiction of said courts.
+
+       This software is licensed to you, for your own use. This is
+       copyrighted software. You are not obtaining title to the
+       software or any copyright rights.  You may not sublicense,
+       rent, lease, convey, modify, or translate this software for
+       any purpose.
+
+       You may make as many copies as you need for back-up
+       purposes.  You may use this software on more than one
+       computer, provided there is no chance it will be used
+       simultaneously on more than one computer.  If you need to
+       use this software on more than one computer simultaneously,
+       you will need to obtain a license for each copy or a site
+       license.
+
+       You may make copies of this software for other parties under
+       the following terms:
+
+          - The copy must be an exact copy as would be obtained
+            directly from Arkkra Enterprises, including this
+            license.  It must clearly state that it is a copy, and
+            must give the address of Arkkra Enterprises.
+
+          - The copy must be used by the obtaining party only for
+            the purpose of trialing the software. If after trialing
+            the software, the receiving party wishes to continue to
+            use the software, they must submit their license fee.
+
+          - All limitations and disclaimers of this license apply
+            to the copy.
diff --git a/mup/docs/mkmupfnt.1 b/mup/docs/mkmupfnt.1
new file mode 100644 (file)
index 0000000..f2438d3
--- /dev/null
@@ -0,0 +1,106 @@
+.TH mkmupfnt 1 "July 31, 1999" "Arkkra Enterprises"
+.SH NAME
+.PP
+mkmupfnt - create fontfile for overriding Mup fonts
+.SH SYNOPSIS
+.PP
+mkmupfnt \fIPostScript_font_name Mup_font_name outfile [file]\fP
+.SH DESCRIPTION
+.PP
+The \fBmkmupfnt\fP program creates an \fIoutfile\fP that can be used
+with the Mup "fontfile" statement to override a Mup font.
+.PP
+The \fIPostScript_font_name\fP is the name of the font you want Mup
+to use. This would be something that could be given as a name
+to the PostScript \fBfindfont\fP procedure.
+.PP
+The \fIMup_font_name\fP is the name of the Mup font you want to
+override, either an abbreviated name, like "PR" or a full
+name, like "palatino rom".
+.PP
+The \fIoutfile\fP is the file that will be generated, which will
+contain character size and other information, to use with
+Mup's "fontfile" statement.
+.PP
+The final optional \fIfile\fP argument is the name of a file that
+contains PostScript to be placed at the end of the Mup PostScript prolog.
+This might be useful if you have a font whose implementation PostScript could
+not find on its own. For example, if you've written your own font
+implementation, you could put it in the given \fIfile\fP.
+The actual characters produced by the font need not be similar to those
+in the font being replaced; they could be in some other alphabet,
+or hieroglyphics or whatever you wish. However, see the CAVEATS section
+for limitations.
+.PP
+An an example, suppose you want Mup to use the Helvetica-Narrow font
+rather than the plain Helvetica font. You could use:
+.br
+.in +0.5i
+mkmupfnt Helvetica-Narrow HR helvnarr
+.in -0.5i
+.br
+to generate a Mup fontfile, then in your Mup program put:
+.br
+.in +0.5i
+fontfile "helvnarr"
+.in -0.5i
+.br
+Then anything that would normally be printed in Helvetica will come out
+in Helvetica-Narrow instead.
+.SH "FILE FORMAT"
+.PP
+Mup requires a \fIfontfile\fP to be in a fairly rigid format.
+This section describes the format of the file that is produced by
+mkmupfnt.
+The file can contain comment lines, which have a '#' in column 1.
+Otherwise the format is:
+.br
+.nf
+.na
+.in +0.3i
+\fBMup font name:\fP \fIMup_font_name\fP
+\fBPostScript font name:\fP \fIPostScript_font_name\fP
+\fBSize data:\fP
+\fB32\fP   \fIwidth   height   ascent\fP
+\fB33\fP   \fIwidth   height   ascent\fP
+       \fI... similar lines for ASCII codes 34-126.
+       Dimension are given in 1/1000ths of an inch for a 12-point character.
+       All codes must be specified, and they must be in order.\fP
+\fBPostScript:\fP
+       \fIZero or more lines of PostScript that will be copied
+       exactly as is to the end of the Mup PostScript prolog.\fP
+.br
+.in -0.3i
+.fi
+.ad
+.SH FILES
+.P
+mkmupfnt.ps    PostScript program that extracts font size information
+.SH "SEE ALSO"
+.PP
+gs(1), mup(1).
+.br
+Mup \(em Music Publisher User's Guide
+.SH "CAVEATS"
+.PP
+You must have ghostscript (gs or gs386.exe) in your PATH
+and it must be built to include the "bit" device.
+.PP
+Mup uses certain fonts for certain things, such as
+time signatures, octave marks, endings, tuplet numbers, etc.
+(The fonts used include all the Times fonts and New Century bold, plus
+Helvetica roman and Helvetica bold for tablature.)
+If your override one of the fonts used for those things, they will
+come out in your new font. On the one hand, if you don't like Mup's
+choices, this provides you a way to get your own. On the other hand,
+if you want to change most, but not all uses of a particular font,
+it may not be possible to do that.
+.PP
+Only the ASCII characters 32-126 can be overridden. The non-ASCII
+characters can not be overridden.
+.PP
+Mup only allows width values up to 1/2 inch for
+a 12-point character. This program does not enforce that limitation.
+.PP
+This program has been tested with various Ghostscript fonts,
+but may not work on just any arbitrary PostScript font.
diff --git a/mup/docs/mkmupfnt.ps b/mup/docs/mkmupfnt.ps
new file mode 100644 (file)
index 0000000..3527c5f
--- /dev/null
@@ -0,0 +1,314 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.17.2
+%%CreationDate: Sat Dec  9 16:59:22 2006
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.17 2
+%%Pages: 2
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.17 2
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/MANUAL{
+statusdict begin/manualfeed true store end
+}bind def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
+def/PL PLG def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
+/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
+/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
+/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
+/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
+/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
+/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
+/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
+/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
+/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
+/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
+/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
+/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
+/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
+/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
+/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
+/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
+/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
+/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
+/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
+/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
+/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE
+/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 358.84(mkmupfnt\(1\) mkmupfnt\(1\))72 48 R/F1
+10.95/Times-Bold@0 SF -.219(NA)72 84 S(ME).219 E F0
+(mkmupfnt - create font\214le for o)108 96 Q -.15(ve)-.15 G
+(rriding Mup fonts).15 E F1(SYNOPSIS)72 112.8 Q F0(mkmupfnt)108 124.8 Q
+/F2 10/Times-Italic@0 SF -.8(Po)2.5 G
+(stScript_font_name Mup_font_name out\214le [\214le]).8 E F1
+(DESCRIPTION)72 141.6 Q F0(The)108 153.6 Q/F3 10/Times-Bold@0 SF
+(mkmupfnt)2.862 E F0 .362(program creates an)2.862 F F2(out\214le)2.862
+E F0 .362(that can be used with the Mup "font\214le" statement to o)
+2.862 F -.15(ve)-.15 G .361(rride a).15 F(Mup font.)108 165.6 Q(The)108
+182.4 Q F2 -.8(Po)3.854 G(stScript_font_name).8 E F0 1.354
+(is the name of the font you w)3.854 F 1.354(ant Mup to use. This w)-.1
+F 1.355(ould be something that)-.1 F(could be gi)108 194.4 Q -.15(ve)
+-.25 G 2.5(na).15 G 2.5(san)-2.5 G(ame to the PostScript)-2.5 E F3
+(\214ndf)2.5 E(ont)-.25 E F0(procedure.)2.5 E(The)108 211.2 Q F2
+(Mup_font_name)3.5 E F0 1(is the name of the Mup font you w)3.5 F .999
+(ant to o)-.1 F -.15(ve)-.15 G .999(rride, either an abbre).15 F .999
+(viated name, lik)-.25 F(e)-.1 E("PR" or a full name, lik)108 223.2 Q
+2.5(e")-.1 G(palatino rom".)-2.5 E(The)108 240 Q F2(out\214le)2.831 E F0
+.331(is the \214le that will be generated, which will contain character\
+ size and other information, to use)2.831 F(with Mup')108 252 Q 2.5(s")
+-.55 G(font\214le" statement.)-2.5 E .49(The \214nal optional)108 268.8
+R F2(\214le)2.99 E F0(ar)2.99 E .489(gument is the name of a \214le tha\
+t contains PostScript to be placed at the end of the)-.18 F .077
+(Mup PostScript prolog.)108 280.8 R .077(This might be useful if you ha)
+5.077 F .378 -.15(ve a f)-.2 H .078
+(ont whose implementation PostScript could not).15 F .233
+(\214nd on its o)108 292.8 R .233(wn. F)-.25 F .233(or e)-.15 F .233
+(xample, if you')-.15 F .533 -.15(ve w)-.5 H .233(ritten your o).15 F
+.232(wn font implementation, you could put it in the gi)-.25 F -.15(ve)
+-.25 G(n).15 E F2(\214le)108 304.8 Q F0 5.103(.T)C .103(he actual chara\
+cters produced by the font need not be similar to those in the font bei\
+ng replaced; the)-5.103 F(y)-.15 E .496
+(could be in some other alphabet, or hieroglyphics or whate)108 316.8 R
+-.15(ve)-.25 G 2.996(ry).15 G .496(ou wish. Ho)-2.996 F(we)-.25 E -.15
+(ve)-.25 G 1.296 -.4(r, s).15 H .496(ee the CA).4 F(VEA)-1.35 E .496
+(TS sec-)-1.11 F(tion for limitations.)108 328.8 Q 1.031(An an e)108
+345.6 R 1.031(xample, suppose you w)-.15 F 1.031
+(ant Mup to use the Helv)-.1 F(etica-Narro)-.15 E 3.531(wf)-.25 G 1.032
+(ont rather than the plain Helv)-3.531 F(etica)-.15 E(font. Y)108 357.6
+Q(ou could use:)-1.1 E(mkmupfnt Helv)144 369.6 Q(etica-Narro)-.15 E 2.5
+(wH)-.25 G 2.5(Rh)-2.5 G(elvnarr)-2.5 E
+(to generate a Mup font\214le, then in your Mup program put:)108 381.6 Q
+(font\214le "helvnarr")144 393.6 Q(Then an)108 405.6 Q(ything that w)
+-.15 E(ould normally be printed in Helv)-.1 E
+(etica will come out in Helv)-.15 E(etica-Narro)-.15 E 2.5(wi)-.25 G
+(nstead.)-2.5 E F1(FILE FORMA)72 422.4 Q(T)-1.04 E F0 .037
+(Mup requires a)108 434.4 R F2(font\214le)2.537 E F0 .037(to be in a f)
+2.537 F .037(airly rigid format.)-.1 F .036
+(This section describes the format of the \214le that is pro-)5.037 F
+.068(duced by mkmupfnt.)108 446.4 R .068
+(The \214le can contain comment lines, which ha)5.068 F .368 -.15
+(ve a ')-.2 H .069(#' in column 1.).15 F .069(Otherwise the for)5.069 F
+(-)-.2 E(mat is:)108 458.4 Q F3(Mup f)129.6 470.4 Q(ont name:)-.25 E F2
+(Mup_font_name)2.5 E F3 -.2(Po)129.6 482.4 S(stScript f).2 E(ont name:)
+-.25 E F2 -.8(Po)2.5 G(stScript_font_name).8 E F3(Size data:)129.6 494.4
+Q(32)129.6 506.4 Q F2 5(width height ascent)7.5 F F3(33)129.6 518.4 Q F2
+5(width height ascent)7.5 F(... similar lines for ASCII codes 34-126.)
+165.6 530.4 Q(Dimension ar)165.6 542.4 Q 2.5(eg)-.37 G
+(iven in 1/1000ths of an inc)-2.5 E 2.5(hf)-.15 G(or a 12-point c)-2.5 E
+(har)-.15 E(acter)-.15 E(.)-1.11 E
+(All codes must be speci\214ed, and the)165.6 554.4 Q 2.5(ym)-.3 G
+(ust be in or)-2.5 E(der)-.37 E(.)-1.11 E F3 -.2(Po)129.6 566.4 S
+(stScript:).2 E F2(Zer)165.6 578.4 Q 2.5(oo)-.45 G 2.5(rm)-2.5 G(or)-2.5
+E 2.5(el)-.37 G(ines of P)-2.5 E(ostScript that will be copied)-.8 E -.2
+(ex)165.6 590.4 S(actly as is to the end of the Mup P).2 E(ostScript pr)
+-.8 E(olo)-.45 E -.15(g.)-.1 G F1(FILES)72 607.2 Q F0 7.5
+(mkmupfnt.ps PostScript)108 619.2 R(program that e)2.5 E
+(xtracts font size information)-.15 E F1(SEE ALSO)72 636 Q F0
+(gs\(1\), mup\(1\).)108 648 Q(Mup \212 Music Publisher User')108 660 Q
+2.5(sG)-.55 G(uide)-2.5 E F1(CA)72 676.8 Q(VEA)-1.588 E(TS)-1.04 E F0
+-1.1(Yo)108 688.8 S 2.5(um)1.1 G(ust ha)-2.5 E .3 -.15(ve g)-.2 H
+(hostscript \(gs or gs386.e).15 E -.15(xe)-.15 G 2.5(\)i).15 G 2.5(ny)
+-2.5 G(our P)-2.5 E -1.11(AT)-.92 G 2.5(Ha)1.11 G(nd it must be b)-2.5 E
+(uilt to include the "bit" de)-.2 E(vice.)-.25 E .79(Mup uses certain f\
+onts for certain things, such as time signatures, octa)108 705.6 R 1.09
+-.15(ve m)-.2 H .79(arks, endings, tuplet numbers,).15 F 2.544
+(etc. \(The)108 717.6 R .044(fonts used include all the T)2.544 F .044
+(imes fonts and Ne)-.35 F 2.544(wC)-.25 G .044(entury bold, plus Helv)
+-2.544 F .045(etica roman and Helv)-.15 F(etica)-.15 E .43
+(bold for tablature.\))108 729.6 R .43(If your o)5.43 F -.15(ve)-.15 G
+.43(rride one of the fonts used for those things, the).15 F 2.93(yw)-.15
+G .43(ill come out in your ne)-2.93 F(w)-.25 E(Arkkra Enterprises)72 768
+Q(July 31, 1999)131.105 E(1)201.915 E EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 358.84(mkmupfnt\(1\) mkmupfnt\(1\))72 48 R .862
+(font. On the one hand, if you don')108 84 R 3.362(tl)-.18 G(ik)-3.362 E
+3.362(eM)-.1 G(up')-3.362 E 3.362(sc)-.55 G .862(hoices, this pro)-3.362
+F .862(vides you a w)-.15 F .862(ay to get your o)-.1 F .862(wn. On the)
+-.25 F .826(other hand, if you w)108 96 R .826(ant to change most, b)-.1
+F .826
+(ut not all uses of a particular font, it may not be possible to do)-.2
+F(that.)108 108 Q(Only the ASCII characters 32-126 can be o)108 124.8 Q
+-.15(ve)-.15 G(rridden. The non-ASCII characters can not be o).15 E -.15
+(ve)-.15 G(rridden.).15 E .682(Mup only allo)108 141.6 R .682
+(ws width v)-.25 F .682(alues up to 1/2 inch for a 12-point character)
+-.25 F 3.182(.T)-.55 G .683(his program does not enforce that)-3.182 F
+(limitation.)108 153.6 Q 2.064(This program has been tested with v)108
+170.4 R 2.064(arious Ghostscript fonts, b)-.25 F 2.064(ut may not w)-.2
+F 2.063(ork on just an)-.1 F 4.563(ya)-.15 G(rbitrary)-4.563 E
+(PostScript font.)108 182.4 Q(Arkkra Enterprises)72 768 Q(July 31, 1999)
+131.105 E(2)201.915 E EP
+%%Trailer
+end
+%%EOF
diff --git a/mup/docs/mup.1 b/mup/docs/mup.1
new file mode 100644 (file)
index 0000000..39f8645
--- /dev/null
@@ -0,0 +1,219 @@
+.TH mup 1 "Sep 25, 2006" "Arkkra Enterprises"
+.SH NAME
+.PP
+mup - music publisher
+.SH SYNOPSIS
+.PP
+\fBmup\fP [\fB-c\fP\fIN\fP] [-C] [\fB-d\fP\fIN\fP] [\fB-D\fP \fIMACRO[=macro-def\fP]]
+[\fB-e\fP \fIerrfile\fP] [-E]
+[\fB-f\fP \fIoutfile\fP] [\fB-F\fP] [\fB-m\fP \fImidifile\fP] [\fB-M\fP] [\fB-o\fP \fIpagelist\fP] [\fB-p\fP\fIN\fP]
+[\fB-v\fP] [\fB-x\fP \fIN\fP[,\fIM\fP] [\fIfile...\fP]
+.SH DESCRIPTION
+.PP
+Mup is a program for producing printed music.
+There is an optional companion program called Mupmate
+that provides a more graphical user interface on top of Mup,
+but this manual page describes the command line interface.
+The Mup User's Guide should be consulted for details of the format of the
+input file.
+Options include:
+.TP
+\fB-c\fP \fIN\fP
+Combine consecutive measures of all rests or spaces into multirests (multiple
+measures of rest printed as a single measure, with the number of measures of
+rest printed above the staff).
+Any time there
+are \fIN\fP or more measures in a row that consist entirely of rests or spaces,
+they will be replaced by a multirest. The combining of measures 
+stops when there is a visible staff that contains notes,
+lyrics, or other musical symbols,
+when there are parameter changes on a visible staff or in score context, or
+when there is a bar line other than an ordinary or invisible bar.
+This option is most likely to be useful when printing a subset of staffs,
+where the particular staff(s) you are printing have long periods of rests.
+(See the -s option.)
+.TP
+\fB-C\fP
+This option is only used in connection with the -E option.
+It specifies that comments
+are to be passed through rather than deleted.
+.TP
+\fB-d\fP \fIN\fP
+Print debugging information. \fIN\fP is a bitmap.
+.RS 4
+.TP
+1
+parse phase information
+.TP
+2
+high level parse phase tracing
+.TP
+4
+low level parse phase tracing
+.TP
+8
+reserved
+.TP
+16
+high level placement phase tracing
+.TP
+32
+low level placement phase tracing
+.TP
+64
+reserved
+.TP
+128
+contents of the main internal list
+.TP
+256
+high level print phase tracing
+.TP
+512
+low level print phase tracing
+.RE
+.IP
+\fIN\fP can be specified in decimal, octal
+(by using a leading zero), or hex (by using a leading 0x).
+This information is intended for debugging of
+\fBMup\fP itself and thus is not likely to be of use to the average user.
+.TP
+\fB-D\fP \fIMACRO[=macro-def]\fP
+Define the macro \fIMACRO\fP. The
+macro name must consist of upper case letters,
+digits, and underscores, beginning
+with an upper case letter. The \fImacro_def\fP is optional, and gives the
+text of the macro. If it contains any white space or other special characters,
+it must be quoted (if quoting is supported by your operating system or shell).
+.TP
+\fB-e\fP \fIerrfile\fP
+Place error messages into \fIerrfile\fP instead of writing them to the standard
+error output stream.
+.TP
+\fB-E\fP
+Rather than produce PostScript or MIDI output, just expand macros and
+includes, and write the result to the standard output stream.
+Comments in the input are deleted, unless the -C option is also specified.
+.TP
+\fB-f\fP \fIoutfile\fP
+Place the output into \fIoutfile\fP instead of writing it to the
+standard output.
+.TP
+\fB-F\fP
+This is like the \fB-f\fP option, except the name of the output file is
+derived from the name of the Mup input file. If the name of the Mup input
+file ends with a ".mup" suffix, the generated PostScript output
+file will end with a ".ps" suffix instead.
+If the name of the Mup input file ends with
+a ".MUP" suffix, the PostScript file will end with a ".PS" suffix.
+Otherwise, a ".ps" suffix will be appended to the end of the Mup
+input file name. If multiple input files are listed, the last is used.
+If none are specified (input is read from standard input),
+the name "stdin.ps" will be used for the output file.
+.TP
+\fB-m\fP \fImidifile\fP
+Instead of generating PostScript output,
+generate standard MIDI (Musical Instrument Digital Interface) output,
+and put it in \fImidifile\fP.
+This option also causes the macro "MIDI" to become defined.
+.TP
+\fB-M\fP
+This is like the \fB-m\fP option, except the name of the MIDI file is
+derived from the name of the Mup input file. If the name of the Mup input
+file ends with a ".mup" suffix, the generated MIDI file will end with
+a ".mid" suffix instead. If the name of the Mup input file ends with
+a ".MUP" suffix, the MIDI file will end with a ".MID" suffix.
+Otherwise, a ".mid" suffix will be appended to the end of the Mup
+input file name. If multiple input files are listed, the last is used.
+If none are specified (input is read from standard input),
+the name "stdin.mid" will be used for the MIDI file.
+.TP
+\fB-o\fP \fIpagelist\fP
+Print only the pages given in \fIpagelist\fP. The \fIpagelist\fP can be
+a comma-separated list of numbers or ranges, where a range is two numbers
+separated by a dash. For example, -o1,7-9,12-14 would print pages 1, 7, 8,
+9, 12, 13, and 14. Pages will be printed in the order given.
+They need not be in order, and a page
+number may be included more than once.
+Alternately, the \fIpagelist\fP can be the special
+keyword "odd" or "even" which will cause all odd or even numbered pages
+to be printed. This may be useful if you have a printer that only makes
+single-sided copies, but you wish to print Mup output double-sided. You could
+print odd-numbered pages, then turn the paper over and feed the pages
+through again for the even-numbered pages. 
+.TP
+\fB-p\fP\fIN\fP
+Start numbering pages at \fIN\fP instead of at 1.
+If \fB-o\fP and \fB-p\fP are used together, the page numbers given in the
+\fB-o\fP\fIpagelist\fP must be the printed page numbers. For example, if you
+use -p10 and want to print just the second page,
+you would need to specify -o11.
+.TP
+\fB-r\fP
+Print a copy of the Mup shareware registration form to the standard output.
+.TP
+\fB-s\fP\fIstafflist\fP
+Only print the staffs that are included in \fIstafflist\fP. This can be a
+comma-separated list of staff numbers or ranges, such as "1,5" or "1-3,7-8"
+To further restrict to a single voice on a staff, add \fBv\fP\fIN\fP where
+\fIN\fP is the voice number (1, 2, or 3), after the staff, as in "2v1,5v2"
+You can't specify a list or range for voices;
+if you only want to make two out of three voices visible,
+you have to specify them separately, like "1v2,1v3".
+No spaces are allowed in the list.
+.TP
+\fB-v\fP
+Print the Mup version number and exit. This manual page is for version 5.3.
+.TP
+\fB-x\fP\fIM,N\fP
+Extract measures \fIM\fP through \fIN\fP of the song. This allows you to print
+or play a part of a song. The comma and second value are optional;
+if not specified, the default is to go to the end of the piece.
+Positive values specify the number of measures from the beginning of the piece,
+while negative values are relative to the end, with -1 referring to the
+last measure of the song.
+So -x1,-1 means the entire song, if the song doesn't have a pickup measure.
+If the song has a pickup measure, that is specified by 0.
+So for a song with a pickup, -x0,-1 would mean the entire song,
+and -x0,0 would mean just the pickup measure.
+As other examples, -x-1,-1 means just the final measure of the song,
+-x2 means starting after the first full measure, -x3,4 means only
+measures 3 and 4, and -x6,6 means just measure 6.
+The starting measure is not allowed to be inside an ending.
+A common use for this option might be to generate a MIDI file
+for just a few measures. For example, if you were
+trying to tweak tempo values for a ritard in the last 2 measures of a song,
+you could use -x-2 to listen to just those measures.
+.PP
+The options, if any, can be followed by one or more \fIfiles\fP in Mup format.
+If no \fIfiles\fP are specified, standard input is read.
+If several \fIfiles\fP are listed, they are effectively concatenated together
+and treated as one big file. Since there are some things (such as header
+and footer) that are only allowed to occur once, if you have several independent
+pieces, mup should be called on each individually rather than trying to
+print them all with one command.
+If a specified file does not exist, and its name does not already end
+with .mup or .MUP, then Mup will append .mup to the specified name and
+attempt to open that.
+.PP
+On most systems, the environment variable MUPPATH can be set
+to a list of paths in which to look for 'include' files. 
+The components are separated by a colon on Unix or Linux systems, and by a
+semicolon on systems with DOS-like file naming conventions.
+.PP
+For more debugging, in addition to the -d option,
+if the environment variable MUP_BB is set to "bcfghnsu" or any subset
+of those letters, the generated output will include "bounding
+boxes" for the things Mup internally calls bars (b), chords (c), feeds (f),
+grpsyls (g), header/footer and top/bottom (h),
+notes (n), staffs (s), and stuff (u).
+While this is intended for use in debugging Mup itself, it may also
+help you understand why Mup places things the way it does,
+since in general, Mup only allows bounding boxes to overlap according
+to specific rules. If viewed with a color PostScript viewer (not mupdisp),
+these boxes will be in color.
+.SH "SEE ALSO"
+.PP
+gs(1), mkmupfnt(1), mupdisp(1), mupmate(1), mupprnt(1).
+.br
+Mup \(em Music Publisher User's Guide
diff --git a/mup/docs/mup.ps b/mup/docs/mup.ps
new file mode 100644 (file)
index 0000000..3383401
--- /dev/null
@@ -0,0 +1,463 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.17.2
+%%CreationDate: Sat Dec  9 16:59:22 2006
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.17 2
+%%Pages: 3
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.17 2
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/MANUAL{
+statusdict begin/manualfeed true store end
+}bind def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
+def/PL PLG def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
+/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
+/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
+/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
+/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
+/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
+/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
+/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
+/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
+/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
+/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
+/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
+/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
+/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
+/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
+/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
+/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
+/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
+/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
+/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
+/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
+/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE
+/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 406.62(mup\(1\) mup\(1\))72 48 R/F1 10.95
+/Times-Bold@0 SF -.219(NA)72 84 S(ME).219 E F0(mup - music publisher)108
+96 Q F1(SYNOPSIS)72 112.8 Q/F2 10/Times-Bold@0 SF(mup)108 124.8 Q F0([)
+3.88 E F2(-c)A/F3 10/Times-Italic@0 SF(N)A F0 3.88(][)C 1.38(-C] [)-3.88
+F F2(-d)A F3(N)A F0 3.88(][)C F2(-D)-3.88 E F3(MA)3.88 E(CR)-.3 E
+(O[=macr)-.4 E(o-def)-.45 E F0 1.38(]] [)B F2(-e)A F3(err\214le)3.88 E
+F0 3.88(][)C 1.38(-E] [)-3.88 F F2(-f)A F3(out\214le)3.88 E F0 3.88(][)C
+F2(-F)-3.88 E F0 3.88(][)C F2(-m)-3.88 E F3(midi\214le)3.88 E F0 3.88
+(][)C F2(-M)-3.88 E F0 3.88(][)C F2(-o)-3.88 E F3(pa)108 136.8 Q -.1(ge)
+-.1 G(list).1 E F0 2.5(][)C F2(-p)-2.5 E F3(N)A F0 2.5(][)C F2(-v)-2.5 E
+F0 2.5(][)C F2(-x)-2.5 E F3(N)2.5 E F0([,)A F3(M)A F0 2.5(][)C F3
+(\214le)-2.5 E(...)-.15 E F0(])A F1(DESCRIPTION)72 153.6 Q F0 .563
+(Mup is a program for producing printed music.)108 165.6 R .564
+(There is an optional companion program called Mupmate)5.563 F .574
+(that pro)108 177.6 R .574(vides a more graphical user interf)-.15 F
+.574(ace on top of Mup, b)-.1 F .573
+(ut this manual page describes the command)-.2 F 2.022(line interf)108
+189.6 R 4.522(ace. The)-.1 F 2.022(Mup User')4.522 F 4.522(sG)-.55 G
+2.022(uide should be consulted for details of the format of the input \
+\214le.)-4.522 F(Options include:)108 201.6 Q F2(-c)108 218.4 Q F3(N)2.5
+E F0 1.544(Combine consecuti)19.06 F 1.843 -.15(ve m)-.25 H 1.543(easur\
+es of all rests or spaces into multirests \(multiple measures of rest)
+.15 F 1.205(printed as a single measure, with the number of measures of\
+ rest printed abo)144 230.4 R 1.505 -.15(ve t)-.15 H 1.205(he staf).15 F
+3.705(f\). An)-.25 F(y)-.15 E 1.014(time there are)144 242.4 R F3(N)
+3.514 E F0 1.013(or more measures in a ro)3.513 F 3.513(wt)-.25 G 1.013
+(hat consist entirely of rests or spaces, the)-3.513 F 3.513(yw)-.15 G
+1.013(ill be)-3.513 F .967(replaced by a multirest. The combining of me\
+asures stops when there is a visible staf)144 254.4 R 3.468(ft)-.25 G
+.968(hat con-)-3.468 F .718(tains notes, lyrics, or other musical symbo\
+ls, when there are parameter changes on a visible staf)144 266.4 R(f)
+-.25 E .347(or in score conte)144 278.4 R .348
+(xt, or when there is a bar line other than an ordinary or in)-.15 F
+.348(visible bar)-.4 F 5.348(.T)-.55 G .348(his option)-5.348 F 1.046
+(is most lik)144 290.4 R 1.046
+(ely to be useful when printing a subset of staf)-.1 F 1.046
+(fs, where the particular staf)-.25 F 1.045(f\(s\) you are)-.25 F
+(printing ha)144 302.4 Q .3 -.15(ve l)-.2 H(ong periods of rests.).15 E
+(\(See the -s option.\))5 E F2(-C)108 319.2 Q F0 1.154
+(This option is only used in connection with the -E option.)25.45 F
+1.155(It speci\214es that comments are to be)6.155 F
+(passed through rather than deleted.)144 331.2 Q F2(-d)108 348 Q F3(N)
+2.5 E F0(Print deb)17.94 E(ugging information.)-.2 E F3(N)2.5 E F0
+(is a bitmap.)2.5 E 31(1p)128 364.8 S(arse phase information)-31 E 31
+(2h)128 381.6 S(igh le)-31 E -.15(ve)-.25 G 2.5(lp).15 G
+(arse phase tracing)-2.5 E 31(4l)128 398.4 S .5 -.25(ow l)-31 H -2.15
+-.25(ev e).25 H 2.5(lp).25 G(arse phase tracing)-2.5 E 31(8r)128 415.2 S
+(eserv)-31 E(ed)-.15 E 23.5(16 high)128 432 R(le)2.5 E -.15(ve)-.25 G
+2.5(lp).15 G(lacement phase tracing)-2.5 E 23.5(32 lo)128 448.8 R 2.5
+(wl)-.25 G -2.15 -.25(ev e)-2.5 H 2.5(lp).25 G(lacement phase tracing)
+-2.5 E 23.5(64 reserv)128 465.6 R(ed)-.15 E 18.5(128 contents)128 482.4
+R(of the main internal list)2.5 E 18.5(256 high)128 499.2 R(le)2.5 E
+-.15(ve)-.25 G 2.5(lp).15 G(rint phase tracing)-2.5 E 18.5(512 lo)128
+516 R 2.5(wl)-.25 G -2.15 -.25(ev e)-2.5 H 2.5(lp).25 G
+(rint phase tracing)-2.5 E F3(N)144 532.8 Q F0 .108(can be speci\214ed \
+in decimal, octal \(by using a leading zero\), or he)2.608 F 2.608(x\()
+-.15 G .108(by using a leading 0x\).)-2.608 F(This)5.107 E .289
+(information is intended for deb)144 544.8 R .289(ugging of)-.2 F F2
+(Mup)2.789 E F0 .289(itself and thus is not lik)2.789 F .289
+(ely to be of use to the a)-.1 F -.15(ve)-.2 G -.2(r-).15 G(age user)144
+556.8 Q(.)-.55 E F2(-D)108 573.6 Q F3(MA)2.5 E(CR)-.3 E(O[=macr)-.4 E
+(o-def])-.45 E F0 .576(De\214ne the macro)144 585.6 R F3(MA)3.076 E(CR)
+-.3 E(O)-.4 E F0 3.076(.T)C .576
+(he macro name must consist of upper case letters, digits, and under)
+-3.076 F(-)-.2 E 1.023(scores, be)144 597.6 R 1.023
+(ginning with an upper case letter)-.15 F 3.523(.T)-.55 G(he)-3.523 E F3
+(macr)3.523 E(o_def)-.45 E F0 1.023(is optional, and gi)3.523 F -.15(ve)
+-.25 G 3.523(st).15 G 1.023(he te)-3.523 F 1.024(xt of the)-.15 F .807
+(macro. If it contains an)144 609.6 R 3.307(yw)-.15 G .807(hite space o\
+r other special characters, it must be quoted \(if quoting is)-3.307 F
+(supported by your operating system or shell\).)144 621.6 Q F2(-e)108
+638.4 Q F3(err\214le)2.5 E F0(Place error messages into)144 650.4 Q F3
+(err\214le)2.5 E F0
+(instead of writing them to the standard error output stream.)2.5 E F2
+(-E)108 667.2 Q F0 1.078
+(Rather than produce PostScript or MIDI output, just e)26 F 1.078
+(xpand macros and includes, and write the)-.15 F .984
+(result to the standard output stream.)144 679.2 R .984
+(Comments in the input are deleted, unless the -C option is)5.984 F
+(also speci\214ed.)144 691.2 Q(Arkkra Enterprises)72 768 Q(Sep 25, 2006)
+131.94 E(1)202.75 E EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 406.62(mup\(1\) mup\(1\))72 48 R/F1 10
+/Times-Bold@0 SF(-f)108 84 Q/F2 10/Times-Italic@0 SF(out\214le)2.5 E F0
+(Place the output into)144 96 Q F2(out\214le)2.5 E F0
+(instead of writing it to the standard output.)2.5 E F1(-F)108 112.8 Q
+F0 .598(This is lik)26.56 F 3.098(et)-.1 G(he)-3.098 E F1(-f)3.098 E F0
+.598(option, e)3.098 F .598(xcept the name of the output \214le is deri)
+-.15 F -.15(ve)-.25 G 3.099(df).15 G .599(rom the name of the Mup)-3.099
+F 1.065(input \214le. If the name of the Mup input \214le ends with a "\
+.mup" suf)144 124.8 R 1.065(\214x, the generated PostScript)-.25 F 1.508
+(output \214le will end with a ".ps" suf)144 136.8 R 1.508
+(\214x instead.)-.25 F 1.509
+(If the name of the Mup input \214le ends with a)6.508 F .992
+(".MUP" suf)144 148.8 R .992
+(\214x, the PostScript \214le will end with a ".PS" suf)-.25 F 3.492
+(\214x. Otherwise,)-.25 F 3.492(a")3.492 G .992(.ps" suf)-3.492 F .991
+(\214x will be)-.25 F .609(appended to the end of the Mup input \214le \
+name. If multiple input \214les are listed, the last is used.)144 160.8
+R .71(If none are speci\214ed \(input is read from standard input\), th\
+e name "stdin.ps" will be used for the)144 172.8 R(output \214le.)144
+184.8 Q F1(-m)108 201.6 Q F2(midi\214le)2.5 E F0 .065(Instead of genera\
+ting PostScript output, generate standard MIDI \(Musical Instrument Dig\
+ital Inter)144 213.6 R(-)-.2 E -.1(fa)144 225.6 S
+(ce\) output, and put it in).1 E F2(midi\214le)2.5 E F0 5(.T)C
+(his option also causes the macro "MIDI" to become de\214ned.)-5 E F1
+(-M)108 242.4 Q F0 .488(This is lik)23.23 F 2.988(et)-.1 G(he)-2.988 E
+F1(-m)2.988 E F0 .488(option, e)2.988 F .488
+(xcept the name of the MIDI \214le is deri)-.15 F -.15(ve)-.25 G 2.988
+(df).15 G .488(rom the name of the Mup)-2.988 F .164(input \214le. If t\
+he name of the Mup input \214le ends with a ".mup" suf)144 254.4 R .165
+(\214x, the generated MIDI \214le will)-.25 F .464
+(end with a ".mid" suf)144 266.4 R .464(\214x instead. If the name of t\
+he Mup input \214le ends with a ".MUP" suf)-.25 F .463(\214x, the)-.25 F
+.151(MIDI \214le will end with a ".MID" suf)144 278.4 R 2.651
+(\214x. Otherwise,)-.25 F 2.651(a")2.651 G .151(.mid" suf)-2.651 F .151
+(\214x will be appended to the end of)-.25 F 1.045(the Mup input \214le\
+ name. If multiple input \214les are listed, the last is used.)144 290.4
+R 1.045(If none are speci\214ed)6.045 F(\(input is read from standard i\
+nput\), the name "stdin.mid" will be used for the MIDI \214le.)144 302.4
+Q F1(-o)108 319.2 Q F2(pa)2.5 E -.1(ge)-.1 G(list).1 E F0 .723
+(Print only the pages gi)144 331.2 R -.15(ve)-.25 G 3.223(ni).15 G(n)
+-3.223 E F2(pa)3.223 E -.1(ge)-.1 G(list).1 E F0 3.223(.T)C(he)-3.223 E
+F2(pa)3.223 E -.1(ge)-.1 G(list).1 E F0 .723
+(can be a comma-separated list of numbers or)3.223 F .069
+(ranges, where a range is tw)144 343.2 R 2.569(on)-.1 G .069
+(umbers separated by a dash. F)-2.569 F .068(or e)-.15 F .068
+(xample, -o1,7-9,12-14 w)-.15 F .068(ould print)-.1 F 1.194
+(pages 1, 7, 8, 9, 12, 13, and 14. P)144 355.2 R 1.194
+(ages will be printed in the order gi)-.15 F -.15(ve)-.25 G 3.695
+(n. The).15 F 3.695(yn)-.15 G 1.195(eed not be in)-3.695 F(order)144
+367.2 Q 3.48(,a)-.4 G .98
+(nd a page number may be included more than once.)-3.48 F(Alternately)
+5.979 E 3.479(,t)-.65 G(he)-3.479 E F2(pa)3.479 E -.1(ge)-.1 G(list).1 E
+F0 .979(can be the)3.479 F .664(special k)144 379.2 R -.15(ey)-.1 G -.1
+(wo).15 G .664(rd "odd" or "e).1 F -.15(ve)-.25 G .664
+(n" which will cause all odd or e).15 F -.15(ve)-.25 G 3.165(nn).15 G
+.665(umbered pages to be printed.)-3.165 F .202
+(This may be useful if you ha)144 391.2 R .502 -.15(ve a p)-.2 H .202
+(rinter that only mak).15 F .201(es single-sided copies, b)-.1 F .201
+(ut you wish to print)-.2 F .335(Mup output double-sided. Y)144 403.2 R
+.335(ou could print odd-numbered pages, then turn the paper o)-1.1 F
+-.15(ve)-.15 G 2.835(ra).15 G .335(nd feed)-2.835 F
+(the pages through ag)144 415.2 Q(ain for the e)-.05 E -.15(ve)-.25 G
+(n-numbered pages.).15 E F1(-p)108 432 Q F2(N)A F0 .245
+(Start numbering pages at)20.44 F F2(N)2.745 E F0 .245(instead of at 1.)
+2.745 F(If)5.245 E F1(-o)2.745 E F0(and)2.745 E F1(-p)2.745 E F0 .245
+(are used together)2.745 F 2.744(,t)-.4 G .244(he page numbers gi)-2.744
+F -.15(ve)-.25 G(n).15 E .152(in the)144 444 R F1(-o)2.652 E F2(pa)A -.1
+(ge)-.1 G(list).1 E F0 .153(must be the printed page numbers. F)2.652 F
+.153(or e)-.15 F .153(xample, if you use -p10 and w)-.15 F .153
+(ant to print)-.1 F(just the second page, you w)144 456 Q
+(ould need to specify -o11.)-.1 E F1(-r)108 472.8 Q F0(Print a cop)28.23
+E 2.5(yo)-.1 G 2.5(ft)-2.5 G(he Mup share)-2.5 E -.1(wa)-.25 G(re re).1
+E(gistration form to the standard output.)-.15 E F1(-s)108 489.6 Q F2
+(staf)A(\215ist)-.18 E F0 .299(Only print the staf)144 501.6 R .298
+(fs that are included in)-.25 F F2(staf)2.798 E(\215ist)-.18 E F0 2.798
+(.T)C .298(his can be a comma-separated list of staf)-2.798 F 2.798(fn)
+-.25 G(um-)-2.798 E .974(bers or ranges, such as "1,5" or "1-3,7-8" T)
+144 513.6 R 3.474(of)-.8 G .974(urther restrict to a single v)-3.474 F
+.975(oice on a staf)-.2 F .975(f, add)-.25 F F1(v)3.475 E F2(N)A F0
+(where)144 525.6 Q F2(N)2.828 E F0 .328(is the v)2.828 F .327
+(oice number \(1, 2, or 3\), after the staf)-.2 F .327
+(f, as in "2v1,5v2" Y)-.25 F .327(ou can')-1.1 F 2.827(ts)-.18 G .327
+(pecify a list or)-2.827 F 1.151(range for v)144 537.6 R 1.151
+(oices; if you only w)-.2 F 1.151(ant to mak)-.1 F 3.651(et)-.1 G 1.351
+-.1(wo o)-3.651 H 1.151(ut of three v).1 F 1.151(oices visible, you ha)
+-.2 F 1.452 -.15(ve t)-.2 H 3.652(os).15 G(pecify)-3.652 E
+(them separately)144 549.6 Q 2.5(,l)-.65 G(ik)-2.5 E 2.5(e")-.1 G 2.5
+(1v2,1v3". No)-2.5 F(spaces are allo)2.5 E(wed in the list.)-.25 E F1
+(-v)108 566.4 Q F0(Print the Mup v)27.67 E(ersion number and e)-.15 E
+(xit. This manual page is for v)-.15 E(ersion 5.3.)-.15 E F1(-x)108
+583.2 Q F2(M,N)A F0 .565(Extract measures)10.17 F F2(M)3.065 E F0
+(through)3.065 E F2(N)3.065 E F0 .565(of the song. This allo)3.065 F
+.565(ws you to print or play a part of a song. The)-.25 F .41
+(comma and second v)144 595.2 R .41
+(alue are optional; if not speci\214ed, the def)-.25 F .411
+(ault is to go to the end of the piece.)-.1 F(Positi)144 607.2 Q 1.409
+-.15(ve v)-.25 H 1.109(alues specify the number of measures from the be)
+-.1 F 1.108(ginning of the piece, while ne)-.15 F -.05(ga)-.15 G(ti).05
+E -.15(ve)-.25 G -.25(va)144 619.2 S .775(lues are relati).25 F 1.075
+-.15(ve t)-.25 H 3.275(ot).15 G .775
+(he end, with -1 referring to the last measure of the song.)-3.275 F
+.775(So -x1,-1 means)5.775 F .336(the entire song, if the song doesn')
+144 631.2 R 2.836(th)-.18 G -2.25 -.2(av e)-2.836 H 2.836(ap)3.036 G
+.336(ickup measure.)-2.836 F .336
+(If the song has a pickup measure, that)5.336 F .08
+(is speci\214ed by 0.)144 643.2 R .08
+(So for a song with a pickup, -x0,-1 w)5.08 F .08
+(ould mean the entire song, and -x0,0 w)-.1 F(ould)-.1 E 1.433
+(mean just the pickup measure.)144 655.2 R 1.433(As other e)6.433 F
+1.432(xamples, -x-1,-1 means just the \214nal measure of the)-.15 F .226
+(song, -x2 means starting after the \214rst full measure, -x3,4 means o\
+nly measures 3 and 4, and -x6,6)144 667.2 R .126(means just measure 6.)
+144 679.2 R .125(The starting measure is not allo)5.126 F .125
+(wed to be inside an ending.)-.25 F 2.625(Ac)5.125 G .125(ommon use)
+-2.625 F .363
+(for this option might be to generate a MIDI \214le for just a fe)144
+691.2 R 2.863(wm)-.25 G .363(easures. F)-2.863 F .363(or e)-.15 F .364
+(xample, if you were)-.15 F .089(trying to tweak tempo v)144 703.2 R
+.088(alues for a ritard in the last 2 measures of a song, you could use\
+ -x-2 to lis-)-.25 F(ten to just those measures.)144 715.2 Q
+(Arkkra Enterprises)72 768 Q(Sep 25, 2006)131.94 E(2)202.75 E EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 406.62(mup\(1\) mup\(1\))72 48 R .448
+(The options, if an)108 84 R 1.748 -.65(y, c)-.15 H .448(an be follo).65
+F .448(wed by one or more)-.25 F/F1 10/Times-Italic@0 SF(\214les)2.948 E
+F0 .448(in Mup format.)2.948 F .448(If no)5.448 F F1(\214les)2.948 E F0
+.448(are speci\214ed, standard)2.948 F .092(input is read.)108 96 R .092
+(If se)5.092 F -.15(ve)-.25 G(ral).15 E F1(\214les)2.592 E F0 .092
+(are listed, the)2.592 F 2.592(ya)-.15 G .092(re ef)-2.592 F(fecti)-.25
+E -.15(ve)-.25 G .091
+(ly concatenated together and treated as one big \214le.).15 F .99(Sinc\
+e there are some things \(such as header and footer\) that are only all\
+o)108 108 R .991(wed to occur once, if you ha)-.25 F -.15(ve)-.2 G(se)
+108 120 Q -.15(ve)-.25 G .777
+(ral independent pieces, mup should be called on each indi).15 F .777
+(vidually rather than trying to print them all)-.25 F .054
+(with one command.)108 132 R .054(If a speci\214ed \214le does not e)
+5.054 F .054(xist, and its name does not already end with .mup or .MUP)
+-.15 F(,)-1.11 E(then Mup will append .mup to the speci\214ed name and \
+attempt to open that.)108 144 Q 1.096(On most systems, the en)108 160.8
+R 1.096(vironment v)-.4 F 1.096(ariable MUPP)-.25 F -1.11(AT)-.92 G
+3.596(Hc)1.11 G 1.096(an be set to a list of paths in which to look for)
+-3.596 F .13('include' \214les.)108 172.8 R .13(The components are sepa\
+rated by a colon on Unix or Linux systems, and by a semicolon on)5.13 F
+(systems with DOS-lik)108 184.8 Q 2.5<658c>-.1 G(le naming con)-2.5 E
+-.15(ve)-.4 G(ntions.).15 E -.15(Fo)108 201.6 S 2.672(rm).15 G .172
+(ore deb)-2.672 F .171(ugging, in addition to the -d option, if the en)
+-.2 F .171(vironment v)-.4 F .171(ariable MUP_BB is set to "bcfghnsu")
+-.25 F .355(or an)108 213.6 R 2.855(ys)-.15 G .356(ubset of those lette\
+rs, the generated output will include "bounding box)-2.855 F .356
+(es" for the things Mup inter)-.15 F(-)-.2 E .465(nally calls bars \(b\
+\), chords \(c\), feeds \(f\), grpsyls \(g\), header/footer and top/bot\
+tom \(h\), notes \(n\), staf)108 225.6 R .465(fs \(s\),)-.25 F .367
+(and stuf)108 237.6 R 2.867(f\()-.25 G 2.867(u\). While)-2.867 F .367
+(this is intended for use in deb)2.867 F .368
+(ugging Mup itself, it may also help you understand wh)-.2 F(y)-.05 E
+.315(Mup places things the w)108 249.6 R .315
+(ay it does, since in general, Mup only allo)-.1 F .314(ws bounding box)
+-.25 F .314(es to o)-.15 F -.15(ve)-.15 G .314(rlap according).15 F
+(to speci\214c rules. If vie)108 261.6 Q
+(wed with a color PostScript vie)-.25 E(wer \(not mupdisp\), these box)
+-.25 E(es will be in color)-.15 E(.)-.55 E/F2 10.95/Times-Bold@0 SF
+(SEE ALSO)72 278.4 Q F0
+(gs\(1\), mkmupfnt\(1\), mupdisp\(1\), mupmate\(1\), mupprnt\(1\).)108
+290.4 Q(Mup \212 Music Publisher User')108 302.4 Q 2.5(sG)-.55 G(uide)
+-2.5 E(Arkkra Enterprises)72 768 Q(Sep 25, 2006)131.94 E(3)202.75 E EP
+%%Trailer
+end
+%%EOF
diff --git a/mup/docs/mupdisp.1 b/mup/docs/mupdisp.1
new file mode 100644 (file)
index 0000000..1be9165
--- /dev/null
@@ -0,0 +1,127 @@
+.TH mupdisp 1 "November 4, 2006" "Arkkra Enterprises"
+.SH NAME
+.PP
+mupdisp - display output from Mup music publisher program
+.SH SYNOPSIS
+.PP
+mupdisp \fI[mup_options] file\fP
+.SH DESCRIPTION
+.PP
+Mupdisp provides a way to view Mup output on your screen.
+The \fIfile\fP is Mup input. Any other Mup options can be given,
+except -f, -m, -M, -r, or -v, which don't produce print output.
+.PP
+Mupdisp will run under MS-DOS or will run under
+UNIX with a TERM of AT386, linux, or xterm (under X windows). 
+.PP
+When running under X windows, several standard X options are
+available:
+.TP
+\fB-geometry\fP \fIXxY+M+N\fP
+Sets the window size and/or location on the screen. The actual window
+width will be determined by the width of the Mup output. The height
+will be adjusted if necessary to be between 400 and the actual height
+of the Mup output. The window placment specifications can be positive
+or negative. The actual placement may be adjusted by your window manager.
+.TP
+\fB-fg\fP \fIcolor\fP or \fB-foreground\fP \fIcolor\fP
+Specifies the foreground color to use.
+.TP
+\fB-bg\fP \fIcolor\fP or \fB-background\fP \fIcolor\fP
+Specifies the background color to use.
+.PP
+These X options can also be set in your .Xdefaults file using resource names of
+mupdisp.geometry, mupdisp.foreground, and mupdisp.background. Command
+line arguments will override values in the .Xdefaults file.
+As an example, you could add these lines to your .Xdefaults file:
+.nf
+.na
+.ft CW
+.in +1i
+
+mupdisp.foreground:   navy
+mupdisp.background:   gray
+mupdisp.geometry:     400x760+100-34
+
+.in -1i
+.ft P
+.fi
+.ad
+.PP
+The Mupdisp program begins in partial page mode,
+which displays output at approximately actual size (depending
+on the size of your monitor). In this mode, most likely
+not all of the page fits on the
+screen, so the scrolling commands can be used to move up and down to view
+different parts of the page. In full page mode, a small version of the
+entire page is displayed.  This is useful
+for seeing overall page layout, but is generally too small to see much detail.
+This mode is now somewhat of a relic of the days when screens were typically
+much smaller than they are today, and is thus becoming less useful.
+.PP
+If the environment variable MUPDISPMODE is set to some value,
+Mupdisp will start in full page rather than partial page mode.
+.PP
+The commands are:
+.TP
+\fInum\fP<Enter>
+Go to page number \fInum\fP.
+.TP
++ or <space> or <control-E> or <control-F>
+move forward on the page by about 1/8 of an inch
+(partial page mode only)
+.TP
+- or <backspace> or <control-Y> or <control-B>
+move backward on the page by about 1/8 of an inch
+(partial page mode only)
+.TP
+b or <control-U> or <control-P> or <up-arrow-key>
+move backward on the page by about an inch
+(partial page mode only)
+.TP
+f or <Enter> or <control-D> or <control-N> or <down-arrow-key>
+move forward on the page by about an inch
+(partial page mode only)
+.TP
+h or ?
+display help screen
+.TP
+m
+toggle between partial page and full page modes.
+.TP
+n or <PageDown>
+go to next page
+.TP
+p or <PageUp>
+go to previous page
+.TP
+q or ZZ
+quit
+.TP
+r
+Repaint the page (useful for exiting help page)
+.PP
+When in X windows, the mouse can be used for scrolling. The left button scrolls
+downward like the f command, while the right button scrolls backwards like
+the b command.
+.PP
+Mupdisp supports page sizes of letter (8.5 x 11.0 inches),
+note (7.5 x 10.0 inches), legal (8.5 x 14.0 inches),
+A4 (8.26 x 11.69 inches), A5 (5.85 x 8.26 inches),
+A6 (4.125 x 5.85 inches), flsa (8.5 x 13.0 inches), and
+halfletter (5.5 x 8.5 inches).
+.SH FILES
+.P
+$HOME/.Xdefaults   default X window resource definitions
+.SH "SEE ALSO"
+.PP
+gs(1), mup(1), mupmate(1), mupprnt(1).
+.br
+Mup \(em Music Publisher User's Guide
+.SH "CAVEATS AND BUGS"
+.PP
+You must have mup in your PATH.
+You must have ghostscript (gs or gs386.exe) in your PATH
+and it must be built to include the "bit" device.
+.PP
+Resizing the window does not resize the full page view.
diff --git a/mup/docs/mupdisp.ps b/mup/docs/mupdisp.ps
new file mode 100644 (file)
index 0000000..fe483c7
--- /dev/null
@@ -0,0 +1,326 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.17.2
+%%CreationDate: Sat Dec  9 16:59:22 2006
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%+ font Courier
+%%DocumentSuppliedResources: procset grops 1.17 2
+%%Pages: 2
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.17 2
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/MANUAL{
+statusdict begin/manualfeed true store end
+}bind def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+%%IncludeResource: font Courier
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
+def/PL PLG def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
+/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
+/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
+/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
+/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
+/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
+/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
+/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
+/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
+/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
+/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
+/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
+/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
+/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
+/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
+/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
+/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
+/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
+/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
+/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
+/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
+/Courier@0 ENC0/Courier RE/Times-Italic@0 ENC0/Times-Italic RE
+/Times-Bold@0 ENC0/Times-Bold RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 373.28(mupdisp\(1\) mupdisp\(1\))72 48 R/F1
+10.95/Times-Bold@0 SF -.219(NA)72 84 S(ME).219 E F0
+(mupdisp - display output from Mup music publisher program)108 96 Q F1
+(SYNOPSIS)72 112.8 Q F0(mupdisp)108 124.8 Q/F2 10/Times-Italic@0 SF
+([mup_options] \214le)2.5 E F1(DESCRIPTION)72 141.6 Q F0 .054
+(Mupdisp pro)108 153.6 R .054(vides a w)-.15 F .053(ay to vie)-.1 F
+2.553(wM)-.25 G .053(up output on your screen.)-2.553 F(The)5.053 E F2
+(\214le)2.553 E F0 .053(is Mup input. An)2.553 F 2.553(yo)-.15 G .053
+(ther Mup options)-2.553 F(can be gi)108 165.6 Q -.15(ve)-.25 G(n, e).15
+E(xcept -f, -m, -M, -r)-.15 E 2.5(,o)-.4 G 2.5(r-)-2.5 G 1.3 -.65(v, w)
+-2.5 H(hich don').65 E 2.5(tp)-.18 G(roduce print output.)-2.5 E .453
+(Mupdisp will run under MS-DOS or will run under UNIX with a TERM of A)
+108 182.4 R .453(T386, linux, or xterm \(under)-1.11 F 2.5(Xw)108 194.4
+S(indo)-2.5 E(ws\).)-.25 E(When running under X windo)108 211.2 Q
+(ws, se)-.25 E -.15(ve)-.25 G(ral standard X options are a).15 E -.25
+(va)-.2 G(ilable:).25 E/F3 10/Times-Bold@0 SF(-geometry)108 228 Q F2
+(XxY+M+N)2.5 E F0 .66(Sets the windo)144 240 R 3.16(ws)-.25 G .659
+(ize and/or location on the screen. The actual windo)-3.16 F 3.159(ww)
+-.25 G .659(idth will be determined)-3.159 F .814(by the width of the M\
+up output. The height will be adjusted if necessary to be between 400 a\
+nd)144 252 R .716(the actual height of the Mup output. The windo)144 264
+R 3.216(wp)-.25 G .716(lacment speci\214cations can be positi)-3.216 F
+1.016 -.15(ve o)-.25 H 3.216(rn).15 G -.15(eg)-3.216 G(-).15 E(ati)144
+276 Q -.15(ve)-.25 G 2.5(.T).15 G
+(he actual placement may be adjusted by your windo)-2.5 E 2.5(wm)-.25 G
+(anager)-2.5 E(.)-.55 E F3(-fg)108 292.8 Q F2(color)2.5 E F0(or)2.5 E F3
+(-f)2.5 E(or)-.25 E(egr)-.18 E(ound)-.18 E F2(color)2.5 E F0
+(Speci\214es the fore)144 304.8 Q(ground color to use.)-.15 E F3(-bg)108
+321.6 Q F2(color)2.5 E F0(or)2.5 E F3(-backgr)2.5 E(ound)-.18 E F2
+(color)2.5 E F0(Speci\214es the background color to use.)144 333.6 Q
+2.483(These X options can also be set in your .Xdef)108 350.4 R 2.484
+(aults \214le using resource names of mupdisp.geometry)-.1 F(,)-.65 E
+(mupdisp.fore)108 362.4 Q .468
+(ground, and mupdisp.background. Command line ar)-.15 F .468
+(guments will o)-.18 F -.15(ve)-.15 G .468(rride v).15 F .468
+(alues in the .Xde-)-.25 F -.1(fa)108 374.4 S(ults \214le.).1 E(As an e)
+5 E(xample, you could add these lines to your .Xdef)-.15 E
+(aults \214le:)-.1 E/F4 10/Courier@0 SF 12(mupdisp.foreground: navy)180
+398.4 R 12(mupdisp.background: gray)180 410.4 R 24
+(mupdisp.geometry: 400x760+100-34)180 422.4 R F0 1.565
+(The Mupdisp program be)108 451.2 R 1.566(gins in partial page mode, wh\
+ich displays output at approximately actual size)-.15 F .446
+(\(depending on the size of your monitor\). In this mode, most lik)108
+463.2 R .445(ely not all of the page \214ts on the screen, so)-.1 F .503
+(the scrolling commands can be used to mo)108 475.2 R .803 -.15(ve u)
+-.15 H 3.003(pa).15 G .503(nd do)-3.003 F .504(wn to vie)-.25 F 3.004
+(wd)-.25 G(if)-3.004 E .504(ferent parts of the page. In full page)-.25
+F .684(mode, a small v)108 487.2 R .683
+(ersion of the entire page is displayed.)-.15 F .683
+(This is useful for seeing o)5.683 F -.15(ve)-.15 G .683
+(rall page layout, b).15 F .683(ut is)-.2 F .968
+(generally too small to see much detail.)108 499.2 R .968
+(This mode is no)5.968 F 3.468(ws)-.25 G(ome)-3.468 E .969
+(what of a relic of the days when screens)-.25 F
+(were typically much smaller than the)108 511.2 Q 2.5(ya)-.15 G
+(re today)-2.5 E 2.5(,a)-.65 G(nd is thus becoming less useful.)-2.5 E
+.965(If the en)108 528 R .965(vironment v)-.4 F .965
+(ariable MUPDISPMODE is set to some v)-.25 F .965
+(alue, Mupdisp will start in full page rather)-.25 F
+(than partial page mode.)108 540 Q(The commands are:)108 556.8 Q F2(num)
+108 573.6 Q F0(<Enter>)A(Go to page number)144 585.6 Q F2(num)2.5 E F0
+(.)A 2.5(+o)108 602.4 S 2.5(r<)-2.5 G
+(space> or <control-E> or <control-F>)-2.5 E(mo)144 614.4 Q .3 -.15
+(ve f)-.15 H(orw).15 E
+(ard on the page by about 1/8 of an inch \(partial page mode only\))-.1
+E 2.5(-o)108 631.2 S 2.5(r<)-2.5 G
+(backspace> or <control-Y> or <control-B>)-2.5 E(mo)144 643.2 Q .3 -.15
+(ve b)-.15 H(ackw).15 E
+(ard on the page by about 1/8 of an inch \(partial page mode only\))-.1
+E 2.5(bo)108 660 S 2.5(r<)-2.5 G(control-U> or <control-P> or <up-arro)
+-2.5 E(w-k)-.25 E -.15(ey)-.1 G(>).15 E(mo)144 672 Q .3 -.15(ve b)-.15 H
+(ackw).15 E(ard on the page by about an inch \(partial page mode only\))
+-.1 E 2.5(fo)108 688.8 S 2.5(r<)-2.5 G
+(Enter> or <control-D> or <control-N> or <do)-2.5 E(wn-arro)-.25 E(w-k)
+-.25 E -.15(ey)-.1 G(>).15 E(mo)144 700.8 Q .3 -.15(ve f)-.15 H(orw).15
+E(ard on the page by about an inch \(partial page mode only\))-.1 E 2.5
+(ho)108 717.6 S 5.73 2.5(r? d)-2.5 H(isplay help screen)-2.5 E
+(Arkkra Enterprises)72 768 Q(No)120.985 E -.15(ve)-.15 G(mber 4, 2006)
+.15 E(1)191.795 E EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 373.28(mupdisp\(1\) mupdisp\(1\))72 48 R 28.22
+(mt)108 84 S(oggle between partial page and full page modes.)-28.22 E
+2.5(no)108 100.8 S 2.5(r<)-2.5 G -.15(Pa)-2.5 G(geDo).15 E(wn>)-.25 E
+(go to ne)144 112.8 Q(xt page)-.15 E 2.5(po)108 129.6 S 2.5(r<)-2.5 G
+-.15(Pa)-2.5 G(geUp>).15 E(go to pre)144 141.6 Q(vious page)-.25 E 2.5
+(qo)108 158.4 S 2.5(rZ)-2.5 G 5.45(Zq)-2.5 G(uit)-5.45 E 32.67(rR)108
+175.2 S(epaint the page \(useful for e)-32.67 E(xiting help page\))-.15
+E .258(When in X windo)108 192 R .258
+(ws, the mouse can be used for scrolling. The left b)-.25 F .259
+(utton scrolls do)-.2 F(wnw)-.25 E .259(ard lik)-.1 F 2.759(et)-.1 G
+.259(he f com-)-2.759 F(mand, while the right b)108 204 Q
+(utton scrolls backw)-.2 E(ards lik)-.1 E 2.5(et)-.1 G(he b command.)
+-2.5 E .119(Mupdisp supports page sizes of letter \(8.5 x 11.0 inches\)\
+, note \(7.5 x 10.0 inches\), le)108 220.8 R -.05(ga)-.15 G 2.619(l\()
+.05 G .119(8.5 x 14.0 inches\),)-2.619 F .658(A4 \(8.26 x 11.69 inches\
+\), A5 \(5.85 x 8.26 inches\), A6 \(4.125 x 5.85 inches\), \215sa \(8.5\
+ x 13.0 inches\), and)108 232.8 R(hal\215etter \(5.5 x 8.5 inches\).)108
+244.8 Q/F1 10.95/Times-Bold@0 SF(FILES)72 261.6 Q F0($HOME/.Xdef)108
+273.6 Q 5(aults def)-.1 F(ault X windo)-.1 E 2.5(wr)-.25 G
+(esource de\214nitions)-2.5 E F1(SEE ALSO)72 290.4 Q F0
+(gs\(1\), mup\(1\), mupmate\(1\), mupprnt\(1\).)108 302.4 Q
+(Mup \212 Music Publisher User')108 314.4 Q 2.5(sG)-.55 G(uide)-2.5 E F1
+(CA)72 331.2 Q(VEA)-1.588 E(TS AND B)-1.04 E(UGS)-.11 E F0 -1.1(Yo)108
+343.2 S 2.814(um)1.1 G .314(ust ha)-2.814 F .614 -.15(ve m)-.2 H .313
+(up in your P).15 F -1.11(AT)-.92 G 2.813(H. Y)1.11 F .313(ou must ha)
+-1.1 F .613 -.15(ve g)-.2 H .313(hostscript \(gs or gs386.e).15 F -.15
+(xe)-.15 G 2.813(\)i).15 G 2.813(ny)-2.813 G .313(our P)-2.813 F -1.11
+(AT)-.92 G 2.813(Ha)1.11 G .313(nd it must)-2.813 F(be b)108 355.2 Q
+(uilt to include the "bit" de)-.2 E(vice.)-.25 E(Resizing the windo)108
+372 Q 2.5(wd)-.25 G(oes not resize the full page vie)-2.5 E -.65(w.)-.25
+G(Arkkra Enterprises)72 768 Q(No)120.985 E -.15(ve)-.15 G(mber 4, 2006)
+.15 E(2)191.795 E EP
+%%Trailer
+end
+%%EOF
diff --git a/mup/docs/mupfeat.txt b/mup/docs/mupfeat.txt
new file mode 100644 (file)
index 0000000..6e22a1e
--- /dev/null
@@ -0,0 +1,115 @@
+
+                Mup - Music Publication Program Highlights
+
+       1.  The Mup Music Publication program
+
+       Mup is a shareware music publication program.  Mup Version
+       5.3 is now available in source form as well as ready-to-run
+       for MS-DOS/Windows and Linux x86.  There is also a Mac
+       version available.
+
+       Music is described by a text file that you can create using
+       your favorite editor or the included Mupmate program.  Mup
+       then determines how to lay out the music, and generates
+       PostScript output for displaying or printing it.  It is a
+       powerful and flexible program, which has been used on
+       thousands of songs in a wide variety of styles, both
+       instrumental and vocal.
+
+       Mup's features include:
+
+          - Up to 40 staffs, which can include 1-line, 5-line, and
+            tablature staffs.  Output can be restricted to any
+            subset of the staffs.  Different staffs can be
+            different sizes.
+
+          - Up to 3 independent voices per staff, up to 70
+            simultaneous notes per voice.
+
+          - Double whole to 256th notes, with any number of dots.
+            Tuplets.
+
+          - Note styles of normal, grace, cue, X, diamond, plus
+            shaped notes.  Optional parentheses around notes and/or
+            accidentals.
+
+          - Cross-staff stems.
+
+          - Time signatures of cut, common, or numerators from 1 to
+            99 and denominators from 1 to 64.  Complicated time
+            signatures, including numerators with two or more
+            numbers added together, or two or more fractions added
+            together, or alternating time signatures.
+
+          - All standard clefs, including treble, treble8, 8treble,
+            French violin, soprano, mezzosoprano, alto, tenor,
+            baritone, and bass, as well as the drum (neutral) clef.
+            Clefs can be changed in the middle of measures.
+
+          - Barline styles of single, double, dashed, dotted, end,
+            repeats, or none.
+
+          - 8th note and shorter notes can have either flags or
+            beams; beams can be cross-staff.
+
+          - Guitar grids
+
+          - Lyrics can be placed above, below, or between staffs.
+            Unlimited number of verses, with control of font and
+            size.
+
+          - Headers and footers.
+
+          - Staffs can be grouped with braces or brackets.
+
+          - Automatic transposition of music and chord marks per
+            staff.
+
+          - First and subsequent endings.
+
+          - Optional rehearsal marks and/or automatic measure
+            numbering.  Rehearsal marks can be boxed, circled, or
+            plain.
+
+          - Crescendo/decrescendo marks.
+
+          - Rolls, ornaments, fermatas, accents.
+
+          - Measure repeats.
+
+          - Ties, slurs, phrase marks, octave marks, piano pedal
+            marks, etc.  Ties, slurs, and phrase marks can be
+            solid, dotted, or dashed.
+
+          - Suport for figured bass, analysis, and chords.
+
+          - Optional MIDI file output. (Very useful for "proof-
+            listening" to your songs to check for input mistakes!)
+
+          - PostScript output for printing on any PostScript
+            compatible output device.  Can be used with
+            Ghostscript.
+
+          - All standard PostScript fonts supported, in 1 to 100
+            point size, including most common non-English
+            characters.
+
+          - Input is a text file, for easy portability between
+            computer systems.
+
+          - Macros and 'include' files.
+
+          - General 'if' clauses that can be used to generate
+            different outputs based on values of parameters.
+
+          - Mup will determine how to lay out the music, but there
+            are numerous user controls available to fine-tune the
+            output to meet your specific needs.
+
+          - Comprehensive User's Guide provided in both PostScript
+            and HTML formats, including many examples.
+
+          - Mup is available via ftp to try out for free.  If you
+            like it and want to keep it, the shareware registration
+            is far lower than the cost of most music publication
+            software.
diff --git a/mup/docs/mupmate.1 b/mup/docs/mupmate.1
new file mode 100644 (file)
index 0000000..b9239cd
--- /dev/null
@@ -0,0 +1,69 @@
+.TH mupmate 1 "November 4, 2006" "Arkkra Enterprises"
+.SH NAME
+.PP
+mupmate - user interface for Mup music publisher
+.SH SYNOPSIS
+.PP
+mupmate [\fIfile\fP]
+.SH DESCRIPTION
+.PP
+.P
+You can create a Mup file using any ordinary text editor.
+On Windows, Notepad is a typical choice; on Linux, editors like
+vim and emacs are commonly used. But if you prefer to be able to
+edit, display, and play from a single integrated and more graphical
+interface, a helper program called "mupmate" is provided. Mupmate is currently
+only supported on Windows and Linux. However, since the source code is
+available, and it is based on the cross-platform FLTK toolkit, it
+can probably be made to run on any system supported by FLTK fairly easily.
+If you prefer to use the Mup program directly rather than via mupmate,
+you can.  The Mupmate program just helps lead you through some of the steps.
+.PP
+Once you have installed Mup and Mupmate on Windows, double clicking
+a .mup file in Windows explorer will run Mupmate on that file.
+Or, you can run Mupmate by going to the Start menu, and choosing
+Programs, then Arkkra, and then Mupmate.  If you would like an icon
+on the desktop, you can create one by right clicking
+the Mupmate choice in the Arkkra menu,
+choosing "copy", right clicking somewhere on the desktop, and choosing "paste."
+.PP
+On Linux, you can just type the mupmate command,
+optionally followed by the name of a Mup input file. 
+Or you can add mupmate to your favorite window manager's menus.
+.P
+Mupmate provides five top level menus: File, Edit, Run, Config, and Help.
+The File menu provides commands for opening new files and saving the
+file you are working on, as well as exit the program. The Edit menu
+provides the kinds of things you would expect in a editor: commands to find
+a pattern, or find and replace; to select text; to copy, cut, and paste;
+to go to a specific line; and to undo the previous operation, if you make
+a mistake or change you mind.
+The Run menu lets you set runtime options,
+and then run the Mup program on your input in various
+ways. You can either just generate a PostScript or MIDI file,
+or display the PostScript or play the MIDI.
+The Config menu lets you specify what application program you want
+to use to view PostScript files and which you want to use to play MIDI files,
+and well as specify locations for other Mup files. Mupmate will try to
+find reasonable default values, but you may want to check that they are
+what you want, and tweak them if they aren't.
+The Config menu also provides a way for you to fill in the Mup registration
+form if you wish to send in a paper form rather than registering online
+via credit card,  as well as a place to entry the registration key you
+will receive once you have paid.
+The Help menu lets you browse the Mup User's Guide, view some startup hints,
+or see the current version number of Mup and Mupmate.
+.SH "SEE ALSO"
+.PP
+gs(1), mup(1).
+.br
+Mup \(em Music Publisher User's Guide
+.SH "CAVEATS"
+.PP
+Mupmate is currently only supported on Windows and Linux or similar.
+.PP
+Mupmate does not directly provide a print facility. Almost any PostScript
+viewer already provides this ability, so you can simply select "Display"
+from the Run menu and use the viewer's print capabilities.
+Alternately you can use the "Write PostScript File" from the Run menu
+and then print the resulting file.
diff --git a/mup/docs/mupmate.ps b/mup/docs/mupmate.ps
new file mode 100644 (file)
index 0000000..e9bd14a
--- /dev/null
@@ -0,0 +1,301 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.17.2
+%%CreationDate: Sat Dec  9 16:59:22 2006
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.17 2
+%%Pages: 1
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.17 2
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/MANUAL{
+statusdict begin/manualfeed true store end
+}bind def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
+def/PL PLG def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
+/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
+/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
+/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
+/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
+/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
+/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
+/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
+/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
+/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
+/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
+/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
+/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
+/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
+/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
+/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
+/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
+/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
+/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
+/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
+/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
+/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE
+/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 367.74(mupmate\(1\) mupmate\(1\))72 48 R/F1
+10.95/Times-Bold@0 SF -.219(NA)72 84 S(ME).219 E F0
+(mupmate - user interf)108 96 Q(ace for Mup music publisher)-.1 E F1
+(SYNOPSIS)72 112.8 Q F0(mupmate [)108 124.8 Q/F2 10/Times-Italic@0 SF
+(\214le)A F0(])A F1(DESCRIPTION)72 141.6 Q F0 -1.1(Yo)108 153.6 S 3.67
+(uc)1.1 G 1.17(an create a Mup \214le using an)-3.67 F 3.67(yo)-.15 G
+1.17(rdinary te)-3.67 F 1.17(xt editor)-.15 F 6.17(.O)-.55 G 3.67(nW)
+-6.17 G(indo)-4.07 E 1.17(ws, Notepad is a typical choice; on)-.25 F
+.084(Linux, editors lik)108 165.6 R 2.584(ev)-.1 G .085(im and emacs ar\
+e commonly used. But if you prefer to be able to edit, display)-2.584 F
+2.585(,a)-.65 G .085(nd play)-2.585 F 1.62(from a single inte)108 177.6
+R 1.619(grated and more graphical interf)-.15 F 1.619
+(ace, a helper program called "mupmate" is pro)-.1 F(vided.)-.15 E .466
+(Mupmate is currently only supported on W)108 189.6 R(indo)-.4 E .467
+(ws and Linux. Ho)-.25 F(we)-.25 E -.15(ve)-.25 G 1.267 -.4(r, s).15 H
+.467(ince the source code is a).4 F -.25(va)-.2 G(ilable,).25 E .164
+(and it is based on the cross-platform FL)108 201.6 R .164
+(TK toolkit, it can probably be made to run on an)-.92 F 2.663(ys)-.15 G
+.163(ystem supported)-2.663 F .98(by FL)108 213.6 R .98(TK f)-.92 F .98
+(airly easily)-.1 F 5.98(.I)-.65 G 3.48(fy)-5.98 G .98(ou prefer to use\
+ the Mup program directly rather than via mupmate, you can.)-3.48 F
+(The Mupmate program just helps lead you through some of the steps.)108
+225.6 Q .38(Once you ha)108 242.4 R .68 -.15(ve i)-.2 H .38
+(nstalled Mup and Mupmate on W).15 F(indo)-.4 E .379
+(ws, double clicking a .mup \214le in W)-.25 F(indo)-.4 E .379(ws e)-.25
+F(xplorer)-.15 E .902(will run Mupmate on that \214le.)108 254.4 R(Or)
+5.902 E 3.402(,y)-.4 G .903
+(ou can run Mupmate by going to the Start menu, and choosing Pro-)-3.402
+F .705(grams, then Arkkra, and then Mupmate.)108 266.4 R .705(If you w)
+5.705 F .705(ould lik)-.1 F 3.205(ea)-.1 G 3.205(ni)-3.205 G .704
+(con on the desktop, you can create one by)-3.205 F .598
+(right clicking the Mupmate choice in the Arkkra menu, choosing "cop)108
+278.4 R .598(y", right clicking some)-.1 F .598(where on the)-.25 F
+(desktop, and choosing "paste.")108 290.4 Q .512
+(On Linux, you can just type the mupmate command, optionally follo)108
+307.2 R .512(wed by the name of a Mup input \214le.)-.25 F
+(Or you can add mupmate to your f)108 319.2 Q -.2(avo)-.1 G(rite windo)
+.2 E 2.5(wm)-.25 G(anager')-2.5 E 2.5(sm)-.55 G(enus.)-2.5 E .665
+(Mupmate pro)108 336 R .665(vides \214v)-.15 F 3.165(et)-.15 G .665
+(op le)-3.165 F -.15(ve)-.25 G 3.165(lm).15 G .665
+(enus: File, Edit, Run, Con\214g, and Help.)-3.165 F .665
+(The File menu pro)5.665 F .665(vides com-)-.15 F .555
+(mands for opening ne)108 348 R 3.055<778c>-.25 G .555(les and sa)-3.055
+F .555(ving the \214le you are w)-.2 F .554(orking on, as well as e)-.1
+F .554(xit the program. The Edit)-.15 F .917(menu pro)108 360 R .917
+(vides the kinds of things you w)-.15 F .917(ould e)-.1 F .918
+(xpect in a editor: commands to \214nd a pattern, or \214nd and)-.15 F
+.232(replace; to select te)108 372 R .232(xt; to cop)-.15 F 1.532 -.65
+(y, c)-.1 H .232
+(ut, and paste; to go to a speci\214c line; and to undo the pre).65 F
+.231(vious operation, if)-.25 F 1.082(you mak)108 384 R 3.582(eam)-.1 G
+(istak)-3.582 E 3.582(eo)-.1 G 3.582(rc)-3.582 G 1.082(hange you mind.)
+-3.582 F 1.083
+(The Run menu lets you set runtime options, and then run the)6.083 F
+.346(Mup program on your input in v)108 396 R .345(arious w)-.25 F .345
+(ays. Y)-.1 F .345
+(ou can either just generate a PostScript or MIDI \214le, or dis-)-1.1 F
+1.273(play the PostScript or play the MIDI.)108 408 R 1.273
+(The Con\214g menu lets you specify what application program you)6.273 F
+-.1(wa)108 420 S .199(nt to use to vie).1 F 2.698(wP)-.25 G .198
+(ostScript \214les and which you w)-2.698 F .198
+(ant to use to play MIDI \214les, and well as specify loca-)-.1 F .859
+(tions for other Mup \214les. Mupmate will try to \214nd reasonable def)
+108 432 R .86(ault v)-.1 F .86(alues, b)-.25 F .86(ut you may w)-.2 F
+.86(ant to check)-.1 F .437(that the)108 444 R 2.937(ya)-.15 G .437
+(re what you w)-2.937 F .437(ant, and tweak them if the)-.1 F 2.937(ya)
+-.15 G(ren')-2.937 E 2.937(t. The)-.18 F .437(Con\214g menu also pro)
+2.937 F .437(vides a w)-.15 F .437(ay for you)-.1 F .95
+(to \214ll in the Mup re)108 456 R .951
+(gistration form if you wish to send in a paper form rather than re)-.15
+F .951(gistering online via)-.15 F .441(credit card,)108 468 R .441
+(as well as a place to entry the re)5.441 F .44(gistration k)-.15 F .74
+-.15(ey y)-.1 H .44(ou will recei).15 F .74 -.15(ve o)-.25 H .44
+(nce you ha).15 F .74 -.15(ve p)-.2 H 2.94(aid. The).15 F(Help)2.94 E
+.243(menu lets you bro)108 480 R .243(wse the Mup User')-.25 F 2.743(sG)
+-.55 G .243(uide, vie)-2.743 F 2.743(ws)-.25 G .244
+(ome startup hints, or see the current v)-2.743 F .244(ersion number of)
+-.15 F(Mup and Mupmate.)108 492 Q F1(SEE ALSO)72 508.8 Q F0
+(gs\(1\), mup\(1\).)108 520.8 Q(Mup \212 Music Publisher User')108 532.8
+Q 2.5(sG)-.55 G(uide)-2.5 E F1(CA)72 549.6 Q(VEA)-1.588 E(TS)-1.04 E F0
+(Mupmate is currently only supported on W)108 561.6 Q(indo)-.4 E
+(ws and Linux or similar)-.25 E(.)-.55 E .159
+(Mupmate does not directly pro)108 578.4 R .159(vide a print f)-.15 F
+(acility)-.1 E 2.659(.A)-.65 G .159(lmost an)-2.659 F 2.659(yP)-.15 G
+.158(ostScript vie)-2.659 F .158(wer already pro)-.25 F .158
+(vides this abil-)-.15 F(ity)108 590.4 Q 3.25(,s)-.65 G 3.25(oy)-3.25 G
+.751(ou can simply select "Display" from the Run menu and use the vie)
+-3.25 F(wer')-.25 E 3.251(sp)-.55 G .751(rint capabilities.)-3.251 F
+(Alter)5.751 E(-)-.2 E(nately you can use the "Write PostScript File" f\
+rom the Run menu and then print the resulting \214le.)108 602.4 Q
+(Arkkra Enterprises)72 768 Q(No)120.985 E -.15(ve)-.15 G(mber 4, 2006)
+.15 E(1)191.795 E EP
+%%Trailer
+end
+%%EOF
diff --git a/mup/docs/mupprnt.1 b/mup/docs/mupprnt.1
new file mode 100644 (file)
index 0000000..0a9141c
--- /dev/null
@@ -0,0 +1,29 @@
+.TH mupprnt 1 "Oct 27, 1995" "Arkkra Enterprises"
+.SH NAME
+.PP
+mupprnt - print output from Mup music publisher
+.SH SYNOPSIS
+.PP
+mupprnt \fI[mup_options] file\fP
+.SH DESCRIPTION
+.PP
+mupprnt provides a way to print Mup output on your printer.
+The \fIfile\fP is Mup input. Any other Mup options can be given,
+except -f, -m, -r, or -v, which don't produce print output.
+.PP
+Under UNIX, if the environment variable COPIES is set to a number,
+that number of copies will be printed. Otherwise only 1 copy will be printed.
+.PP
+.PP
+The GS_DEVICE shell variable must be set to the proper value for your printer
+type.  Mupprnt is a shell script (under UNIX) or batch script (under MS-DOS),
+so you can customize it if you wish.
+.SH "SEE ALSO"
+.PP
+gs(1), mup(1), mupdisp(1).
+.br
+Mup \(em Music Publisher User's Guide
+.SH "CAVEATS AND BUGS"
+.PP
+You must have mup in your PATH.
+You must have ghostscript (gs or gs386.exe) in your PATH.
diff --git a/mup/docs/mupprnt.ps b/mup/docs/mupprnt.ps
new file mode 100644 (file)
index 0000000..d33bf40
--- /dev/null
@@ -0,0 +1,236 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.17.2
+%%CreationDate: Sat Dec  9 16:59:22 2006
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.17 2
+%%Pages: 1
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.17 2
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/MANUAL{
+statusdict begin/manualfeed true store end
+}bind def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
+def/PL PLG def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
+/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
+/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
+/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
+/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
+/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
+/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
+/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
+/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
+/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
+/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
+/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
+/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
+/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
+/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
+/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
+/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
+/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
+/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
+/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
+/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
+/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE
+/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 374.4(mupprnt\(1\) mupprnt\(1\))72 48 R/F1 10.95
+/Times-Bold@0 SF -.219(NA)72 84 S(ME).219 E F0
+(mupprnt - print output from Mup music publisher)108 96 Q F1(SYNOPSIS)72
+112.8 Q F0(mupprnt)108 124.8 Q/F2 10/Times-Italic@0 SF
+([mup_options] \214le)2.5 E F1(DESCRIPTION)72 141.6 Q F0 .127
+(mupprnt pro)108 153.6 R .127(vides a w)-.15 F .127
+(ay to print Mup output on your printer)-.1 F 5.127(.T)-.55 G(he)-5.127
+E F2(\214le)2.627 E F0 .127(is Mup input. An)2.627 F 2.626(yo)-.15 G
+.126(ther Mup options)-2.626 F(can be gi)108 165.6 Q -.15(ve)-.25 G
+(n, e).15 E(xcept -f, -m, -r)-.15 E 2.5(,o)-.4 G 2.5(r-)-2.5 G 1.3 -.65
+(v, w)-2.5 H(hich don').65 E 2.5(tp)-.18 G(roduce print output.)-2.5 E
+.095(Under UNIX, if the en)108 182.4 R .095(vironment v)-.4 F .095
+(ariable COPIES is set to a number)-.25 F 2.596(,t)-.4 G .096
+(hat number of copies will be printed.)-2.596 F(Otherwise only 1 cop)108
+194.4 Q 2.5(yw)-.1 G(ill be printed.)-2.5 E .822(The GS_DEVICE shell v)
+108 216 R .821(ariable must be set to the proper v)-.25 F .821
+(alue for your printer type.)-.25 F .821(Mupprnt is a shell)5.821 F(scr\
+ipt \(under UNIX\) or batch script \(under MS-DOS\), so you can customi\
+ze it if you wish.)108 228 Q F1(SEE ALSO)72 244.8 Q F0
+(gs\(1\), mup\(1\), mupdisp\(1\).)108 256.8 Q
+(Mup \212 Music Publisher User')108 268.8 Q 2.5(sG)-.55 G(uide)-2.5 E F1
+(CA)72 285.6 Q(VEA)-1.588 E(TS AND B)-1.04 E(UGS)-.11 E F0 -1.1(Yo)108
+297.6 S 2.5(um)1.1 G(ust ha)-2.5 E .3 -.15(ve m)-.2 H(up in your P).15 E
+-1.11(AT)-.92 G 2.5(H. Y)1.11 F(ou must ha)-1.1 E .3 -.15(ve g)-.2 H
+(hostscript \(gs or gs386.e).15 E -.15(xe)-.15 G 2.5(\)i).15 G 2.5(ny)
+-2.5 G(our P)-2.5 E -1.11(AT)-.92 G(H.)1.11 E(Arkkra Enterprises)72 768
+Q(Oct 27, 1995)132.22 E(1)203.03 E EP
+%%Trailer
+end
+%%EOF
diff --git a/mup/docs/mupqref.ps b/mup/docs/mupqref.ps
new file mode 100644 (file)
index 0000000..e2f1b28
--- /dev/null
@@ -0,0 +1,2896 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.17.2
+%%CreationDate: Mon Dec  4 22:55:33 2006
+%%DocumentNeededResources: font Times-Bold
+%%+ font Times-Italic
+%%+ font Times-Roman
+%%+ font Courier
+%%+ font Times-BoldItalic
+%%+ font NewCenturySchlbk-BoldItalic
+%%+ font NewCenturySchlbk-Roman
+%%DocumentSuppliedResources: file extlist.ps
+%%+ file muschar.ps
+%%+ procset grops 1.17 2
+%%Pages: 6
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+% Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2004 by Arkkra Enterprises
+% All rights reserved
+
+% Mup PostScript Prolog 5.3 for use with Mup 5.3
+
+% lwid is used as the width of a standard (thin) line in the music
+% character definitions.
+/lwid 70 def
+/halflwid lwid 2 div def
+
+% Define the following for use in do_upshortnote, do_dnshortnote, and
+% do_shortrest; it has to be done outside of the music font definition.
+/utildict 10 dict def
+utildict begin
+       /setnumflags    {       /numflags       exch def } def
+       /sethooksm1     {       /hooksm1        exch def } def
+       /setoffsets     {       /offsets        exch def } def
+       /setx           {       /x              exch def } def
+       /sety           {       /y              exch def } def
+end
+
+% Define a music character font.  Each music character is defined as if it
+% were a normal ASCII character in a strange font where "A" looks like a
+% treble clef, "B" looks like a bass clef, etc.
+
+/mfont0 100 dict def
+mfont0 begin
+       /FontType 3 def
+       /FontMatrix [ .001 0 0 0.001 0 0 ] def
+       /FontBBox [ -2000 -4030 2000 4030 ] def
+       /FontName (Mfont0) def
+
+       % set up Encoding vector with standard names
+       /Encoding 256 array def
+       StandardEncoding Encoding copy
+       pop
+
+       % the following definitions are used for quarter rests
+       /topx -170 def /topy 950 def
+       /cor1x 250 def /cor1y 450 def
+       /cor2x -300 def /cor2y 200 def
+       /cor3x 250 def /cor3y -400 def
+
+       % the following definitions are used for double sharps
+       /limit 300 halflwid add def
+       /off 70 def
+       /inbendsmall limit 200 sub def
+       /inbendbig limit 20 sub def
+       /outbendsmall 100 def
+       /outbendbig outbendsmall off add def
+
+       %%%%% define routines that will be used by multiple characters %%%%%
+       /do_1n {
+               gsave
+               newpath -10 rotate 1.6 1 scale
+               0 0 325 0 360 arc               %outer ellipse
+               1 1.6 div 1 scale 10 rotate     %back to original
+               35 rotate 0.85 1.1 scale
+               0 0 275 0 360 arc               %inner ellipse
+               eofill
+               grestore
+       } def
+       /do_upflag {
+               -315 0 moveto
+               -300 100 -100 480 0 600 curveto
+               300 960 350 1500 200 1700 curveto
+               130 1700 lineto
+               350 1200 50 650 -315 600 curveto
+               fill
+       } def
+       /do_flat {
+               -250 -400 moveto        %outer edge of loop
+               500 0 350 650 -250 160 curveto
+               -250 160 lwid sub lineto %inner edge of loop
+               100 400 300 0 -250 -400 lwid add curveto
+               fill
+
+               lwid setlinewidth       %stem
+               -250 1100 moveto -250 -400 lineto stroke
+       } def
+       /do_diamond {
+               newpath
+               420 0 moveto 0 300 lineto -420 0 lineto
+               0 -300 lineto closepath
+               259 -29 moveto -41 185 lineto -259 29 lineto
+               41 -185 lineto closepath
+               eofill
+       } def
+       /do_2n {
+               gsave
+               newpath 25 rotate 1.4 1 scale
+               0 0 315 0 360 arc               %outer ellipse
+               1 1.4 div 1 scale               %back to original
+               1.3 0.5 scale
+               0 0 310 0 360 arc               %inner ellipse
+               eofill
+               grestore
+       } def
+       /do_4n {
+               gsave
+               newpath 25 rotate 1.35 1 scale
+               0 0 310 0 360 arc fill
+               grestore
+       } def
+       /do_com {
+               newpath
+               330 250 150 0 360 arc fill      %knob at upper right
+               465 300 moveto                  %outer boundary
+               410 500 200 635 0 635 curveto
+               -750 635 -750 -635 0 -635 curveto
+               350 -635 480 -300 500 -100 curveto
+               430 -100 lineto                 %inner boundary
+               380 -300 250 -565 0 -565 curveto
+               -450 -565 -450 565 0 565 curveto
+               200 565 370 350 395 300 curveto
+               fill
+       } def
+       /do_ferm {
+               0 0 800 lwid sub 0 180 arc      %inner arc
+               -800 0 lineto
+               0 270 lwid sub 800 180 0 arcn   %outer arc
+               800 0 lineto fill
+               0 120 120 0 360 arc fill        %the dot
+       } def
+       /do_mor {
+               gsave
+               0.7 1 scale     %scrunch the following horizontally
+               45 rotate       %to pretend all lines horz or vertical
+               0 1 1 {
+                       pop     %we don't need the loop variable
+                       %one half of the mordent
+                       0 40 moveto 350 40 lineto 350 -460 lineto
+                       750 -460 lineto 750 -540 lineto
+                       150 -540 lineto 150 -40 lineto
+                       0 -40 lineto fill
+                       180 rotate      %to do the other half
+               } for
+               grestore
+       } def
+       /do_turn {
+               gsave
+               0 1 1 {
+                       pop     %we don't need the loop variable
+                       0 -100 moveto   %outer boundary
+                       200 -400 625 -400 625 0 curveto
+                       625 200 500 325 300 325 curveto
+                       300 185 lineto  %inner boundary
+                       450 255 555 150 555 0 curveto
+                       555 -350 250 -250 0 100 curveto
+                       fill
+                       300 255 70 0 360 arc fill %knob on end
+                       180 rotate      %to do the other half
+               } for
+               grestore
+       } def
+
+       /do_upshortnote {
+               utildict begin
+               setnumflags             %set numflags from the stack
+               gsave
+               -330 0 translate        %half a flag width
+               do_4n                   %do a quarter note head
+               lwid setlinewidth
+               370 0 moveto
+               370 2100 numflags 2 sub flagsep mul add lineto stroke
+               670 2100 numflags 2 sub flagsep mul add translate
+               1 -1 scale              %reflect across X axis
+               0 1 numflags 1 sub {
+                       do_upflag       %do an upflag
+                       pop             %we don't need the loop variable
+                       0 flagsep translate
+               } for
+               grestore
+               end
+       } def
+
+       /do_dnshortnote {
+               utildict begin
+               setnumflags             %set numflags from the stack
+               do_4n                   %do a quarter note head
+               lwid setlinewidth
+               -370 0 moveto
+               -370 -2100 numflags 2 sub flagsep mul sub lineto stroke
+               gsave
+               -70 -2100 numflags 2 sub flagsep mul sub translate
+               0 1 numflags 1 sub {
+                       do_upflag       %do an upflag
+                       pop             %we don't need the loop variable
+                       0 flagsep translate
+               } for
+               grestore
+               end
+       } def
+
+       /do_shortrest {
+               utildict begin
+               sety setx setoffsets sethooksm1 %set variable from the stack
+               gsave
+               -105.8 offsets mul -600 offsets mul translate
+               0 1 hooksm1 {           %loop once per hook
+                       newpath
+                       1 setlinewidth
+                       gsave
+                       1 1.2 scale
+                       -150 300 1.2 div 140 0 360 arc fill     %the dot
+                       grestore
+                       lwid setlinewidth
+                       -50 700 550 255 315 arc         %rest of the hook
+                       hooksm1 lt { stroke 105.8 600 translate } if
+               } for
+               x y lineto stroke
+               grestore
+               end
+       } def
+
+
+       % subsidiary dictionary of character definitions
+       /CharStrings 128 dict def
+       CharStrings begin
+
+               /.notdef {} def
+
+               % Here are the definitions of the characters.  A stepsize here
+               % is 300 units (assuming the character is drawn at its default
+               % size).
+
+               % gclef
+               /A {
+                       newpath
+                       %start with inner curl, inside boundary
+                       -50 -300 moveto
+                       -450 600 700 700 750 0 curveto
+                       750 -800 -700 -800 -700 200 curveto
+                       -700 900 500 1400 520 2250 curveto
+                       520 2900 300 3000 200 3000 curveto
+                       100 3000 -400 2500 -200 1800 curveto
+                       350 -600 lineto
+                       720 -1600 0 -1650 -400 -1400 curveto
+
+                       %go back to start, drawing the other boundary
+                       -400 -1480 lineto
+                       0 -1700 800 -1700 430 -600 curveto
+                       -120 1800 lineto
+                       -300 2400 200 2800 250 2800 curveto
+                       400 2800 430 2700 430 2450 curveto
+                       430 1800 -900 1200 -900 300 curveto
+                       -750 -900 800 -900 850 0 curveto
+                       900 1100 -750 900 -120 -300 curveto fill
+
+                       %circle at the bottom
+                       -300 -1250 250 0 360 arc fill
+               } def
+
+               % fclef
+               /B {
+                       newpath
+                       %start with outside boundary, at bottom
+                       -1000 -1700 moveto
+                       100 -1100 500 -600 450 0 curveto
+                       450 850 -1100 850 -950 0 curveto
+
+                       %go back to start, drawing the other boundary
+                       -880 0 lineto
+                       -920 400 -600 560 -300 560 curveto
+                       0 560 150 400 150 0 curveto
+                       150 -400 100 -900 -1000 -1620 curveto fill
+
+                       %circle at the left
+                       newpath
+                       -700 0 250 0 360 arc fill
+
+                       %do the two dots after the main curve
+                       700 -300 100 0 360 arc fill
+                       700 300 100 0 360 arc fill
+               } def
+
+               % cclef
+               /C {
+                       gsave
+                       %do upper curved part, then scale to do mirror image
+                       0 1 1 {
+                               pop     %we don't need the loop variable
+                               %outer boundary of curve
+                               -170 0 moveto 100 300 lineto
+                               400 -200 750 300 750 650 curveto
+                               750 1100 450 1235 250 1235 curveto
+                               0 1235 -143 1100 -143 950 curveto
+
+                               %inner boundary of curve
+                               0 950 lineto
+                               0 1100 30 1165 250 1165 curveto
+                               300 1165 450 1100 450 650 curveto
+                               450 400 400 -100 100 400 curveto
+                               -270 0 lineto fill
+                               %stroke
+                               %-270 0 moveto 100 400 lineto
+                               %400 -100 450 400 450 650 curveto
+                               %450 1100 300 1165 250 1165 curveto
+                               %30 1165 0 1100 0 950 curveto
+                               %stroke
+
+                               %elliptical ball at end of curve
+                               gsave
+                               1.3 1 scale
+                               10 950 120 0 360 arc fill
+                               grestore
+                               1 -1 scale      %reflect across X axis
+                       } for
+                       grestore
+
+                       % two vertical lines on the left
+                       300 setlinewidth -600 -1200 halflwid sub moveto
+                       -600 1200 halflwid add lineto stroke
+                       lwid setlinewidth -300 -1200 halflwid sub moveto
+                       -300 1200 halflwid add lineto stroke
+               } def
+
+               % dblwhole
+               /D {
+                       do_1n           %do a whole note
+                       lwid setlinewidth
+                       -490 -600 moveto -490 600 lineto stroke
+                       490 -600 moveto 490 600 lineto stroke
+               } def
+
+               % 1n
+               /E {
+                       do_1n           %do a whole note
+               } def
+
+               % 2n
+               /F {
+                       do_2n           %do a half note
+               } def
+
+               % 4n
+               /G {
+                       do_4n           %do a quarter note head
+               } def
+
+               % upflag
+               /H {
+                       do_upflag               %do an upflag
+               } def
+
+               % dnflag
+               /I {
+                       gsave
+                       1 -1 scale      %reflect across X axis
+                       do_upflag               %do an upflag
+                       grestore
+               } def
+
+               % dwhrest
+               /J {
+                       300 setlinewidth
+                       0 0 moveto 0 600 lineto stroke
+               } def
+
+               % 1rest
+               /K {
+                       lwid setlinewidth
+                       -750 600 moveto 750 600 lineto stroke
+                       300 setlinewidth
+                       -400 450 moveto 400 450 lineto stroke
+               } def
+
+               % 2rest
+               /L {
+                       lwid setlinewidth
+                       -750 0 moveto 750 0 lineto stroke
+                       300 setlinewidth
+                       -400 150 moveto 400 150 lineto stroke
+               } def
+
+               % 4rest
+               /M {
+                       newpath
+                       cor3x cor3y halflwid add moveto
+                       %-400 -200 -450 -650 50 -950 lwid add curveto
+                       -450 -50 -450 -650 50 -950 lwid add curveto
+                       -150 -650 -100 -250 cor3x cor3y halflwid sub curveto
+                       fill
+
+                       cor1x cor1y moveto cor1x 200 sub cor1y 200 add lineto
+                       cor2x cor2y lineto cor2x 200 add cor2y 200 sub lineto
+                       fill
+
+                       lwid setlinewidth
+                       topx topy moveto cor1x cor1y lineto stroke
+                       cor2x cor2y moveto cor3x cor3y lineto stroke
+               } def
+
+               % 8rest
+               /N {
+                       0 0 0 -600 do_shortrest
+               } def
+
+               % 16rest
+               /O {
+                       1 1 100 -1200 do_shortrest
+               } def
+
+               % 32rest
+               /P {
+                       2 1 0 -1800 do_shortrest
+               } def
+
+               % 64rest
+               /Q {
+                       3 2 -80 -2100 do_shortrest
+               } def
+
+               % 128rest
+               /R {
+                       4 2 -150 -2700 do_shortrest
+               } def
+
+               % 256rest
+               /S {
+                       5 3 -280 -3300 do_shortrest
+               } def
+
+               % dot
+               /T {
+                       newpath
+                       0 0 120 0 360 arc fill
+               } def
+
+               % nat
+               /U {
+                       % fill crossbars so that we can do parallelograms
+                       -235 -470 moveto -235 -270 lineto
+                       235 -130 lineto 235 -330 lineto fill
+                       -235 130 moveto -235 330 lineto
+                       235 470 lineto 235 270 lineto fill
+
+                       % vertical strokes
+                       lwid setlinewidth
+                       -200 -380 moveto -200 850 lineto stroke
+                       200 -850 moveto 200 380 lineto stroke
+               } def
+
+               % sharp
+               /V {
+                       % fill crossbars so that we can do parallelograms
+                       -325 -480 moveto -325 -280 lineto
+                       325 -120 lineto 325 -320 lineto fill
+                       -325 120 moveto -325 320 lineto
+                       325 480 lineto 325 280 lineto fill
+
+                       % vertical strokes
+                       lwid setlinewidth
+                       -150 -930 moveto -150 880 lineto stroke
+                       150 -880 moveto 150 930 lineto stroke
+               } def
+
+               % flat
+               /W {
+                       do_flat         %do a flat
+               } def
+
+               % dblsharp
+               /X {
+                       gsave
+                       0 1 3 {         %loop once for each of 4 sticks
+                               pop     %we don't need the loop variable
+                               0 off neg moveto
+                               outbendbig outbendsmall lineto
+                               inbendbig inbendsmall lineto
+                               limit limit lineto
+                               inbendsmall inbendbig lineto
+                               outbendsmall outbendbig lineto
+                               off neg 0 lineto
+                               fill
+                               -90 rotate
+                       } for
+                       grestore
+               } def
+
+               % dblflat
+               /Y {
+                       -290 580 290 {  %loop once for each flat
+
+                               gsave
+                               1 setlinewidth
+                               0 translate     %translate left/right (loop var)
+                               do_flat         %do a flat
+                               grestore
+
+                       } for
+               } def
+
+               % xnote
+               /Z {
+                       gsave
+                       1.15 1 scale 120 setlinewidth 1 setlinecap      %round
+                       -300 -300 moveto 300 300 lineto stroke
+                       -300 300 moveto 300 -300 lineto stroke
+                       grestore
+               } def
+
+               % dwhdiamond
+               /a {
+                       do_diamond      %do a diamond
+                       lwid setlinewidth
+                       -420 -600 moveto -420 600 lineto stroke
+                       420 -600 moveto 420 600 lineto stroke
+               } def
+
+               % diamond
+               /b {
+                       do_diamond      %do a diamond
+               } def
+
+               % filldiamond
+               /c {
+                       420 0 moveto 0 300 lineto
+                       -420 0 lineto 0 -300 lineto fill
+               } def
+
+               % up2n
+               /d {
+                       lwid setlinewidth
+                       380 0 moveto 380 2100 lineto stroke
+                       do_2n           %do a half note
+               } def
+
+               % dn2n
+               /e {
+                       lwid setlinewidth
+                       -380 0 moveto -380 -2100 lineto stroke
+                       do_2n           %do a half note
+               } def
+
+               % up4n
+               /f {
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       370 0 moveto 370 2100 lineto stroke
+               } def
+
+               % dn4n
+               /g {
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       -370 0 moveto -370 -2100 lineto stroke
+               } def
+
+               % up8n
+               /h {
+                       gsave
+                       -330 0 translate        % half a flag width
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       370 0 moveto 370 2100 lineto stroke
+                       670 2100 translate
+                       1 -1 scale      %reflect across X axis
+                       do_upflag               %do an upflag
+                       grestore
+               } def
+
+               % dn8n
+               /i {
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       -370 0 moveto -370 -2100 lineto stroke
+                       gsave
+                       -70 -2100 translate
+                       do_upflag               %do an upflag
+                       grestore
+               } def
+
+               % up16n
+               /j {
+                       2 do_upshortnote
+               } def
+
+               % dn16n
+               /k {
+                       2 do_dnshortnote
+               } def
+
+               % up32n
+               /l {
+                       3 do_upshortnote
+               } def
+
+               % dn32n
+               /m {
+                       3 do_dnshortnote
+               } def
+
+               % up64n
+               /n {
+                       4 do_upshortnote
+               } def
+
+               % dn64n
+               /o {
+                       4 do_dnshortnote
+               } def
+
+               % up128n
+               /p {
+                       5 do_upshortnote
+               } def
+
+               % dn128n
+               /q {
+                       5 do_dnshortnote
+               } def
+
+               % up256n
+               /r {
+                       6 do_upshortnote
+               } def
+
+               % dn256n
+               /s {
+                       6 do_dnshortnote
+               } def
+
+               % com
+               /t {
+                       do_com          %do a common time symbol
+               } def
+
+               % cut
+               /u {
+                       do_com          %do a common time symbol
+                       lwid setlinewidth
+                       0 -900 moveto 0 900 lineto stroke
+               } def
+
+               % begped
+               /v {
+                       lwid setlinewidth
+                       -200 600 moveto -200 0 lineto 200 0 lineto stroke
+               } def
+
+               % pedal
+               /w {
+                       lwid setlinewidth
+                       -500 0 moveto -450 0 lineto 0 600 lineto
+                       450 0 lineto 500 0 lineto stroke
+               } def
+
+               % endped
+               /x {
+                       lwid setlinewidth
+                       200 600 moveto 200 0 lineto -200 0 lineto stroke
+               } def
+
+               % dnbow
+               /y {
+                       lwid setlinewidth
+                       -350 0 moveto -350 900 lineto stroke
+                       350 0 moveto 350 900 lineto stroke
+                       200 setlinewidth
+                       -350 800 moveto 350 800 lineto stroke
+               } def
+
+               % upbow
+               /z {
+                       lwid setlinewidth
+                       -300 900 moveto 0 0 lineto 300 900 lineto stroke
+               } def
+
+               % wedge
+               /one {
+                       0 0 moveto -150 500 lineto 150 500 lineto fill
+               } def
+
+               % uwedge
+               /two {
+                       -150 0 moveto 150 0 lineto 0 500 lineto fill
+               } def
+
+               % ferm
+               /three {
+                       newpath
+                       do_ferm         %do a right side up fermata
+               } def
+
+               % uferm
+               /four {
+                       newpath
+                       gsave
+                       0 270 lwid sub 800 add translate %baseline at bottom
+                       180 rotate                      %upside down
+                       do_ferm         %do a right side up fermata
+                       grestore
+               } def
+
+               % sign
+               /five {
+                       gsave
+                       %do upper left curved part, upper right dot;
+                       %then rotate 180 to do other half
+                       0 1 1 {
+                               pop     %we don't need the loop variable
+                               0 100 moveto            %inner boundary
+                               -1000 300 -400 750 -200 700 curveto
+                               -200 800 lineto         %outer boundary
+                               -550 900 -1100 100 0 -100 curveto
+                               fill
+                               %dot at end of curve
+                               -200 700 100 0 360 arc fill
+                               %dot in upper right quadrant
+                               500 200 70 0 360 arc fill
+                               180 rotate
+                       } for
+                       grestore
+
+                       %slash through middle
+                       lwid setlinewidth
+                       -400 -800 moveto 400 800 lineto stroke
+               } def
+
+               % coda
+               /six {
+                       newpath
+                       gsave
+                       0.6 1 scale
+                       0 0 550 0 360 arc       %outside boundary
+                       1 0.6 div 1 scale       %back to original
+                       0.9 1 scale
+                       0 0 650 0 360 arc       %inside boundary
+                       eofill
+                       grestore
+                       lwid setlinewidth
+                       0 -850 moveto 0 850 lineto stroke
+                       -800 0 moveto 800 0 lineto stroke
+               } def
+
+               % mor
+               /seven {
+                       do_mor          %do a mordent
+               } def
+
+               % invmor
+               /eight {
+                       do_mor          %do a mordent
+                       lwid setlinewidth
+                       0 -450 moveto 0 450 lineto stroke
+               } def
+
+               % turn
+               /nine {
+                       do_turn         %do a turn
+               } def
+
+               % invturn
+               /zero {
+                       gsave
+                       1 -1 scale      %reflect across X axis
+                       do_turn         %do a turn
+                       grestore
+               } def
+
+               % acc_gt
+               /numbersign {
+                       lwid setlinewidth
+                       -500 300 moveto 500 0 lineto -500 -300 lineto stroke
+               } def
+
+               % acc_hat
+               /dollar {
+                       newpath
+                       -365 0 moveto 0 860 lineto 365 0 lineto
+                       150 0 lineto -75 530 lineto -300 0 lineto fill
+               } def
+
+               % acc_uhat
+               /quotedbl {
+                       newpath
+                       365 860 moveto 0 0 lineto -365 860 lineto
+                       -150 860 lineto 75 330 lineto 300 860 lineto fill
+               } def
+
+               % tr
+               /asterisk {
+                       %vertical bar of t
+                       -350 1000 moveto -550 200 lineto
+                       -612.5 -50 -212.5 -50 -160 200 curveto
+                       -230 200 lineto
+                       -300 50 -420 50 -400 200 curveto
+                       -200 1000 lineto fill
+
+                       %crossbar of t and vertical bar of r
+                       -700 600 moveto -160 600 lineto
+                       20 600 30 520 60 440 curveto
+                       -50 0 lineto 70 0 lineto 180 440 lineto
+                       190 480 100 670 -150 670 curveto
+                       -690 670 lineto fill
+
+                       %horizontal curve of r
+                       100 480 moveto
+                       300 630 450 700 650 550 curveto
+                       560 480 lineto
+                       450 630 300 560 100 390 curveto
+                       fill
+
+                       %knob at end of r
+                       600 460 100 0 360 arc fill
+               } def
+
+               % leg
+               /comma {
+                       100 setlinewidth
+                       -400 0 moveto 400 0 lineto stroke
+               } def
+
+               % rr
+               /hyphen {
+                       100 setlinewidth
+                       -400 0 moveto 0 1000 lineto stroke
+                       0 0 moveto 400 1000 lineto stroke
+               } def
+
+               % measrpt
+               /period {
+                       newpath -450 400 150 0 360 arc fill
+                       newpath 450 -400 150 0 360 arc fill
+                       200 setlinewidth
+                       -550 -600 moveto 550 600 lineto stroke
+               } def
+
+               % copyright
+               /slash {
+                       lwid setlinewidth
+                       newpath 0 400 400 0 360 arc stroke
+                       newpath 0 400 200 45 315 arc stroke
+               } def
+
+               % dim
+               /quoteleft {
+                       50 setlinewidth
+                       newpath 0 640 220 0 360 arc stroke
+               } def
+
+               % halfdim
+               /quoteright {
+                       50 setlinewidth
+                       newpath 0 640 220 0 360 arc stroke
+                       newpath -340 300 moveto 340 980 lineto stroke
+               } def
+
+               % triangle
+               /asciicircum {
+                       50 setlinewidth
+                       newpath -340 -10 moveto 0 710 lineto
+                       340 -10 lineto closepath stroke
+               } def
+
+               % qwhrest
+               /ampersand {
+                       300 setlinewidth
+                       0 -600 moveto 0 600 lineto stroke
+               } def
+
+               % ll1rest
+               /exclam {
+                       310 setlinewidth
+                       -400 455 moveto 400 450 lineto stroke
+               } def
+
+               % ll2rest
+               /at {
+                       310 setlinewidth
+                       -400 145 moveto 400 150 lineto stroke
+               } def
+       end
+
+       /BuildChar {
+
+               exch begin
+               Encoding exch get
+
+               dup
+               Mcbbox0 exch get
+               aload pop setcachedevice
+
+               CharStrings exch get
+               exec
+               end
+       } def
+end
+
+
+% Define another music character font, since there are too many to fit in one
+% font.  It works the same way as the first one.
+
+/mfont1 100 dict def
+mfont1 begin
+       /FontType 3 def
+       /FontMatrix [ .001 0 0 0.001 0 0 ] def
+       /FontBBox [ -2000 -4030 2000 4030 ] def
+       /FontName (Mfont1) def
+
+       % set up Encoding vector with standard names
+       /Encoding 256 array def
+       StandardEncoding Encoding copy
+       pop
+
+       %%%%% define routines that will be used by multiple characters %%%%%
+
+       /do_dwh_bars {
+               % the two bars surrounding a double whole note
+               lwid setlinewidth
+               -420 -600 moveto -420 600 lineto stroke
+               420 -600 moveto 420 600 lineto stroke
+       } def
+       /do_righttriangle {
+               newpath
+               420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto
+               350 150 moveto -140 150 lineto 350 -213 lineto
+               eofill
+       } def
+       /do_fillrighttriangle {
+               newpath
+               420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto
+               fill
+       } def
+       /do_rectangle {
+               newpath
+               420 270 moveto -420 270 lineto -420 -270 lineto 420 -270 lineto
+               350 150 moveto -350 150 lineto -350 -150 lineto 350 -150 lineto
+               eofill
+       } def
+       /do_isostriangle {
+               newpath
+               0 300 moveto -420 -270 lineto 420 -270 lineto
+               0 182 moveto -245 -150 lineto 245 -150 lineto
+               eofill
+       } def
+       /do_piewedge {
+               newpath
+               0 -300 moveto 0 -244 514 35 145 arc
+               0 -209 moveto 0 -244 394 43 137 arc
+               eofill
+       } def
+       /do_semicircle {
+               newpath
+               gsave
+               1 1.357 scale 420 199 moveto 0 199 420 180 360 arc
+               1 1.09 scale 350 111 moveto 0 199 350 194.1 345.9 arc
+               eofill
+               grestore
+       } def
+       /do_slashhead {
+               newpath
+               lwid setlinewidth
+               -620 -530 moveto -480 -670 lineto 620 530 lineto 480 670 lineto
+               closepath stroke
+       } def
+
+       % subsidiary dictionary of character definitions
+       /CharStrings 128 dict def
+       CharStrings begin
+
+               /.notdef {} def
+
+               % Here are the definitions of the characters.  A stepsize here
+               % is 300 units (assuming the character is drawn at its default
+               % size).
+
+               % dwhrighttriangle
+               /A {
+                       do_righttriangle
+                       do_dwh_bars
+               } def
+
+               % righttriangle
+               /B {
+                       do_righttriangle
+               } def
+
+               % fillrighttriangle
+               /C {
+                       newpath
+                       420 270 moveto -420 270 lineto 350 -300 lineto
+                       420 -300 lineto
+                       fill
+               } def
+
+               % udwhrighttriangle
+               /D {
+                       gsave
+                       180 rotate
+                       do_righttriangle
+                       do_dwh_bars
+                       grestore
+               } def
+
+               % urighttriangle
+               /E {
+                       gsave
+                       180 rotate
+                       do_righttriangle
+                       grestore
+               } def
+
+               % ufillrighttriangle
+               /F {
+                       gsave
+                       180 rotate
+                       do_fillrighttriangle
+                       grestore
+               } def
+
+               % dwhrectangle
+               /G {
+                       do_rectangle
+                       do_dwh_bars
+               } def
+
+               % rectangle
+               /H {
+                       do_rectangle
+               } def
+
+               % fillrectangle
+               /I {
+                       newpath
+                       420 270 moveto -420 270 lineto -420 -270 lineto
+                       420 -270 lineto
+                       fill
+               } def
+
+               % dwhisostriangle
+               /J {
+                       do_isostriangle
+                       do_dwh_bars
+               } def
+
+               % isostriangle
+               /K {
+                       do_isostriangle
+               } def
+
+               % fillisostriangle
+               /L {
+                       newpath
+                       0 300 moveto -420 -270 lineto 420 -270 lineto
+                       fill
+               } def
+
+               % dwhpiewedge
+               /M {
+                       do_piewedge
+                       do_dwh_bars
+               } def
+
+               % piewedge
+               /N {
+                       do_piewedge
+               } def
+
+               % fillpiewedge
+               /O {
+                       newpath
+                       0 -300 moveto 0 -244 514 35 145 arc
+                       fill
+               } def
+
+               % dwhsemicircle
+               /P {
+                       do_semicircle
+                       do_dwh_bars
+               } def
+
+               % semicircle
+               /Q {
+                       do_semicircle
+               } def
+
+               % fillsemicircle
+               /R {
+                       newpath
+                       gsave
+                       1 570 420 div scale
+                       420 199 moveto 0 199 420 180 360 arc
+                       fill
+                       grestore
+               } def
+
+               % dwhslashhead
+               /S {
+                       do_slashhead
+                       lwid setlinewidth
+                       -650 -600 moveto -650 600 lineto stroke
+                       650 -600 moveto 650 600 lineto stroke
+               } def
+
+               % slashhead
+               /T {
+                       do_slashhead
+               } def
+
+               % fillslashhead
+               /U {
+                       newpath
+                       200 setlinewidth
+                       -550 -600 moveto 550 600 lineto stroke
+               } def
+
+               % blankhead
+               /V {
+                       %print nothing
+               } def
+       end
+
+       /BuildChar {
+
+               exch begin
+               Encoding exch get
+
+               dup
+               Mcbbox1 exch get
+               aload pop setcachedevice
+
+               CharStrings exch get
+               exec
+               end
+       } def
+end
+
+
+% General routines for printing any music character, invoked by each music
+% character's specific routine below.  The scaling factor (default 1) needs
+% to be multiplied by 10 to get the actual size.  These routines restore the
+% preexisting current font when they are done.
+
+/printmchar0 {
+       gsave
+       /musicchar exch def
+       /Mfont0 findfont exch 10 mul scalefont setfont moveto 
+       musicchar show
+       grestore
+} def
+/printmchar1 {
+       gsave
+       /musicchar exch def
+       /Mfont1 findfont exch 10 mul scalefont setfont moveto 
+       musicchar show
+       grestore
+} def
+
+% Define each music character name to be a routine that prints the character.
+% Each character is to be invoked as in this example:
+%      100 200 1 gclef         % at (100, 200), scale to default size & print
+
+/gclef                 { (A) printmchar0 } def
+/fclef                 { (B) printmchar0 } def
+/cclef                 { (C) printmchar0 } def
+/dblwhole              { (D) printmchar0 } def
+/1n                    { (E) printmchar0 } def
+/2n                    { (F) printmchar0 } def
+/4n                    { (G) printmchar0 } def
+/upflag                        { (H) printmchar0 } def
+/dnflag                        { (I) printmchar0 } def
+/dwhrest               { (J) printmchar0 } def
+/1rest                 { (K) printmchar0 } def
+/2rest                 { (L) printmchar0 } def
+/4rest                 { (M) printmchar0 } def
+/8rest                 { (N) printmchar0 } def
+/16rest                        { (O) printmchar0 } def
+/32rest                        { (P) printmchar0 } def
+/64rest                        { (Q) printmchar0 } def
+/128rest               { (R) printmchar0 } def
+/256rest               { (S) printmchar0 } def
+/dot                   { (T) printmchar0 } def
+/nat                   { (U) printmchar0 } def
+/sharp                 { (V) printmchar0 } def
+/flat                  { (W) printmchar0 } def
+/dblsharp              { (X) printmchar0 } def
+/dblflat               { (Y) printmchar0 } def
+/xnote                 { (Z) printmchar0 } def
+/dwhdiamond            { (a) printmchar0 } def
+/diamond               { (b) printmchar0 } def
+/filldiamond           { (c) printmchar0 } def
+/up2n                  { (d) printmchar0 } def
+/dn2n                  { (e) printmchar0 } def
+/up4n                  { (f) printmchar0 } def
+/dn4n                  { (g) printmchar0 } def
+/up8n                  { (h) printmchar0 } def
+/dn8n                  { (i) printmchar0 } def
+/up16n                 { (j) printmchar0 } def
+/dn16n                 { (k) printmchar0 } def
+/up32n                 { (l) printmchar0 } def
+/dn32n                 { (m) printmchar0 } def
+/up64n                 { (n) printmchar0 } def
+/dn64n                 { (o) printmchar0 } def
+/up128n                        { (p) printmchar0 } def
+/dn128n                        { (q) printmchar0 } def
+/up256n                        { (r) printmchar0 } def
+/dn256n                        { (s) printmchar0 } def
+/com                   { (t) printmchar0 } def
+/cut                   { (u) printmchar0 } def
+/begped                        { (v) printmchar0 } def
+/pedal                 { (w) printmchar0 } def
+/endped                        { (x) printmchar0 } def
+/dnbow                 { (y) printmchar0 } def
+/upbow                 { (z) printmchar0 } def
+/wedge                 { (1) printmchar0 } def
+/uwedge                        { (2) printmchar0 } def
+/ferm                  { (3) printmchar0 } def
+/uferm                 { (4) printmchar0 } def
+/sign                  { (5) printmchar0 } def
+/coda                  { (6) printmchar0 } def
+/mor                   { (7) printmchar0 } def
+/invmor                        { (8) printmchar0 } def
+/turn                  { (9) printmchar0 } def
+/invturn               { (0) printmchar0 } def
+/acc_gt                        { (#) printmchar0 } def
+/acc_hat               { ($) printmchar0 } def
+/acc_uhat              { (") printmchar0 } def
+/tr                    { (*) printmchar0 } def
+/leg                   { (,) printmchar0 } def
+/rr                    { (-) printmchar0 } def
+/measrpt               { (.) printmchar0 } def
+/copyright             { (/) printmchar0 } def
+/dim                   { (`) printmchar0 } def
+/halfdim               { (') printmchar0 } def
+/triangle              { (^) printmchar0 } def
+/qwhrest               { (&) printmchar0 } def
+/ll1rest               { (!) printmchar0 } def
+/ll2rest               { (@) printmchar0 } def
+/dwhrighttriangle      { (A) printmchar1 } def
+/righttriangle         { (B) printmchar1 } def
+/fillrighttriangle     { (C) printmchar1 } def
+/udwhrighttriangle     { (D) printmchar1 } def
+/urighttriangle                { (E) printmchar1 } def
+/ufillrighttriangle    { (F) printmchar1 } def
+/dwhrectangle          { (G) printmchar1 } def
+/rectangle             { (H) printmchar1 } def
+/fillrectangle         { (I) printmchar1 } def
+/dwhisostriangle       { (J) printmchar1 } def
+/isostriangle          { (K) printmchar1 } def
+/fillisostriangle      { (L) printmchar1 } def
+/dwhpiewedge           { (M) printmchar1 } def
+/piewedge              { (N) printmchar1 } def
+/fillpiewedge          { (O) printmchar1 } def
+/dwhsemicircle         { (P) printmchar1 } def
+/semicircle            { (Q) printmchar1 } def
+/fillsemicircle                { (R) printmchar1 } def
+/dwhslashhead          { (S) printmchar1 } def
+/slashhead             { (T) printmchar1 } def
+/fillslashhead         { (U) printmchar1 } def
+/blankhead             { (V) printmchar1 } def
+
+
+% Define routines for Mup output other than music characters.
+
+/stepsize 3 def           % define a step size as 3 points (at default magnification)
+
+% x1 y1 x2 lines dist staffscale staff
+%              draw a staff starting at x1, y1 and extending to x2 with "lines"
+%              lines, 2*dist*stepsize apart, scaled by staffscale
+/staff {
+       /staffscale exch def
+       /dist exch def
+       /lines exch def
+       /x2 exch def
+       /y1 exch def
+       /x1 exch def
+       0.7 staffscale mul sb setlinewidth
+       1 lines sub  2  lines 1 sub {   % loop from bottom line to top line
+               dup stepsize mul staffscale mul dist mul y1 add x1 exch moveto
+               stepsize mul staffscale mul dist mul y1 add x2 exch lineto stroke
+       } for
+} def
+
+% x y1 y2 bracket      draw a bracket; y1 is the top
+/bracket {
+       /y2 exch def
+       /y1 exch def
+       /x exch def
+       gsave
+       3 setlinewidth
+       x 2 sub y1 1 add moveto
+       x 2 sub y2 1 sub lineto
+       stroke
+       x 2 sub y1 1 add moveto
+       x 1 sub y1 1 add   x 3 add y1 1 add   x 5 add y1 6 add   curveto
+       x 6 add y1 5 add lineto
+       x 5 add y1 2 add   x 1 add y1 2 sub   x 2 sub y1 2 sub   curveto
+       fill
+       x 2 sub y2 1 sub moveto
+       x 1 sub y2 1 sub   x 3 add y2 1 sub   x 5 add y2 6 sub   curveto
+       x 6 add y2 5 sub lineto
+       x 5 add y2 2 sub   x 1 add y2 2 add   x 2 sub y2 2 add   curveto
+       fill
+       grestore
+} def
+
+% x y1 y2 brace                draw a brace; y1 is the top
+/brace {
+       /y2 exch def
+       /y1 exch def
+       /x exch def
+       gsave
+       x 9 sub y1 y2 add 2 div translate
+       /topy y1 y2 sub 2 div 1 sub def
+       0 1 1 {
+               pop
+               %0 topy moveto 0 0 lineto stroke
+               0 0 moveto
+               16 topy 0.2 mul   -11 topy 0.6 mul   8 topy   curveto
+               8.7 topy lineto
+               -7 topy 0.7 mul   20 topy 0.3 mul   1 0   curveto
+               fill
+               1 -1 scale      % flip to do bottom half
+       } for
+       grestore
+} def
+
+% endx endy wavy staffscale    draw a wavy line from current point to here,
+%                              scaled by staffscale
+/wavy {
+       /staffscale exch def
+       /endy exch def          % define the end point of the line
+       /endx exch def
+       currentpoint            % line starts at current point
+       /begy exch def          % define the beginning point of the line
+       /begx exch def
+       gsave
+       /dx endx begx sub def   % find delta x and delta y
+       /dy endy begy sub def
+       /r dx dx mul dy dy mul add sqrt def     % hypotenuse
+       /theta dy dx atan def                   % angle with positive x axis
+       begx begy translate     % change axes so that we can draw the line
+       theta rotate            %   from (0, 0) to (r, 0)
+       staffscale staffscale scale     % scale everything by staffscale
+       /scaledr r staffscale div def   % but scale r in reverse to keep length
+
+       % Each outer loop draws one cycle of the squiggle.  It continues until
+       % we are at or beyond the desired end point.
+       0 0 moveto
+       0 6 scaledr {
+               gsave
+               % first loop draws left half of squiggle; second draws right
+               0 1 1 {
+                       0.0 0.4 moveto
+                       2.0 1.9 3.4 2.3 3.9 0.0 curveto
+                       2.1 0.0 lineto
+                       1.9 0.8 1.4 0.7 0.0 -0.4 curveto
+                       fill
+                       pop 180 rotate -6 0 translate
+               } for
+               grestore
+
+               pop 6 0 translate       % shift axes right one squiggle
+       } for
+
+       grestore
+} def
+
+% x y space frets fretno numvert curvel curver [ f1 f2 f3 ... ] grid
+%                              print a guitar grid diagram
+/grid {
+       /grid_positions exch def % 0="o", -1="x", -2=nothing, positive=dot
+       /curver exch def        % right string for curve, 0 if none
+       /curvel exch def        % left string for curve, 0 if none
+       /numvert exch def       % vertical position to print fretno, 0 if none
+       /fretno exch def        % fret no. to print at right, 0 if none
+       /frets exch def         % number of fret lines
+       /space exch def         % points between two neighboring lines
+       /y exch def             % y coord of top fret line
+       /x exch def             % x coord of left strings
+
+       gsave
+       /strings grid_positions length def      % number of strings
+       /lmarky 0.4 space mul y add def         % lowest Y of a "o" or "x"
+       space 10 div setlinewidth
+       2 setlinecap
+
+       % draw the lines of the grid
+       0  1  strings 1 sub {   % loop from left string to right string
+               dup space mul x add y moveto
+               space mul x add frets 1 sub space mul y exch sub lineto stroke
+       } for
+       0  -1  1 frets sub {    % loop from top fret (nut) to bottom fret
+               dup space mul y add x exch moveto
+               space mul y add strings 1 sub space mul x add exch lineto stroke
+       } for
+
+       % draw the curved line if there is one
+       curvel 0 gt {
+               % within strings curvel to curver, find smallest positive fret
+               /minfret 1000 def
+               curvel 1 curver {
+                       /strno exch def
+                       /grid_p grid_positions strno 1 sub get def
+                       grid_p 0 gt grid_p minfret lt and {
+                               /minfret grid_p def
+                       } if
+               } for
+
+               % if curve goes above top fret, other marks must be higher
+               minfret 1 eq {
+                       /hmarky 1.2 space mul y add def
+               } {
+                       /hmarky lmarky def
+               } ifelse
+
+               /strdiff curver curvel sub def
+               space 8 div setlinewidth
+
+               % set endpoint coords of curve; higher if curve is short
+               /curvex1 curvel 1 sub space mul x add def
+               /curvex2 curver 1 sub space mul x add def
+               /curvey 1 minfret sub space mul y add def
+               strdiff 3 lt {
+                       /curvey 0.2 strdiff div space mul curvey add def
+               } if
+
+               % move to left end, set other points, draw curve
+               curvex1 curvey moveto
+
+               curvex1 curvex2 curvex1 sub 3 div add
+               curvey space 0.4 strdiff sqrt mul mul add
+
+               curvex2 curvex2 curvex1 sub 3 div sub
+               curvey space 0.4 strdiff sqrt mul mul add
+
+               curvex2 curvey curveto stroke
+       } if
+
+       space 10 div setlinewidth
+
+       % draw dots and x and o marks
+       0  1  strings 1 sub {   % loop from left string to right string
+               /strno exch def % first string is 0
+               /grid_p grid_positions strno get def
+               /strx strno space mul x add def
+
+               % set Y of mark higher if curved line covers this string
+               strno 1 add curvel ge  strno 1 add curver le  and {
+                       /marky hmarky def
+               } {
+                       /marky lmarky def
+               } ifelse
+
+               grid_p -1 eq {          % draw an X above the string
+                       /xhwid space 3 div def
+                       strx xhwid sub marky xhwid sub moveto
+                       strx xhwid add marky xhwid add lineto stroke
+                       strx xhwid sub marky xhwid add moveto
+                       strx xhwid add marky xhwid sub lineto stroke
+               } if
+               grid_p 0 eq {           % draw a circle above the string
+                       strx marky space 0.3 mul 0 360 arc stroke
+               } if
+               grid_p 1 ge {           % draw a dot by the proper fret
+                       strx y grid_p space mul sub space 3 div add
+                       space 3 div 0 360 arc fill
+               } if
+       } for
+
+       % print "X fr" if requested
+       fretno 0 gt {
+               /Palatino-Roman findfont space 1.9 mul scalefont setfont
+               x strings 0.5 sub space mul add
+               y space numvert 0.3 add mul sub moveto
+               fretno 2 string cvs show ( fr) show
+       } if
+       grestore
+} def
+
+% x1 y1 x2 y2 whitebox         draw a white rectangle with opposite
+%                              corners of (x1,y1) and (x2,y2)
+/whitebox {
+       /y2 exch def
+       /x2 exch def
+       /y1 exch def
+       /x1 exch def
+       1.0 setgray
+       newpath
+       x1 y1 moveto
+       x1 y2 lineto
+       x2 y2 lineto
+       x2 y1 lineto
+       closepath
+       fill
+       stroke
+       0.0 setgray
+} def
+
+
+/LineNum 0 def
+/InputFile (unknown) def
+
+% n linenum
+/linenum {
+       /LineNum exch def
+} def
+
+% (inputfilename) inputfile
+/inputfile {
+       /InputFile exch def
+} def
+
+% find size of Encoding and make a dictionary
+% that size for bounding box information
+mfont0 begin
+/dictsize Encoding length def
+mfont0 /Mcbbox0 dictsize dict put
+
+% temporarily redefine printmchar0 to get code
+5 dict begin
+/printmchar0 { {} forall } def
+
+Mcbbox0 Encoding 128rest get [ 1140.0 0 -515.0 -1515.0 615.0 1685.0 ] put
+Mcbbox0 Encoding 16rest get [ 830.0 0 -415.0 -1215.0 405.0 485.0 ] put
+Mcbbox0 Encoding 1n get [ 1080.0 0 -535.0 -335.0 535.0 345.0 ] put
+Mcbbox0 Encoding 1rest get [ 1540.0 0 -765.0 -5.0 765.0 645.0 ] put
+Mcbbox0 Encoding 256rest get [ 1250.0 0 -625.0 -2115.0 615.0 1685.0 ] put
+Mcbbox0 Encoding 2n get [ 880.0 0 -435.0 -345.0 435.0 355.0 ] put
+Mcbbox0 Encoding 2rest get [ 1540.0 0 -765.0 -45.0 765.0 315.0 ] put
+Mcbbox0 Encoding 32rest get [ 940.0 0 -415.0 -1215.0 515.0 1085.0 ] put
+Mcbbox0 Encoding 4n get [ 840.0 0 -415.0 -335.0 415.0 345.0 ] put
+Mcbbox0 Encoding 4rest get [ 650.0 0 -345.0 -885.0 295.0 985.0 ] put
+Mcbbox0 Encoding 64rest get [ 1040.0 0 -515.0 -1515.0 515.0 1085.0 ] put
+Mcbbox0 Encoding 8rest get [ 750.0 0 -305.0 -615.0 435.0 485.0 ] put
+Mcbbox0 Encoding acc_gt get [ 1170.0 0 -525.0 -335.0 635.0 345.0 ] put
+Mcbbox0 Encoding acc_hat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put
+Mcbbox0 Encoding acc_uhat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put
+Mcbbox0 Encoding begped get [ 470.0 0 -245.0 -45.0 215.0 615.0 ] put
+Mcbbox0 Encoding cclef get [ 1540.0 0 -765.0 -1245.0 765.0 1255.0 ] put
+Mcbbox0 Encoding coda get [ 1640.0 0 -815.0 -855.0 815.0 865.0 ] put
+Mcbbox0 Encoding com get [ 1100.0 0 -575.0 -635.0 515.0 655.0 ] put
+Mcbbox0 Encoding copyright get [ 920.0 0 -455.0 -45.0 455.0 855.0 ] put
+Mcbbox0 Encoding cut get [ 1100.0 0 -575.0 -905.0 515.0 915.0 ] put
+Mcbbox0 Encoding dblflat get [ 1170.0 0 -595.0 -405.0 565.0 1115.0 ] put
+Mcbbox0 Encoding dblsharp get [ 720.0 0 -355.0 -345.0 355.0 355.0 ] put
+Mcbbox0 Encoding dblwhole get [ 1090.0 0 -535.0 -605.0 545.0 615.0 ] put
+Mcbbox0 Encoding diamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put
+Mcbbox0 Encoding dim get [ 540.0 0 -265.0 -5.0 265.0 905.0 ] put
+Mcbbox0 Encoding dn128n get [ 840.0 0 -415.0 -3545.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn16n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn256n get [ 840.0 0 -415.0 -3965.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn2n get [ 880.0 0 -435.0 -2105.0 435.0 355.0 ] put
+Mcbbox0 Encoding dn32n get [ 840.0 0 -415.0 -2585.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn4n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn64n get [ 840.0 0 -415.0 -3065.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn8n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put
+Mcbbox0 Encoding dnbow get [ 810.0 0 -395.0 -5.0 405.0 915.0 ] put
+Mcbbox0 Encoding dnflag get [ 640.0 0 -335.0 -1705.0 295.0 15.0 ] put
+Mcbbox0 Encoding dot get [ 280.0 0 -135.0 -125.0 135.0 135.0 ] put
+Mcbbox0 Encoding dwhdiamond get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox0 Encoding dwhrest get [ 340.0 0 -165.0 -5.0 165.0 615.0 ] put
+Mcbbox0 Encoding endped get [ 480.0 0 -215.0 -45.0 255.0 615.0 ] put
+Mcbbox0 Encoding fclef get [ 1840.0 0 -1015.0 -1705.0 815.0 655.0 ] put
+Mcbbox0 Encoding ferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put
+Mcbbox0 Encoding filldiamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put
+Mcbbox0 Encoding flat get [ 580.0 0 -295.0 -405.0 275.0 1115.0 ] put
+Mcbbox0 Encoding gclef get [ 1790.0 0 -915.0 -1605.0 865.0 3015.0 ] put
+Mcbbox0 Encoding halfdim get [ 760.0 0 -375.0 -5.0 375.0 1015.0 ] put
+Mcbbox0 Encoding invmor get [ 1320.0 0 -655.0 -455.0 655.0 465.0 ] put
+Mcbbox0 Encoding invturn get [ 1300.0 0 -645.0 -335.0 645.0 345.0 ] put
+Mcbbox0 Encoding leg get [ 840.0 0 -415.0 -55.0 415.0 65.0 ] put
+Mcbbox0 Encoding ll1rest get [ 840.0 0 -415.0 -5.0 415.0 625.0 ] put
+Mcbbox0 Encoding ll2rest get [ 840.0 0 -415.0 -15.0 415.0 315.0 ] put
+Mcbbox0 Encoding measrpt get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put
+Mcbbox0 Encoding mor get [ 1320.0 0 -655.0 -285.0 655.0 295.0 ] put
+Mcbbox0 Encoding nat get [ 520.0 0 -255.0 -855.0 255.0 865.0 ] put
+Mcbbox0 Encoding pedal get [ 1040.0 0 -515.0 -45.0 515.0 675.0 ] put
+Mcbbox0 Encoding qwhrest get [ 340.0 0 -165.0 -605.0 165.0 615.0 ] put
+Mcbbox0 Encoding rr get [ 940.0 0 -465.0 -25.0 465.0 1035.0 ] put
+Mcbbox0 Encoding sharp get [ 700.0 0 -345.0 -935.0 345.0 945.0 ] put
+Mcbbox0 Encoding sign get [ 1340.0 0 -665.0 -825.0 665.0 835.0 ] put
+Mcbbox0 Encoding tr get [ 1440.0 0 -715.0 -5.0 715.0 1015.0 ] put
+Mcbbox0 Encoding triangle get [ 800.0 0 -395.0 -45.0 395.0 785.0 ] put
+Mcbbox0 Encoding turn get [ 1300.0 0 -645.0 -325.0 645.0 345.0 ] put
+Mcbbox0 Encoding uferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put
+Mcbbox0 Encoding up128n get [ 1390.0 0 -745.0 -335.0 635.0 3555.0 ] put
+Mcbbox0 Encoding up16n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put
+Mcbbox0 Encoding up256n get [ 1390.0 0 -745.0 -335.0 635.0 3975.0 ] put
+Mcbbox0 Encoding up2n get [ 880.0 0 -435.0 -345.0 435.0 2115.0 ] put
+Mcbbox0 Encoding up32n get [ 1390.0 0 -745.0 -335.0 635.0 2595.0 ] put
+Mcbbox0 Encoding up4n get [ 850.0 0 -415.0 -335.0 425.0 2115.0 ] put
+Mcbbox0 Encoding up64n get [ 1390.0 0 -745.0 -335.0 635.0 3075.0 ] put
+Mcbbox0 Encoding up8n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put
+Mcbbox0 Encoding upbow get [ 720.0 0 -355.0 -115.0 355.0 925.0 ] put
+Mcbbox0 Encoding upflag get [ 640.0 0 -335.0 -5.0 295.0 1715.0 ] put
+Mcbbox0 Encoding uwedge get [ 340.0 0 -165.0 -5.0 165.0 505.0 ] put
+Mcbbox0 Encoding wedge get [ 340.0 0 -165.0 5.0 165.0 515.0 ] put
+Mcbbox0 Encoding xnote get [ 880.0 0 -435.0 -365.0 435.0 375.0 ] put
+
+end
+end
+
+/Mfont0 mfont0 definefont
+
+
+% find size of Encoding and make a dictionary
+% that size for bounding box information
+mfont1 begin
+/dictsize Encoding length def
+mfont1 /Mcbbox1 dictsize dict put
+
+% temporarily redefine printmchar1 to get code
+5 dict begin
+/printmchar1 { {} forall } def
+
+Mcbbox1 Encoding blankhead get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put
+Mcbbox1 Encoding dwhisostriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhpiewedge get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhrectangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhsemicircle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhslashhead get [ 1410.0 0 -695.0 -725.0 705.0 735.0 ] put
+Mcbbox1 Encoding fillisostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+Mcbbox1 Encoding fillpiewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillrectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillrighttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillsemicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillslashhead get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put
+Mcbbox1 Encoding isostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+Mcbbox1 Encoding piewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding rectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put
+Mcbbox1 Encoding righttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding semicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding slashhead get [ 1380.0 0 -685.0 -725.0 685.0 735.0 ] put
+Mcbbox1 Encoding udwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding ufillrighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+Mcbbox1 Encoding urighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+
+end
+end
+
+/Mfont1 mfont1 definefont
+
+/makeExtEncoding {
+       /extendedencoding 256 array def
+       StandardEncoding extendedencoding copy
+       extendedencoding 32 /exclamdown put
+       extendedencoding 33 /cent put
+       extendedencoding 34 /sterling put
+       extendedencoding 35 /yen put
+       extendedencoding 36 /quotedblleft put
+       extendedencoding 37 /guillemotleft put
+       extendedencoding 38 /guillemotright put
+       extendedencoding 39 /guilsinglleft put
+       extendedencoding 40 /guilsinglright put
+       extendedencoding 41 /dagger put
+       extendedencoding 42 /daggerdbl put
+       extendedencoding 43 /bullet put
+       extendedencoding 44 /quotedblbase put
+       extendedencoding 45 /quotedblright put
+       extendedencoding 46 /questiondown put
+       extendedencoding 47 /grave put
+       extendedencoding 48 /acute put
+       extendedencoding 49 /macron put
+       extendedencoding 50 /breve put
+       extendedencoding 51 /dotaccent put
+       extendedencoding 52 /dieresis put
+       extendedencoding 53 /ring put
+       extendedencoding 54 /cedilla put
+       extendedencoding 55 /hungarumlaut put
+       extendedencoding 56 /ogonek put
+       extendedencoding 57 /caron put
+       extendedencoding 58 /emdash put
+       extendedencoding 59 /AE put
+       extendedencoding 60 /ae put
+       extendedencoding 61 /ordfeminine put
+       extendedencoding 62 /ordmasculine put
+       extendedencoding 63 /Lslash put
+       extendedencoding 64 /lslash put
+       extendedencoding 65 /Oslash put
+       extendedencoding 66 /oslash put
+       extendedencoding 67 /OE put
+       extendedencoding 68 /oe put
+       extendedencoding 69 /dotlessi put
+       extendedencoding 70 /germandbls put
+       extendedencoding 71 /Aacute put
+       extendedencoding 72 /aacute put
+       extendedencoding 73 /Acircumflex put
+       extendedencoding 74 /acircumflex put
+       extendedencoding 75 /Adieresis put
+       extendedencoding 76 /adieresis put
+       extendedencoding 77 /Agrave put
+       extendedencoding 78 /agrave put
+       extendedencoding 79 /Aring put
+       extendedencoding 80 /aring put
+       extendedencoding 81 /Atilde put
+       extendedencoding 82 /atilde put
+       extendedencoding 83 /Ccedilla put
+       extendedencoding 84 /ccedilla put
+       extendedencoding 85 /Eacute put
+       extendedencoding 86 /eacute put
+       extendedencoding 87 /Ecircumflex put
+       extendedencoding 88 /ecircumflex put
+       extendedencoding 89 /Edieresis put
+       extendedencoding 90 /edieresis put
+       extendedencoding 91 /Egrave put
+       extendedencoding 92 /egrave put
+       extendedencoding 93 /Iacute put
+       extendedencoding 94 /iacute put
+       extendedencoding 95 /Icircumflex put
+       extendedencoding 96 /icircumflex put
+       extendedencoding 97 /Idieresis put
+       extendedencoding 98 /idieresis put
+       extendedencoding 99 /Igrave put
+       extendedencoding 100 /igrave put
+       extendedencoding 101 /Ntilde put
+       extendedencoding 102 /ntilde put
+       extendedencoding 103 /Oacute put
+       extendedencoding 104 /oacute put
+       extendedencoding 105 /Ocircumflex put
+       extendedencoding 106 /ocircumflex put
+       extendedencoding 107 /Odieresis put
+       extendedencoding 108 /odieresis put
+       extendedencoding 109 /Ograve put
+       extendedencoding 110 /ograve put
+       extendedencoding 111 /Otilde put
+       extendedencoding 112 /otilde put
+       extendedencoding 113 /Scaron put
+       extendedencoding 114 /scaron put
+       extendedencoding 115 /Uacute put
+       extendedencoding 116 /uacute put
+       extendedencoding 117 /Ucircumflex put
+       extendedencoding 118 /ucircumflex put
+       extendedencoding 119 /Udieresis put
+       extendedencoding 120 /udieresis put
+       extendedencoding 121 /Ugrave put
+       extendedencoding 122 /ugrave put
+       extendedencoding 123 /Ydieresis put
+       extendedencoding 124 /ydieresis put
+       extendedencoding 125 /Zcaron put
+       extendedencoding 126 /zcaron put
+       extendedencoding 127 /space put
+} def
+
+/makeExtendedFont {
+       findfont
+       dup length dict /newdict exch def
+       { 1 index /FID ne
+               { newdict 3 1 roll put }
+               { pop pop }
+               ifelse
+       } forall
+       newdict /Encoding extendedencoding put
+       newdict /UniqueID newdict /UniqueID get 1 add put
+       newdict definefont pop
+} def
+/flagsep 1.60 300 mul def       % 1.60 stepsizes
+/scv 149508 def /sf 962 string def
+/fa {/p 0 def /chr exch -3 bitshift 127 and def {sf exch p add dup /p exch def chr put} forall} def
+[ 74 62 70 54 29 55 36 37 19 26 45 40 41 50 45 52 19 73 11 68 ] 1567304784 fa
+[ 961 ] 1341740116 fa
+[ 12 4 5 4 4 2 4 3 3 7 7 3 5 5 4 5 4 2 5 3 ] 1969419526 fa
+[ 96 4 4 3 2 4 11 2 6 23 13 16 8 3 28 13 8 3 6 11 ] 387152134 fa
+[ 268 4 13 12 5 4 4 5 4 5 3 2 4 3 4 8 3 3 9 2 ] 305899779 fa
+[ 369 3 4 9 3 3 9 2 4 3 4 7 4 4 4 9 5 3 5 4 ] 477458695 fa
+[ 498 4 36 4 37 4 42 4 4 37 4 4 35 4 4 5 13 3 4 4 ] 1130513667 fa
+[ 759 3 5 33 4 5 9 29 5 4 3 5 4 4 5 4 4 5 4 3 ] 1205319942 fa
+[ 902 8 4 2 3 4 3 4 4 3 2 3 9 ] 1708988675 fa
+[ 468 6 4 10 3 30 5 3 24 40 4 3 3 3 3 8 23 1 1 1 ] 123455756 fa
+[ 664 23 4 2 13 66 4 5 9 ] 2061720845 fa
+[ 795 ] 1622189328 fa
+[ 463 45 40 41 50 45 84 ] 304180545 fa
+[ 494 40 41 49 45 43 84 ] 251711819 fa
+[ 149 203 37 144 ] 358262127 fa
+[ 456 142 52 ] 95949173 fa
+[ 0 13 13 10 65 36 6 26 38 17 13 53 4 13 13 25 36 183 7 140 ] 1751712121 fa
+[ 839 5 13 12 13 13 48 ] 1943250302 fa
+[ 30 164 254 7 42 4 36 4 18 1 18 4 46 3 1 41 4 39 4 41 ] 499619205 fa
+[ 798 1 3 1 ] 1277775234 fa
+[ 76 32 135 79 99 8 246 43 30 160 ] 734015880 fa
+[ 265 70 36 12 25 87 4 36 4 37 4 46 4 41 43 83 4 83 41 3 ] 1546658194 fa
+[ 193 49 180 8 17 134 ] 831070621 fa
+[ 353 366 ] 1033403809 fa
+[ 266 1 190 39 40 41 50 45 43 45 ] 1758436783 fa
+[ 423 8 109 ] 508918194 fa
+[ 328 6 30 6 31 6 269 ] 212071871 fa
+[ 390 357 2 ] 1671244225 fa
+[ 500 ] 347047368 fa
+[ 558 ] 1276946910 fa
+[ 651 ] 2109048312 fa
+[ 644 ] 1914352160 fa
+[ 520 ] 471204394 fa
+[ 512 5 2 ] 1930983991 fa
+[ 665 ] 154021439 fa
+[ 513 ] 777103941 fa
+[ 514 ] 260959830 fa
+[ 530 239 ] 1284535922 fa
+[ 510 ] 1982423675 fa
+[ 150 ] 1969948305 fa
+[ 511 7 134 ] 1407991454 fa
+[ 144 371 ] 1896661664 fa
+[ 464 52 ] 1444653737 fa
+[ 509 81 ] 1712172720 fa
+[ 110 11 32 24 22 18 40 12 54 7 17 19 18 19 22 13 377 94 9 11 ] 889612 fa
+[ 954 ] 1802916616 fa
+[ 80 146 51 78 37 84 8 8 73 5 44 45 33 9 73 9 130 9 11 12 ] 1808121621 fa
+[ 19 42 3 22 8 82 63 23 25 13 8 5 176 248 40 73 12 13 13 12 ] 1752602397 fa
+[ 22 10 37 42 1 2 19 26 6 38 17 13 38 11 21 13 16 9 27 9 ] 1598682919 fa
+[ 405 9 13 46 49 50 50 213 18 12 13 13 12 45 10 ] 160257827 fa
+[ 1 8 8 6 10 10 16 11 14 8 23 19 13 19 13 7 15 3 9 8 ] 882894639 fa
+[ 234 40 9 15 6 7 6 25 36 37 19 6 47 16 40 41 50 45 43 6 ] 185215791 fa
+[ 733 19 37 16 12 13 3 3 12 6 6 6 7 6 7 6 6 6 45 10 ] 1706915629 fa
+[ 24 10 37 45 2 17 5 1 15 4 7 5 8 8 17 17 13 11 8 26 ] 1713964852 fa
+[ 284 21 13 25 18 18 19 18 28 1 7 28 2 4 106 24 3 2 32 36 ] 1218620208 fa
+[ 695 62 1 7 13 1 7 2 37 4 8 5 13 12 13 13 12 45 5 1 ] 1317868340 fa
+[ 960 ] 75399990 fa
+[ 45 9 155 6 245 68 21 98 60 109 ] 1430691640 fa
+[ 20 27 15 25 8 33 173 13 45 37 83 170 5 34 8 115 40 12 13 13 ] 841629509 fa
+[ 901 ] 422446918 fa
+[ 27 25 37 13 3 40 12 73 49 77 4 33 4 68 89 219 21 27 3 4 ] 560155470 fa
+[ 466 6 135 41 7 6 36 6 89 ] 803193686 fa
+[ 42 80 1 55 80 1 80 36 37 155 1 263 40 65 ] 189315943 fa
+[ 6 31 36 9 43 21 6 185 36 37 210 ] 1031359337 fa
+[ 44 9 101 4 4 20 8 80 3 23 30 5 19 17 20 17 15 7 7 36 ] 586694517 fa
+[ 552 22 20 16 3 55 42 31 10 33 ] 343336822 fa
+[ 7 4 54 54 10 22 10 20 8 8 53 5 226 12 115 38 17 42 26 13 ] 1808462718 fa
+[ 780 32 ] 847653755 fa
+[ 3 63 31 408 18 4 18 6 22 13 15 3 32 9 17 4 15 5 18 4 ] 1627872128 fa
+[ 724 83 7 ] 1643402114 fa
+[ 228 296 8 25 39 16 159 14 34 ] 670118796 fa
+[ 2 2 47 69 19 34 23 20 35 5 187 10 51 2 38 2 39 2 48 2 ] 888380310 fa
+[ 680 2 41 2 2 5 13 11 10 40 2 50 80 ] 1392580498 fa
+[ 14 25 10 7 22 49 21 22 1 4 10 23 4 13 15 5 16 15 12 3 ] 2114772893 fa
+[ 295 30 24 9 28 9 23 19 13 1 8 24 67 16 3 30 3 3 53 9 ] 453068702 fa
+[ 694 6 9 20 11 23 1 23 23 22 8 5 1 24 41 9 11 4 5 1 ] 1393470366 fa
+[ 944 8 ] 1770206109 fa
+[ 10 5 25 6 4 7 42 39 25 20 4 4 7 2 14 17 126 5 32 5 ] 113705892 fa
+[ 442 25 4 6 114 27 38 42 32 25 20 47 19 112 ] 998588323 fa
+[ 79 19 131 109 36 37 74 70 1 59 8 34 3 25 5 9 3 80 11 27 ] 1221405612 fa
+[ 912 9 11 ] 273962927 fa
+[ 8 230 25 23 6 17 130 31 61 64 16 127 32 ] 1881483187 fa
+[ 130 683 ] 1406620603 fa
+[ 18 10 32 25 5 3 10 3 143 50 13 9 61 93 86 1 1 180 48 58 ] 1980878788 fa
+[ 861 13 9 4 12 8 17 3 ] 1447963591 fa
+[ 67 143 8 128 115 435 19 2 ] 477757388 fa
+[ 490 35 ] 1151262673 fa
+[ 5 70 67 32 37 16 14 7 27 18 142 301 17 90 103 ] 1523362782 fa
+[ 117 14 33 38 17 13 20 26 3 453 89 3 8 113 10 ] 1908448236 fa
+sf cvx exec
+%%BeginResource: procset grops 1.17 2
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/MANUAL{
+statusdict begin/manualfeed true store end
+}bind def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Courier
+%%IncludeResource: font Times-BoldItalic
+%%IncludeResource: font NewCenturySchlbk-BoldItalic
+%%IncludeResource: font NewCenturySchlbk-Roman
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
+def/PL PLG def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
+/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
+/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
+/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
+/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
+/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
+/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
+/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
+/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
+/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
+/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
+/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
+/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
+/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
+/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
+/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
+/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
+/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
+/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
+/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
+/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
+/NewCenturySchlbk-Roman@0 ENC0/NewCenturySchlbk-Roman RE
+/NewCenturySchlbk-BoldItalic@0 ENC0/NewCenturySchlbk-BoldItalic RE
+/Times-BoldItalic@0 ENC0/Times-BoldItalic RE/Courier@0 ENC0/Courier RE
+/Times-Roman@0 ENC0/Times-Roman RE/Times-Italic@0 ENC0/Times-Italic RE
+/Times-Bold@0 ENC0/Times-Bold RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 11/Times-Bold@0 SF(Mup V)195.888 43 Q(ersion 5.3 Statement Summary)
+-1.1 E/F1 11/Times-Italic@0 SF(conte)36 56 Q(xt)-.22 E(staf)36 69 Q
+(fs voices & staf)-.198 E(fs voices)-.198 E F0(:)A F1 -.165(ch)2.75 G
+(or).165 E(d)-.407 E F0(;)2.75 E F1(....)2.75 E F0([)36 82 Q F1(staf)A
+(fs voices & staf)-.198 E(fs voices)-.198 E F0(;)A F1(staf)2.75 E
+(fs voices)-.198 E F0 2.75(]:)C F1 -.165(ch)C(or).165 E(d)-.407 E F0(;)
+2.75 E F1(....)2.75 E F0(lyrics)36 95 Q F1(place staf)2.75 E(f)-.198 E
+F0(:)2.75 E F1(time_valuelist)2.75 E F0([)2.75 E F1(ver)2.75 E(ses)-.11
+E F0 2.75(]")2.75 G F1(te)-2.75 E(xt)-.22 E F0(";)A F1(...)2.75 E
+(linetype bartype)36 108 Q F0(pad)2.75 E F1(num ending_mark)2.75 E F0
+-.198(re)2.75 G(hearsal).198 E F1(fontfamily font)2.75 E F0(\()2.75 E F1
+(size)A F0(\))A F1 -.407(re)2.75 G(hear).407 E(sal_mark)-.11 E F0(mnum=)
+2.75 E F1(num)A F0(=)2.75 E F1(ta)A(g)-.11 E F0(hidechanges)2.75 E F1
+(par)36 121 Q(ameter)-.165 E F0(=)A F1(value)A F0(multir)36 134 Q(est)
+-.198 E F1(num)2.75 E F0(newscor)36 147 Q 2.75(el)-.198 G(eftmar)-2.75 E
+(gin=)-.11 E F1(num)A F0(rightmar)2.75 E(gin=)-.11 E F1(num)A F0
+(newpage leftmar)36 160 Q(gin=)-.11 E F1(num)A F0(rightmar)2.75 E(gin=)
+-.11 E F1(num)A(fontfamily font)36 173 Q F0(\()2.75 E F1(size)A F0(\))A
+F1(modi\214er place staf)2.75 E(fs)-.198 E F0(dist)2.75 E F1(num)2.75 E
+F0 2.75(!:)2.75 G F1(beat)A F0(")2.75 E F1(te)A(xt)-.22 E F0 2.75("t)C
+(il)-2.75 E F1(num)2.75 E F0(m+)A F1(num)A F0(;)A F1(....)2.75 E F0
+(mussym \()36 186 Q F1(size)A/F2 11/Times-Roman@0 SF(\))A F1(place staf)
+2.75 E(fs)-.198 E F0(:)2.75 E F1(beat)2.75 E F0(")2.75 E F1(mus_symbol)A
+F0 2.75("t)C(il)-2.75 E F1(num)2.75 E F0(m+)A F1(num)A F0(;)A F1(....)
+2.75 E(linetype)36 199 Q F0(phrase)2.75 E F1(place staf)2.75 E(fs)-.198
+E F0(:)2.75 E F1(beat til num)2.75 E F0(m+)A F1(num)A F0(;)A F1(....)
+2.75 E F0(octa)36 212 Q -.11(ve)-.275 G F1(place staf)2.86 E(fs)-.198 E
+F0(:)2.75 E F1(beat)2.75 E F0(")2.75 E F1(te)A(xt)-.22 E F0 2.75("t)C
+(il)-2.75 E F1(num)2.75 E F0(m+)A F1(num)A F0(;)A F1(....)2.75 E F0
+(pedal)36 225 Q F1(place staf)2.75 E(fs)-.198 E F0(:)2.75 E F1(beat)2.75
+E F0 2.75(*;)2.75 G F1(....)A(cr)36 238 Q(es_mark place staf)-.407 E(fs)
+-.198 E F0(:)2.75 E F1(beat til num)2.75 E F0(m+)A F1(num)A F0(;)A F1
+(....)2.75 E F0(midi)36 251 Q F1(staf)2.75 E(fs voices)-.198 E F0(:)2.75
+E F1(beat)2.75 E F0(")2.75 E F1(midi_k)A -.33(ey)-.11 G(wor).33 E(d)
+-.407 E F0(=)A F1(value)A F0(";)A F1(....)2.75 E F0 -.198(ro)36 264 S
+(ll).198 E F1(dir)2.75 E(ection staf)-.407 E(fnum voicenum)-.198 E F0
+(to)2.75 E F1(staf)2.75 E(fnum voicenum)-.198 E F0(:)2.75 E F1(beat)2.75
+E F0(;)2.75 E F1(....)2.75 E(printcmd location)36 277 Q F0(")2.75 E F1
+(te)A(xt)-.22 E F0(")A(title)36 290 Q F1(fontfamily font)2.75 E F0(\()
+2.75 E F1(size)A F0 2.75(\)")C F1(te)-2.75 E(xt)-.22 E F0 2.75("")C F1
+(te)-2.75 E(xt)-.22 E F0 2.75("")C F1(te)-2.75 E(xt)-.22 E F0(")A F1
+(justifytype)36 303 Q F0(paragraph)2.75 E F1(fontfamily font)2.75 E F0
+(\()2.75 E F1(size)A F0 2.75(\)")C F1(te)-2.75 E(xt)-.22 E F0(")A F1
+(linetype)36 316 Q F0(line)2.75 E F1(location)2.75 E F0(to)2.75 E F1
+(location)2.75 E F0(with)2.75 E F1(fontfamily font)2.75 E F0(\()2.75 E
+F1(size)A F0 2.75(\)")C F1(te)-2.75 E(xt)-.22 E F0(")A F1(linetype)36
+329 Q F0(cur)2.75 E -.11(ve)-.11 G F1(location)2.86 E F0(to)2.75 E F1
+(location)2.75 E F0(to)2.75 E F1(location ....)2.75 E(linetype)36 342 Q
+F0(cur)2.75 E -.11(ve)-.11 G F1(location)2.86 E F0(to)2.75 E F1
+(location)2.75 E F0 -.22(bu)2.75 G(lge).22 E F1(num ....)2.75 E F0
+(de\214ne)36 355 Q F1(MA)2.75 E(CR)-.33 E(O_N)-.44 E(AME)-.297 E F0(\()A
+F1(mac_par)A(ams)-.165 E F0(\))A F1(macr)2.75 E(o_de\214nition)-.495 E
+F0(@)2.75 E(ifdef)36 368 Q F1(MA)2.75 E(CR)-.33 E(O_N)-.44 E(AME .....)
+-.297 E F0(else)2.75 E F1(.....)2.75 E F0(endif)2.75 E(ifndef)36 381 Q
+F1(MA)2.75 E(CR)-.33 E(O_N)-.44 E(AME .....)-.297 E F0(else)2.75 E F1
+(.....)2.75 E F0(endif)2.75 E(undef)36 394 Q F1(MA)2.75 E(CR)-.33 E(O_N)
+-.44 E(AME)-.297 E F0(if)36 407 Q F1 -.22(ex)2.75 G(pr).22 E
+(ession .....)-.407 E F0(else)2.75 E F1(.....)2.75 E F0(endif)2.75 E
+(include ")36 420 Q F1(\214lename)A F0(")A -.275(fo)36 433 S(nt\214le ")
+.275 E F1(\214lename)A F0(")A(//)36 446 Q F1(comment\212arbitr)2.75 E
+(ary te)-.165 E(xt that will be ignor)-.22 E(ed.)-.407 E F0 -1.012(Va)
+211.877 472 S(lues used in Mup statements)1.012 E F1(accidental)36 485 Q
+F0(#)40.574 E F2(,)A F0(&)2.75 E F2(,)A F0(x)2.75 E F2(,)A F0(&&)2.75 E
+F2 2.75(,o)C(r)-2.75 E F0(n)2.75 E F1(bartype)36 498 Q F0(bar)52.795 E
+F2(,)A F0(dblbar)2.75 E F2(,)A F0 -.198(re)2.75 G(peatstart).198 E F2(,)
+A F0 -.198(re)2.75 G(peatend).198 E F2(,)A F0 -.198(re)2.75 G(peatboth)
+.198 E F2(,)A F0(endbar)2.75 E F2(,)A F0(in)2.75 E(visbar)-.44 E F2 2.75
+(,o)C(r)-2.75 E F0 -.198(re)2.75 G(start).198 E F1(beat)36 511 Q F2(num\
+ber from 0.0 to time signature denominator plus 1.0, optionally follo)
+67.458 E(wed)-.275 E(by ho)122.4 524 Q 2.75(wm)-.275 G(an)-2.75 E 2.75
+(yg)-.165 G(race notes to back up from there, as a ne)-2.75 E -.055(ga)
+-.165 G(ti).055 E .33 -.165(ve n)-.275 H(umber in parentheses,).165 E
+(and an of)122.4 537 Q(fset as a signed number in square brack)-.275 E
+(ets)-.11 E F1 -.165(ch)36 550 S(or).165 E(d)-.407 E F0(<<)61.309 E F1
+(conte)A(xt par)-.22 E(ameter=value)-.165 E F0(>> [)A F1 -.165(ch)C(or)
+.165 E(d_style)-.407 E F0(])A F1(time_value pitc)2.75 E
+(h\(es\) note_attrib)-.165 E(utes inter)-.22 E(-c)-.22 E(hor)-.165 E
+(d_attr)-.407 E F2 -.495(Tu)122.4 563 S(plets speci\214ed by).495 E F0
+({)8.25 E F1 -.165(ch)2.75 G(or).165 E(d)-.407 E F0(;)2.75 E F1(....)
+2.75 E F0(})2.75 E F1(side num tupstyle)2.75 E 2.75(,t)-.11 G(ime_value)
+-2.75 E F0(;)2.75 E F2(On tablature staf)122.4 576 Q(f, the)-.275 E F1
+(pitc)2.75 E(h)-.165 E F2(is:)2.75 E F1(string fr)2.75 E(et)-.407 E F0
+(")2.75 E F1(bend)A F0(")A F1(bend)36 589 Q F0(full)65.016 E F2 2.75(,o)
+C(r)-2.75 E F1(num)2.75 E F2(and/or a fraction as)2.75 E F1(num)2.75 E
+F0(/)A F1(num)A -.165(ch)36 602 S(or).165 E(d_style)-.407 E F2
+(one or more \(semicolon-separated\) from the follo)35.646 E(wing:)-.275
+E F0(grace)122.4 615 Q F2(,)A F0(cue)2.75 E F2(,)A F0(xnote)2.75 E F2(,)
+A F0(diam)2.75 E F2(,)A F0(with)2.75 E F1(withlist)2.75 E F2(,)A F0(pad)
+2.75 E F1(num)2.75 E F2(,)A F0(slash)2.75 E F1(num)2.75 E F2(,)A F1
+(stemdir)2.75 E F2(,)A F0(len)2.75 E F1(num)2.75 E F2(,)A F0(dist)2.75 E
+F1(num)2.75 E F2(,)A F0(ho)122.4 628 Q F1(num)2.75 E F2(,)A F0(hs ")2.75
+E F1(headshape)A F0(")A F2 2.75(,o)C(r)-2.75 E F0(=)2.75 E F1(ta)A(g)
+-.11 E F2(Putting)122.4 641 Q F0(...)2.75 E F2(after the)2.75 E F0(])
+2.75 E F2(will repeat the)2.75 E F1 -.165(ch)2.75 G(or).165 E(d_style)
+-.407 E F2(until)2.75 E F0([-])2.75 E F2(or end of measure.)2.75 E F1
+(clef)36 654 Q F0(tr)70.516 E(eble)-.198 E F2(,)A F0(soprano)2.75 E F2
+(,)A F0(mezzosoprano)2.75 E F2(,)A F0(alto)2.75 E F2(\(these ha)5.5 E
+.33 -.165(ve d)-.22 H(ef).165 E(ault octa)-.11 E .33 -.165(ve o)-.22 H
+2.75(f4).165 G(\))-2.75 E F0(tr)122.4 667 Q(eble8)-.198 E F2(,)A F0
+(tenor)2.75 E F2(,)A F0(baritone)2.75 E F2(,)A F0(bass)2.75 E F2
+(\(these ha)5.5 E .33 -.165(ve d)-.22 H(ef).165 E(ault octa)-.11 E .33
+-.165(ve o)-.22 H 2.75(f3).165 G(\))-2.75 E F0(fr)122.4 680 Q
+(enchviolin)-.198 E F2(,)A F0(8tr)2.75 E(eble)-.198 E F2(\(these ha)2.75
+E .33 -.165(ve d)-.22 H(ef).165 E(ault octa)-.11 E .33 -.165(ve o)-.22 H
+2.75(f5).165 G(\))-2.75 E F1(conte)36 693 Q(xt)-.22 E F0(scor)54.852 E
+(e)-.198 E F2(,)A F0(staff)2.75 E F1(staf)2.75 E(fnum)-.198 E F2(,)A F0
+-.11(vo)2.75 G(ice).11 E F1(staf)2.75 E(fnum voicenum)-.198 E F2(,)A F0
+(music)2.75 E F2(,)A F0(top)2.75 E F2(,)A F0(bottom)2.75 E F2(,)A F0
+(top2)2.75 E F2(,)A F0(bottom2)2.75 E F2(,)A F0(header)122.4 706 Q F2(,)
+A F0 -.275(fo)2.75 G(oter).275 E F2(,)A F0(header2)2.75 E F2(,)A F0
+-.275(fo)2.75 G(oter2).275 E F2(,)A F0(grids)2.75 E F2 2.75(,o)C(r)-2.75
+E F0(headshapes)2.75 E F1(cr)36 719 Q(es_mark)-.407 E F0(<)40.376 E F2
+(\(crescendo\) or)2.75 E F0(>)2.75 E F2(\(decrescendo\))2.75 E F1(dir)36
+732 Q(ection)-.407 E F0(up)47.086 E F2(or)2.75 E F0(do)2.75 E(wn)-.11 E
+F1(ending_mark)36 745 Q F0(ending ")28.353 E F1(te)A(xt)-.22 E F0(")A F2
+(or)5.5 E F0(endending)2.75 E F1 -.22(ex)36 758 S(pr).22 E(ession)-.407
+E F2(can contain)39.98 E F0 2.75
+(de\214ned\(\) \(\) + - ~ ! * / % ^ & | << >> < > <= >= == != && || ?:)
+2.75 F F1(\214lename)36 771 Q F2
+(path to a \214le on your system; uses MUPP)49.132 E -1.221(AT)-1.012 G
+2.75(Ht)1.221 G 2.75<6f8c>-2.75 G(nd, if not in current directory)-2.75
+E(and not absolute path)122.4 784 Q EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 9/Times-Roman@0 SF 2.25(-2-)262.503 44.5 S/F1 11/Times-Italic@0 SF
+(font)36 70.5 Q/F2 11/Times-Bold@0 SF -.198(ro)69.284 G(m).198 E/F3 11
+/Times-Roman@0 SF(,)A F2(ital)2.75 E F3(,)A F2(bold)2.75 E F3 2.75(,o)C
+(r)-2.75 E F2(boldital)2.75 E F1(fontfamily)36 83.5 Q F2 -2.31 -.275
+(av a)41.784 H(ntgarde).275 E F3(,)A F2(bookman)2.75 E F3(,)A F2
+(courier)2.75 E F3(,)A F2(helv)2.75 E(etica)-.11 E F3(,)A F2(newcentury)
+2.75 E F3(,)A F2(palatino, or times)2.75 E F1(fr)36 96.5 Q(et)-.407 E F3
+(number from 0 to 99)71.528 E F1(he)36 109.5 Q(x_data)-.22 E F3 -2.365
+-.275(ev e)46.294 H 2.75(nn).275 G(umber of he)-2.75 E(xadecimal digits)
+-.165 E F1(inter)36 122.5 Q(-c)-.22 E(hor)-.165 E 12.942
+(d_attr tieslur_style)-.407 F F2(tie)2.75 E F1(dir)2.75 E(ection)-.407 E
+F3(,)A F1(tieslur_style)2.75 E F2(slur)2.75 E F1(dir)2.75 E(ection)-.407
+E F3(,)A F2(bm)2.75 E F3(,)A F2(bm with staff)2.75 E F1(side)2.75 E F3
+(,)A F2(ebm)2.75 E F3(,)A F2(esbm)2.75 E F3(,)A F2(slope)122.4 135.5 Q
+F1(num)2.75 E F3 2.75(,o)C(r)-2.75 E F2(alt)2.75 E F1(num)2.75 E
+(interval)36 148.5 Q F2(perfect)52.179 E F3(,)A F2(major)2.75 E F3(,)A
+F2(minor)2.75 E F3(,)A F2(augmented)2.75 E F3 2.75(,o)C(r)-2.75 E F2
+(diminished)2.75 E F1(justifytype)36 161.5 Q F2(justi\214ed)41.179 E F3
+2.75(,o)C(r)-2.75 E F2(ragged)2.75 E F1(linetype)36 174.5 Q F2(medium)
+51.574 E F3(,)A F2(wide)2.75 E F3(,)A F2(dashed)2.75 E F3 2.75(,o)C(r)
+-2.75 E F2(dotted)2.75 E F3(\(if omitted,)2.75 E F1(linetype)2.75 E F3
+(is narro)2.75 E(w\))-.275 E F1(location)36 187.5 Q F2(\()50.342 E F1
+(ta)2.75 E(g)-.11 E F2(.)A F1(X)A F2(+)2.75 E F1(steps)2.75 E F2 2.75
+(+t)2.75 G(ime)-2.75 E F1(time_value)2.75 E F2(,)A F1(ta)2.75 E(g)-.11 E
+F2(.)A F1(Y)A F2(+)2.75 E F1(steps)2.75 E F2(\))2.75 E F1(mac_par)36
+200.5 Q(ams)-.165 E F3
+(comma-separated list of parameter names, same naming rules as)29.739 E
+F1(MA)2.75 E(CR)-.33 E(O_N)-.44 E(AME)-.297 E(MA)36 213.5 Q(CR)-.33 E
+(O_N)-.44 E(AME)-.297 E F3
+(upper case letters, digits, and/or underscores, be)14.141 E
+(ginning with a letter)-.165 E F1(macr)36 226.5 Q(o_de\214nition)-.495 E
+F3(arbitrary te)11.732 E(xt that will be used where)-.165 E -.165(ve)
+-.275 G(r).165 E F1(MA)2.75 E(CR)-.33 E(O_N)-.44 E(AME)-.297 E F3
+(appears in input)2.75 E F1(midi_k)36 239.5 Q -.33(ey)-.11 G(wor).33 E
+(d)-.407 E F3(an)24.921 E 2.75(yo)-.165 G 2.75(ft)-2.75 G(he follo)-2.75
+E(wing:)-.275 E F2(tempo=)122.4 252.5 Q F1(num)A F2(pr)46.262 E(ogram=)
+-.198 E F1(num)A F2(parameter=)34.239 E F1(num)A F2(,)A F1(num)A F2
+(port=)4.418 E F1(num)A F2(on)122.4 265.5 Q -.11(ve)-.44 G(locity=).11 E
+F1(num)A F2(offv)28.475 E(elocity=)-.11 E F1(num)A F2(channel=)26.825 E
+F1(num)A F2(chanpr)38.914 E(essur)-.198 E(e=)-.198 E F1(num)A F2
+(seqnum=)122.4 278.5 Q F1(num)A F2(text=)38.914 E F1(te)A(xt)-.22 E F2
+(copyright=)61.156 E F1(te)A(xt)-.22 E F2(name=)33.645 E F1(te)A(xt)-.22
+E F2(instrument=)122.4 291.5 Q F1(num)A F2(mark)23.646 E(er=)-.11 E F1
+(te)A(xt)-.22 E F2(cue=)43.545 E F1(te)A(xt)-.22 E F2(hex=)62.982 E F1
+(he)A(x_data)-.22 E(modi\214er)36 304.5 Q F2(chord)49.737 E F3(,)A F2
+(analysis)2.75 E F3(,)A F2(\214gbass)2.75 E F3 2.75(,o)C 2.75(ro)-2.75 G
+(mitted)-2.75 E F1(mus_symbol)36 317.5 Q F3
+(musical symbol; see chart on page 6 for complete list.)32.016 E F1
+(note_attrib)36 330.5 Q(utes)-.22 E F3(one or more of the follo)20.004 E
+(wing:)-.275 E F1(tieslur_style)2.75 E F2(~)2.75 E F1(dir)2.75 E(ection)
+-.407 E F3(\(tie\),)2.75 E F1(tieslur_style)2.75 E F2 2.75(<>)2.75 G F1
+(dir)A(ection\) \(slur\),)-.407 E F2(?)122.4 343.5 Q F3(\(small\),)2.75
+E F2(^)2.75 E F1(pitc)A(h)-.165 E F3(\(bend\),)2.75 E F2(hs ")2.75 E F1
+(headshape)A F2(")A F3 2.75(,o)C(r)-2.75 E F2(=)2.75 E F1(ta)A(g)-.11 E
+(num)36 356.5 Q F3(some number; v)67.458 E(alid v)-.275 E
+(alues depend on where it appears)-.275 E F1(octave)36 369.5 Q F3
+(number from)57.69 E F2(0)2.75 E F3(to)2.75 E F2(9)2.75 E F3
+(or one or more)2.75 E F2(+)2.75 E F3(or)2.75 E F2(-)2.75 E F3(signs)
+2.75 E F1(par)36 382.5 Q(ameter)-.165 E F3
+(See parameter table on page 5 for complete list)40.739 E F1(pitc)36
+395.5 Q(h)-.165 E F3(letter from)64.565 E F2(a)2.75 E F3(to)2.75 E F2(g)
+2.75 E F3 2.75(,o)C(ptionally follo)-2.75 E(wed by)-.275 E F1
+(accidental)2.75 E F3(and/or)2.75 E F1(octave)2.75 E F3(,)A(or)122.4
+408.5 Q F2(r)2.75 E F3(\(rest\),)2.75 E F2(s)2.75 E F3(\(space\),)2.75 E
+F2(us)2.75 E F3(\(uncollapseable space\), or)2.75 E F2 -.11(rp)2.75 G(t)
+.11 E F3(\(repeat\))2.75 E F1(place)36 421.5 Q F2(abo)62.574 E -.11(ve)
+-.11 G F3(,).11 E F2(belo)2.75 E(w)-.11 E F3 2.75(,o)C(r)-2.75 E F2
+(between)2.75 E F3 2.75(.I)C(f)-2.75 E F2(between)2.75 E F3(,)A F1(staf)
+2.75 E(fs)-.198 E F3(must be of the form)2.75 E F1(num)2.75 E F2(&)A F1
+(num)A(printcmd)36 434.5 Q F2(left)46.679 E F3(,)A F2(right)2.75 E F3(,)
+A F2(center)2.75 E F3(,)A F2(print)2.75 E F3(or)2.75 E F2(postscript)
+2.75 E F1 -.407(re)36 447.5 S(hear).407 E(sal_mark)-.11 E F2(let)16.649
+E F3(,)A F2(num)2.75 E F3(,)A F2(mnum)2.75 E F3 2.75(,o)C(r)-2.75 E F2
+(")2.75 E F1(te)A(xt)-.22 E F2(")A F1(side)36 460.5 Q F2(abo)68.679 E
+-.11(ve)-.11 G F3(or)2.86 E F2(belo)2.75 E(w)-.11 E F1(size)36 473.5 Q
+F3(number from 1 to 100 \(points\))69.9 E F1(staf)36 486.5 Q(fnum)-.198
+E F3(number from 1 to 40)48.703 E F1(staf)36 499.5 Q(fs)-.198 E F3
+(number from 1 to 40, or comma-separated list of dash-separated ranges)
+63.366 E F1(stemdir)36 512.5 Q F2(up)53.4 E F3(or)2.75 E F2(do)2.75 E
+(wn)-.11 E F1(stemlen)36 525.5 Q F3 2.75(an)52.795 G(umber)-2.75 E 2.75
+(,i)-.44 G 2.75(ns)-2.75 G(tepsizes)-2.75 E F1(steps)36 538.5 Q F3 2.75
+(an)64.4 G
+(umber of stepsizes, where a stepsize is 1/2 the distance between tw)
+-2.75 E 2.75(os)-.11 G(taf)-2.75 E 2.75(fl)-.275 G(ines)-2.75 E F1
+(string)36 551.5 Q F3(in tablature chord:)60.726 E F1(pitc)2.75 E 2.75
+(ha)-.165 G(ccidental)-2.75 E F3(follo)2.75 E(wed by zero or more)-.275
+E F2(')2.75 E F3(marks)2.75 E F1(tab_string)36 564.5 Q F3
+(list of tablature strings. Each includes a)41.168 E F1(pitc)2.75 E(h)
+-.165 E F3 2.75(,o)C(ptional)-2.75 E F2(')2.75 E F3(marks, and optional)
+2.75 E F1(octave)2.75 E(.)-.165 E(ta)36 577.5 Q(g)-.11 E F3 2.75(al)
+72.452 G -.275(ow)-2.75 G(er case letter).275 E 2.75(,o)-.44 G 2.75(ra)
+-2.75 G 2.75(nu)-2.75 G(nderscore follo)-2.75 E(wed by lo)-.275 E
+(wer case letters, digits, and/or underscores)-.275 E
+(Each has 6 associated v)122.4 590.5 Q(alues:)-.275 E F2(x)2.75 E F3(,)A
+F2(y)2.75 E F3(,)A F2(n)2.75 E F3(,)A F2(s)2.75 E F3(,)A F2(e)2.75 E F3
+2.75(,a)C(nd)-2.75 E F2(w)2.75 E F3(Prede\214ned tag names are)122.4
+603.5 Q F2(_win)2.75 E F3(,)A F2(_page)2.75 E F3 2.75(,a)C(nd)-2.75 E F2
+(_cur)2.75 E F1(te)36 616.5 Q(xt)-.22 E F3(arbitrary te)70.736 E
+(xt; use)-.165 E F2(\\")2.75 E F3(to include quotes,)2.75 E F2(\\f\()
+2.75 E F1(fontfamily font)A F2(\))A F3(to change font,)2.75 E F2(\\s\()
+2.75 E F1(num)A F2(\))A F3(to change size,)2.75 E F2(\\\()122.4 629.5 Q
+F1(xx)A F2(\))A F3(to include special characters,)2.75 E F2(\\v\()2.75 E
+F1(num)A F2(\))A F3(for v)2.75 E(ertical motion,)-.165 E F2(\\:)2.75 E
+F3(to toggle piling,)2.75 E F2(\\|)2.75 E F3(or)2.75 E F2(\\^)2.75 E F3
+(for alignment)2.75 E F1(time_value)36 642.5 Q F2(1/4)38.132 E F3(,)A F2
+(1/2)2.75 E F3(,)A F2(1)2.75 E F3(,)A F2(2)2.75 E F3(,)A F2(4)2.75 E F3
+(,)A F2(8)2.75 E F3(,)A F2(16)2.75 E F3(,)A F2(32)2.75 E F3(,)A F2(64)
+2.75 E F3(,)A F2(128)2.75 E F3 2.75(,o)C(r)-2.75 E F2(256)2.75 E F3
+(with optional dots,)2.75 E F2(+)2.75 E F3(or)2.75 E F2(-)2.75 E F3 2.75
+(;o)C(r)-2.75 E F2(m)2.75 E F3(\(measure\))2.75 E F1(tieslur_style)36
+655.5 Q F2(dotted)32.621 E F3(,)A F2(dashed)2.75 E F3 2.75(,o)C 2.75(ro)
+-2.75 G(mitted)-2.75 E F1(tuplet)36 668.5 Q F3(See)61.342 E F1 -.165(ch)
+2.75 G(or).165 E(d)-.407 E(tupstyle)36 681.5 Q F2(y)52.179 E F3(\(al)
+2.75 E -.11(wa)-.11 G(ys print brack).11 E(et\),)-.11 E F2(n)2.75 E F3
+(\(no number or brack)2.75 E(et\),)-.11 E F2(num)2.75 E F3
+(\(number only\), or omitted \(def)2.75 E(ault\))-.11 E F1(value)36
+694.5 Q F3(See information about the item to the left of the = for v)
+62.574 E(alid v)-.275 E(alues)-.275 E F1(ver)36 707.5 Q(ses)-.11 E F3
+(number or comma-separated list of dash-separated ranges)59.021 E F1
+(voicenum)36 720.5 Q F2(1)44.248 E F3(,)A F2(2)2.75 E F3 2.75(,o)C(r)
+-2.75 E F2(3)2.75 E F1 56.161(voices comma-separ)36 733.5 R
+(ated list of dash-separ)-.165 E(ated r)-.165 E(ang)-.165 E
+(es of voicenum)-.11 E F3(s)A F1(withlist)36 746.5 Q F3
+(comma-separated list of the follo)53.994 E(wing:)-.275 E F2(.)2.75 E F3
+(\(stacatto\),)2.75 E F2(-)2.75 E F3(\(le)2.75 E -.055(ga)-.165 G(to\),)
+.055 E F2(^)2.75 E F3(\(accent\),)2.75 E F2(>)2.75 E F3(\(accent\), or)
+2.75 E F2(")2.75 E F1(te)A(xt)-.22 E F2(")A F1(X)36 759.5 Q F2(x)79.679
+E F3(,)A F2(w)2.75 E F3 2.75(,o)C(r)-2.75 E F2(e)2.75 E F3
+(\(x, west, or east\))5.5 E F1(Y)36 772.5 Q F2(y)80.284 E F3(,)A F2(n)
+2.75 E F3 2.75(,o)C(r)-2.75 E F2(s)2.75 E F3(\(y)5.5 E 2.75(,n)-.715 G
+(orth, or south\))-2.75 E EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 9/Times-Roman@0 SF 2.25(-3-)262.503 44.5 S/F1 11/Times-Bold@0 SF
+-.275(Fo)209.985 71.5 S(nt/size changes in text strings).275 E/F2 11
+/Times-Roman@0 SF 1.76 -.88(To c)36 99.5 T
+(hange font inside a quoted te).88 E(xt string, use)-.165 E F1(\\f\()
+2.75 E/F3 11/Times-Italic@0 SF(fontfamily font)A F1(\))A F2(or)2.75 E F1
+(\\f\()2.75 E F3(font_abbr)A F1(\))A F2(from the table:)2.75 E F3
+182.957(font fontfamily)44.558 113.5 R F2 -.22(av)86.732 127.5 S(antg)
+-.055 E 13.75(arde bookman courier helv)-.055 F 13.75(etica ne)-.165 F
+13.75(wcentury palatino times)-.275 F .44 LW 455.397 132.25 36 132.25 DL
+(rom)36 143.5 Q/F4 11/Courier@0 SF 41.025(AR BR)50.264 F 32.048(CR HR)
+39.347 F 39.941(NR PR)48.593 F(TR)32.939 E F1(bold)36 157.5 Q F4 41.025
+(AB BB)47.195 F 32.048(CB HB)39.347 F 39.941(NB PB)48.593 F(TB)32.939 E
+F3(ital)36 171.5 Q F4 41.025(AI BI)53.311 F 32.048(CI HI)39.347 F 39.941
+(NI PI)48.593 F(TI)32.939 E/F5 11/Times-BoldItalic@0 SF(boldital)36
+185.5 Q F4 41.025(AX BX)33.753 F 32.048(CX HX)39.347 F 39.941(NX PX)
+48.593 F(TX)32.939 E F1(\\f\(pr)36 199.5 Q -.165(ev)-.198 G(ious\)).165
+E F2(or)2.75 E F1(\\f\(PV\))2.75 E F2(changes to pre)2.75 E(vious font.)
+-.275 E F1(\\s\()2.75 E F3(num)A F1(\))A F2(changes to point size)2.75 E
+F3(num)2.75 E F2 2.75(,1t)C 2.75(o1)-2.75 G(00.)-2.75 E F1(\\s\(+)36
+213.5 Q F3(num)A F1(\))A F2(increases the size by)2.75 E F3(num)2.75 E
+F2(while)2.75 E F1(\\s\(-)2.75 E F3(num)A F1(\))A F2(decreases it by)
+2.75 E F3(num)2.75 E F2(points.)2.75 E F1(\\s\(PV\))36 227.5 Q F2(or)
+2.75 E F1(\\s\(pr)2.75 E -.165(ev)-.198 G(ious\)).165 E F2(re)2.75 E
+-.165(ve)-.275 G(rts to pre).165 E(vious size.)-.275 E F1
+(Mup command line ar)212.19 255.5 Q(guments)-.11 E(-c)36 283.5 Q F3(num)
+2.75 E F2(combine)113.761 E F3(num)2.75 E F2
+(or more measures of rest into multirest)2.75 E F1(-C)36 297.5 Q F2
+(used with -E, k)132.395 E(eep comments rather than discarding them)-.11
+E F1(-d)36 311.5 Q F3(num)2.75 E F2(turn on deb)112.529 E(ugging le)-.22
+E -.165(ve)-.275 G(l).165 E F3(num)2.75 E F1(-D)36 325.5 Q F3(MA)2.75 E
+(CR)-.33 E(O)-.44 E F1(=)A F3(def)A F2(de\214ne)72.819 E F3(MA)2.75 E
+(CR)-.33 E(O)-.44 E F2(as)2.75 E F3(def)2.75 E F1(-e)36 339.5 Q F3
+(err\214le)2.75 E F2(put error output into)105.819 E F3(err\214le)2.75 E
+F1(-E)36 353.5 Q F2(just e)133 E
+(xpand macros and "include" \214les and write result to standard output)
+-.165 E F1(-f)36 367.5 Q F3(out\214le)2.75 E F2(put output into)106.424
+E F3(out\214le)2.75 E F1(-F)36 381.5 Q F2(put output into \214le, deri)
+133.616 E(ving output \214le name from input \214le name)-.275 E F1(-m)
+36 395.5 Q F3(midi\214le)2.75 E F2(generate MIDI output into)95.424 E F3
+(midi\214le)2.75 E F1(-M)36 409.5 Q F2(generate MIDI output, deri)
+129.953 E .33 -.165(ve \214)-.275 H(le name).165 E F1(-o)36 423.5 Q F3
+(pa)2.75 E -.11(ge)-.11 G(list).11 E F2(only print pages in)97.47 E F3
+(pa)2.75 E -.11(ge)-.11 G(list).11 E F2 2.75(,c)C
+(an be list of numbers, or)-2.75 E F1(odd)2.75 E F2(or)2.75 E F1 -2.53
+-.165(ev e)2.75 H(n).165 E(-p)36 437.5 Q F3(num)2.75 E F2
+(start numbering pages at)112.529 E F3(num)2.75 E F1(-r)36 451.5 Q F2
+(print share)135.453 E -.11(wa)-.275 G(re re).11 E(gistration form)-.165
+E F1(-s)36 465.5 Q F3(staf)2.75 E(\215ist)-.198 E F2
+(print only the staf)101.716 E(fs listed in)-.275 E F3(staf)2.75 E
+(\215ist)-.198 E F2 2.75(;a)C(dd)-2.75 E F1(v)2.75 E F3(N)A F2
+(to restrict to v)2.75 E(oice)-.22 E F3(N)2.75 E F1(-v)36 479.5 Q F2
+(print v)134.837 E(ersion number and e)-.165 E(xit)-.165 E F1(-x)36
+493.5 Q F3(M)2.75 E F1(,)A F3(N)A F2 -.165(ex)112.837 G(tract measures)
+.165 E F3(M)2.75 E F2(through)2.75 E F3(N)2.75 E F2 2.75(,n)C -2.475
+-.165(eg a)-2.75 H(ti).165 E .33 -.165(ve r)-.275 H(elati).165 E .33
+-.165(ve t)-.275 H 2.75(oe).165 G(nd, 0 for pickup)-2.75 E F1
+(Mupdisp commands)236.572 521.5 Q F3(num)36 549.5 Q F2 194.074
+(<Enter> go)B(to page)2.75 E F3(num)2.75 E F1(+)36 563.5 Q F2
+(or <space> or <cntl-E> or <cntl-F>)2.75 E(forw)86.923 E(ard 1/8")-.11 E
+F1(f)36 577.5 Q F2(or <Enter> or <cntl-D> or <cntl-N>)2.75 E(forw)87.088
+E(ard 1")-.11 E F1(-)36 591.5 Q F2
+(or <backspace> or <cntl-Y> or <cntl-B>)2.75 E(backw)66.32 E(ard 1/8")
+-.11 E F1(b)36 605.5 Q F2(or <cntrl-U> or <cntl-P> or <cntl-B>)2.75 E
+(backw)79.124 E(ard 1")-.11 E F1(h)36 619.5 Q F2(or)2.75 E F1(?)2.75 E
+F2(help)225.721 E F1(m)36 633.5 Q F2
+(toggle between full and partial page modes)242.837 E F1(n)36 647.5 Q F2
+(ne)245.884 E(xt page)-.165 E F1(p)36 661.5 Q F2(pre)245.884 E
+(vious page)-.275 E F1(q)36 675.5 Q F2(or)2.75 E F1(ZZ)2.75 E F2(quit)
+216.547 E F1(r)36 689.5 Q F2(repaint the screen)247.116 E EP
+%%Page: 4 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 9/Times-Roman@0 SF 2.25(-4-)262.503 44.5 S/F1 11/Times-Bold@0 SF
+(Mup P)244.591 70.5 Q(arameters)-.11 E .32 LW 578.6 74.5 36 74.5 DL/F2 8
+/Times-Roman@0 SF -.12(Pa)57.964 86.5 S 27.964(rameter Score).12 F(Staf)
+12 E 16(fV)-.2 G 10(oice Hd/Ft)-17.032 F -.888(Va)130.812 G(lid V).888 E
+137.96(alues Def)-.888 F(ault)-.08 E 578.6 90.5 36 90.5 DL 578.6 92.5 36
+92.5 DL/F3 8/Times-Bold@0 SF(abo)40 104.5 Q -.08(ve)-.08 G(order).08 E
+F2 27.984<8383>49.004 G F3(mussym,octa)53.036 E -.08(ve)-.2 G
+(,dyn&othertext&chord,lyrics,ending,r).08 E 97.84(eh as)-.144 F(listed)2
+E 578.6 108.5 36 108.5 DL(addtranspose)40 120.5 Q F2 27.984<8383>42.164
+G F3(up)53.036 E F2(or)2 E F3(do)2 E(wn)-.08 E F2 2(,f)C(ollo)-2 E
+(wed by)-.2 E/F4 8/Times-Italic@0 SF(interval)2 E F2(and)2 E F4(num)2 E
+F2(up perfect 1)153.232 E 578.6 124.5 36 124.5 DL F3(barstyle)40 136.5 Q
+F2 111.804<8363>60.396 G(omma-separated lists of staf)-111.804 E
+(fs or dash-separated ranges)-.2 E 578.6 140.5 36 140.5 DL F3(beamslope)
+40 152.5 Q F2 27.984<8383>51.948 G 50.308<8330>-.072 G
+(.0 to 1.0, 0.0 to 45.0)-50.308 E(1.0,20.0)221.392 E 578.6 156.5 36
+156.5 DL F3(beamstyle)40 168.5 Q F2 27.984<8383>53.732 G 50.308<8363>
+-.072 G(omma-separated list of)-50.308 E F4(time_values)2 E F2
+(that add up to a measure)2 E 578.6 172.5 36 172.5 DL F3(belo)40 184.5 Q
+-.08(wo)-.08 G(rder).08 E F2 27.984<8383>49.004 G F3(mussym,octa)53.036
+E -.08(ve)-.2 G 115.696(,dyn&othertext&chord,lyrics,pedal as).08 F
+(listed)2 E 578.6 188.5 36 188.5 DL(betweenorder)40 200.5 Q F2 27.984
+<8383>40.852 G F3 159.856(mussym,dyn&othertext&chord,lyrics as)53.036 F
+(listed)2 E 578.6 204.5 36 204.5 DL(bottommar)40 216.5 Q(gin)-.08 E F2
+111.804<8330>38.7 G(.0 to pageheight minus 0.5 inches)-111.804 E
+(0.5 inches)178.512 E 578.6 220.5 36 220.5 DL F3(brace)40 232.5 Q F2
+111.804<8363>68.844 G(omma-separated list of staf)-111.804 E
+(fs or dash-separated ranges)-.2 E 578.6 236.5 36 236.5 DL F3(brack)40
+248.5 Q(et)-.08 E F2 111.804<8363>61.812 G(omma-separated list of staf)
+-111.804 E(fs or dash-separated ranges)-.2 E 578.6 252.5 36 252.5 DL F3
+(cancelk)40 264.5 Q(ey)-.08 E F2 27.984<8383>54.7 G F3(y)53.036 E F2(or)
+2 E F3(n)2 E F2(n)270.728 E 578.6 268.5 36 268.5 DL F3(chorddist)40
+280.5 Q F2 23.052 27.984<83832030>55.5 H(to 50 \(stepsizes\))-25.984 E
+(3)231.848 E 578.6 284.5 36 284.5 DL F3(clef)40 296.5 Q F2 312.892
+27.984<83832074>75.956 H(reble)-27.984 E F3(tr)242.552 296.5 Q(eble,tr)
+-.144 E(eble8)-.144 E F2(,)A F3(8tr)A(eble)-.144 E F2(,)A F3(fr)A
+(enchviolin)-.144 E F2(,)A F3(soprano)A F2(,)A F3(mezzosoprano)A F2(,)A
+F3(alto)A F2(,)A F3(tenor)A F2(,)A F3(baritone)A F2(,)A F3(bass)A 578.6
+300.5 36 300.5 DL(def)40 312.5 Q(oct)-.2 E F2 27.984<8383>67.268 G
+50.308<8330>-.072 G(to 9)-48.308 E(based on clef)271.616 E 578.6 316.5
+36 316.5 DL F3(dist)40 328.5 Q F2 23.052 27.984<83832030>75.5 H
+(to 50 \(stepsizes\))-25.984 E(2)231.848 E 578.6 332.5 36 332.5 DL F3
+(di)40 344.5 Q(vision)-.08 E F2 111.804<834d>61.348 G(IDI di)-111.804 E
+(vision, 1 to 1536 \(ticks per quarter note\))-.2 E(192)134.728 E 578.6
+348.5 36 348.5 DL F3(dyndist)40 360.5 Q F2 23.052 27.984<83832030>62.604
+H(to 50 \(stepsizes\))-25.984 E(2)231.848 E 578.6 364.5 36 364.5 DL F3
+(endingstyle)40 376.5 Q F2<83>49.276 E F3(top)111.804 E F2(,)A F3(barr)2
+E(ed)-.144 E F2 2(,o)C(r)-2 E F3(gr)2 E(ouped)-.144 E F2(top)210.352 E
+578.6 380.5 36 380.5 DL F3(\214rstpage)40 392.5 Q F2 111.804<8331>58.172
+G(to 5000)-109.804 E(1)259.616 E 578.6 396.5 36 396.5 DL F3 -.2(fo)40
+408.5 S(nt).2 E F2 .316 27.984<83832083>74.372 H F3 -.144(ro)-8.048 G(m)
+.144 E F2(,)A F3(bold)2 E F2(,)A F3(ital)2 E F2 2(,o)C(r)-2 E F3
+(boldital)2 E F2(rom)202.64 E 578.6 412.5 36 412.5 DL F3 -.2(fo)40 424.5
+S(ntfamily).2 E F2 .316 27.984<83832083>52.596 H(times)281.792 E F3
+-1.68 -.2(av a)242.552 424.5 T(ntgarde).2 E F2(,)A F3(bookman)2 E F2(,)A
+F3(courier)2 E F2(,)A F3(helv)2 E(etica)-.08 E F2(,)A F3(newcentury)2 E
+F2(,)A F3(palatino)2 E F2 2(,o)C(r)-2 E F3(times)2 E 578.6 428.5 36
+428.5 DL(gridfr)40 440.5 Q(et)-.144 E F2 23.052 27.984<83832032>61.436 H
+(to 99)-25.984 E(4)267.616 E 578.6 444.5 36 444.5 DL F3(gridsatend)40
+456.5 Q F2<83>51.5 E F3(y)111.804 E F2(or)2 E F3(n)2 E F2(n)270.728 E
+578.6 460.5 36 460.5 DL F3(gridswher)40 472.5 Q(eused)-.144 E F2 27.984
+<8383>34.316 G F3(y)53.036 E F2(or)2 E F3(n)2 E F2(n)270.728 E 578.6
+476.5 36 476.5 DL F3(gridscale)40 488.5 Q F2 23.052 27.984<83832030>
+57.284 H(.1 to 10.0)-27.984 E(1.0)255.616 E 578.6 492.5 36 492.5 DL F3
+-.08(ke)40 504.5 S(y).08 E F2 312.892 27.984<83832063>76.028 H(major)
+-25.984 E F4(pitc)242.552 504.5 Q(h)-.12 E F3(major)2 E F2(or)2 E F3
+(minor)2 E F2 2(;o)C 2(r0t)-2 G 2(o7)-2 G F3(#)A F2(or)2 E F3(&)2 E F2
+(and optional)2 E F3(major)2 E F2(or)2 E F3(minor)2 E 578.6 508.5 36
+508.5 DL(label2)40 520.5 Q F2 27.984<8383>67.5 G F3(")53.036 E F4(te)A
+(xt)-.16 E F3(")A F2("")269.568 E 578.6 524.5 36 524.5 DL F3(label)40
+536.5 Q F2 27.984<8383>71.5 G F3(")53.036 E F4(te)A(xt)-.16 E F3(")A F2
+24("")269.568 G 578.6 540.5 36 540.5 DL F3(leftmar)40 552.5 Q(gin)-.08 E
+F2 111.804<8330>52.036 G(.0 to page)-111.804 E(width minus 0.5 inches)
+-.2 E(0.5 inches)180.488 E 578.6 556.5 36 556.5 DL F3(lyricsalign)40
+568.5 Q F2 23.052 27.984<83832030>52.388 H(.0 to 1.0)-27.984 E(0.25)
+259.616 E 578.6 572.5 36 572.5 DL F3(lyricsf)40 584.5 Q(ont)-.2 E F2
+27.984<8383>55.708 G F3 -.144(ro)53.036 G(m).144 E F2(,)A F3(bold)2 E F2
+(,)A F3(ital)2 E F2 2(,o)C(r)-2 E F3(boldital)2 E F2(rom)202.64 E 578.6
+588.5 36 588.5 DL F3(lyricsf)40 600.5 Q(ontfamily)-.2 E F2 312.892
+27.984<83832074>33.932 H(imes)-27.984 E F3 -1.68 -.2(av a)242.552 600.5
+T(ntgarde).2 E F2(,)A F3(bookman)2 E F2(,)A F3(courier)2 E F2(,)A F3
+(helv)2 E(etica)-.08 E F2(,)A F3(newcentury)2 E F2(,)A F3(palatino)2 E
+F2 2(,o)C(r)-2 E F3(times)2 E 578.6 604.5 36 604.5 DL(lyricssize)40
+616.5 Q F2 23.052 27.984<83832031>56.844 H(to 100 \(points\))-25.984 E
+(12)236.728 E 578.6 620.5 36 620.5 DL F3(measnum)40 632.5 Q F2<83>55.06
+E F3(y)111.804 E F2(or)2 E F3(n)2 E F2(n)270.728 E 578.6 636.5 36 636.5
+DL F3(measnumf)40 648.5 Q(ont)-.2 E F2<83>41.484 E F3 -.144(ro)111.804 G
+(m).144 E F2(,)A F3(bold)2 E F2(,)A F3(ital)2 E F2 2(,o)C(r)-2 E F3
+(boldital)2 E F2(rom)202.64 E 578.6 652.5 36 652.5 DL F3(measnumf)40
+664.5 Q(ontfamily)-.2 E F2 401.644<8374>19.708 G(imes)-401.644 E F3
+-1.68 -.2(av a)242.552 664.5 T(ntgarde).2 E F2(,)A F3(bookman)2 E F2(,)A
+F3(courier)2 E F2(,)A F3(helv)2 E(etica)-.08 E F2(,)A F3(newcentury)2 E
+F2(,)A F3(palatino)2 E F2 2(,o)C(r)-2 E F3(times)2 E 578.6 668.5 36
+668.5 DL(measnumsize)40 680.5 Q F2 111.804<8331>42.62 G
+(to 100 \(points\))-109.804 E(11)236.728 E 578.6 684.5 36 684.5 DL 578.6
+74.5 578.6 684.5 DL 36 74.5 36 684.5 DL 526.392 74.5 526.392 684.5 DL
+236.552 74.5 236.552 684.5 DL 205.88 74.5 205.88 684.5 DL 175.808 74.5
+175.808 684.5 DL 144.456 74.5 144.456 684.5 DL 114.24 74.5 114.24 684.5
+DL EP
+%%Page: 5 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 9/Times-Roman@0 SF 2.25(-5-)262.503 47 S .32 LW 545.656 65 36 65 DL
+/F1 8/Times-Roman@0 SF -.12(Pa)48.472 77 S 20.164(rameter Score).12 F
+(Staf)14.816 E 18.888(fV)-.2 G 13.228(oice Hd/Ft)-19.92 F -.888(Va)
+119.356 G(lid V).888 E 124.936(alues Def)-.888 F(ault)-.08 E 545.656 81
+36 81 DL 545.656 83 36 83 DL/F2 8/Times-Bold@0 SF(noteheads)40 95 Q F1
+-8.6 30.8<8383832073>36.432 H(tring containing 1 or 7 headshape names)
+-30.8 E("norm")131.576 E 545.656 99 36 99 DL F2(numbermr)40 111 Q(pt)
+-.08 E F1 30.8<8383>26.296 G F2(y)57.8 E F1(or)2 E F2(n)2 E F1(y)244.888
+E 545.656 115 36 115 DL F2(ontheline)40 127 Q F1 30.8<838383>39.096 G F2
+(y)24.2 E F1(or)2 E F2(n)2 E F1(y)244.888 E 545.656 131 36 131 DL F2
+(pack)40 143 Q(exp)-.08 E F1 122.2<8330>42.288 G(.0 to 1.0)-122.2 E(0.8)
+233.776 E 545.656 147 36 147 DL F2(packfact)40 159 Q F1 122.2<8330>
+41.328 G(.0 to 10.0)-122.2 E(1.0)229.776 E 545.656 163 36 163 DL F2(pad)
+40 175 Q F1 -8.6 30.8<838383202d>57.76 H(5.0 to 50.0)-30.8 E(0.0)227.112
+E 545.656 179 36 179 DL F2(pageheight)40 191 Q F1 122.2<8332>33.32 G
+(.0 to 24.0 inches or 5.0 to 61.0 cm)-122.2 E(11.0 inches)150.672 E
+545.656 195 36 195 DL F2(pagesize)40 207 Q F1<83>42.216 E F2(letter)
+122.2 E 2(,l)-.736 G(egal, \215sa, hal\215etter)-2 E 2(,a)-.736 G
+(4, a5, a6)-2 E F1(then optional)2 E F2(portrait)2 E F1(or)2 E F2
+(landscape)2 E F1(letter)23.048 E 545.656 211 36 211 DL F2(pagewidth)40
+223 Q F1 122.2<8332>35.096 G(.0 to 24.0 inches or 5.0 to 61.0 cm)-122.2
+E(8.5 inches)150.672 E 545.656 227 36 227 DL F2(panelsper)40 239 Q(page)
+-.08 E F1 122.2<8331>21.4 G(or 2)-120.2 E(1)245.336 E 545.656 243 36 243
+DL F2(pedstyle)40 255 Q F1 30.8<8383>42.656 G F2(line)57.8 E F1(,)A F2
+(pedstar)2 E F1 2(,o)C(r)-2 E F2(alt pedstar)2 E F1(line)172.448 E
+545.656 259 36 259 DL F2(printmultnum)40 271 Q F1 30.8<8383>21.76 G F2
+(y)57.8 E F1(or)2 E F2(n)2 E F1(y)244.888 E 545.656 275 36 275 DL F2
+-.144(re)40 287 S(hstyle).144 E F1 30.8<8383>43.696 G F2(boxed)57.8 E F1
+(,)A F2(cir)2 E(cled)-.144 E F1 2(,o)C(r)-2 E F2(plain)2 E F1(box)
+186.584 E(ed)-.12 E 545.656 291 36 291 DL F2 -.144(re)40 303 S(lease)
+.144 E F1 -8.6 30.8<8383832030>47.256 H(to 500 \(milliseconds\))-28.8 E
+(20)190 E 545.656 307 36 307 DL F2 -.144(re)40 319 S(stcombine).144 E F1
+122.2<8332>29.032 G(to 1000)-120.2 E(not set)233.776 E 545.656 323 36
+323 DL F2 -.144(re)40 335 S(stsymmult).144 E F1 30.8<8383>28.144 G F2(y)
+57.8 E F1(or)2 E F2(n)2 E F1(n)244.888 E 545.656 339 36 339 DL F2
+(rightmar)40 351 Q(gin)-.08 E F1 122.2<8330>28.96 G(.0 to page)-122.2 E
+(width minus 0.5 inches)-.2 E(0.5 inches)154.648 E 545.656 355 36 355 DL
+F2(scale)40 367 Q F1 122.2<8330>54.216 G(.1 to 10.0)-122.2 E(1.0)229.776
+E 545.656 371 36 371 DL F2(scor)40 383 Q(epad)-.144 E F1<83>40.136 E/F3
+8/Times-Italic@0 SF(num)122.2 E F1 2(,o)C(r)-2 E F3(num)2 E F2(,)A F3
+(num)A F1 2(,n)C -1.8 -.12(eg a)-2 H(ti).12 E .24 -.12(ve p)-.2 H
+(ageheight to pageheight \(stepsizes\)).12 E(2,2)59.184 E 545.656 387 36
+387 DL F2(scor)40 399 Q(esep)-.144 E F1<83>41.92 E F3(num)122.2 E F1 2
+(,o)C(r)-2 E F3(num)2 E F2(,)A F3(num)A F1 2(,6t)C 2(op)-2 G
+(ageheight \(stepsizes\))-2 E(12,20)118.912 E 545.656 403 36 403 DL F2
+(size)40 415 Q F1 .8 30.8<83832083>58.216 H 2(1t)-9.4 G 2(o1)-2 G
+235.776(00 12)-2 F 545.656 419 36 419 DL F2(staf\215ines)40 431 Q F1
+30.8<8383>40.432 G F2(1)57.8 E F1(,)A F2(1n)2 E F1(,)A F2(5)2 E F1(,)A
+F2(5n)2 E F1(,)A F2 2(5d)2 G(rum)-2 E F1(,)A F2 2(1d)2 G(rum)-2 E F1 2
+(,o)C(r)-2 E F2(tab \()2 E F3(tab_strings)A F2(\))A F1(5)101.768 E
+545.656 435 36 435 DL F2(staffpad)40 447 Q F1 25 30.8<8383206e>42.656 H
+-1.8 -.12(eg a)-30.8 H(ti).12 E .24 -.12(ve p)-.2 H
+(ageheight to pageheight \(stepsizes\)).12 E(0)119.176 E 545.656 451 36
+451 DL F2(staffs)40 463 Q F1 122.2<8331>52.44 G(to 40)-120.2 E(1)241.776
+E 545.656 467 36 467 DL F2(staffscale)40 479 Q F1 25 30.8<83832030>
+39.112 H(.1 to 10.0)-30.8 E(1.0)229.776 E 545.656 483 36 483 DL F2
+(staffsep)40 495 Q F1 25 30.8<83832036>44.44 H
+(to pageheight \(stepsizes\))-28.8 E(10)178.904 E 545.656 499 36 499 DL
+F2(stemlen)40 511 Q F1 -8.6 30.8<8383832030>44.44 H
+(.0 to 100.0 \(stepsizes\))-30.8 E(7.0)190.008 E 545.656 515 36 515 DL
+F2(stemshorten)40 527 Q F1 -8.6 30.8<8383832030>28.888 H
+(.0 to 2.0 \(stepsizes\))-30.8 E(1.0)198.008 E 545.656 531 36 531 DL F2
+(swingunit)40 543 Q F1 -8.6 30.8<8383832074>37.312 H(ime v)-30.8 E
+(alue or nothing)-.2 E(nothing)195.536 E 545.656 547 36 547 DL F2
+(sylposition)40 559 Q F1 25 30.8<8383202d>34.2 H(100 to 100 \(points\))
+-30.8 E(-5)200.224 E 545.656 563 36 563 DL F2(tabwhitebox)40 575 Q F1
+30.8<838383>28.432 G F2(y)24.2 E F1(or)2 E F2(n)2 E F1(n)244.888 E
+545.656 579 36 579 DL F2(time)40 591 Q F1<83>55.552 E F2(common)122.2 E
+F1(,)A F2(cut)2 E F1(or)2 E F3(N)2 E F2(/)A F3(D)A F1(where)2 E F3(N)2 E
+F1(is 1 to 99 and)2 E F3(D)2 E F1(is)2 E F2(1)2 E F1(,)A F2(2)2 E F1(,)A
+F2(4)2 E F1(,)A F2(8)2 E F1(,)A F2(16)2 E F1(,)A F2(32)2 E F1 2(,o)C(r)
+-2 E F2(64)2 E F1(4/4)32.24 E 545.656 595 36 595 DL F2(timeunit)40 607 Q
+F1 30.8<838383>41.768 G F3(time_value)24.2 E F1(\(can include dots\))2 E
+F3(D)169.576 E F1(of time sig)2 E 545.656 611 36 611 DL F2(topmar)40 623
+Q(gin)-.08 E F1 122.2<8330>34.736 G(.0 to pageheight minus 0.5 inches)
+-122.2 E(0.5 inches)152.672 E 545.656 627 36 627 DL F2(transpose)40 639
+Q F1 30.8<8383>37.768 G F2(up)57.8 E F1(or)2 E F2(do)2 E(wn)-.08 E F1 2
+(,f)C(ollo)-2 E(wed by)-.2 E F3(interval)2 E F1(and)2 E F3(num)2 E F1
+(up perfect 1)127.392 E 545.656 643 36 643 DL F2(units)40 655 Q F1<83>
+53.76 E F2(inches)122.2 E F1(or)2 E F2(cm)2 E F1(inches)221.784 E
+545.656 659 36 659 DL F2(visible)40 671 Q F1 30.8<838383>48.872 G F2(y)
+24.2 E F1(,)A F2(n)2 E F1 2(,o)C(r)-2 E F2(wher)2 E(eused)-.144 E F1(y)
+202.592 E 545.656 675 36 675 DL F2(vcombine)40 687 Q F1 25 30.8
+<8383206c>37.768 H(ist of staf)-30.8 E(fs, plus optional)-.2 E F2(noo)2
+E -.08(ve)-.08 G(rlap).08 E F1(,)A F2(shar)2 E(eone)-.144 E F1 2(,o)C(r)
+-2 E F2 -.08(ove)2 G(rlap).08 E F1 2(,o)C 2(rn)-2 G 32.888
+(othing nothing)-2 F 545.656 691 36 691 DL F2(vscheme)40 703 Q F1 30.8
+<8383>41.776 G F2(1)57.8 E F1(,)A F2(2o)2 E F1(,)A F2(2f)2 E F1(,)A F2
+(3o)2 E F1 2(,o)C(r)-2 E F2(3f)2 E F1(1)206.008 E 545.656 707 36 707 DL
+F2(war)40 719 Q(n)-.12 E F1<83>53 E F2(y)122.2 E F1(or)2 E F2(n)2 E F1
+(y)244.888 E 545.656 723 36 723 DL 545.656 65 545.656 723 DL 36 65 36
+723 DL 493.656 65 493.656 723 DL 229.656 65 229.656 723 DL 196.056 65
+196.056 723 DL 162.456 65 162.456 723 DL 128.856 65 128.856 723 DL
+95.256 65 95.256 723 DL EP
+%%Page: 6 6
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 9/Times-Roman@0 SF 2.25(-6-)262.503 47 S/F1 8/Times-Roman@0 SF
+(Music symbols can be used in te)36 61 Q(xt strings by using)-.12 E/F2 8
+/Times-Bold@0 SF(\\\()2 E/F3 8/Times-Italic@0 SF(symbol_name)A F2(\))A
+F1 2(.P)C(re\214x with)-2 E F2(sm)2 E F1(for smaller v)2 E(ersion.)-.12
+E 70 157 443 443 -589 589 14.4 663 PBEGIN
+%%BeginDocument: muschar.ps
+%%BoundingBox: 70 157 513 746
+/boxheight 62 def
+/boxwidth 40 def
+/nameheight 10 def
+/tmpstring 50 string def
+/flagsep 1.6 300 mul def
+
+/Times-Roman findfont nameheight 2 sub scalefont setfont
+/prm {
+       /yoff exch def
+       /xoff exch def
+       /sym exch def
+       /name sym tmpstring cvs def
+       /realboxheight boxheight extra add def
+
+       save
+       xoff yoff translate
+
+       % draw box
+       newpath
+       0 0 moveto
+       boxwidth 0 lineto
+       boxwidth realboxheight lineto
+       0 realboxheight lineto
+       closepath
+       stroke
+
+       % print name of music character
+       gsave
+       nameheight 4 sub
+       realboxheight name stringwidth pop sub 2 div 4 add moveto
+       55 rotate
+       0 0.25 0.75 setrgbcolor
+       name show
+       grestore
+       % display the music character
+       boxwidth 2 div nameheight add
+       realboxheight nameheight sub 2 div
+       1.0 sym cvx exec
+       restore
+} def
+
+/offset 72 def
+/col 0 def
+/row 11 def
+/extra 0 def
+/extraoffset 0 def
+
+% go to next display slot on the page and show one music character
+/showone {
+       col boxwidth mul offset add row boxheight mul
+               extra sub extraoffset sub prm
+       /col col 1 add def
+       % go to next column when current one is full
+       col 11 ge { /col 0 def /row row 1 sub def } if
+       % one row has to be extra tall
+       row 5 eq { /extra 28 def } if
+       row 4 eq { /extraoffset 28 def /extra 0 def } if
+} def
+
+/gclef  showone
+/fclef  showone
+/cclef  showone
+/dblwhole  showone
+/1n  showone
+/2n  showone
+/4n  showone
+/upflag  showone
+/dnflag  showone
+/qwhrest  showone
+/dwhrest  showone
+/1rest  showone
+/2rest  showone
+/4rest  showone
+/8rest  showone
+/16rest  showone
+/32rest  showone
+/64rest  showone
+/128rest  showone
+/256rest  showone
+/ll1rest  showone
+/ll2rest  showone
+/dot  showone
+/nat  showone
+/sharp  showone
+/flat  showone
+/dblsharp  showone
+/dblflat  showone
+/xnote  showone
+/dwhdiamond  showone
+/diamond  showone
+/filldiamond  showone
+/up2n  showone
+/dn2n  showone
+/up4n  showone
+/dn4n  showone
+/com  showone
+/cut  showone
+/begped  showone
+/pedal  showone
+/endped  showone
+/dnbow  showone
+/upbow  showone
+/wedge  showone
+/uwedge  showone
+/ferm  showone
+/uferm  showone
+/sign  showone
+/coda  showone
+/mor  showone
+/invmor  showone
+/turn  showone
+/invturn  showone
+/acc_gt  showone
+/acc_hat  showone
+/acc_uhat  showone
+/tr  showone
+/leg  showone
+/rr  showone
+/dim  showone
+/halfdim  showone
+/triangle  showone
+/measrpt  showone
+/copyright  showone
+/up8n  showone
+/dn8n  showone
+/up16n  showone
+/dn16n  showone
+/up32n  showone
+/dn32n  showone
+/up64n  showone
+/dn64n  showone
+/up128n  showone
+/dn128n  showone
+/up256n  showone
+/dn256n  showone
+/dwhrighttriangle  showone
+/righttriangle  showone
+/fillrighttriangle  showone
+/udwhrighttriangle  showone
+/urighttriangle  showone
+/ufillrighttriangle  showone
+/dwhrectangle  showone
+/rectangle  showone
+/fillrectangle  showone
+/dwhisostriangle  showone
+/isostriangle  showone
+/fillisostriangle  showone
+/dwhpiewedge  showone
+/piewedge  showone
+/fillpiewedge  showone
+/dwhsemicircle  showone
+/semicircle  showone
+/fillsemicircle  showone
+/dwhslashhead  showone
+/slashhead  showone
+/fillslashhead  showone
+/blankhead  showone
+showpage
+%%EndDocument
+end PEND 9 90 115 115 -669 669 471.8 734 PBEGIN
+%%BeginDocument: extlist.ps
+%%BoundingBox: 9 90 124 759
+makeExtEncoding
+/Ext-Times-Roman /Times-Roman makeExtendedFont
+/do1char {
+       15 y moveto
+       /Ext-Times-Roman findfont 7 scalefont setfont
+       show
+       /Times-Roman findfont 7 scalefont setfont
+       50 y moveto
+       show
+       110 y moveto
+       show
+       /y y 7 sub def
+} def
+save
+1.000000 1.000000 scale
+newpath
+10 91 moveto
+10 758 lineto
+123 758 lineto
+123 91 lineto
+closepath
+stroke
+/y 748 def
+( ) (exclamdown) ( ) do1char
+( ) (questiondown) (.) do1char
+( ) (sterling) (") do1char
+( ) (yen) (#) do1char
+(\301\301) (quotedblleft) ($) do1char
+(\302\302) (quotedblright) (-) do1char
+(<<) (guillemotleft) (%) do1char
+(>>) (guillemotright) (&) do1char
+( ) (guilsinglleft) (') do1char
+( ) (guilsinglright) (\() do1char
+( ) (dagger) (\)) do1char
+( ) (daggerdbl) (*) do1char
+( ) (grave) (/) do1char
+( ) (acute) (0) do1char
+( ) (macron) (1) do1char
+( ) (breve) (2) do1char
+( ) (dotaccent) (3) do1char
+( ) (dieresis) (4) do1char
+( ) (ring) (5) do1char
+( ) (cedilla) (6) do1char
+( ) (hungarumlaut) (7) do1char
+( ) (ogonek) (8) do1char
+( ) (caron) (9) do1char
+( ) (emdash) (:) do1char
+(  ) (space) (\177) do1char
+( ) (AE) (;) do1char
+( ) (ae) (<) do1char
+( ) (ordfeminine) (=) do1char
+( ) (ordmasculine) (>) do1char
+(L/) (Lslash) (?) do1char
+(l/) (lslash) (@) do1char
+(O/) (Oslash) (A) do1char
+(o/) (oslash) (B) do1char
+( ) (OE) (C) do1char
+( ) (oe) (D) do1char
+( ) (dotlessi) (E) do1char
+(ss) (germandbls) (F) do1char
+(A') (Aacute) (G) do1char
+(a') (aacute) (H) do1char
+(A^) (Acircumflex) (I) do1char
+(a^) (acircumflex) (J) do1char
+(A:) (Adieresis) (K) do1char
+(a:) (adieresis) (L) do1char
+(A`) (Agrave) (M) do1char
+(a`) (agrave) (N) do1char
+(Ao) (Aring) (O) do1char
+(ao) (oring) (P) do1char
+(A~) (Atilde) (Q) do1char
+(a~) (atilde) (R) do1char
+(C,) (Ccedilla) (S) do1char
+(c,) (ccedilla) (T) do1char
+(E') (Eacute) (U) do1char
+(e') (eacute) (V) do1char
+(E^) (Ecircumflex) (W) do1char
+(e^) (ecircumflex) (X) do1char
+(E:) (Edieresis) (Y) do1char
+(e:) (edieresis) (Z) do1char
+(E`) (Egrave) ([) do1char
+(e`) (egrave) (\\) do1char
+(I') (Iacute) (]) do1char
+(i') (iacute) (^) do1char
+(I^) (Icircumflex) (_) do1char
+(i^) (icircumflex) (`) do1char
+(I:) (Idieresis) (a) do1char
+(i:) (idieresis) (b) do1char
+(I`) (Igrave) (c) do1char
+(i`) (igrave) (d) do1char
+(N~) (Ntilde) (e) do1char
+(n~) (ntilde) (f) do1char
+(O') (Oacute) (g) do1char
+(o') (oacute) (h) do1char
+(O^) (Ocircumflex) (i) do1char
+(o^) (ocircumflex) (j) do1char
+(O:) (Odieresis) (k) do1char
+(o:) (odieresis) (l) do1char
+(O`) (Ograve) (m) do1char
+(o`) (ograve) (n) do1char
+(O~) (Otilde) (o) do1char
+(o~) (otilde) (p) do1char
+(Sv) (Scaron) (q) do1char
+(sv) (scaron) (r) do1char
+(U') (Uacute) (s) do1char
+(u') (uacute) (t) do1char
+(U^) (Ucircumflex) (u) do1char
+(u^) (ucircumflex) (v) do1char
+(U:) (Udieresis) (w) do1char
+(u:) (udieresis) (x) do1char
+(U`) (Ugrave) (y) do1char
+(u`) (ugrave) (z) do1char
+(Y:) (Ydieresis) ({) do1char
+(y:) (ydieresis) (|) do1char
+(Zv) (Zcaron) (}) do1char
+(zv) (zcaron) (~) do1char
+( ) (bullet) (+) do1char
+showpage
+restore
+%%Pages: 1
+%%EndDocument
+end PEND/F4 9/NewCenturySchlbk-BoldItalic@0 SF -2.502(Ar kkr)266.832
+688.5 R 2.583(aE)-.099 G(nter)-2.583 E(pr)-.153 E(ises)-.126 E/F5 9
+/NewCenturySchlbk-Roman@0 SF -1.125(P.)285.201 701.5 S .666 -.333(O. B)
+1.125 H(ox 315).333 E -.675(Wa)249.885 714.5 S(rrenville).675 E 2.502
+(,I)-.162 G 2.502(L6)-2.502 G 10.008(0555 USA)-2.502 F(http://www)
+263.785 727.5 Q(.arkkra.com)-1.125 E(support@arkkra.com)268.249 740.5 Q
+EP
+%%Trailer
+end
+%%EOF
diff --git a/mup/docs/overview.txt b/mup/docs/overview.txt
new file mode 100644 (file)
index 0000000..e05762e
--- /dev/null
@@ -0,0 +1,143 @@
+
+                               MUP Overview
+
+       1.  OVERVIEW OF THE MUP MUSIC PUBLICATION PROGRAM
+
+       Mup is a shareware program for printing music. It takes an
+       input file containing ordinary (ASCII) text describing
+       music, and produces PostScript output for printing the
+       musical score described by the input.  Arkkra Enterprises
+       was established to make Mup readily available at low cost to
+       anyone who would like to use Mup.
+
+       A Mup input file can contains several kinds of sections or
+       contexts.  The description of musical notes is given in the
+       "music" context.  There are contexts for defining page
+       headers and footers.  There are also several contexts used
+       for setting various parameters.  For example, there is a
+       "score" context in which global aspects are listed, such as
+       the number of staffs, the time signature, page margins, etc.
+       It is also possible to set parameters for individual staffs
+       and even individual voices. (Each staff can have up to three
+       independent voices.)  Any parameter that can be set for an
+       individual voice can also be set for a staff, and any
+       parameter that can be set for a staff can be set for the
+       score as a whole. The actual value used for a given
+       parameter is obtained by searching from the most specific
+       (i.e., voice), to the most general (i.e., score) until a
+       value is found. All values are given a default at the score
+       level, so that everything will always resolve to some value.
+       Parameters include items such as:
+
+          - Number of staffs
+
+          - Number of voices per staff
+
+          - Time signature
+
+          - Key signature
+
+          - Clef
+
+          - Transposition amount
+
+          - Whether to use beams or flags on notes of 8th note
+            duration or shorter
+
+          - Margins
+
+          - Which staffs to group with braces or brackets, and what
+            labels to use
+
+          - How tightly to pack output together, both horizontally
+            and vertically.
+
+          - Whether to print measure numbers
+
+       Mup can handle up to 40 parallel staffs. Each staff can have
+       a different key signature, clef, and transposition value.
+       Staffs can be 5-line, 1-line, or tablature (1 to 9 lines).
+       It is possible to print a subset of staffs or voices.
+       Guitar grids are supported.
+
+       Music data is organized into measures. Each measure consists
+       of data for one or more voices followed by a bar line.  Data
+       for each voice consists of one or more chords. Each chord
+       consists of a time value and one or more notes, and possibly
+       additional items associated with the chord. To minimize
+       input, an omitted time value defaults to being the same as
+       the previous time value, and if the notes are omitted, the
+       notes of the previous chord are used.  There are also two
+       special kinds of "notes": rests and space.  Time values from
+       double whole through 256th are supported, as well as
+       tuplets, and any number of dots.  Notes are specified by a
+       letter 'a' to 'g', which may be followed by an accidental
+       (#, &, x, &&, or n for sharp, flat, double sharp, double
+       flat, and natural respectively), and an optional octave. The
+       octave can be an absolute number 0 to 9 or one or more + or
+       - signs to indicate one or more octaves above or below the
+       default octave.  It is also possible to specify that octave
+       marks are to be printed.
+
+       Individual notes or entire chords can be tied or slurred to
+       notes in the following chord.  Slides, bends, and phrase
+       marks can also be specified.  Mup takes care of all details
+       of drawing appropriate curves and splitting the curves
+       across scores or pages if necessary.
+
+       Grace notes can be specified before any chord. It is also
+       possible to specify that notes are to be printed in "cue"
+       (small) size rather than regular size, or that "X" or
+       diamond shaped notes are to be used.  Shaped note used in
+       "Sacred Harp" music are also supported.
+
+       Each measure ends with a bar line. There are several types
+       of bars: an ordinary bar, a double bar, a heavy bar to end
+       the song, and bars with repeat signs.  There is also an
+       "invisible bar" which allows for organizing the input into
+       bars without having the bar lines printed on the output.
+
+       First and subsequent endings can be specified at bar lines.
+       Rehearsal marks can be requested at any bar line.
+
+       Macros can be defined to minimize input or improve
+       readability.  There is a generalized  "if" clause that lets
+       you produce different outputs based on macro values.  It is
+       also possible to "include" one file in another.
+
+       Lyrics can be specified for zero or more verses, above,
+       below or between staffs. You can control the font and size
+       used for the lyrics.
+
+       Music symbols or words can be placed relative to staffs and
+       notes.  This may include musical marks such as fermatas and
+       accents, as well as words to indicate tempo or dynamics,
+       etc.
+
+       Since both the input and output of Mup are ASCII text files,
+       it is easy to write programs to do various transformations.
+       For example, a program could be written to move voices from
+       one staff to another, or any sort of PostScript filter
+       program could be used on the output.
+
+       Mup will optionally provide output in standard Musical
+       Instrument Digital Interface (MIDI) format, for performance
+       rather than PostScript output for printing.
+
+       While Mup itself bucks the trend of graphical, mouse-driven
+       input, it has proven to be a very useful and powerful method
+       of capturing the complexities of musical notation, and there
+       is a companion program, called Mupmate, that provides a
+       graphical interface on top of Mup for those who are more
+       comfortable with that kind of interface. The use of ordinary
+       text input and PostScript output make it largely device
+       independent. Mup was designed and written by people who are
+       both musicians and computer programmers.  The result is a
+       program that provides the capability to produce full-
+       featured, very high quality musical scores with a minimum of
+       effort. It is available ready-to-run for selected computer
+       operating systems, and source code is also available so that
+       it can be run on most platforms that have a C compiler.  You
+       can get a copy of Mup to try out with no obligation, and if
+       you like it, the registration fee is far lower than the
+       price of most music publication software.
diff --git a/mup/docs/register.txt b/mup/docs/register.txt
new file mode 100644 (file)
index 0000000..a7773aa
--- /dev/null
@@ -0,0 +1,28 @@
+Mup is SHAREWARE.  You can try out a copy for free, but if you decide
+to keep and use it, you must register by filling out the form below
+and sending the form and cash, check, or money order to:
+                Arkkra Enterprises
+                P. O. Box 315
+                Warrenville, IL  60555    USA
+
+Name______________________________________________________________
+
+Address___________________________________________________________
+
+City_____________________________ State/Province__________________
+
+Zip code/Postal code_____________________ Country_________________
+
+Email address (please print clearly)______________________________
+
+How did you find out about Mup?___________________________________
+
+__________________________________________________________________
+
+___Linux  ___ Windows/MS-DOS  ___Mac  ___Other____________________
+
+Would you like to join the Mup users mailing list? ___ Yes  ___ No
+
+___ Mup Version 5.3 Registrations.........................$29 each
+                       (Illinois residents, add $2.18 sales tax)
+(For credit card payment, see http://www.arkkra.com/doc/credtcrd.html)
diff --git a/mup/docs/sample.mup b/mup/docs/sample.mup
new file mode 100644 (file)
index 0000000..e568452
--- /dev/null
@@ -0,0 +1,576 @@
+
+
+//**********************************************************************
+// NOTE:
+//
+// This is a sample Mup input file. This file is intended to demonstrate
+// lots of the features of Mup, including advanced features.
+// In most cases, you'll probably only need to use a few basic features,
+// so your input file will usually be a lot simpler.
+//
+//**********************************************************************
+
+
+// header to go on first page
+header
+       title (18) "Sample Song to Show What Mup Can Do"
+       title palatino ital (12) "This is a subtitle"
+       title "Text: Ann Onymous"  "Tune: Arthur Unknown"
+       title ""  "(1995)"
+
+// header for subsequent pages
+header2
+       title "Sample Songs" "This is the title" "page \% of \#"
+
+// footer for first page
+footer
+       // use a printing command other than "title" to show how others work
+       center nl "This is a sample of a Mup footer"
+       // leave a blank line
+       title (12) " "
+
+       title (11) "Published by Arkkra Enterprises" \
+               "P. O. Box 315 Warrenville, IL 60555" \
+               "http://www.arkkra.com"
+
+// footer for subsequent pages
+footer2
+       print nl "This is a sample remark at the bottom of the page"
+
+// top/top2/bottom/bottom2 are like header/header2/footer/footer2 except
+// they can be changed later; for example, you could use header/header2 for
+// the whole song, but have a new top/top2 for each section of the song.
+
+// to be printed right below the header on this page (the first page)
+top
+       title (13) "First Movement"
+// to be printed right below the header2 on later pages
+top2
+       title "First movement"
+
+// set some score-wide parameters
+score
+       staffs = 9
+       key = c minor
+       time = 9/8
+
+       // beam things a dotted quarter at a time, and beam across rests
+       // have the main beams group together notes a dotted quarter at a
+       // time, but have subgroupings an 8th note at a time; also, beam
+       // across rests
+       beamstyle = (8,8,8), (8,8,8), (8,8,8) r
+
+       // put bracket to left of top 2 staffs, and bottom 2, with labels
+       bracket = 1-2 ("Choir", "Ch"), 7-8 ("Guitar", "Gtr")
+
+       // put brace on keyboard's staffs
+       brace = 5-6 ("keyboard", "Kbd")
+
+       // bar the staffs 5 and 6 together, and 7 and 8 together
+       barstyle = 5-6, 7-8
+
+       // put rehearsal marks in circles, instead of the default rectangles
+       rehstyle = circled
+
+       // make a little smaller than normal
+       scale = 0.77
+
+       // pack notes together
+       packexp = 0.7
+       packfact = 0.75
+
+       // set the margins, allowing choice depending on whether -DBIGMARGINS
+       // is used on the command line or not
+       ifdef BIGMARGINS
+               topmargin = 1.0
+               bottommargin = 1.1
+               leftmargin = 1
+               rightmargin = 1
+       else
+               topmargin = 0.8
+               bottommargin = 0.8
+               leftmargin = 0.7
+               rightmargin = 0.6
+       endif
+
+       // make sure chord marks are a ways away from staffs
+       chorddist = 4
+
+       // make sure other things are a ways away too
+       dist = 3
+
+       // spread scores and staffs apart more than normal
+       scoresep = 14, 24
+       scorepad = 5
+       staffsep = 14
+       staffpad = 2
+
+       // label endings above staffs that are grouped by brace or bracket
+       endingstyle = grouped
+
+       // use palatino fonts by default, in 14 point
+       fontfamily = palatino
+       font = rom
+       size = 14
+
+       // put lyrics in helvetica italics, 11 point
+       lyricsfontfamily = helvetica
+       lyricsfont = ital
+       lyricssize = 11
+
+       // print measure numbers at the beginning of each score
+       // in Helvetica italics
+       measnumfontfamily = helvetica
+       measnumfont = ital
+       measnumsize = 9
+       measnum = y
+
+       // When there are chords, print guitar grids with them.  To put them
+       // at the end of the song we would use gridsatend.  If we wanted
+       // to make them bigger or smaller, we could set "gridscale".
+       gridswhereused = y
+
+       // If the lowest fret used is 3 or more, use "N fr" notation instead
+       // of showing the whole guitar neck up to that point in the grid.
+       // The default value of this is 4, and it can be turned off.
+       gridfret = 3
+
+
+//set some things for particular staffs
+staff 2
+       clef = bass
+
+staff 3
+       label = "foghorn\nin G\(smflat)"
+       staffscale = 0.8        // make this staff a little smaller
+       clef = baritone
+       transpose = down dim 5
+       // make staff 3 visible only when there is something on it
+       visible = whereused
+
+       // set different default octave
+       defoct = 4
+
+staff 4
+       // make staff 4 a 1-line staff, with a "drum clef"
+       stafflines = 1 drum
+
+staff 5
+       // Use three voices on staff 5.  Allow the stems of the top and bottom
+       // voices (1 and 2) to float to whichever way is appropriate.  (We
+       // could use 2o to force their stems to be in opposite directions.)
+       // Voice 3 is an extra voice, typically in the middle, whose stems can
+       // go either way.
+       vscheme = 3f
+
+staff 6
+       clef = bass
+
+       // use dotted quarter for default time unit instead of
+       // the normal time signature denominator
+       timeunit = 4.
+
+staff 7
+       vscheme = 2f
+
+staff 8
+       // Make staff 8 a tablature staff for standard guitar.  This
+       // automatically makes the preceding staff (7) a "tabnote" staff,
+       // meaning its notes will be derived from staff 8 automatically,
+       // unless overriden.
+       stafflines = tab
+
+       // make fret numbers more readable by putting a white background there
+       tabwhitebox = y
+
+       vscheme = 2f    // allow two voices on this tab staff
+
+staff 9
+       // On staff 9, use "shaped notes".  Each scale degree uses a different
+       // shape of note head.
+       label = "Soprano"
+       noteheads = "isostri semicirc diam righttri norm rect pie"
+
+// define a macro to allow saying "DRUM" instead of "4:" for the 4th staff
+define DRUM 4:  @
+
+grids
+       // define grids to be printed with guitar chords
+       "Cm"    "- (3 5 5 4 3)"
+       "G:9 7" "3 x o o o 5"
+       "Go7"   "o 1 2 o 2 o"
+       "G"     "3 x o o o 3"
+
+// now do musical data
+music
+
+// put a tempo mark above staffs 1 and 6, and set MIDI tempo to 92
+// quarter notes per minute
+       rom above 1,6 : 1 "Andante";
+       midi all: 0 "tempo = 92";
+// set the instruments to use for MIDI
+       midi 1-2: 0 "channel=5"; 0 "program=52"; 0 "onvelocity=92";
+       midi 3: 0 "channel=6"; 0 "program=109"; 0 "onvelocity=61";
+       midi 4: 0 "channel=10";         // percussion channel
+// set onvelocity to accent the top note
+       midi 5-6: 0 "channel=11"; 0 "program=1"; 0 "onvelocity=104,88";
+       midi 5 2: 0 "channel=11";
+       midi 7: 0 "channel=14"; 0 "program=25"; 0 "onvelocity=83";
+
+// Note that lines of input within a given measure can be entered in any order.
+// It is usually a good idea to enter music data a staff at a time from top
+// to bottom, just to make it easy to keep track of, although Mup makes no
+// such requirement. You may choose to intersperse other things like lyrics
+// and phrase marks, or do them all at once before or after the music data,
+// or in whatever order you choose. 
+
+// Also note that you can indent things any way you want in your Mup
+// input file, and can put extra blank spaces almost anywhere
+// except in the middle of a word.
+
+// For MIDI purposes, the first two measures get played an extra time
+// before the Coda, so put them inside a macro.
+define FIRST2MEASURES
+
+// staff 1, three dotted quarter notes, second chord same as the first
+       1 1: 4.ceg;;dfb;
+
+// staff 2, dotted quarter, two eighths with a rest between, dotted quarter
+       2: 4.c;8c;r;e;4.f;
+
+// phrase on staff 2 from beginning note to first count of next measure
+       phrase 2: 1 til 1m+1;
+
+// two verses of lyrics between top two staffs
+// use "|" to align the first syllables 8 points left of the notes' centers
+       lyrics between 1&2: 4.;;; "-8|These are the"; "-8|This is verse";
+
+// a grace note and an accent on staff 3
+       3: [grace; slash 1]c#; [with >] 2.f#;4.r;
+
+// measure rest for staff 4
+       DRUM mr;
+
+// staff 5, voice 1, begins with duplet, also has a tied note
+       5 1:  {4c+;g;}2,4.; 4.c+;4f+~;16;;
+
+// second voice for staff 5
+       5 2: 2.c;4.d;
+
+// third voice for staff 5 starts with a "space", nothing printed; force
+// horizontal offsets (ho) on two of the notes to fine tune their spacing
+       5 3: 4.s; [ho 3.5]8e;f;g; [ho 3]an; 4;
+
+// staff 6, some notes an octave or two away from the default octave
+       6: 4.c-c--;;d-d--;
+
+// put piano pedal mark at the bottom
+       pedal below 6: 1;6;
+
+// show the fret numbers on guitar strings on the tablature staff
+       8: 4. a3d1g0; 8 a3; e'3; a3; 4. d0g2b3e1;
+
+// Print music theory analysis symbols at counts 1 and 7.  The ":" makes the
+// following space-separated items be stacked on top of each other.
+       rom analysis above 5: 1 "i"; 7 "VII:6 #5";
+
+// print figured bass numbers below count 7; the slash goes through the "5"
+       rom figbass below 6: 7 "6 5/";
+
+       9: 4.c+; 8e+; c+; e+; 4.f+;
+       lyrics 9: 2.+4.; "ah_";
+
+// ordinary bar line, with a reherasal letter
+       bar reh let
+
+
+
+// next measure
+       1: 2.c+gc;4.r;
+       2: 2.ce;4.r;
+
+// lyrics with an underscore
+       // This time, since the time values of the lyrics match those
+       // of the music, we'll let Mup derive the time values,
+       // rather than specifying them.  Notice that we are chanting multiple
+       // syllables on the last word, so we show that they are to be treated
+       // as one syllable by separating them by a special \(space) character
+       // instead of simple space.
+       lyrics between 1&2: [1] "words!_"; [2] "two\(space)oh\(space)yes.";
+
+// include a note with a double flat
+       3: 2.f&&;4.r;
+
+// you can specify a pitch for a 1-line staff, even though all notes will be
+// placed on the line. The pitch will be used for MIDI output, if you use
+// the -m option to Mup to get a MIDI file instead of printed output.
+       DRUM 4.f&;2.r;
+
+// because of the beamstyle setting, the 16th notes here are joined in pairs
+// by both beams, but only one beam joins all six
+       5 1: 2.c++;4.r;
+       5 2: 8e;g;e; 16g;e;g;e;g;e; 4.r;
+       6: 2.c- alt 2;c;4.r;
+       pedal below 6: 1;6*;
+
+// print 3 tremelo slashes on this chord
+       8: [slash 3] 2. d1g0b1e3; 4.r;
+
+       9: 2.e+; 4.r;
+
+// at count 9.9 (almost the dblbar), back up 19 stepsizes and print this coda
+// indication, including the actual coda symbol; do this in italics of font
+// size 13 (but turn off the italics for the symbol), and above all the staffs
+       ital(13) all: 9.9[-19] "To coda \f(TR)\(coda)";
+
+       // double bar
+       dblbar
+@      // end the macro definition of the first measures
+// Now call the macro for the first measures
+       FIRST2MEASURES
+
+
+
+// start a new score. Normally, Mup will place things
+// as best it can, but you can force things if you like.
+newscore
+
+// now more music data
+music
+
+
+       // set location tags on the two notes, then draw a wavy line between
+       // them saying that it is a glissando
+       1: 2.c =h; 4.g =k;
+               wavy line (h.e+3, h.y) to (k.w-3, k.y) with ital (11) "gliss."
+       2: 4.e; 8..; 32f;8g;4.c;
+
+// a crescendo mark
+       < below 2: 3 til 7.5;
+
+// trill the foghorn from count 1 to 7; put a "turn" symbol above the note
+// at count 8. For MIDI, specify exactly how to play it.
+       ifndef MIDI
+               3: 2..d&; 4d;
+               mussym 3: 1 "tr" til 7; 8 "turn";
+       else
+               3: 16d&;e;d;e;d;e;d;e;d;e;d;e;d;e; {d;e;d;c;d;}5;
+       endif
+
+       4: [slash 2] 2.c; [with .]4.c-;
+       5: 4.ceg;;;
+
+// a dynamic mark
+       times boldital between 5&6: 7 "ff";
+
+// roll up on first chord, down on second, default (up) on third
+       roll up   5: 1;
+       roll down 5: 4;
+       roll      5: 7;
+
+// the <> indicates a slur
+       6: 2.c e?;8e<>;4c;
+
+// For the second note, "bend" the previous note up 1/2 step by stretching
+// the E string.  Then bend to a full step, and release back to normal.
+       8 1: 4.e5; e "1/2"; 8e "full"; 4e "";
+
+// Put some notes in the second tab voice.  These will be translated to the
+// the second voice of the tabnote staff above.
+       8 2: 4.g0; 4; 8; 4.;
+
+       9: 8c+; b; an; g; c; d; 4.e;
+
+// chord symbols will be transposed if the music is transposed.
+// In this particular example, transposition is not in effect
+       bold chord above all: 1 "Cm";
+
+       bar ending "1."
+
+
+
+// two measures of rest
+       multirest 2
+       repeatend ending "2."
+
+
+staff 4
+// From now on, staff 4 (the one-line staff) will have two voices with stems
+// that are always opposing.  Set it so that the notes will not be on the line
+// but rather above and below it.
+       vscheme = 2o
+       ontheline = n
+music
+       midi 4 2: 0 "channel=10";
+
+// Define a macro with parameters for printing a chord name at a given count.
+// Note that the chord name is passed in and then the ` ` cause it to be
+// put in quotes.
+define K(COUNT, NAME) bold chord all: COUNT `NAME`; @
+
+// Define a "map" for chord-at-a-time input.  (By "chord" here we mean a group
+// of notes, not the symbolic chord name as above.)  Since all the voices in
+// the choir have the same rhythm from now on, it's convenient to use this
+// method of input instead of the usual voice-at-a-time method.  Set it up
+// to enter bass and tenor on staff 2, then alto and soprano on staff 1.
+define M [ 2; 2; 1; 1 ] @
+
+
+       K(1,Cm)         // print a C minor chord at count 1
+
+// assign all the notes for staffs 1 and 2, using the map.  Each goes to its
+// proper octave according to defoct.
+       M: 4.cgce; ceeg; cgce;
+
+// Put phrase marks on each staff, from count 1 until count 7 of the next
+// measure.  We didn't specify "above" or "below", so Mup chooses the side.
+       phrase 1,2: 1 til 1m+7;
+
+// Increase the size of the lyrics by 3 points.  This will carry forward to
+// the end of the song unless changed again.  Also, use the non-ASCII
+// character n-tilde, indicated by \(n~).  If you can type non-ASCII characters
+// directly on your keyboard, you can do that instead of using this notation.
+       lyrics between 1&2: "\s(+3)Ma-\(n~)a-na";
+
+// put the last note's accidental in parentheses, since it is just a
+// reminder to the player that this accidental is still in force
+       3: 4.an; b; a(n);
+
+// Use X-shaped notes on the top voice.  Use the "..." to show that this
+// applies for the rest of this measure, not just the first chord.
+       4 1: [xnote]... 4.; ; 8;;;
+       4 2: 4.; ; ;
+
+// Beam notes together across both staffs.  Set a location tag (=h) on the
+// first note, for later use.
+       5: 4.s bm with staff below; ; 8c; e; g ebm;
+       6: 8c- =h bm with staff above; e-; g-; c; e; g; 4.s ebm;
+
+       8: 2. a3 d5 g5 b4 e3; 4. tie;
+
+       // For the last two notes, override the head shape to be a slash, to
+       // indicate repeating the first part of the measure.
+       9: 8g; e; ; [hs "slash"]... 4.b; ;
+       bar endending
+
+
+
+       ital all: 1 "\[A special note, on\ntwo lines, in a box.\]";
+       1: 4.ce; eg; ;
+       lyrics between 1&2: "am gr\(o:)\(ss)t-en,";     // non-ACSII chars
+       2: 4.cg; ce; ;
+
+// draw a measure repeat sign
+       3: mrpt;
+
+       // put a text string in an ellipse
+       ital 4: 1 "\{mute\}";
+       4 1: [xnote]... 4.; ; 8;;;
+       4 2: 2.; 4.;
+
+       6: 8 with e+c++ above; c+ with g+ above; g with e+ above; ec+; g; e; \
+                       4.c =k; // set loc tag "k"
+       8: 4. a3 d5 g5 b4 e3; 2.;
+       9: mrpt;
+       bar
+
+// Draw a curve, with endpoints based on the "=h" and "=k" location tags with
+// vertical offsets of 11 and 8 stepsizes upwards.  The curve bulges upwards
+// 20 and 23 stepsizes 1/3 and 2/3 of the way through it.
+       medium curve (h.x, h.y + 11) to (k.x, k.y + 8) bulge 20, 23;
+
+
+// print the chord G97, with the 9 above the 7
+       K(1,G:9 7)
+
+       ital(15) all: 9.9[-20] "D.C. al Coda";
+
+// use a C double sharp (cx) and B natural
+       1: 4.cxbn; 2.;
+       lyrics between 1&2: "tr\(e`)s bien!";   // another non-ASCII character
+       2: 4.g-f; 2.;
+       4 1: 4.r; c; ;  // the pitch is arbitrary except for MIDI on one-line
+       4 2: 4.; r; ;
+       5: 4.dfgbn; ; dfan;
+
+// force first note stem to point upwards, which would by default have
+// pointed down; change clef in the middle of the measure
+       6: [up] 4.d; c; <<staff clef = treble>> d+;
+
+// The first note is a "prebend" (stretch the string before plucking).  On the
+// last note, do a slide upwards after it that doesn't end at any specific note.
+       8: 4. a10 "full" b8 "full"; 4. a10 "" b8 ""; [grace] 16 e0; 4.e1 <n/>;
+       9: 2.+4.g;
+       lyrics 9: "oo_";
+       dblbar
+
+// For MIDI, insert the D.C. al Coda fragment
+       ifdef MIDI
+               FIRST2MEASURES
+       endif
+
+// leave a gap and start all the staffs anew, showing clefs and key signatures
+       restart
+
+staff 6
+       clef = bass     // change the clef back to bass
+
+music
+// override the "dist" parameter, and specify a minimum distance of 5 stepsizes
+// from the staff for this coda sign
+       mussym(13) all dist 5: 0.5 "coda";
+       ital(15) all: 1 "Coda";
+
+// at count 1 print G diminished 7 (the "o" is translated to a diminished
+// symbol), and at count 7 print G
+       K(1,Go7)
+       K(7,G)
+
+// Another duplet.  If we put "n" after the first number it would prevent the
+// bracket from being printed.
+       1: 2.d&g; { 4gbn; ; }2,4.;
+
+// Draw parentheses around the one D natural.  Force this duplet's bracket to
+// be below; this one would have defaulted to above.
+       2: 2.b&f&; { 4d-n(dn)g; dbn; } below 2,4.;
+
+// Print both keyboard hands on its top staff, using two voices.  Since the
+// top notes are so high, set their stems to extend only 5 stepsizes instead
+// of the usual 7 (octave).  Slur and tie the notes, using dashed or dotted
+// rather than solid curves.
+       5 1: [len 5]... 2.g++b++d&+++f&+++ dashed slur; 4.g++bn++d+++g+++;
+       5 2: 2.gg+ dotted tie; 4.;
+
+// leave staff 6 unspecified, so that it will default to a space
+
+       8: [slash 1] 2. e'0 a1 d2 g0 b2 e0; 4. e'3 d0 g0 b0 e3;
+
+       9: 2.g; 4.bn;
+       lyrics 9: "At the";
+       bar
+
+
+
+score
+// set a time signature that combines two simple time signatures
+       time = 2/4 + 3/8
+
+music
+// use shorthand to enter the same data for two staffs at once
+       1,2:  2egc+ tie; 4.;
+
+       4 1,2: mr;      // measure rest on both voices of staff 4
+       5-6: 2c tie; 4.;
+
+// mark notes an octave lower than normal
+       octave below 6: 1 "8va" til 7.5;
+
+// put a fermata above staffs 1, 2, and 4 to 6
+       mussym above 1,2,4-6: 5 "ferm";
+// for MIDI, slow the tempo, to produce the fermata
+       midi all: 3 "tempo=50";
+       8: 2 e20~; 4.;
+       9: 2+4.c+;
+       lyrics 9: "end.";
+       K(1,Cm)
+       endbar
diff --git a/mup/docs/sample.ps b/mup/docs/sample.ps
new file mode 100644 (file)
index 0000000..b759ada
--- /dev/null
@@ -0,0 +1,6024 @@
+%!PS-Adobe-1.0
+%%Creator: Mup
+%%Title: music:  from /home/johnkr/mup/5.3/doc/arkkra/sample.mup
+%%CreationDate: Sat Dec 9 16:59:22 2006
+%%Pages: (atend)
+%%DocumentFonts: (atend)
+%%BoundingBox: 0 0 612 792
+%%EndComments
+% Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2004 by Arkkra Enterprises
+% All rights reserved
+
+% Mup PostScript Prolog 5.3 for use with Mup 5.3
+
+% lwid is used as the width of a standard (thin) line in the music
+% character definitions.
+/lwid 70 def
+/halflwid lwid 2 div def
+
+% Define the following for use in do_upshortnote, do_dnshortnote, and
+% do_shortrest; it has to be done outside of the music font definition.
+/utildict 10 dict def
+utildict begin
+       /setnumflags    {       /numflags       exch def } def
+       /sethooksm1     {       /hooksm1        exch def } def
+       /setoffsets     {       /offsets        exch def } def
+       /setx           {       /x              exch def } def
+       /sety           {       /y              exch def } def
+end
+
+% Define a music character font.  Each music character is defined as if it
+% were a normal ASCII character in a strange font where "A" looks like a
+% treble clef, "B" looks like a bass clef, etc.
+
+/mfont0 100 dict def
+mfont0 begin
+       /FontType 3 def
+       /FontMatrix [ .001 0 0 0.001 0 0 ] def
+       /FontBBox [ -2000 -4030 2000 4030 ] def
+       /FontName (Mfont0) def
+
+       % set up Encoding vector with standard names
+       /Encoding 256 array def
+       StandardEncoding Encoding copy
+       pop
+
+       % the following definitions are used for quarter rests
+       /topx -170 def /topy 950 def
+       /cor1x 250 def /cor1y 450 def
+       /cor2x -300 def /cor2y 200 def
+       /cor3x 250 def /cor3y -400 def
+
+       % the following definitions are used for double sharps
+       /limit 300 halflwid add def
+       /off 70 def
+       /inbendsmall limit 200 sub def
+       /inbendbig limit 20 sub def
+       /outbendsmall 100 def
+       /outbendbig outbendsmall off add def
+
+       %%%%% define routines that will be used by multiple characters %%%%%
+       /do_1n {
+               gsave
+               newpath -10 rotate 1.6 1 scale
+               0 0 325 0 360 arc               %outer ellipse
+               1 1.6 div 1 scale 10 rotate     %back to original
+               35 rotate 0.85 1.1 scale
+               0 0 275 0 360 arc               %inner ellipse
+               eofill
+               grestore
+       } def
+       /do_upflag {
+               -315 0 moveto
+               -300 100 -100 480 0 600 curveto
+               300 960 350 1500 200 1700 curveto
+               130 1700 lineto
+               350 1200 50 650 -315 600 curveto
+               fill
+       } def
+       /do_flat {
+               -250 -400 moveto        %outer edge of loop
+               500 0 350 650 -250 160 curveto
+               -250 160 lwid sub lineto %inner edge of loop
+               100 400 300 0 -250 -400 lwid add curveto
+               fill
+
+               lwid setlinewidth       %stem
+               -250 1100 moveto -250 -400 lineto stroke
+       } def
+       /do_diamond {
+               newpath
+               420 0 moveto 0 300 lineto -420 0 lineto
+               0 -300 lineto closepath
+               259 -29 moveto -41 185 lineto -259 29 lineto
+               41 -185 lineto closepath
+               eofill
+       } def
+       /do_2n {
+               gsave
+               newpath 25 rotate 1.4 1 scale
+               0 0 315 0 360 arc               %outer ellipse
+               1 1.4 div 1 scale               %back to original
+               1.3 0.5 scale
+               0 0 310 0 360 arc               %inner ellipse
+               eofill
+               grestore
+       } def
+       /do_4n {
+               gsave
+               newpath 25 rotate 1.35 1 scale
+               0 0 310 0 360 arc fill
+               grestore
+       } def
+       /do_com {
+               newpath
+               330 250 150 0 360 arc fill      %knob at upper right
+               465 300 moveto                  %outer boundary
+               410 500 200 635 0 635 curveto
+               -750 635 -750 -635 0 -635 curveto
+               350 -635 480 -300 500 -100 curveto
+               430 -100 lineto                 %inner boundary
+               380 -300 250 -565 0 -565 curveto
+               -450 -565 -450 565 0 565 curveto
+               200 565 370 350 395 300 curveto
+               fill
+       } def
+       /do_ferm {
+               0 0 800 lwid sub 0 180 arc      %inner arc
+               -800 0 lineto
+               0 270 lwid sub 800 180 0 arcn   %outer arc
+               800 0 lineto fill
+               0 120 120 0 360 arc fill        %the dot
+       } def
+       /do_mor {
+               gsave
+               0.7 1 scale     %scrunch the following horizontally
+               45 rotate       %to pretend all lines horz or vertical
+               0 1 1 {
+                       pop     %we don't need the loop variable
+                       %one half of the mordent
+                       0 40 moveto 350 40 lineto 350 -460 lineto
+                       750 -460 lineto 750 -540 lineto
+                       150 -540 lineto 150 -40 lineto
+                       0 -40 lineto fill
+                       180 rotate      %to do the other half
+               } for
+               grestore
+       } def
+       /do_turn {
+               gsave
+               0 1 1 {
+                       pop     %we don't need the loop variable
+                       0 -100 moveto   %outer boundary
+                       200 -400 625 -400 625 0 curveto
+                       625 200 500 325 300 325 curveto
+                       300 185 lineto  %inner boundary
+                       450 255 555 150 555 0 curveto
+                       555 -350 250 -250 0 100 curveto
+                       fill
+                       300 255 70 0 360 arc fill %knob on end
+                       180 rotate      %to do the other half
+               } for
+               grestore
+       } def
+
+       /do_upshortnote {
+               utildict begin
+               setnumflags             %set numflags from the stack
+               gsave
+               -330 0 translate        %half a flag width
+               do_4n                   %do a quarter note head
+               lwid setlinewidth
+               370 0 moveto
+               370 2100 numflags 2 sub flagsep mul add lineto stroke
+               670 2100 numflags 2 sub flagsep mul add translate
+               1 -1 scale              %reflect across X axis
+               0 1 numflags 1 sub {
+                       do_upflag       %do an upflag
+                       pop             %we don't need the loop variable
+                       0 flagsep translate
+               } for
+               grestore
+               end
+       } def
+
+       /do_dnshortnote {
+               utildict begin
+               setnumflags             %set numflags from the stack
+               do_4n                   %do a quarter note head
+               lwid setlinewidth
+               -370 0 moveto
+               -370 -2100 numflags 2 sub flagsep mul sub lineto stroke
+               gsave
+               -70 -2100 numflags 2 sub flagsep mul sub translate
+               0 1 numflags 1 sub {
+                       do_upflag       %do an upflag
+                       pop             %we don't need the loop variable
+                       0 flagsep translate
+               } for
+               grestore
+               end
+       } def
+
+       /do_shortrest {
+               utildict begin
+               sety setx setoffsets sethooksm1 %set variable from the stack
+               gsave
+               -105.8 offsets mul -600 offsets mul translate
+               0 1 hooksm1 {           %loop once per hook
+                       newpath
+                       1 setlinewidth
+                       gsave
+                       1 1.2 scale
+                       -150 300 1.2 div 140 0 360 arc fill     %the dot
+                       grestore
+                       lwid setlinewidth
+                       -50 700 550 255 315 arc         %rest of the hook
+                       hooksm1 lt { stroke 105.8 600 translate } if
+               } for
+               x y lineto stroke
+               grestore
+               end
+       } def
+
+
+       % subsidiary dictionary of character definitions
+       /CharStrings 128 dict def
+       CharStrings begin
+
+               /.notdef {} def
+
+               % Here are the definitions of the characters.  A stepsize here
+               % is 300 units (assuming the character is drawn at its default
+               % size).
+
+               % gclef
+               /A {
+                       newpath
+                       %start with inner curl, inside boundary
+                       -50 -300 moveto
+                       -450 600 700 700 750 0 curveto
+                       750 -800 -700 -800 -700 200 curveto
+                       -700 900 500 1400 520 2250 curveto
+                       520 2900 300 3000 200 3000 curveto
+                       100 3000 -400 2500 -200 1800 curveto
+                       350 -600 lineto
+                       720 -1600 0 -1650 -400 -1400 curveto
+
+                       %go back to start, drawing the other boundary
+                       -400 -1480 lineto
+                       0 -1700 800 -1700 430 -600 curveto
+                       -120 1800 lineto
+                       -300 2400 200 2800 250 2800 curveto
+                       400 2800 430 2700 430 2450 curveto
+                       430 1800 -900 1200 -900 300 curveto
+                       -750 -900 800 -900 850 0 curveto
+                       900 1100 -750 900 -120 -300 curveto fill
+
+                       %circle at the bottom
+                       -300 -1250 250 0 360 arc fill
+               } def
+
+               % fclef
+               /B {
+                       newpath
+                       %start with outside boundary, at bottom
+                       -1000 -1700 moveto
+                       100 -1100 500 -600 450 0 curveto
+                       450 850 -1100 850 -950 0 curveto
+
+                       %go back to start, drawing the other boundary
+                       -880 0 lineto
+                       -920 400 -600 560 -300 560 curveto
+                       0 560 150 400 150 0 curveto
+                       150 -400 100 -900 -1000 -1620 curveto fill
+
+                       %circle at the left
+                       newpath
+                       -700 0 250 0 360 arc fill
+
+                       %do the two dots after the main curve
+                       700 -300 100 0 360 arc fill
+                       700 300 100 0 360 arc fill
+               } def
+
+               % cclef
+               /C {
+                       gsave
+                       %do upper curved part, then scale to do mirror image
+                       0 1 1 {
+                               pop     %we don't need the loop variable
+                               %outer boundary of curve
+                               -170 0 moveto 100 300 lineto
+                               400 -200 750 300 750 650 curveto
+                               750 1100 450 1235 250 1235 curveto
+                               0 1235 -143 1100 -143 950 curveto
+
+                               %inner boundary of curve
+                               0 950 lineto
+                               0 1100 30 1165 250 1165 curveto
+                               300 1165 450 1100 450 650 curveto
+                               450 400 400 -100 100 400 curveto
+                               -270 0 lineto fill
+                               %stroke
+                               %-270 0 moveto 100 400 lineto
+                               %400 -100 450 400 450 650 curveto
+                               %450 1100 300 1165 250 1165 curveto
+                               %30 1165 0 1100 0 950 curveto
+                               %stroke
+
+                               %elliptical ball at end of curve
+                               gsave
+                               1.3 1 scale
+                               10 950 120 0 360 arc fill
+                               grestore
+                               1 -1 scale      %reflect across X axis
+                       } for
+                       grestore
+
+                       % two vertical lines on the left
+                       300 setlinewidth -600 -1200 halflwid sub moveto
+                       -600 1200 halflwid add lineto stroke
+                       lwid setlinewidth -300 -1200 halflwid sub moveto
+                       -300 1200 halflwid add lineto stroke
+               } def
+
+               % dblwhole
+               /D {
+                       do_1n           %do a whole note
+                       lwid setlinewidth
+                       -490 -600 moveto -490 600 lineto stroke
+                       490 -600 moveto 490 600 lineto stroke
+               } def
+
+               % 1n
+               /E {
+                       do_1n           %do a whole note
+               } def
+
+               % 2n
+               /F {
+                       do_2n           %do a half note
+               } def
+
+               % 4n
+               /G {
+                       do_4n           %do a quarter note head
+               } def
+
+               % upflag
+               /H {
+                       do_upflag               %do an upflag
+               } def
+
+               % dnflag
+               /I {
+                       gsave
+                       1 -1 scale      %reflect across X axis
+                       do_upflag               %do an upflag
+                       grestore
+               } def
+
+               % dwhrest
+               /J {
+                       300 setlinewidth
+                       0 0 moveto 0 600 lineto stroke
+               } def
+
+               % 1rest
+               /K {
+                       lwid setlinewidth
+                       -750 600 moveto 750 600 lineto stroke
+                       300 setlinewidth
+                       -400 450 moveto 400 450 lineto stroke
+               } def
+
+               % 2rest
+               /L {
+                       lwid setlinewidth
+                       -750 0 moveto 750 0 lineto stroke
+                       300 setlinewidth
+                       -400 150 moveto 400 150 lineto stroke
+               } def
+
+               % 4rest
+               /M {
+                       newpath
+                       cor3x cor3y halflwid add moveto
+                       %-400 -200 -450 -650 50 -950 lwid add curveto
+                       -450 -50 -450 -650 50 -950 lwid add curveto
+                       -150 -650 -100 -250 cor3x cor3y halflwid sub curveto
+                       fill
+
+                       cor1x cor1y moveto cor1x 200 sub cor1y 200 add lineto
+                       cor2x cor2y lineto cor2x 200 add cor2y 200 sub lineto
+                       fill
+
+                       lwid setlinewidth
+                       topx topy moveto cor1x cor1y lineto stroke
+                       cor2x cor2y moveto cor3x cor3y lineto stroke
+               } def
+
+               % 8rest
+               /N {
+                       0 0 0 -600 do_shortrest
+               } def
+
+               % 16rest
+               /O {
+                       1 1 100 -1200 do_shortrest
+               } def
+
+               % 32rest
+               /P {
+                       2 1 0 -1800 do_shortrest
+               } def
+
+               % 64rest
+               /Q {
+                       3 2 -80 -2100 do_shortrest
+               } def
+
+               % 128rest
+               /R {
+                       4 2 -150 -2700 do_shortrest
+               } def
+
+               % 256rest
+               /S {
+                       5 3 -280 -3300 do_shortrest
+               } def
+
+               % dot
+               /T {
+                       newpath
+                       0 0 120 0 360 arc fill
+               } def
+
+               % nat
+               /U {
+                       % fill crossbars so that we can do parallelograms
+                       -235 -470 moveto -235 -270 lineto
+                       235 -130 lineto 235 -330 lineto fill
+                       -235 130 moveto -235 330 lineto
+                       235 470 lineto 235 270 lineto fill
+
+                       % vertical strokes
+                       lwid setlinewidth
+                       -200 -380 moveto -200 850 lineto stroke
+                       200 -850 moveto 200 380 lineto stroke
+               } def
+
+               % sharp
+               /V {
+                       % fill crossbars so that we can do parallelograms
+                       -325 -480 moveto -325 -280 lineto
+                       325 -120 lineto 325 -320 lineto fill
+                       -325 120 moveto -325 320 lineto
+                       325 480 lineto 325 280 lineto fill
+
+                       % vertical strokes
+                       lwid setlinewidth
+                       -150 -930 moveto -150 880 lineto stroke
+                       150 -880 moveto 150 930 lineto stroke
+               } def
+
+               % flat
+               /W {
+                       do_flat         %do a flat
+               } def
+
+               % dblsharp
+               /X {
+                       gsave
+                       0 1 3 {         %loop once for each of 4 sticks
+                               pop     %we don't need the loop variable
+                               0 off neg moveto
+                               outbendbig outbendsmall lineto
+                               inbendbig inbendsmall lineto
+                               limit limit lineto
+                               inbendsmall inbendbig lineto
+                               outbendsmall outbendbig lineto
+                               off neg 0 lineto
+                               fill
+                               -90 rotate
+                       } for
+                       grestore
+               } def
+
+               % dblflat
+               /Y {
+                       -290 580 290 {  %loop once for each flat
+
+                               gsave
+                               1 setlinewidth
+                               0 translate     %translate left/right (loop var)
+                               do_flat         %do a flat
+                               grestore
+
+                       } for
+               } def
+
+               % xnote
+               /Z {
+                       gsave
+                       1.15 1 scale 120 setlinewidth 1 setlinecap      %round
+                       -300 -300 moveto 300 300 lineto stroke
+                       -300 300 moveto 300 -300 lineto stroke
+                       grestore
+               } def
+
+               % dwhdiamond
+               /a {
+                       do_diamond      %do a diamond
+                       lwid setlinewidth
+                       -420 -600 moveto -420 600 lineto stroke
+                       420 -600 moveto 420 600 lineto stroke
+               } def
+
+               % diamond
+               /b {
+                       do_diamond      %do a diamond
+               } def
+
+               % filldiamond
+               /c {
+                       420 0 moveto 0 300 lineto
+                       -420 0 lineto 0 -300 lineto fill
+               } def
+
+               % up2n
+               /d {
+                       lwid setlinewidth
+                       380 0 moveto 380 2100 lineto stroke
+                       do_2n           %do a half note
+               } def
+
+               % dn2n
+               /e {
+                       lwid setlinewidth
+                       -380 0 moveto -380 -2100 lineto stroke
+                       do_2n           %do a half note
+               } def
+
+               % up4n
+               /f {
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       370 0 moveto 370 2100 lineto stroke
+               } def
+
+               % dn4n
+               /g {
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       -370 0 moveto -370 -2100 lineto stroke
+               } def
+
+               % up8n
+               /h {
+                       gsave
+                       -330 0 translate        % half a flag width
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       370 0 moveto 370 2100 lineto stroke
+                       670 2100 translate
+                       1 -1 scale      %reflect across X axis
+                       do_upflag               %do an upflag
+                       grestore
+               } def
+
+               % dn8n
+               /i {
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       -370 0 moveto -370 -2100 lineto stroke
+                       gsave
+                       -70 -2100 translate
+                       do_upflag               %do an upflag
+                       grestore
+               } def
+
+               % up16n
+               /j {
+                       2 do_upshortnote
+               } def
+
+               % dn16n
+               /k {
+                       2 do_dnshortnote
+               } def
+
+               % up32n
+               /l {
+                       3 do_upshortnote
+               } def
+
+               % dn32n
+               /m {
+                       3 do_dnshortnote
+               } def
+
+               % up64n
+               /n {
+                       4 do_upshortnote
+               } def
+
+               % dn64n
+               /o {
+                       4 do_dnshortnote
+               } def
+
+               % up128n
+               /p {
+                       5 do_upshortnote
+               } def
+
+               % dn128n
+               /q {
+                       5 do_dnshortnote
+               } def
+
+               % up256n
+               /r {
+                       6 do_upshortnote
+               } def
+
+               % dn256n
+               /s {
+                       6 do_dnshortnote
+               } def
+
+               % com
+               /t {
+                       do_com          %do a common time symbol
+               } def
+
+               % cut
+               /u {
+                       do_com          %do a common time symbol
+                       lwid setlinewidth
+                       0 -900 moveto 0 900 lineto stroke
+               } def
+
+               % begped
+               /v {
+                       lwid setlinewidth
+                       -200 600 moveto -200 0 lineto 200 0 lineto stroke
+               } def
+
+               % pedal
+               /w {
+                       lwid setlinewidth
+                       -500 0 moveto -450 0 lineto 0 600 lineto
+                       450 0 lineto 500 0 lineto stroke
+               } def
+
+               % endped
+               /x {
+                       lwid setlinewidth
+                       200 600 moveto 200 0 lineto -200 0 lineto stroke
+               } def
+
+               % dnbow
+               /y {
+                       lwid setlinewidth
+                       -350 0 moveto -350 900 lineto stroke
+                       350 0 moveto 350 900 lineto stroke
+                       200 setlinewidth
+                       -350 800 moveto 350 800 lineto stroke
+               } def
+
+               % upbow
+               /z {
+                       lwid setlinewidth
+                       -300 900 moveto 0 0 lineto 300 900 lineto stroke
+               } def
+
+               % wedge
+               /one {
+                       0 0 moveto -150 500 lineto 150 500 lineto fill
+               } def
+
+               % uwedge
+               /two {
+                       -150 0 moveto 150 0 lineto 0 500 lineto fill
+               } def
+
+               % ferm
+               /three {
+                       newpath
+                       do_ferm         %do a right side up fermata
+               } def
+
+               % uferm
+               /four {
+                       newpath
+                       gsave
+                       0 270 lwid sub 800 add translate %baseline at bottom
+                       180 rotate                      %upside down
+                       do_ferm         %do a right side up fermata
+                       grestore
+               } def
+
+               % sign
+               /five {
+                       gsave
+                       %do upper left curved part, upper right dot;
+                       %then rotate 180 to do other half
+                       0 1 1 {
+                               pop     %we don't need the loop variable
+                               0 100 moveto            %inner boundary
+                               -1000 300 -400 750 -200 700 curveto
+                               -200 800 lineto         %outer boundary
+                               -550 900 -1100 100 0 -100 curveto
+                               fill
+                               %dot at end of curve
+                               -200 700 100 0 360 arc fill
+                               %dot in upper right quadrant
+                               500 200 70 0 360 arc fill
+                               180 rotate
+                       } for
+                       grestore
+
+                       %slash through middle
+                       lwid setlinewidth
+                       -400 -800 moveto 400 800 lineto stroke
+               } def
+
+               % coda
+               /six {
+                       newpath
+                       gsave
+                       0.6 1 scale
+                       0 0 550 0 360 arc       %outside boundary
+                       1 0.6 div 1 scale       %back to original
+                       0.9 1 scale
+                       0 0 650 0 360 arc       %inside boundary
+                       eofill
+                       grestore
+                       lwid setlinewidth
+                       0 -850 moveto 0 850 lineto stroke
+                       -800 0 moveto 800 0 lineto stroke
+               } def
+
+               % mor
+               /seven {
+                       do_mor          %do a mordent
+               } def
+
+               % invmor
+               /eight {
+                       do_mor          %do a mordent
+                       lwid setlinewidth
+                       0 -450 moveto 0 450 lineto stroke
+               } def
+
+               % turn
+               /nine {
+                       do_turn         %do a turn
+               } def
+
+               % invturn
+               /zero {
+                       gsave
+                       1 -1 scale      %reflect across X axis
+                       do_turn         %do a turn
+                       grestore
+               } def
+
+               % acc_gt
+               /numbersign {
+                       lwid setlinewidth
+                       -500 300 moveto 500 0 lineto -500 -300 lineto stroke
+               } def
+
+               % acc_hat
+               /dollar {
+                       newpath
+                       -365 0 moveto 0 860 lineto 365 0 lineto
+                       150 0 lineto -75 530 lineto -300 0 lineto fill
+               } def
+
+               % acc_uhat
+               /quotedbl {
+                       newpath
+                       365 860 moveto 0 0 lineto -365 860 lineto
+                       -150 860 lineto 75 330 lineto 300 860 lineto fill
+               } def
+
+               % tr
+               /asterisk {
+                       %vertical bar of t
+                       -350 1000 moveto -550 200 lineto
+                       -612.5 -50 -212.5 -50 -160 200 curveto
+                       -230 200 lineto
+                       -300 50 -420 50 -400 200 curveto
+                       -200 1000 lineto fill
+
+                       %crossbar of t and vertical bar of r
+                       -700 600 moveto -160 600 lineto
+                       20 600 30 520 60 440 curveto
+                       -50 0 lineto 70 0 lineto 180 440 lineto
+                       190 480 100 670 -150 670 curveto
+                       -690 670 lineto fill
+
+                       %horizontal curve of r
+                       100 480 moveto
+                       300 630 450 700 650 550 curveto
+                       560 480 lineto
+                       450 630 300 560 100 390 curveto
+                       fill
+
+                       %knob at end of r
+                       600 460 100 0 360 arc fill
+               } def
+
+               % leg
+               /comma {
+                       100 setlinewidth
+                       -400 0 moveto 400 0 lineto stroke
+               } def
+
+               % rr
+               /hyphen {
+                       100 setlinewidth
+                       -400 0 moveto 0 1000 lineto stroke
+                       0 0 moveto 400 1000 lineto stroke
+               } def
+
+               % measrpt
+               /period {
+                       newpath -450 400 150 0 360 arc fill
+                       newpath 450 -400 150 0 360 arc fill
+                       200 setlinewidth
+                       -550 -600 moveto 550 600 lineto stroke
+               } def
+
+               % copyright
+               /slash {
+                       lwid setlinewidth
+                       newpath 0 400 400 0 360 arc stroke
+                       newpath 0 400 200 45 315 arc stroke
+               } def
+
+               % dim
+               /quoteleft {
+                       50 setlinewidth
+                       newpath 0 640 220 0 360 arc stroke
+               } def
+
+               % halfdim
+               /quoteright {
+                       50 setlinewidth
+                       newpath 0 640 220 0 360 arc stroke
+                       newpath -340 300 moveto 340 980 lineto stroke
+               } def
+
+               % triangle
+               /asciicircum {
+                       50 setlinewidth
+                       newpath -340 -10 moveto 0 710 lineto
+                       340 -10 lineto closepath stroke
+               } def
+
+               % qwhrest
+               /ampersand {
+                       300 setlinewidth
+                       0 -600 moveto 0 600 lineto stroke
+               } def
+
+               % ll1rest
+               /exclam {
+                       310 setlinewidth
+                       -400 455 moveto 400 450 lineto stroke
+               } def
+
+               % ll2rest
+               /at {
+                       310 setlinewidth
+                       -400 145 moveto 400 150 lineto stroke
+               } def
+       end
+
+       /BuildChar {
+
+               exch begin
+               Encoding exch get
+
+               dup
+               Mcbbox0 exch get
+               aload pop setcachedevice
+
+               CharStrings exch get
+               exec
+               end
+       } def
+end
+
+
+% Define another music character font, since there are too many to fit in one
+% font.  It works the same way as the first one.
+
+/mfont1 100 dict def
+mfont1 begin
+       /FontType 3 def
+       /FontMatrix [ .001 0 0 0.001 0 0 ] def
+       /FontBBox [ -2000 -4030 2000 4030 ] def
+       /FontName (Mfont1) def
+
+       % set up Encoding vector with standard names
+       /Encoding 256 array def
+       StandardEncoding Encoding copy
+       pop
+
+       %%%%% define routines that will be used by multiple characters %%%%%
+
+       /do_dwh_bars {
+               % the two bars surrounding a double whole note
+               lwid setlinewidth
+               -420 -600 moveto -420 600 lineto stroke
+               420 -600 moveto 420 600 lineto stroke
+       } def
+       /do_righttriangle {
+               newpath
+               420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto
+               350 150 moveto -140 150 lineto 350 -213 lineto
+               eofill
+       } def
+       /do_fillrighttriangle {
+               newpath
+               420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto
+               fill
+       } def
+       /do_rectangle {
+               newpath
+               420 270 moveto -420 270 lineto -420 -270 lineto 420 -270 lineto
+               350 150 moveto -350 150 lineto -350 -150 lineto 350 -150 lineto
+               eofill
+       } def
+       /do_isostriangle {
+               newpath
+               0 300 moveto -420 -270 lineto 420 -270 lineto
+               0 182 moveto -245 -150 lineto 245 -150 lineto
+               eofill
+       } def
+       /do_piewedge {
+               newpath
+               0 -300 moveto 0 -244 514 35 145 arc
+               0 -209 moveto 0 -244 394 43 137 arc
+               eofill
+       } def
+       /do_semicircle {
+               newpath
+               gsave
+               1 1.357 scale 420 199 moveto 0 199 420 180 360 arc
+               1 1.09 scale 350 111 moveto 0 199 350 194.1 345.9 arc
+               eofill
+               grestore
+       } def
+       /do_slashhead {
+               newpath
+               lwid setlinewidth
+               -620 -530 moveto -480 -670 lineto 620 530 lineto 480 670 lineto
+               closepath stroke
+       } def
+
+       % subsidiary dictionary of character definitions
+       /CharStrings 128 dict def
+       CharStrings begin
+
+               /.notdef {} def
+
+               % Here are the definitions of the characters.  A stepsize here
+               % is 300 units (assuming the character is drawn at its default
+               % size).
+
+               % dwhrighttriangle
+               /A {
+                       do_righttriangle
+                       do_dwh_bars
+               } def
+
+               % righttriangle
+               /B {
+                       do_righttriangle
+               } def
+
+               % fillrighttriangle
+               /C {
+                       newpath
+                       420 270 moveto -420 270 lineto 350 -300 lineto
+                       420 -300 lineto
+                       fill
+               } def
+
+               % udwhrighttriangle
+               /D {
+                       gsave
+                       180 rotate
+                       do_righttriangle
+                       do_dwh_bars
+                       grestore
+               } def
+
+               % urighttriangle
+               /E {
+                       gsave
+                       180 rotate
+                       do_righttriangle
+                       grestore
+               } def
+
+               % ufillrighttriangle
+               /F {
+                       gsave
+                       180 rotate
+                       do_fillrighttriangle
+                       grestore
+               } def
+
+               % dwhrectangle
+               /G {
+                       do_rectangle
+                       do_dwh_bars
+               } def
+
+               % rectangle
+               /H {
+                       do_rectangle
+               } def
+
+               % fillrectangle
+               /I {
+                       newpath
+                       420 270 moveto -420 270 lineto -420 -270 lineto
+                       420 -270 lineto
+                       fill
+               } def
+
+               % dwhisostriangle
+               /J {
+                       do_isostriangle
+                       do_dwh_bars
+               } def
+
+               % isostriangle
+               /K {
+                       do_isostriangle
+               } def
+
+               % fillisostriangle
+               /L {
+                       newpath
+                       0 300 moveto -420 -270 lineto 420 -270 lineto
+                       fill
+               } def
+
+               % dwhpiewedge
+               /M {
+                       do_piewedge
+                       do_dwh_bars
+               } def
+
+               % piewedge
+               /N {
+                       do_piewedge
+               } def
+
+               % fillpiewedge
+               /O {
+                       newpath
+                       0 -300 moveto 0 -244 514 35 145 arc
+                       fill
+               } def
+
+               % dwhsemicircle
+               /P {
+                       do_semicircle
+                       do_dwh_bars
+               } def
+
+               % semicircle
+               /Q {
+                       do_semicircle
+               } def
+
+               % fillsemicircle
+               /R {
+                       newpath
+                       gsave
+                       1 570 420 div scale
+                       420 199 moveto 0 199 420 180 360 arc
+                       fill
+                       grestore
+               } def
+
+               % dwhslashhead
+               /S {
+                       do_slashhead
+                       lwid setlinewidth
+                       -650 -600 moveto -650 600 lineto stroke
+                       650 -600 moveto 650 600 lineto stroke
+               } def
+
+               % slashhead
+               /T {
+                       do_slashhead
+               } def
+
+               % fillslashhead
+               /U {
+                       newpath
+                       200 setlinewidth
+                       -550 -600 moveto 550 600 lineto stroke
+               } def
+
+               % blankhead
+               /V {
+                       %print nothing
+               } def
+       end
+
+       /BuildChar {
+
+               exch begin
+               Encoding exch get
+
+               dup
+               Mcbbox1 exch get
+               aload pop setcachedevice
+
+               CharStrings exch get
+               exec
+               end
+       } def
+end
+
+
+% General routines for printing any music character, invoked by each music
+% character's specific routine below.  The scaling factor (default 1) needs
+% to be multiplied by 10 to get the actual size.  These routines restore the
+% preexisting current font when they are done.
+
+/printmchar0 {
+       gsave
+       /musicchar exch def
+       /Mfont0 findfont exch 10 mul scalefont setfont moveto 
+       musicchar show
+       grestore
+} def
+/printmchar1 {
+       gsave
+       /musicchar exch def
+       /Mfont1 findfont exch 10 mul scalefont setfont moveto 
+       musicchar show
+       grestore
+} def
+
+% Define each music character name to be a routine that prints the character.
+% Each character is to be invoked as in this example:
+%      100 200 1 gclef         % at (100, 200), scale to default size & print
+
+/gclef                 { (A) printmchar0 } def
+/fclef                 { (B) printmchar0 } def
+/cclef                 { (C) printmchar0 } def
+/dblwhole              { (D) printmchar0 } def
+/1n                    { (E) printmchar0 } def
+/2n                    { (F) printmchar0 } def
+/4n                    { (G) printmchar0 } def
+/upflag                        { (H) printmchar0 } def
+/dnflag                        { (I) printmchar0 } def
+/dwhrest               { (J) printmchar0 } def
+/1rest                 { (K) printmchar0 } def
+/2rest                 { (L) printmchar0 } def
+/4rest                 { (M) printmchar0 } def
+/8rest                 { (N) printmchar0 } def
+/16rest                        { (O) printmchar0 } def
+/32rest                        { (P) printmchar0 } def
+/64rest                        { (Q) printmchar0 } def
+/128rest               { (R) printmchar0 } def
+/256rest               { (S) printmchar0 } def
+/dot                   { (T) printmchar0 } def
+/nat                   { (U) printmchar0 } def
+/sharp                 { (V) printmchar0 } def
+/flat                  { (W) printmchar0 } def
+/dblsharp              { (X) printmchar0 } def
+/dblflat               { (Y) printmchar0 } def
+/xnote                 { (Z) printmchar0 } def
+/dwhdiamond            { (a) printmchar0 } def
+/diamond               { (b) printmchar0 } def
+/filldiamond           { (c) printmchar0 } def
+/up2n                  { (d) printmchar0 } def
+/dn2n                  { (e) printmchar0 } def
+/up4n                  { (f) printmchar0 } def
+/dn4n                  { (g) printmchar0 } def
+/up8n                  { (h) printmchar0 } def
+/dn8n                  { (i) printmchar0 } def
+/up16n                 { (j) printmchar0 } def
+/dn16n                 { (k) printmchar0 } def
+/up32n                 { (l) printmchar0 } def
+/dn32n                 { (m) printmchar0 } def
+/up64n                 { (n) printmchar0 } def
+/dn64n                 { (o) printmchar0 } def
+/up128n                        { (p) printmchar0 } def
+/dn128n                        { (q) printmchar0 } def
+/up256n                        { (r) printmchar0 } def
+/dn256n                        { (s) printmchar0 } def
+/com                   { (t) printmchar0 } def
+/cut                   { (u) printmchar0 } def
+/begped                        { (v) printmchar0 } def
+/pedal                 { (w) printmchar0 } def
+/endped                        { (x) printmchar0 } def
+/dnbow                 { (y) printmchar0 } def
+/upbow                 { (z) printmchar0 } def
+/wedge                 { (1) printmchar0 } def
+/uwedge                        { (2) printmchar0 } def
+/ferm                  { (3) printmchar0 } def
+/uferm                 { (4) printmchar0 } def
+/sign                  { (5) printmchar0 } def
+/coda                  { (6) printmchar0 } def
+/mor                   { (7) printmchar0 } def
+/invmor                        { (8) printmchar0 } def
+/turn                  { (9) printmchar0 } def
+/invturn               { (0) printmchar0 } def
+/acc_gt                        { (#) printmchar0 } def
+/acc_hat               { ($) printmchar0 } def
+/acc_uhat              { (") printmchar0 } def
+/tr                    { (*) printmchar0 } def
+/leg                   { (,) printmchar0 } def
+/rr                    { (-) printmchar0 } def
+/measrpt               { (.) printmchar0 } def
+/copyright             { (/) printmchar0 } def
+/dim                   { (`) printmchar0 } def
+/halfdim               { (') printmchar0 } def
+/triangle              { (^) printmchar0 } def
+/qwhrest               { (&) printmchar0 } def
+/ll1rest               { (!) printmchar0 } def
+/ll2rest               { (@) printmchar0 } def
+/dwhrighttriangle      { (A) printmchar1 } def
+/righttriangle         { (B) printmchar1 } def
+/fillrighttriangle     { (C) printmchar1 } def
+/udwhrighttriangle     { (D) printmchar1 } def
+/urighttriangle                { (E) printmchar1 } def
+/ufillrighttriangle    { (F) printmchar1 } def
+/dwhrectangle          { (G) printmchar1 } def
+/rectangle             { (H) printmchar1 } def
+/fillrectangle         { (I) printmchar1 } def
+/dwhisostriangle       { (J) printmchar1 } def
+/isostriangle          { (K) printmchar1 } def
+/fillisostriangle      { (L) printmchar1 } def
+/dwhpiewedge           { (M) printmchar1 } def
+/piewedge              { (N) printmchar1 } def
+/fillpiewedge          { (O) printmchar1 } def
+/dwhsemicircle         { (P) printmchar1 } def
+/semicircle            { (Q) printmchar1 } def
+/fillsemicircle                { (R) printmchar1 } def
+/dwhslashhead          { (S) printmchar1 } def
+/slashhead             { (T) printmchar1 } def
+/fillslashhead         { (U) printmchar1 } def
+/blankhead             { (V) printmchar1 } def
+
+
+% Define routines for Mup output other than music characters.
+
+/stepsize 3 def           % define a step size as 3 points (at default magnification)
+
+% x1 y1 x2 lines dist staffscale staff
+%              draw a staff starting at x1, y1 and extending to x2 with "lines"
+%              lines, 2*dist*stepsize apart, scaled by staffscale
+/staff {
+       /staffscale exch def
+       /dist exch def
+       /lines exch def
+       /x2 exch def
+       /y1 exch def
+       /x1 exch def
+       0.7 staffscale mul sb setlinewidth
+       1 lines sub  2  lines 1 sub {   % loop from bottom line to top line
+               dup stepsize mul staffscale mul dist mul y1 add x1 exch moveto
+               stepsize mul staffscale mul dist mul y1 add x2 exch lineto stroke
+       } for
+} def
+
+% x y1 y2 bracket      draw a bracket; y1 is the top
+/bracket {
+       /y2 exch def
+       /y1 exch def
+       /x exch def
+       gsave
+       3 setlinewidth
+       x 2 sub y1 1 add moveto
+       x 2 sub y2 1 sub lineto
+       stroke
+       x 2 sub y1 1 add moveto
+       x 1 sub y1 1 add   x 3 add y1 1 add   x 5 add y1 6 add   curveto
+       x 6 add y1 5 add lineto
+       x 5 add y1 2 add   x 1 add y1 2 sub   x 2 sub y1 2 sub   curveto
+       fill
+       x 2 sub y2 1 sub moveto
+       x 1 sub y2 1 sub   x 3 add y2 1 sub   x 5 add y2 6 sub   curveto
+       x 6 add y2 5 sub lineto
+       x 5 add y2 2 sub   x 1 add y2 2 add   x 2 sub y2 2 add   curveto
+       fill
+       grestore
+} def
+
+% x y1 y2 brace                draw a brace; y1 is the top
+/brace {
+       /y2 exch def
+       /y1 exch def
+       /x exch def
+       gsave
+       x 9 sub y1 y2 add 2 div translate
+       /topy y1 y2 sub 2 div 1 sub def
+       0 1 1 {
+               pop
+               %0 topy moveto 0 0 lineto stroke
+               0 0 moveto
+               16 topy 0.2 mul   -11 topy 0.6 mul   8 topy   curveto
+               8.7 topy lineto
+               -7 topy 0.7 mul   20 topy 0.3 mul   1 0   curveto
+               fill
+               1 -1 scale      % flip to do bottom half
+       } for
+       grestore
+} def
+
+% endx endy wavy staffscale    draw a wavy line from current point to here,
+%                              scaled by staffscale
+/wavy {
+       /staffscale exch def
+       /endy exch def          % define the end point of the line
+       /endx exch def
+       currentpoint            % line starts at current point
+       /begy exch def          % define the beginning point of the line
+       /begx exch def
+       gsave
+       /dx endx begx sub def   % find delta x and delta y
+       /dy endy begy sub def
+       /r dx dx mul dy dy mul add sqrt def     % hypotenuse
+       /theta dy dx atan def                   % angle with positive x axis
+       begx begy translate     % change axes so that we can draw the line
+       theta rotate            %   from (0, 0) to (r, 0)
+       staffscale staffscale scale     % scale everything by staffscale
+       /scaledr r staffscale div def   % but scale r in reverse to keep length
+
+       % Each outer loop draws one cycle of the squiggle.  It continues until
+       % we are at or beyond the desired end point.
+       0 0 moveto
+       0 6 scaledr {
+               gsave
+               % first loop draws left half of squiggle; second draws right
+               0 1 1 {
+                       0.0 0.4 moveto
+                       2.0 1.9 3.4 2.3 3.9 0.0 curveto
+                       2.1 0.0 lineto
+                       1.9 0.8 1.4 0.7 0.0 -0.4 curveto
+                       fill
+                       pop 180 rotate -6 0 translate
+               } for
+               grestore
+
+               pop 6 0 translate       % shift axes right one squiggle
+       } for
+
+       grestore
+} def
+
+% x y space frets fretno numvert curvel curver [ f1 f2 f3 ... ] grid
+%                              print a guitar grid diagram
+/grid {
+       /grid_positions exch def % 0="o", -1="x", -2=nothing, positive=dot
+       /curver exch def        % right string for curve, 0 if none
+       /curvel exch def        % left string for curve, 0 if none
+       /numvert exch def       % vertical position to print fretno, 0 if none
+       /fretno exch def        % fret no. to print at right, 0 if none
+       /frets exch def         % number of fret lines
+       /space exch def         % points between two neighboring lines
+       /y exch def             % y coord of top fret line
+       /x exch def             % x coord of left strings
+
+       gsave
+       /strings grid_positions length def      % number of strings
+       /lmarky 0.4 space mul y add def         % lowest Y of a "o" or "x"
+       space 10 div setlinewidth
+       2 setlinecap
+
+       % draw the lines of the grid
+       0  1  strings 1 sub {   % loop from left string to right string
+               dup space mul x add y moveto
+               space mul x add frets 1 sub space mul y exch sub lineto stroke
+       } for
+       0  -1  1 frets sub {    % loop from top fret (nut) to bottom fret
+               dup space mul y add x exch moveto
+               space mul y add strings 1 sub space mul x add exch lineto stroke
+       } for
+
+       % draw the curved line if there is one
+       curvel 0 gt {
+               % within strings curvel to curver, find smallest positive fret
+               /minfret 1000 def
+               curvel 1 curver {
+                       /strno exch def
+                       /grid_p grid_positions strno 1 sub get def
+                       grid_p 0 gt grid_p minfret lt and {
+                               /minfret grid_p def
+                       } if
+               } for
+
+               % if curve goes above top fret, other marks must be higher
+               minfret 1 eq {
+                       /hmarky 1.2 space mul y add def
+               } {
+                       /hmarky lmarky def
+               } ifelse
+
+               /strdiff curver curvel sub def
+               space 8 div setlinewidth
+
+               % set endpoint coords of curve; higher if curve is short
+               /curvex1 curvel 1 sub space mul x add def
+               /curvex2 curver 1 sub space mul x add def
+               /curvey 1 minfret sub space mul y add def
+               strdiff 3 lt {
+                       /curvey 0.2 strdiff div space mul curvey add def
+               } if
+
+               % move to left end, set other points, draw curve
+               curvex1 curvey moveto
+
+               curvex1 curvex2 curvex1 sub 3 div add
+               curvey space 0.4 strdiff sqrt mul mul add
+
+               curvex2 curvex2 curvex1 sub 3 div sub
+               curvey space 0.4 strdiff sqrt mul mul add
+
+               curvex2 curvey curveto stroke
+       } if
+
+       space 10 div setlinewidth
+
+       % draw dots and x and o marks
+       0  1  strings 1 sub {   % loop from left string to right string
+               /strno exch def % first string is 0
+               /grid_p grid_positions strno get def
+               /strx strno space mul x add def
+
+               % set Y of mark higher if curved line covers this string
+               strno 1 add curvel ge  strno 1 add curver le  and {
+                       /marky hmarky def
+               } {
+                       /marky lmarky def
+               } ifelse
+
+               grid_p -1 eq {          % draw an X above the string
+                       /xhwid space 3 div def
+                       strx xhwid sub marky xhwid sub moveto
+                       strx xhwid add marky xhwid add lineto stroke
+                       strx xhwid sub marky xhwid add moveto
+                       strx xhwid add marky xhwid sub lineto stroke
+               } if
+               grid_p 0 eq {           % draw a circle above the string
+                       strx marky space 0.3 mul 0 360 arc stroke
+               } if
+               grid_p 1 ge {           % draw a dot by the proper fret
+                       strx y grid_p space mul sub space 3 div add
+                       space 3 div 0 360 arc fill
+               } if
+       } for
+
+       % print "X fr" if requested
+       fretno 0 gt {
+               /Palatino-Roman findfont space 1.9 mul scalefont setfont
+               x strings 0.5 sub space mul add
+               y space numvert 0.3 add mul sub moveto
+               fretno 2 string cvs show ( fr) show
+       } if
+       grestore
+} def
+
+% x1 y1 x2 y2 whitebox         draw a white rectangle with opposite
+%                              corners of (x1,y1) and (x2,y2)
+/whitebox {
+       /y2 exch def
+       /x2 exch def
+       /y1 exch def
+       /x1 exch def
+       1.0 setgray
+       newpath
+       x1 y1 moveto
+       x1 y2 lineto
+       x2 y2 lineto
+       x2 y1 lineto
+       closepath
+       fill
+       stroke
+       0.0 setgray
+} def
+
+
+/LineNum 0 def
+/InputFile (unknown) def
+
+% n linenum
+/linenum {
+       /LineNum exch def
+} def
+
+% (inputfilename) inputfile
+/inputfile {
+       /InputFile exch def
+} def
+
+% find size of Encoding and make a dictionary
+% that size for bounding box information
+mfont0 begin
+/dictsize Encoding length def
+mfont0 /Mcbbox0 dictsize dict put
+
+% temporarily redefine printmchar0 to get code
+5 dict begin
+/printmchar0 { {} forall } def
+
+Mcbbox0 Encoding 128rest get [ 1140.0 0 -515.0 -1515.0 615.0 1685.0 ] put
+Mcbbox0 Encoding 16rest get [ 830.0 0 -415.0 -1215.0 405.0 485.0 ] put
+Mcbbox0 Encoding 1n get [ 1080.0 0 -535.0 -335.0 535.0 345.0 ] put
+Mcbbox0 Encoding 1rest get [ 1540.0 0 -765.0 -5.0 765.0 645.0 ] put
+Mcbbox0 Encoding 256rest get [ 1250.0 0 -625.0 -2115.0 615.0 1685.0 ] put
+Mcbbox0 Encoding 2n get [ 880.0 0 -435.0 -345.0 435.0 355.0 ] put
+Mcbbox0 Encoding 2rest get [ 1540.0 0 -765.0 -45.0 765.0 315.0 ] put
+Mcbbox0 Encoding 32rest get [ 940.0 0 -415.0 -1215.0 515.0 1085.0 ] put
+Mcbbox0 Encoding 4n get [ 840.0 0 -415.0 -335.0 415.0 345.0 ] put
+Mcbbox0 Encoding 4rest get [ 650.0 0 -345.0 -885.0 295.0 985.0 ] put
+Mcbbox0 Encoding 64rest get [ 1040.0 0 -515.0 -1515.0 515.0 1085.0 ] put
+Mcbbox0 Encoding 8rest get [ 750.0 0 -305.0 -615.0 435.0 485.0 ] put
+Mcbbox0 Encoding acc_gt get [ 1170.0 0 -525.0 -335.0 635.0 345.0 ] put
+Mcbbox0 Encoding acc_hat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put
+Mcbbox0 Encoding acc_uhat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put
+Mcbbox0 Encoding begped get [ 470.0 0 -245.0 -45.0 215.0 615.0 ] put
+Mcbbox0 Encoding cclef get [ 1540.0 0 -765.0 -1245.0 765.0 1255.0 ] put
+Mcbbox0 Encoding coda get [ 1640.0 0 -815.0 -855.0 815.0 865.0 ] put
+Mcbbox0 Encoding com get [ 1100.0 0 -575.0 -635.0 515.0 655.0 ] put
+Mcbbox0 Encoding copyright get [ 920.0 0 -455.0 -45.0 455.0 855.0 ] put
+Mcbbox0 Encoding cut get [ 1100.0 0 -575.0 -905.0 515.0 915.0 ] put
+Mcbbox0 Encoding dblflat get [ 1170.0 0 -595.0 -405.0 565.0 1115.0 ] put
+Mcbbox0 Encoding dblsharp get [ 720.0 0 -355.0 -345.0 355.0 355.0 ] put
+Mcbbox0 Encoding dblwhole get [ 1090.0 0 -535.0 -605.0 545.0 615.0 ] put
+Mcbbox0 Encoding diamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put
+Mcbbox0 Encoding dim get [ 540.0 0 -265.0 -5.0 265.0 905.0 ] put
+Mcbbox0 Encoding dn128n get [ 840.0 0 -415.0 -3545.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn16n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn256n get [ 840.0 0 -415.0 -3965.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn2n get [ 880.0 0 -435.0 -2105.0 435.0 355.0 ] put
+Mcbbox0 Encoding dn32n get [ 840.0 0 -415.0 -2585.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn4n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn64n get [ 840.0 0 -415.0 -3065.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn8n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put
+Mcbbox0 Encoding dnbow get [ 810.0 0 -395.0 -5.0 405.0 915.0 ] put
+Mcbbox0 Encoding dnflag get [ 640.0 0 -335.0 -1705.0 295.0 15.0 ] put
+Mcbbox0 Encoding dot get [ 280.0 0 -135.0 -125.0 135.0 135.0 ] put
+Mcbbox0 Encoding dwhdiamond get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox0 Encoding dwhrest get [ 340.0 0 -165.0 -5.0 165.0 615.0 ] put
+Mcbbox0 Encoding endped get [ 480.0 0 -215.0 -45.0 255.0 615.0 ] put
+Mcbbox0 Encoding fclef get [ 1840.0 0 -1015.0 -1705.0 815.0 655.0 ] put
+Mcbbox0 Encoding ferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put
+Mcbbox0 Encoding filldiamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put
+Mcbbox0 Encoding flat get [ 580.0 0 -295.0 -405.0 275.0 1115.0 ] put
+Mcbbox0 Encoding gclef get [ 1790.0 0 -915.0 -1605.0 865.0 3015.0 ] put
+Mcbbox0 Encoding halfdim get [ 760.0 0 -375.0 -5.0 375.0 1015.0 ] put
+Mcbbox0 Encoding invmor get [ 1320.0 0 -655.0 -455.0 655.0 465.0 ] put
+Mcbbox0 Encoding invturn get [ 1300.0 0 -645.0 -335.0 645.0 345.0 ] put
+Mcbbox0 Encoding leg get [ 840.0 0 -415.0 -55.0 415.0 65.0 ] put
+Mcbbox0 Encoding ll1rest get [ 840.0 0 -415.0 -5.0 415.0 625.0 ] put
+Mcbbox0 Encoding ll2rest get [ 840.0 0 -415.0 -15.0 415.0 315.0 ] put
+Mcbbox0 Encoding measrpt get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put
+Mcbbox0 Encoding mor get [ 1320.0 0 -655.0 -285.0 655.0 295.0 ] put
+Mcbbox0 Encoding nat get [ 520.0 0 -255.0 -855.0 255.0 865.0 ] put
+Mcbbox0 Encoding pedal get [ 1040.0 0 -515.0 -45.0 515.0 675.0 ] put
+Mcbbox0 Encoding qwhrest get [ 340.0 0 -165.0 -605.0 165.0 615.0 ] put
+Mcbbox0 Encoding rr get [ 940.0 0 -465.0 -25.0 465.0 1035.0 ] put
+Mcbbox0 Encoding sharp get [ 700.0 0 -345.0 -935.0 345.0 945.0 ] put
+Mcbbox0 Encoding sign get [ 1340.0 0 -665.0 -825.0 665.0 835.0 ] put
+Mcbbox0 Encoding tr get [ 1440.0 0 -715.0 -5.0 715.0 1015.0 ] put
+Mcbbox0 Encoding triangle get [ 800.0 0 -395.0 -45.0 395.0 785.0 ] put
+Mcbbox0 Encoding turn get [ 1300.0 0 -645.0 -325.0 645.0 345.0 ] put
+Mcbbox0 Encoding uferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put
+Mcbbox0 Encoding up128n get [ 1390.0 0 -745.0 -335.0 635.0 3555.0 ] put
+Mcbbox0 Encoding up16n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put
+Mcbbox0 Encoding up256n get [ 1390.0 0 -745.0 -335.0 635.0 3975.0 ] put
+Mcbbox0 Encoding up2n get [ 880.0 0 -435.0 -345.0 435.0 2115.0 ] put
+Mcbbox0 Encoding up32n get [ 1390.0 0 -745.0 -335.0 635.0 2595.0 ] put
+Mcbbox0 Encoding up4n get [ 850.0 0 -415.0 -335.0 425.0 2115.0 ] put
+Mcbbox0 Encoding up64n get [ 1390.0 0 -745.0 -335.0 635.0 3075.0 ] put
+Mcbbox0 Encoding up8n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put
+Mcbbox0 Encoding upbow get [ 720.0 0 -355.0 -115.0 355.0 925.0 ] put
+Mcbbox0 Encoding upflag get [ 640.0 0 -335.0 -5.0 295.0 1715.0 ] put
+Mcbbox0 Encoding uwedge get [ 340.0 0 -165.0 -5.0 165.0 505.0 ] put
+Mcbbox0 Encoding wedge get [ 340.0 0 -165.0 5.0 165.0 515.0 ] put
+Mcbbox0 Encoding xnote get [ 880.0 0 -435.0 -365.0 435.0 375.0 ] put
+
+end
+end
+
+/Mfont0 mfont0 definefont
+
+
+% find size of Encoding and make a dictionary
+% that size for bounding box information
+mfont1 begin
+/dictsize Encoding length def
+mfont1 /Mcbbox1 dictsize dict put
+
+% temporarily redefine printmchar1 to get code
+5 dict begin
+/printmchar1 { {} forall } def
+
+Mcbbox1 Encoding blankhead get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put
+Mcbbox1 Encoding dwhisostriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhpiewedge get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhrectangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhsemicircle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhslashhead get [ 1410.0 0 -695.0 -725.0 705.0 735.0 ] put
+Mcbbox1 Encoding fillisostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+Mcbbox1 Encoding fillpiewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillrectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillrighttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillsemicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillslashhead get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put
+Mcbbox1 Encoding isostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+Mcbbox1 Encoding piewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding rectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put
+Mcbbox1 Encoding righttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding semicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding slashhead get [ 1380.0 0 -685.0 -725.0 685.0 735.0 ] put
+Mcbbox1 Encoding udwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding ufillrighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+Mcbbox1 Encoding urighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+
+end
+end
+
+/Mfont1 mfont1 definefont
+
+/makeExtEncoding {
+       /extendedencoding 256 array def
+       StandardEncoding extendedencoding copy
+       extendedencoding 32 /exclamdown put
+       extendedencoding 33 /cent put
+       extendedencoding 34 /sterling put
+       extendedencoding 35 /yen put
+       extendedencoding 36 /quotedblleft put
+       extendedencoding 37 /guillemotleft put
+       extendedencoding 38 /guillemotright put
+       extendedencoding 39 /guilsinglleft put
+       extendedencoding 40 /guilsinglright put
+       extendedencoding 41 /dagger put
+       extendedencoding 42 /daggerdbl put
+       extendedencoding 43 /bullet put
+       extendedencoding 44 /quotedblbase put
+       extendedencoding 45 /quotedblright put
+       extendedencoding 46 /questiondown put
+       extendedencoding 47 /grave put
+       extendedencoding 48 /acute put
+       extendedencoding 49 /macron put
+       extendedencoding 50 /breve put
+       extendedencoding 51 /dotaccent put
+       extendedencoding 52 /dieresis put
+       extendedencoding 53 /ring put
+       extendedencoding 54 /cedilla put
+       extendedencoding 55 /hungarumlaut put
+       extendedencoding 56 /ogonek put
+       extendedencoding 57 /caron put
+       extendedencoding 58 /emdash put
+       extendedencoding 59 /AE put
+       extendedencoding 60 /ae put
+       extendedencoding 61 /ordfeminine put
+       extendedencoding 62 /ordmasculine put
+       extendedencoding 63 /Lslash put
+       extendedencoding 64 /lslash put
+       extendedencoding 65 /Oslash put
+       extendedencoding 66 /oslash put
+       extendedencoding 67 /OE put
+       extendedencoding 68 /oe put
+       extendedencoding 69 /dotlessi put
+       extendedencoding 70 /germandbls put
+       extendedencoding 71 /Aacute put
+       extendedencoding 72 /aacute put
+       extendedencoding 73 /Acircumflex put
+       extendedencoding 74 /acircumflex put
+       extendedencoding 75 /Adieresis put
+       extendedencoding 76 /adieresis put
+       extendedencoding 77 /Agrave put
+       extendedencoding 78 /agrave put
+       extendedencoding 79 /Aring put
+       extendedencoding 80 /aring put
+       extendedencoding 81 /Atilde put
+       extendedencoding 82 /atilde put
+       extendedencoding 83 /Ccedilla put
+       extendedencoding 84 /ccedilla put
+       extendedencoding 85 /Eacute put
+       extendedencoding 86 /eacute put
+       extendedencoding 87 /Ecircumflex put
+       extendedencoding 88 /ecircumflex put
+       extendedencoding 89 /Edieresis put
+       extendedencoding 90 /edieresis put
+       extendedencoding 91 /Egrave put
+       extendedencoding 92 /egrave put
+       extendedencoding 93 /Iacute put
+       extendedencoding 94 /iacute put
+       extendedencoding 95 /Icircumflex put
+       extendedencoding 96 /icircumflex put
+       extendedencoding 97 /Idieresis put
+       extendedencoding 98 /idieresis put
+       extendedencoding 99 /Igrave put
+       extendedencoding 100 /igrave put
+       extendedencoding 101 /Ntilde put
+       extendedencoding 102 /ntilde put
+       extendedencoding 103 /Oacute put
+       extendedencoding 104 /oacute put
+       extendedencoding 105 /Ocircumflex put
+       extendedencoding 106 /ocircumflex put
+       extendedencoding 107 /Odieresis put
+       extendedencoding 108 /odieresis put
+       extendedencoding 109 /Ograve put
+       extendedencoding 110 /ograve put
+       extendedencoding 111 /Otilde put
+       extendedencoding 112 /otilde put
+       extendedencoding 113 /Scaron put
+       extendedencoding 114 /scaron put
+       extendedencoding 115 /Uacute put
+       extendedencoding 116 /uacute put
+       extendedencoding 117 /Ucircumflex put
+       extendedencoding 118 /ucircumflex put
+       extendedencoding 119 /Udieresis put
+       extendedencoding 120 /udieresis put
+       extendedencoding 121 /Ugrave put
+       extendedencoding 122 /ugrave put
+       extendedencoding 123 /Ydieresis put
+       extendedencoding 124 /ydieresis put
+       extendedencoding 125 /Zcaron put
+       extendedencoding 126 /zcaron put
+       extendedencoding 127 /space put
+} def
+
+/makeExtendedFont {
+       findfont
+       dup length dict /newdict exch def
+       { 1 index /FID ne
+               { newdict 3 1 roll put }
+               { pop pop }
+               ifelse
+       } forall
+       newdict /Encoding extendedencoding put
+       newdict /UniqueID newdict /UniqueID get 1 add put
+       newdict definefont pop
+} def
+/flagsep 1.60 300 mul def       % 1.60 stepsizes
+/scv 147460 def /sf 962 string def
+/fa {/p 0 def /chr exch -3 bitshift 127 and def {sf exch p add dup /p exch def chr put} forall} def
+[ 74 62 70 54 29 55 36 37 19 26 45 40 41 50 45 52 19 73 11 68 ] 1567304784 fa
+[ 961 ] 1341740116 fa
+[ 12 4 5 4 4 2 4 3 3 7 7 3 5 5 4 5 4 2 5 3 ] 1969419526 fa
+[ 96 4 4 3 2 4 11 2 6 23 13 16 8 3 28 13 8 3 6 11 ] 387152134 fa
+[ 268 4 13 12 5 4 4 5 4 5 3 2 4 3 4 8 3 3 9 2 ] 305899779 fa
+[ 369 3 4 9 3 3 9 2 4 3 4 7 4 4 4 9 5 3 5 4 ] 477458695 fa
+[ 498 4 36 4 37 4 42 4 4 37 4 4 35 4 4 5 13 3 4 4 ] 1130513667 fa
+[ 759 3 5 33 4 5 9 29 5 4 3 5 4 4 5 4 4 5 4 3 ] 1205319942 fa
+[ 902 8 4 2 3 4 3 4 4 3 2 3 9 ] 1708988675 fa
+[ 468 6 4 10 3 30 5 3 24 40 4 3 3 3 3 8 23 1 1 1 ] 123455756 fa
+[ 664 23 4 2 13 66 4 5 9 ] 2061720845 fa
+[ 795 ] 1622189328 fa
+[ 463 45 40 41 50 45 84 ] 304180545 fa
+[ 494 40 41 49 45 43 84 ] 251711819 fa
+[ 149 203 37 144 ] 358262127 fa
+[ 456 142 52 ] 95949173 fa
+[ 0 13 13 10 65 36 6 26 38 17 13 53 4 13 13 25 36 183 7 140 ] 1751712121 fa
+[ 839 5 13 12 13 13 48 ] 1943250302 fa
+[ 30 164 254 7 42 4 36 4 18 1 18 4 46 3 1 41 4 39 4 41 ] 499619205 fa
+[ 798 1 3 1 ] 1277775234 fa
+[ 76 32 135 79 99 8 246 43 30 160 ] 734015880 fa
+[ 265 70 36 12 25 87 4 36 4 37 4 46 4 41 43 83 4 83 41 3 ] 1546658194 fa
+[ 193 49 180 8 17 134 ] 831070621 fa
+[ 353 366 ] 1033403809 fa
+[ 266 1 190 39 40 41 50 45 43 45 ] 1758436783 fa
+[ 423 8 109 ] 508918194 fa
+[ 328 6 30 6 31 6 269 ] 212071871 fa
+[ 390 357 2 ] 1671244225 fa
+[ 500 ] 347047368 fa
+[ 558 ] 1276946910 fa
+[ 651 ] 2109048312 fa
+[ 644 ] 1914352160 fa
+[ 520 ] 471204394 fa
+[ 512 5 2 ] 1930983991 fa
+[ 665 ] 154021439 fa
+[ 513 ] 777103941 fa
+[ 514 ] 260959830 fa
+[ 530 239 ] 1284535922 fa
+[ 510 ] 1982423675 fa
+[ 150 ] 1969948305 fa
+[ 511 7 134 ] 1407991454 fa
+[ 144 371 ] 1896661664 fa
+[ 464 52 ] 1444653737 fa
+[ 509 81 ] 1712172720 fa
+[ 110 11 32 24 22 18 40 12 54 7 17 19 18 19 22 13 377 94 9 11 ] 889612 fa
+[ 954 ] 1802916616 fa
+[ 80 146 51 78 37 84 8 8 73 5 44 45 33 9 73 9 130 9 11 12 ] 1808121621 fa
+[ 19 42 3 22 8 82 63 23 25 13 8 5 176 248 40 73 12 13 13 12 ] 1752602397 fa
+[ 22 10 37 42 1 2 19 26 6 38 17 13 38 11 21 13 16 9 27 9 ] 1598682919 fa
+[ 405 9 13 46 49 50 50 213 18 12 13 13 12 45 10 ] 160257827 fa
+[ 1 8 8 6 10 10 16 11 14 8 23 19 13 19 13 7 15 3 9 8 ] 882894639 fa
+[ 234 40 9 15 6 7 6 25 36 37 19 6 47 16 40 41 50 45 43 6 ] 185215791 fa
+[ 733 19 37 16 12 13 3 3 12 6 6 6 7 6 7 6 6 6 45 10 ] 1706915629 fa
+[ 24 10 37 45 2 17 5 1 15 4 7 5 8 8 17 17 13 11 8 26 ] 1713964852 fa
+[ 284 21 13 25 18 18 19 18 28 1 7 28 2 4 106 24 3 2 32 36 ] 1218620208 fa
+[ 695 62 1 7 13 1 7 2 37 4 8 5 13 12 13 13 12 45 5 1 ] 1317868340 fa
+[ 960 ] 75399990 fa
+[ 45 9 155 6 245 68 21 98 60 109 ] 1430691640 fa
+[ 20 27 15 25 8 33 173 13 45 37 83 170 5 34 8 115 40 12 13 13 ] 841629509 fa
+[ 901 ] 422446918 fa
+[ 27 25 37 13 3 40 12 73 49 77 4 33 4 68 89 219 21 27 3 4 ] 560155470 fa
+[ 466 6 135 41 7 6 36 6 89 ] 803193686 fa
+[ 42 80 1 55 80 1 80 36 37 155 1 263 40 65 ] 189315943 fa
+[ 6 31 36 9 43 21 6 185 36 37 210 ] 1031359337 fa
+[ 44 9 101 4 4 20 8 80 3 23 30 5 19 17 20 17 15 7 7 36 ] 586694517 fa
+[ 552 22 20 16 3 55 42 31 10 33 ] 343336822 fa
+[ 7 4 54 54 10 22 10 20 8 8 53 5 226 12 115 38 17 42 26 13 ] 1808462718 fa
+[ 780 32 ] 847653755 fa
+[ 3 63 31 408 18 4 18 6 22 13 15 3 32 9 17 4 15 5 18 4 ] 1627872128 fa
+[ 724 83 7 ] 1643402114 fa
+[ 228 296 8 25 39 16 159 14 34 ] 670118796 fa
+[ 2 2 47 69 19 34 23 20 35 5 187 10 51 2 38 2 39 2 48 2 ] 888380310 fa
+[ 680 2 41 2 2 5 13 11 10 40 2 50 80 ] 1392580498 fa
+[ 14 25 10 7 22 49 21 22 1 4 10 23 4 13 15 5 16 15 12 3 ] 2114772893 fa
+[ 295 30 24 9 28 9 23 19 13 1 8 24 67 16 3 30 3 3 53 9 ] 453068702 fa
+[ 694 6 9 20 11 23 1 23 23 22 8 5 1 24 41 9 11 4 5 1 ] 1393470366 fa
+[ 944 8 ] 1770206109 fa
+[ 10 5 25 6 4 7 42 39 25 20 4 4 7 2 14 17 126 5 32 5 ] 113705892 fa
+[ 442 25 4 6 114 27 38 42 32 25 20 47 19 112 ] 998588323 fa
+[ 79 19 131 109 36 37 74 70 1 59 8 34 3 25 5 9 3 80 11 27 ] 1221405612 fa
+[ 912 9 11 ] 273962927 fa
+[ 8 230 25 23 6 17 130 31 61 64 16 127 32 ] 1881483187 fa
+[ 130 683 ] 1406620603 fa
+[ 18 10 32 25 5 3 10 3 143 50 13 9 61 93 86 1 1 180 48 58 ] 1980878788 fa
+[ 861 13 9 4 12 8 17 3 ] 1447963591 fa
+[ 67 143 8 128 115 435 19 2 ] 477757388 fa
+[ 490 35 ] 1151262673 fa
+[ 5 70 67 32 37 16 14 7 27 18 142 301 17 90 103 ] 1523362782 fa
+[ 117 14 33 38 17 13 20 26 3 453 89 3 8 113 10 ] 1908448236 fa
+sf cvx exec
+
+% set up extended character set fonts
+makeExtEncoding
+/Ext-Helvetica-Oblique /Helvetica-Oblique makeExtendedFont
+%%EndProlog
+%%Page: 1 1
+save
+1216322504 1216321786 sv
+0.770000 0.770000 scale
+%  S_SSV
+(/home/johnkr/mup/5.3/doc/arkkra/sample.mup) inputfile
+53 linenum
+%  S_SSV
+141 linenum
+%  S_SSV
+144 linenum
+%  S_SSV
+155 linenum
+%  S_SSV
+159 linenum
+%  S_SSV
+167 linenum
+%  S_SSV
+174 linenum
+%  S_SSV
+177 linenum
+%  S_SSV
+189 linenum
+%  S_FEED
+46 linenum
+/Times-Roman findfont
+13 scalefont
+setfont
+360.43 884.59 moveto
+(First Movement) show
+274.11 1314.68 738.70 5 1.000000 1.000000 stf
+274.11 1234.26 738.70 5 1.000000 1.000000 stf
+274.11 1170.66 738.70 5 1.000000 0.800000 stf
+274.11 1107.06 738.70 1 1.000000 1.000000 stf
+274.11 1028.13 738.70 5 1.000000 1.000000 stf
+274.11 946.01 738.70 5 1.000000 1.000000 stf
+274.11 831.00 738.70 5 1.000000 1.000000 stf
+274.11 750.98 738.70 6 1.735000 1.000000 stf
+274.11 670.95 738.70 5 1.000000 1.000000 stf
+/Times-Roman findfont
+12 scalefont
+setfont
+83.90 766.44 moveto
+(Choir) show
+/Palatino-Roman findfont
+11 scalefont
+setfont
+78.07 669.93 moveto
+(foghorn) show
+84.99 657.45 moveto
+(in G) show
+107.90 659.39 0.583333 flat
+110.08 657.45 moveto
+/Times-Roman findfont
+12 scalefont
+setfont
+66.62 480.26 moveto
+(keyboard) show
+/Times-Roman findfont
+12 scalefont
+setfont
+80.59 282.96 moveto
+(Guitar) show
+/Palatino-Roman findfont
+14 scalefont
+setfont
+65.45 164.05 moveto
+(Soprano) show
+128.11 825.68 715.26 bracket
+129.61 536.13 430.01 brace
+128.11 342.00 217.95 bracket
+0.70 setlinewidth
+130.11 822.68 moveto
+130.11 154.95 lineto stroke
+%  S_CLEFSIG
+141.91 804.68 1.000000 gclef
+142.16 736.26 1.000000 fclef
+138.54 676.26 0.800000 cclef
+136.11 595.56 moveto
+136.11 610.56 lineto stroke
+138.21 595.56 moveto
+138.21 610.56 lineto stroke
+141.91 518.13 1.000000 gclef
+142.16 448.01 1.000000 fclef
+141.91 321.00 1.000000 gclef
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+133.11 256.92 moveto
+(T) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+133.11 239.04 moveto
+(A) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+133.11 221.16 moveto
+(B) show
+141.91 160.95 1.000000 gclef
+155.95 810.68 1.000000 flat
+161.43 819.68 1.000000 flat
+166.92 807.68 1.000000 flat
+155.95 724.26 1.000000 flat
+161.43 733.26 1.000000 flat
+166.92 721.26 1.000000 flat
+156.06 666.66 0.800000 sharp
+161.51 676.26 0.800000 sharp
+166.97 669.06 0.800000 sharp
+155.95 524.13 1.000000 flat
+161.43 533.13 1.000000 flat
+166.92 521.13 1.000000 flat
+155.95 436.01 1.000000 flat
+161.43 445.01 1.000000 flat
+166.92 433.01 1.000000 flat
+155.95 327.00 1.000000 flat
+161.43 336.00 1.000000 flat
+166.92 324.00 1.000000 flat
+155.95 166.95 1.000000 flat
+161.43 175.95 1.000000 flat
+166.92 163.95 1.000000 flat
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+172.67 810.68 moveto
+(9) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+172.67 798.48 moveto
+(8) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+172.67 730.26 moveto
+(9) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+172.67 718.05 moveto
+(8) show
+/NewCenturySchlbk-Bold findfont
+13 scalefont
+setfont
+172.67 666.66 moveto
+(9) show
+/NewCenturySchlbk-Bold findfont
+13 scalefont
+setfont
+172.67 656.72 moveto
+(8) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+172.67 603.06 moveto
+(9) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+172.67 590.85 moveto
+(8) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+172.67 524.13 moveto
+(9) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+172.67 511.92 moveto
+(8) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+172.67 442.01 moveto
+(9) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+172.67 429.80 moveto
+(8) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+172.67 327.00 moveto
+(9) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+172.67 314.79 moveto
+(8) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+172.67 166.95 moveto
+(9) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+172.67 154.74 moveto
+(8) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+331 linenum
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+211.06 776.32 moveto
+(These) show
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+285.74 776.32 moveto
+(are) show
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+366.84 776.32 moveto
+(the) show
+331 linenum
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+211.06 764.51 moveto
+(This) show
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+287.74 764.51 moveto
+(is) show
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+363.95 764.51 moveto
+(verse) show
+219.06 804.68 1.000000 4n
+228.32 807.68 1.000000 dot
+219.06 798.68 1.000000 4n
+228.32 801.68 1.000000 dot
+219.06 792.68 1.000000 4n
+228.32 795.68 1.000000 dot
+212.83 792.68 moveto
+225.29 792.68 lineto stroke
+222.74 793.43 moveto
+222.74 825.68 lineto stroke
+289.72 804.68 1.000000 4n
+298.98 807.68 1.000000 dot
+289.72 798.68 1.000000 4n
+298.98 801.68 1.000000 dot
+289.72 792.68 1.000000 4n
+298.98 795.68 1.000000 dot
+283.49 792.68 moveto
+295.95 792.68 lineto stroke
+293.40 793.43 moveto
+293.40 825.68 lineto stroke
+370.67 810.68 1.000000 4n
+379.93 813.68 1.000000 dot
+370.67 801.68 1.000000 4n
+379.93 801.68 1.000000 dot
+370.67 795.68 1.000000 4n
+379.93 795.68 1.000000 dot
+374.35 796.43 moveto
+374.35 831.68 lineto stroke
+/Palatino-Roman findfont
+14 scalefont
+setfont
+213.60 835.46 moveto
+(Andante ) show
+restore
+%  S_STAFF
+% staff 2
+save
+219.06 727.26 1.000000 4n
+228.32 727.26 1.000000 dot
+0.70 setlinewidth
+222.74 728.01 moveto
+222.74 748.26 lineto stroke
+289.72 727.26 1.000000 4n
+286.04 726.51 moveto
+286.04 707.32 lineto stroke
+318.60 724.26 1.000000 8rest
+344.67 733.26 1.000000 4n
+340.98 732.51 moveto
+340.98 713.32 lineto stroke
+370.67 736.26 1.000000 4n
+379.93 739.26 1.000000 dot
+366.99 735.51 moveto
+366.99 715.26 lineto stroke
+newpath
+285.69 708.82 moveto
+341.33 714.82 lineto
+341.33 711.82 lineto
+285.69 705.82 lineto
+closepath
+fill
+219.81 751.26 moveto
+219.80 751.41 lineto
+263.09 755.16 306.44 756.06 349.85 754.11 curveto
+393.25 752.17 436.35 747.40 479.13 739.79 curveto
+479.09 739.50 lineto
+436.24 746.30 393.13 750.67 349.78 752.62 curveto
+306.43 754.56 263.10 754.06 219.81 751.11 curveto
+fill
+restore
+%  S_STAFF
+% staff 3
+save
+202.61 666.66 0.466667 4n
+198.01 666.66 0.466667 dblsharp
+0.56 setlinewidth
+204.21 667.05 moveto
+204.21 678.66 lineto stroke
+205.72 678.66 0.466667 dnflag
+newpath
+201.61 669.66 moveto
+201.61 670.86 lineto
+206.81 676.46 lineto
+206.81 675.26 lineto
+closepath
+fill
+219.06 673.86 0.800000 2n
+211.55 673.86 0.800000 sharp
+226.64 673.86 0.800000 dot
+/Palatino-Roman findfont
+11 scalefont
+setfont
+212.92 680.53 moveto
+219.06 680.53 0.916667 acc_gt
+225.20 680.53 moveto
+215.94 673.26 moveto
+215.94 657.06 lineto stroke
+370.67 666.66 0.800000 4rest
+377.52 669.06 0.800000 dot
+restore
+%  S_STAFF
+% staff 4
+save
+325.58 597.06 1.000000 ll1rest
+restore
+%  S_STAFF
+% staff 5
+save
+219.06 527.13 1.000000 4n
+0.70 setlinewidth
+222.74 527.88 moveto
+222.74 548.13 lineto stroke
+256.90 518.13 1.000000 4n
+260.59 518.88 moveto
+260.59 539.13 lineto stroke
+289.72 527.13 1.000000 4n
+298.98 527.13 1.000000 dot
+293.40 527.88 moveto
+293.40 548.13 lineto stroke
+370.67 536.13 1.000000 4n
+374.35 536.88 moveto
+374.35 557.13 lineto stroke
+425.61 536.13 1.000000 4n
+429.29 536.88 moveto
+429.29 555.63 lineto stroke
+443.17 536.13 1.000000 4n
+446.85 536.88 moveto
+446.85 555.63 lineto stroke
+/NewCenturySchlbk-BoldItalic findfont
+11 scalefont
+setfont
+234.81 545.91 moveto
+(2) show
+215.03 554.41 moveto
+232.81 550.77 lineto stroke
+243.15 549.06 moveto
+260.94 545.41 lineto stroke
+215.03 554.41 moveto
+215.03 551.41 lineto stroke
+260.94 545.41 moveto
+260.94 542.41 lineto stroke
+newpath
+428.94 557.13 moveto
+447.20 557.13 lineto
+447.20 554.13 lineto
+428.94 554.13 lineto
+closepath
+fill
+newpath
+428.94 552.13 moveto
+447.20 552.13 lineto
+447.20 549.13 lineto
+428.94 549.13 lineto
+closepath
+fill
+219.06 506.13 1.000000 2n
+228.54 503.13 1.000000 dot
+212.61 506.13 moveto
+225.51 506.13 lineto stroke
+215.16 505.38 moveto
+215.16 485.13 lineto stroke
+370.67 509.13 1.000000 4n
+379.93 509.13 1.000000 dot
+366.99 508.38 moveto
+366.99 488.13 lineto stroke
+300.22 512.13 1.000000 4n
+303.90 512.88 moveto
+303.90 532.22 lineto stroke
+318.60 515.13 1.000000 4n
+322.28 515.88 moveto
+322.28 534.68 lineto stroke
+344.67 518.13 1.000000 4n
+348.35 518.88 moveto
+348.35 538.17 lineto stroke
+379.67 521.13 1.000000 4n
+371.22 521.13 1.000000 nat
+383.35 521.88 moveto
+383.35 542.13 lineto stroke
+386.38 542.13 1.000000 dnflag
+400.18 521.13 1.000000 4n
+403.86 521.88 moveto
+403.86 542.13 lineto stroke
+newpath
+303.55 533.72 moveto
+348.70 539.67 lineto
+348.70 536.67 lineto
+303.55 530.72 lineto
+closepath
+fill
+376.70 541.23 moveto
+376.68 541.37 lineto
+384.59 544.22 392.75 545.64 401.16 545.64 curveto
+409.56 545.64 417.72 544.22 425.63 541.37 curveto
+425.59 541.08 lineto
+417.57 543.12 409.43 544.14 401.16 544.14 curveto
+392.88 544.14 384.74 543.12 376.72 541.08 curveto
+fill
+/Palatino-Roman findfont
+14 scalefont
+setfont
+365.63 561.91 moveto
+(VII) show
+388.72 569.09 moveto
+/Palatino-Roman findfont
+9 scalefont
+setfont
+(6) show
+385.12 558.82 moveto
+386.92 562.11 0.416667 sharp
+388.72 558.82 moveto
+388.72 559.64 moveto
+(5) show
+393.20 561.91 moveto
+/Palatino-Roman findfont
+14 scalefont
+setfont
+( ) show
+/Palatino-Roman findfont
+14 scalefont
+setfont
+217.04 562.91 moveto
+(i ) show
+restore
+%  S_STAFF
+% staff 6
+save
+219.06 418.01 1.000000 4n
+228.32 421.01 1.000000 dot
+0.70 setlinewidth
+212.83 418.01 moveto
+225.29 418.01 lineto stroke
+212.83 424.01 moveto
+225.29 424.01 lineto stroke
+219.06 397.01 1.000000 4n
+228.32 397.01 1.000000 dot
+212.83 400.01 moveto
+225.29 400.01 lineto stroke
+212.83 406.01 moveto
+225.29 406.01 lineto stroke
+212.83 412.01 moveto
+225.29 412.01 lineto stroke
+212.83 418.01 moveto
+225.29 418.01 lineto stroke
+212.83 424.01 moveto
+225.29 424.01 lineto stroke
+222.74 397.76 moveto
+222.74 442.01 lineto stroke
+289.72 418.01 1.000000 4n
+298.98 421.01 1.000000 dot
+283.49 418.01 moveto
+295.95 418.01 lineto stroke
+283.49 424.01 moveto
+295.95 424.01 lineto stroke
+289.72 397.01 1.000000 4n
+298.98 397.01 1.000000 dot
+283.49 400.01 moveto
+295.95 400.01 lineto stroke
+283.49 406.01 moveto
+295.95 406.01 lineto stroke
+283.49 412.01 moveto
+295.95 412.01 lineto stroke
+283.49 418.01 moveto
+295.95 418.01 lineto stroke
+283.49 424.01 moveto
+295.95 424.01 lineto stroke
+293.40 397.76 moveto
+293.40 442.01 lineto stroke
+370.67 421.01 1.000000 4n
+379.93 421.01 1.000000 dot
+364.44 424.01 moveto
+376.90 424.01 lineto stroke
+370.67 400.01 1.000000 4n
+379.93 403.01 1.000000 dot
+364.44 400.01 moveto
+376.90 400.01 lineto stroke
+364.44 406.01 moveto
+376.90 406.01 lineto stroke
+364.44 412.01 moveto
+376.90 412.01 lineto stroke
+364.44 418.01 moveto
+376.90 418.01 lineto stroke
+364.44 424.01 moveto
+376.90 424.01 lineto stroke
+374.35 400.76 moveto
+374.35 442.01 lineto stroke
+/Palatino-Roman findfont
+14 scalefont
+setfont
+213.60 466.79 moveto
+(Andante ) show
+219.06 377.80 moveto
+219.06 370.81 lineto stroke
+219.06 370.81 moveto
+221.59 370.81 lineto stroke
+220.92 370.81 moveto
+339.96 370.81 lineto stroke
+339.63 370.81 moveto
+344.67 377.80 lineto stroke
+344.67 377.80 moveto
+349.71 370.81 lineto stroke
+/Palatino-Roman findfont
+14 scalefont
+setfont
+368.43 381.58 moveto
+368.43 388.76 moveto
+/Palatino-Roman findfont
+9 scalefont
+setfont
+(6) show
+368.43 379.31 moveto
+(5) show
+gsave
+0.58 setlinewidth
+368.43 380.78 moveto
+372.91 383.71 lineto stroke
+grestore
+372.91 379.31 moveto
+372.91 381.58 moveto
+/Palatino-Roman findfont
+14 scalefont
+setfont
+( ) show
+restore
+%  S_STAFF
+% staff 7
+save
+219.06 321.00 1.000000 4n
+228.32 324.00 1.000000 dot
+219.06 315.00 1.000000 4n
+228.32 318.00 1.000000 dot
+219.06 309.00 1.000000 4n
+228.32 312.00 1.000000 dot
+0.70 setlinewidth
+212.83 309.00 moveto
+225.29 309.00 lineto stroke
+222.74 309.75 moveto
+222.74 342.00 lineto stroke
+289.72 309.00 1.000000 4n
+283.49 309.00 moveto
+295.95 309.00 lineto stroke
+293.40 309.75 moveto
+293.40 325.50 lineto stroke
+318.60 300.00 1.000000 4n
+312.37 303.00 moveto
+324.83 303.00 lineto stroke
+312.37 309.00 moveto
+324.83 309.00 lineto stroke
+322.28 300.75 moveto
+322.28 325.50 lineto stroke
+344.67 309.00 1.000000 4n
+338.43 309.00 moveto
+350.90 309.00 lineto stroke
+348.35 309.75 moveto
+348.35 325.50 lineto stroke
+370.67 339.00 1.000000 4n
+379.93 342.00 1.000000 dot
+370.67 333.00 1.000000 4n
+379.93 336.00 1.000000 dot
+370.67 324.00 1.000000 4n
+362.22 324.00 1.000000 nat
+379.93 324.00 1.000000 dot
+370.67 312.00 1.000000 4n
+379.93 312.00 1.000000 dot
+374.35 312.75 moveto
+374.35 360.00 lineto stroke
+newpath
+293.05 327.00 moveto
+348.70 327.00 lineto
+348.70 324.00 lineto
+293.05 324.00 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 8
+save
+215.71 246.71 222.41 257.65 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+215.71 247.86 moveto
+(0) show
+215.71 236.51 222.41 247.03 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+215.71 237.52 moveto
+(1) show
+215.71 225.89 222.41 236.83 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+215.71 227.11 moveto
+(3) show
+286.37 225.89 293.07 236.83 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+286.37 227.11 moveto
+(3) show
+315.25 215.48 321.95 226.42 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+315.25 216.70 moveto
+(3) show
+341.32 225.89 348.01 236.83 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+341.32 227.11 moveto
+(3) show
+367.32 267.74 374.02 278.26 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+367.32 268.75 moveto
+(1) show
+367.32 257.12 374.02 268.06 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+367.32 258.34 moveto
+(3) show
+367.32 246.82 374.02 257.54 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+367.32 247.75 moveto
+(2) show
+367.32 236.30 374.02 247.24 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+367.32 237.45 moveto
+(0) show
+restore
+%  S_STAFF
+% staff 9
+save
+331 linenum
+0.70 setlinewidth
+232.87 138.97 moveto
+484.11 138.97 lineto stroke
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+214.45 138.97 moveto
+(ah) show
+219.06 169.95 1.000000 fillrectangle
+228.54 169.95 1.000000 dot
+215.16 169.95 moveto
+215.16 148.95 lineto stroke
+289.72 175.95 1.000000 fillisostriangle
+285.82 173.55 moveto
+285.82 153.45 lineto stroke
+318.60 169.95 1.000000 fillrectangle
+314.70 169.95 moveto
+314.70 153.45 lineto stroke
+344.67 175.95 1.000000 fillisostriangle
+340.77 173.55 moveto
+340.77 153.45 lineto stroke
+370.67 178.95 1.000000 fillsemicircle
+380.15 181.95 1.000000 dot
+366.77 181.35 moveto
+366.77 157.95 lineto stroke
+newpath
+285.47 154.95 moveto
+341.12 154.95 lineto
+341.12 151.95 lineto
+285.47 151.95 lineto
+closepath
+fill
+restore
+%  S_BAR
+331 linenum
+0.70 setlinewidth
+461.45 822.68 moveto
+461.45 798.68 lineto stroke
+461.45 742.26 moveto
+461.45 718.26 lineto stroke
+461.45 676.26 moveto
+461.45 657.06 lineto stroke
+461.45 609.06 moveto
+461.45 597.06 lineto stroke
+461.45 536.13 moveto
+461.45 430.01 lineto stroke
+461.45 339.00 moveto
+461.45 220.95 lineto stroke
+461.45 178.95 moveto
+461.45 154.95 lineto stroke
+/Palatino-Bold findfont
+12 scalefont
+setfont
+gsave
+newpath
+1.000000 1.000000 scale
+461.45 355.72 7.72 0 360 arc
+1.000000 1.000000 scale
+1.000000 1.000000 scale
+461.45 355.72 7.22 0 360 arc
+eofill
+grestore
+456.77 351.65 moveto
+(A) show
+/Palatino-Bold findfont
+12 scalefont
+setfont
+gsave
+newpath
+1.000000 1.000000 scale
+461.45 552.85 7.72 0 360 arc
+1.000000 1.000000 scale
+1.000000 1.000000 scale
+461.45 552.85 7.22 0 360 arc
+eofill
+grestore
+456.77 548.78 moveto
+(A) show
+/Palatino-Bold findfont
+12 scalefont
+setfont
+gsave
+newpath
+1.000000 1.000000 scale
+461.45 839.41 7.72 0 360 arc
+1.000000 1.000000 scale
+1.000000 1.000000 scale
+461.45 839.41 7.22 0 360 arc
+eofill
+grestore
+456.77 835.34 moveto
+(A) show
+0.70 setlinewidth
+349.37 370.81 moveto
+460.45 370.81 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+331 linenum
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+470.24 776.32 moveto
+(words!) show
+331 linenum
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+465.97 764.51 moveto
+(two) show
+/Ext-Helvetica-Oblique findfont
+11 scalefont
+setfont
+(\7f) show
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+(oh) show
+/Ext-Helvetica-Oblique findfont
+11 scalefont
+setfont
+(\7f) show
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+(yes.) show
+479.86 813.68 1.000000 2n
+489.34 813.68 1.000000 dot
+479.86 804.68 1.000000 2n
+489.34 807.68 1.000000 dot
+479.86 792.68 1.000000 2n
+489.34 795.68 1.000000 dot
+473.41 792.68 moveto
+486.31 792.68 lineto stroke
+483.76 793.43 moveto
+483.76 834.68 lineto stroke
+682.24 810.68 1.000000 4rest
+690.54 813.68 1.000000 dot
+/Palatino-Italic findfont
+13 scalefont
+setfont
+674.54 845.57 moveto
+(To coda ) show
+727.93 854.86 1.083333 coda
+737.72 845.57 moveto
+/Times-Roman findfont
+13 scalefont
+setfont
+674.54 831.68 moveto
+restore
+%  S_STAFF
+% staff 2
+save
+479.86 733.26 1.000000 2n
+489.34 733.26 1.000000 dot
+479.86 727.26 1.000000 2n
+489.34 727.26 1.000000 dot
+0.70 setlinewidth
+475.96 732.51 moveto
+475.96 706.26 lineto stroke
+682.24 730.26 1.000000 4rest
+690.54 733.26 1.000000 dot
+restore
+%  S_STAFF
+% staff 3
+save
+479.86 673.86 0.800000 2n
+470.53 673.86 0.800000 dblflat
+487.44 673.86 0.800000 dot
+0.56 setlinewidth
+476.74 673.26 moveto
+476.74 657.06 lineto stroke
+682.24 666.66 0.800000 4rest
+689.09 669.06 0.800000 dot
+restore
+%  S_STAFF
+% staff 4
+save
+479.86 603.06 1.000000 4n
+489.12 606.06 1.000000 dot
+0.70 setlinewidth
+483.54 603.81 moveto
+483.54 624.06 lineto stroke
+574.99 603.06 1.000000 ll2rest
+584.26 606.06 1.000000 dot
+restore
+%  S_STAFF
+% staff 5
+save
+479.86 548.13 1.000000 2n
+489.34 551.13 1.000000 dot
+0.70 setlinewidth
+473.41 548.13 moveto
+486.31 548.13 lineto stroke
+473.41 542.13 moveto
+486.31 542.13 lineto stroke
+483.76 548.88 moveto
+483.76 569.13 lineto stroke
+682.24 536.13 1.000000 4rest
+690.54 539.13 1.000000 dot
+479.86 512.13 1.000000 4n
+476.18 511.38 moveto
+476.18 495.63 lineto stroke
+522.39 518.13 1.000000 4n
+518.71 517.38 moveto
+518.71 495.63 lineto stroke
+549.56 512.13 1.000000 4n
+545.88 511.38 moveto
+545.88 495.63 lineto stroke
+574.99 518.13 1.000000 4n
+571.31 517.38 moveto
+571.31 495.63 lineto stroke
+591.72 512.13 1.000000 4n
+588.03 511.38 moveto
+588.03 495.63 lineto stroke
+608.44 518.13 1.000000 4n
+604.76 517.38 moveto
+604.76 495.63 lineto stroke
+625.17 512.13 1.000000 4n
+621.48 511.38 moveto
+621.48 495.63 lineto stroke
+641.89 518.13 1.000000 4n
+638.21 517.38 moveto
+638.21 495.63 lineto stroke
+658.78 512.13 1.000000 4n
+655.09 511.38 moveto
+655.09 495.63 lineto stroke
+682.24 512.13 1.000000 4rest
+690.54 515.13 1.000000 dot
+newpath
+475.83 497.13 moveto
+546.23 497.13 lineto
+546.23 494.13 lineto
+475.83 494.13 lineto
+closepath
+fill
+newpath
+570.96 497.13 moveto
+655.44 497.13 lineto
+655.44 494.13 lineto
+570.96 494.13 lineto
+closepath
+fill
+newpath
+570.96 502.13 moveto
+588.38 502.13 lineto
+588.38 499.13 lineto
+570.96 499.13 lineto
+closepath
+fill
+newpath
+604.41 502.13 moveto
+621.83 502.13 lineto
+621.83 499.13 lineto
+604.41 499.13 lineto
+closepath
+fill
+newpath
+637.86 502.13 moveto
+655.44 502.13 lineto
+655.44 499.13 lineto
+637.86 499.13 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 6
+save
+479.86 418.01 1.000000 2n
+489.34 421.01 1.000000 dot
+0.70 setlinewidth
+473.41 418.01 moveto
+486.31 418.01 lineto stroke
+473.41 424.01 moveto
+486.31 424.01 lineto stroke
+483.76 418.76 moveto
+483.76 440.51 lineto stroke
+newpath
+483.76 434.01 moveto
+483.76 437.01 lineto
+578.89 455.94 lineto
+578.89 452.94 lineto
+closepath
+fill
+newpath
+483.76 439.01 moveto
+483.76 442.01 lineto
+578.89 460.94 lineto
+578.89 457.94 lineto
+closepath
+fill
+574.99 439.01 1.000000 2n
+584.47 439.01 1.000000 dot
+578.89 439.76 moveto
+578.89 459.44 lineto stroke
+682.24 442.01 1.000000 4rest
+690.54 445.01 1.000000 dot
+460.45 370.81 moveto
+475.15 370.81 lineto stroke
+474.82 370.81 moveto
+479.86 377.80 lineto stroke
+479.86 377.80 moveto
+484.90 370.81 lineto stroke
+484.57 370.81 moveto
+639.62 370.81 lineto stroke
+638.95 370.81 moveto
+641.89 370.81 lineto stroke
+641.89 377.80 moveto
+641.89 370.81 lineto stroke
+restore
+%  S_STAFF
+% staff 7
+save
+479.86 342.00 1.000000 2n
+489.34 342.00 1.000000 dot
+479.86 330.00 1.000000 2n
+489.34 330.00 1.000000 dot
+479.86 321.00 1.000000 2n
+489.34 324.00 1.000000 dot
+479.86 315.00 1.000000 2n
+489.34 318.00 1.000000 dot
+0.70 setlinewidth
+475.96 341.25 moveto
+475.96 289.20 lineto stroke
+newpath
+470.96 300.50 moveto
+470.96 303.50 lineto
+480.96 307.90 lineto
+480.96 304.90 lineto
+closepath
+fill
+newpath
+470.96 295.50 moveto
+470.96 298.50 lineto
+480.96 302.90 lineto
+480.96 299.90 lineto
+closepath
+fill
+newpath
+470.96 290.50 moveto
+470.96 293.50 lineto
+480.96 297.90 lineto
+480.96 294.90 lineto
+closepath
+fill
+682.24 327.00 1.000000 4rest
+690.54 330.00 1.000000 dot
+restore
+%  S_STAFF
+% staff 8
+save
+476.51 267.53 483.21 278.47 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+476.51 268.75 moveto
+(3) show
+476.51 257.33 483.21 267.85 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+476.51 258.34 moveto
+(1) show
+476.51 246.71 483.21 257.65 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+476.51 247.86 moveto
+(0) show
+476.51 236.51 483.21 247.03 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+476.51 237.52 moveto
+(1) show
+newpath
+474.86 227.27 moveto
+474.86 230.27 lineto
+484.86 234.67 lineto
+484.86 231.67 lineto
+closepath
+fill
+newpath
+474.86 222.27 moveto
+474.86 225.27 lineto
+484.86 229.67 lineto
+484.86 226.67 lineto
+closepath
+fill
+newpath
+474.86 217.27 moveto
+474.86 220.27 lineto
+484.86 224.67 lineto
+484.86 221.67 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 9
+save
+479.86 175.95 1.000000 isostriangle
+489.34 175.95 1.000000 dot
+0.70 setlinewidth
+475.96 173.55 moveto
+475.96 154.95 lineto stroke
+682.24 166.95 1.000000 4rest
+690.54 169.95 1.000000 dot
+restore
+%  S_BAR
+331 linenum
+0.70 setlinewidth
+735.35 822.68 moveto
+735.35 798.68 lineto stroke
+738.35 822.68 moveto
+738.35 798.68 lineto stroke
+735.35 742.26 moveto
+735.35 718.26 lineto stroke
+738.35 742.26 moveto
+738.35 718.26 lineto stroke
+735.35 676.26 moveto
+735.35 657.06 lineto stroke
+738.35 676.26 moveto
+738.35 657.06 lineto stroke
+735.35 609.06 moveto
+735.35 597.06 lineto stroke
+738.35 609.06 moveto
+738.35 597.06 lineto stroke
+735.35 536.13 moveto
+735.35 430.01 lineto stroke
+738.35 536.13 moveto
+738.35 430.01 lineto stroke
+735.35 339.00 moveto
+735.35 220.95 lineto stroke
+738.35 339.00 moveto
+738.35 220.95 lineto stroke
+735.35 178.95 moveto
+735.35 154.95 lineto stroke
+738.35 178.95 moveto
+738.35 154.95 lineto stroke
+%  S_FEED
+336 linenum
+%  Printing header/footer
+/Times-Roman findfont
+18 scalefont
+setfont
+251.47 939.19 moveto
+(Sample Song to Show What Mup Can Do) show
+/Palatino-Italic findfont
+12 scalefont
+setfont
+362.15 925.15 moveto
+(This is a subtitle) show
+/Times-Roman findfont
+12 scalefont
+setfont
+65.45 912.33 moveto
+(Text: Ann Onymous) show
+/Times-Roman findfont
+12 scalefont
+setfont
+625.73 912.33 moveto
+(Tune: Arthur Unknown) show
+/Times-Roman findfont
+12 scalefont
+setfont
+65.45 899.51 moveto
+/Times-Roman findfont
+12 scalefont
+setfont
+706.88 899.51 moveto
+(\(1995\)) show
+/Times-Roman findfont
+12 scalefont
+setfont
+323.99 103.77 moveto
+(This is a sample of a Mup footer) show
+/Times-Roman findfont
+12 scalefont
+setfont
+400.57 90.96 moveto
+( ) show
+/Times-Roman findfont
+11 scalefont
+setfont
+65.45 79.21 moveto
+(Published by Arkkra Enterprises) show
+/Times-Roman findfont
+11 scalefont
+setfont
+320.17 79.21 moveto
+(P. O. Box 315 Warrenville, IL 60555) show
+/Times-Roman findfont
+11 scalefont
+setfont
+636.34 79.21 moveto
+(http://www.arkkra.com) show
+showpage
+restore
+%%Page: 2 2
+save
+1361190600 1361190394 sv
+0.770000 0.770000 scale
+/Times-Roman findfont
+12 scalefont
+setfont
+364.28 930.22 moveto
+(First movement) show
+240.05 1338.43 1098.70 5 1.000000 1.000000 stf
+/Helvetica-Oblique findfont
+9 scalefont
+setfont
+100.55 860.43 moveto
+(3) show
+240.05 1255.27 1098.70 5 1.000000 1.000000 stf
+240.05 1191.67 1098.70 5 1.000000 0.800000 stf
+240.05 1125.09 1098.70 1 1.000000 1.000000 stf
+240.05 1052.07 1098.70 5 1.000000 1.000000 stf
+/Helvetica-Oblique findfont
+9 scalefont
+setfont
+100.55 574.07 moveto
+(3) show
+240.05 979.83 1098.70 5 1.000000 1.000000 stf
+240.05 895.55 1098.70 5 1.000000 1.000000 stf
+/Helvetica-Oblique findfont
+9 scalefont
+setfont
+100.55 417.55 moveto
+(3) show
+240.05 791.31 1098.70 6 1.735000 1.000000 stf
+240.05 711.29 1098.70 5 1.000000 1.000000 stf
+/Times-Roman findfont
+12 scalefont
+setfont
+72.08 788.82 moveto
+(Ch) show
+/Times-Roman findfont
+12 scalefont
+setfont
+65.45 507.92 moveto
+(Kbd) show
+/Times-Roman findfont
+12 scalefont
+setfont
+70.13 335.40 moveto
+(Gtr) show
+94.05 849.43 736.27 bracket
+95.55 560.07 463.83 brace
+94.05 406.55 258.29 bracket
+0.70 setlinewidth
+96.05 846.43 moveto
+96.05 195.29 lineto stroke
+316.27 429.55 moveto
+316.27 440.55 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+319.27 430.55 moveto
+(1.) show
+316.27 440.55 moveto
+419.86 440.55 lineto stroke
+419.86 440.55 moveto
+419.86 429.55 lineto stroke
+316.27 578.09 moveto
+316.27 589.09 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+319.27 579.09 moveto
+(1.) show
+316.27 589.09 moveto
+419.86 589.09 lineto stroke
+419.86 589.09 moveto
+419.86 578.09 lineto stroke
+316.27 899.98 moveto
+316.27 910.98 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+319.27 900.98 moveto
+(1.) show
+316.27 910.98 moveto
+419.86 910.98 lineto stroke
+419.86 910.98 moveto
+419.86 899.98 lineto stroke
+423.86 429.55 moveto
+423.86 440.55 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+426.86 430.55 moveto
+(2.) show
+423.86 440.55 moveto
+579.34 440.55 lineto stroke
+423.86 578.09 moveto
+423.86 589.09 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+426.86 579.09 moveto
+(2.) show
+423.86 589.09 moveto
+579.34 589.09 lineto stroke
+423.86 899.98 moveto
+423.86 910.98 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+426.86 900.98 moveto
+(2.) show
+423.86 910.98 moveto
+579.34 910.98 lineto stroke
+%  S_CLEFSIG
+107.84 828.43 1.000000 gclef
+108.09 757.27 1.000000 fclef
+104.47 697.27 0.800000 cclef
+102.05 613.59 moveto
+102.05 628.59 lineto stroke
+104.15 613.59 moveto
+104.15 628.59 lineto stroke
+107.84 542.07 1.000000 gclef
+108.09 481.83 1.000000 fclef
+107.84 385.55 1.000000 gclef
+107.84 201.29 1.000000 gclef
+121.88 834.43 1.000000 flat
+127.37 843.43 1.000000 flat
+132.85 831.43 1.000000 flat
+121.88 745.27 1.000000 flat
+127.37 754.27 1.000000 flat
+132.85 742.27 1.000000 flat
+121.99 687.67 0.800000 sharp
+127.45 697.27 0.800000 sharp
+132.90 690.07 0.800000 sharp
+121.88 548.07 1.000000 flat
+127.37 557.07 1.000000 flat
+132.85 545.07 1.000000 flat
+121.88 469.83 1.000000 flat
+127.37 478.83 1.000000 flat
+132.85 466.83 1.000000 flat
+121.88 391.55 1.000000 flat
+127.37 400.55 1.000000 flat
+132.85 388.55 1.000000 flat
+121.88 207.29 1.000000 flat
+127.37 216.29 1.000000 flat
+132.85 204.29 1.000000 flat
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+165.79 816.43 1.000000 2n
+175.27 819.43 1.000000 dot
+159.34 816.43 moveto
+172.24 816.43 lineto stroke
+169.69 817.18 moveto
+169.69 837.43 lineto stroke
+267.32 828.43 1.000000 4n
+276.59 831.43 1.000000 dot
+271.01 829.18 moveto
+271.01 849.43 lineto stroke
+/Times-Roman findfont
+14 scalefont
+setfont
+155.67 887.89 moveto
+(Cm) show
+153.79 880.03 4.80 5 3 1 2 6 [ -2 1 3 3 2 1 ] grid
+restore
+%  S_STAFF
+% staff 2
+save
+165.79 754.27 1.000000 4n
+175.06 754.27 1.000000 dot
+0.70 setlinewidth
+162.11 753.52 moveto
+162.11 733.27 lineto stroke
+213.33 754.27 1.000000 4n
+222.59 754.27 1.000000 dot
+229.06 754.27 1.000000 dot
+209.65 753.52 moveto
+209.65 729.77 lineto stroke
+242.03 757.27 1.000000 4n
+238.35 756.52 moveto
+238.35 733.85 lineto stroke
+252.89 760.27 1.000000 4n
+249.20 759.52 moveto
+249.20 735.39 lineto stroke
+267.32 748.27 1.000000 4n
+276.59 748.27 1.000000 dot
+271.01 749.02 moveto
+271.01 769.27 lineto stroke
+newpath
+209.30 731.27 moveto
+249.55 736.89 lineto
+249.55 733.89 lineto
+209.30 728.27 lineto
+closepath
+fill
+newpath
+238.00 740.35 moveto
+229.94 739.21 lineto
+229.94 736.21 lineto
+238.00 737.35 lineto
+closepath
+fill
+newpath
+238.00 745.35 moveto
+229.94 744.21 lineto
+229.94 741.21 lineto
+238.00 742.35 lineto
+closepath
+fill
+198.10 722.27 moveto
+278.32 726.27 lineto stroke
+198.10 722.27 moveto
+278.32 718.26 lineto stroke
+restore
+%  S_STAFF
+% staff 3
+save
+165.79 690.07 0.800000 2n
+158.97 690.07 0.800000 nat
+173.38 690.07 0.800000 dot
+178.70 690.07 0.800000 dot
+0.56 setlinewidth
+162.67 689.47 moveto
+162.67 673.27 lineto stroke
+289.31 690.07 0.800000 4n
+286.37 689.47 moveto
+286.37 673.27 lineto stroke
+/Palatino-Roman findfont
+11 scalefont
+setfont
+282.58 701.96 moveto
+289.31 701.96 0.916667 turn
+296.04 701.96 moveto
+173.15 703.79 moveto
+267.32 703.79 0.800000 wavy
+/Palatino-Roman findfont
+11 scalefont
+setfont
+158.43 698.99 moveto
+165.79 698.99 0.916667 tr
+173.15 698.99 moveto
+restore
+%  S_STAFF
+% staff 4
+save
+165.79 621.09 1.000000 2n
+175.27 624.09 1.000000 dot
+0.70 setlinewidth
+169.69 621.84 moveto
+169.69 642.09 lineto stroke
+newpath
+164.69 628.39 moveto
+164.69 631.39 lineto
+174.69 635.79 lineto
+174.69 632.79 lineto
+closepath
+fill
+newpath
+164.69 633.39 moveto
+164.69 636.39 lineto
+174.69 640.79 lineto
+174.69 637.79 lineto
+closepath
+fill
+267.32 621.09 1.000000 4n
+276.59 624.09 1.000000 dot
+/Palatino-Roman findfont
+14 scalefont
+setfont
+264.72 614.55 moveto
+267.32 614.55 1.166667 dot
+269.93 614.55 moveto
+271.01 621.84 moveto
+271.01 642.09 lineto stroke
+restore
+%  S_STAFF
+% staff 5
+save
+165.79 542.07 1.000000 4n
+175.06 545.07 1.000000 dot
+165.79 536.07 1.000000 4n
+175.06 539.07 1.000000 dot
+165.79 530.07 1.000000 4n
+175.06 533.07 1.000000 dot
+0.70 setlinewidth
+159.56 530.07 moveto
+172.02 530.07 lineto stroke
+169.47 530.82 moveto
+169.47 563.07 lineto stroke
+154.76 545.35 moveto
+154.76 526.79 1.000000 wavy
+154.76 548.35 moveto
+150.76 540.35 lineto stroke
+154.76 548.35 moveto
+158.76 540.35 lineto stroke
+213.33 542.07 1.000000 4n
+222.59 545.07 1.000000 dot
+213.33 536.07 1.000000 4n
+222.59 539.07 1.000000 dot
+213.33 530.07 1.000000 4n
+222.59 533.07 1.000000 dot
+207.10 530.07 moveto
+219.56 530.07 lineto stroke
+217.01 530.82 moveto
+217.01 563.07 lineto stroke
+202.30 545.35 moveto
+202.30 526.79 1.000000 wavy
+202.30 523.79 moveto
+198.30 531.79 lineto stroke
+202.30 523.79 moveto
+206.30 531.79 lineto stroke
+267.32 542.07 1.000000 4n
+276.59 545.07 1.000000 dot
+267.32 536.07 1.000000 4n
+276.59 539.07 1.000000 dot
+267.32 530.07 1.000000 4n
+276.59 533.07 1.000000 dot
+261.09 530.07 moveto
+273.56 530.07 lineto stroke
+271.01 530.82 moveto
+271.01 563.07 lineto stroke
+256.29 545.35 moveto
+256.29 526.79 1.000000 wavy
+/Times-BoldItalic findfont
+14 scalefont
+setfont
+265.01 512.04 moveto
+(ff ) show
+restore
+%  S_STAFF
+% staff 6
+save
+164.02 478.83 0.583333 2n
+175.27 478.83 1.000000 dot
+165.79 472.83 1.000000 2n
+175.27 472.83 1.000000 dot
+0.70 setlinewidth
+161.89 478.34 moveto
+161.89 451.83 lineto stroke
+267.32 478.83 1.000000 4n
+263.64 478.08 moveto
+263.64 457.83 lineto stroke
+266.67 457.83 1.000000 upflag
+289.31 472.83 1.000000 4n
+292.99 473.58 moveto
+292.99 493.83 lineto stroke
+269.32 483.93 moveto
+269.33 484.16 lineto
+272.99 485.22 276.63 485.20 280.27 484.11 curveto
+283.91 483.01 286.97 481.02 289.43 478.12 curveto
+289.19 477.73 lineto
+286.48 480.14 283.39 481.87 279.92 482.92 curveto
+276.44 483.96 272.91 484.22 269.32 483.69 curveto
+fill
+restore
+%  S_STAFF
+% staff 7
+save
+165.79 409.55 1.000000 4n
+157.34 409.55 1.000000 nat
+175.06 412.55 1.000000 dot
+0.70 setlinewidth
+159.56 409.55 moveto
+172.02 409.55 lineto stroke
+169.47 410.30 moveto
+169.47 430.55 lineto stroke
+213.33 412.55 1.000000 4n
+222.59 412.55 1.000000 dot
+207.10 409.55 moveto
+219.56 409.55 lineto stroke
+217.01 413.30 moveto
+217.01 433.55 lineto stroke
+267.32 412.55 1.000000 4n
+258.87 412.55 1.000000 nat
+261.09 409.55 moveto
+273.56 409.55 lineto stroke
+271.01 413.30 moveto
+271.01 433.55 lineto stroke
+274.03 433.55 1.000000 dnflag
+289.31 409.55 1.000000 4n
+283.08 409.55 moveto
+295.54 409.55 lineto stroke
+292.99 410.30 moveto
+292.99 430.55 lineto stroke
+165.79 385.55 1.000000 4n
+175.06 382.55 1.000000 dot
+162.11 384.80 moveto
+162.11 364.55 lineto stroke
+213.33 385.55 1.000000 4n
+209.65 384.80 moveto
+209.65 364.55 lineto stroke
+252.89 385.55 1.000000 4n
+249.20 384.80 moveto
+249.20 364.55 lineto stroke
+252.23 364.55 1.000000 upflag
+267.32 385.55 1.000000 4n
+276.59 382.55 1.000000 dot
+263.64 384.80 moveto
+263.64 364.55 lineto stroke
+273.36 417.65 moveto
+281.86 418.94 lineto stroke
+281.86 418.94 moveto
+289.31 414.65 lineto stroke
+227.59 417.65 moveto
+247.46 425.75 lineto stroke
+247.46 425.75 moveto
+267.32 417.65 lineto stroke
+180.06 414.65 moveto
+195.97 424.22 lineto stroke
+195.97 424.22 moveto
+213.33 417.65 lineto stroke
+restore
+%  S_STAFF
+% staff 8
+save
+162.44 307.87 169.14 318.81 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+162.44 309.09 moveto
+(5) show
+/Helvetica findfont
+12 scalefont
+setfont
+204.98 331.11 moveto
+(1/2) show
+0.70 setlinewidth
+171.64 314.34 moveto
+173.72 314.22 175.81 314.22 177.89 314.34 curveto
+185.58 314.76 193.26 315.32 200.82 316.86 curveto
+202.25 317.15 203.69 317.42 204.99 318.12 curveto
+208.24 319.87 211.64 321.45 213.33 325.06 curveto
+213.63 325.69 213.63 326.32 213.33 326.95 curveto
+stroke
+213.33 324.53 1.000000 uwedge
+/Helvetica findfont
+12 scalefont
+setfont
+259.66 346.72 moveto
+(full) show
+213.33 327.95 moveto
+216.03 327.82 218.73 327.82 221.43 327.95 curveto
+231.38 328.44 241.31 329.08 251.13 330.88 curveto
+252.97 331.21 254.82 331.51 256.53 332.34 curveto
+260.63 334.33 265.07 335.89 267.32 340.38 curveto
+267.69 341.11 267.69 341.84 267.32 342.57 curveto
+stroke
+267.32 340.15 1.000000 uwedge
+267.32 343.57 moveto
+268.42 343.80 269.52 343.80 270.62 343.57 curveto
+275.03 342.64 279.11 340.95 282.72 338.21 curveto
+283.66 337.49 284.36 336.57 284.92 335.53 curveto
+287.37 330.91 288.56 325.91 289.31 320.78 curveto
+289.51 319.44 289.51 318.10 289.31 316.76 curveto
+stroke
+289.31 314.34 1.000000 wedge
+162.44 287.05 169.14 297.99 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+162.44 288.20 moveto
+(0) show
+209.98 287.05 216.68 297.99 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+209.98 288.20 moveto
+(0) show
+249.54 287.05 256.23 297.99 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+249.54 288.20 moveto
+(0) show
+263.98 287.05 270.67 297.99 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+263.98 288.20 moveto
+(0) show
+restore
+%  S_STAFF
+% staff 9
+save
+165.79 210.29 1.000000 fillrectangle
+0.70 setlinewidth
+161.89 210.29 moveto
+161.89 191.55 lineto stroke
+180.19 207.29 1.000000 4n
+176.51 206.54 moveto
+176.51 188.89 lineto stroke
+198.10 204.29 1.000000 ufillrighttriangle
+189.43 204.29 1.000000 nat
+194.20 204.29 moveto
+194.20 185.57 lineto stroke
+213.33 201.29 1.000000 filldiamond
+217.23 201.29 moveto
+217.23 216.99 lineto stroke
+227.77 189.29 1.000000 fillrectangle
+221.32 189.29 moveto
+234.22 189.29 lineto stroke
+231.67 189.29 moveto
+231.67 214.26 lineto stroke
+252.89 192.29 1.000000 fillpiewedge
+256.78 192.59 moveto
+256.78 209.52 lineto stroke
+267.32 195.29 1.000000 fillisostriangle
+276.80 198.29 1.000000 dot
+271.22 192.89 moveto
+271.22 216.29 lineto stroke
+newpath
+161.54 193.05 moveto
+194.55 187.07 lineto
+194.55 184.07 lineto
+161.54 190.05 lineto
+closepath
+fill
+newpath
+216.88 218.49 moveto
+257.13 211.02 lineto
+257.13 208.02 lineto
+216.88 215.49 lineto
+closepath
+fill
+restore
+%  S_LINE
+345 linenum
+gsave
+179.04 816.43 translate
+9.1 rotate
+/Palatino-Italic findfont
+11 scalefont
+setfont
+26.65 6.89 moveto
+(gliss.) show
+grestore
+179.04 816.43 moveto
+254.29 828.43 1.000000 wavy
+%  S_CURVE
+480 linenum
+441.19 484.83 moveto
+441.10 484.94 lineto
+461.94 513.57 488.54 535.07 520.90 549.43 curveto
+547.42 561.20 574.40 569.92 603.93 562.46 curveto
+641.95 552.86 670.65 531.02 690.05 496.95 curveto
+689.87 496.71 lineto
+670.10 530.27 641.31 551.71 603.49 561.03 curveto
+574.36 568.21 547.73 559.54 521.55 548.08 curveto
+489.27 533.95 462.52 512.83 441.29 484.71 curveto
+fill
+%  S_BAR
+388 linenum
+0.70 setlinewidth
+314.27 846.43 moveto
+314.27 822.43 lineto stroke
+314.27 763.27 moveto
+314.27 739.27 lineto stroke
+314.27 697.27 moveto
+314.27 678.07 lineto stroke
+314.27 627.09 moveto
+314.27 615.09 lineto stroke
+314.27 560.07 moveto
+314.27 463.83 lineto stroke
+314.27 403.55 moveto
+314.27 261.29 lineto stroke
+314.27 219.29 moveto
+314.27 195.29 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+1.50 setlinewidth
+331.38 828.43 moveto
+331.38 840.43 lineto stroke
+400.24 828.43 moveto
+400.24 840.43 lineto stroke
+3.00 setlinewidth
+331.38 834.43 moveto
+400.24 834.43 lineto stroke
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+361.20 849.43 moveto
+(2) show
+restore
+%  S_STAFF
+% staff 2
+save
+1.50 setlinewidth
+331.38 745.27 moveto
+331.38 757.27 lineto stroke
+400.24 745.27 moveto
+400.24 757.27 lineto stroke
+3.00 setlinewidth
+331.38 751.27 moveto
+400.24 751.27 lineto stroke
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+361.20 766.27 moveto
+(2) show
+restore
+%  S_STAFF
+% staff 3
+save
+1.20 setlinewidth
+335.22 682.87 moveto
+335.22 692.47 lineto stroke
+396.40 682.87 moveto
+396.40 692.47 lineto stroke
+2.40 setlinewidth
+335.22 687.67 moveto
+396.40 687.67 lineto stroke
+/NewCenturySchlbk-Bold findfont
+13 scalefont
+setfont
+362.07 699.67 moveto
+(2) show
+restore
+%  S_STAFF
+% staff 4
+save
+1.50 setlinewidth
+331.38 615.09 moveto
+331.38 627.09 lineto stroke
+400.24 615.09 moveto
+400.24 627.09 lineto stroke
+3.00 setlinewidth
+331.38 621.09 moveto
+400.24 621.09 lineto stroke
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+361.20 627.09 moveto
+(2) show
+restore
+%  S_STAFF
+% staff 5
+save
+1.50 setlinewidth
+331.38 542.07 moveto
+331.38 554.07 lineto stroke
+400.24 542.07 moveto
+400.24 554.07 lineto stroke
+3.00 setlinewidth
+331.38 548.07 moveto
+400.24 548.07 lineto stroke
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+361.20 563.07 moveto
+(2) show
+restore
+%  S_STAFF
+% staff 6
+save
+1.50 setlinewidth
+331.38 469.83 moveto
+331.38 481.83 lineto stroke
+400.24 469.83 moveto
+400.24 481.83 lineto stroke
+3.00 setlinewidth
+331.38 475.83 moveto
+400.24 475.83 lineto stroke
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+361.20 490.83 moveto
+(2) show
+restore
+%  S_STAFF
+% staff 7
+save
+1.50 setlinewidth
+331.38 385.55 moveto
+331.38 397.55 lineto stroke
+400.24 385.55 moveto
+400.24 397.55 lineto stroke
+3.00 setlinewidth
+331.38 391.55 moveto
+400.24 391.55 lineto stroke
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+361.20 406.55 moveto
+(2) show
+restore
+%  S_STAFF
+% staff 8
+save
+restore
+%  S_STAFF
+% staff 9
+save
+1.50 setlinewidth
+331.38 201.29 moveto
+331.38 213.29 lineto stroke
+400.24 201.29 moveto
+400.24 213.29 lineto stroke
+3.00 setlinewidth
+331.38 207.29 moveto
+400.24 207.29 lineto stroke
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+361.20 222.29 moveto
+(2) show
+restore
+%  S_BAR
+394 linenum
+417.86 837.43 1.000000 dot
+417.86 831.43 1.000000 dot
+0.70 setlinewidth
+421.86 846.43 moveto
+421.86 822.43 lineto stroke
+3.00 setlinewidth
+425.86 846.43 moveto
+425.86 822.43 lineto stroke
+0.70 setlinewidth
+417.86 754.27 1.000000 dot
+417.86 748.27 1.000000 dot
+421.86 763.27 moveto
+421.86 739.27 lineto stroke
+3.00 setlinewidth
+425.86 763.27 moveto
+425.86 739.27 lineto stroke
+0.70 setlinewidth
+417.86 690.07 0.800000 dot
+417.86 685.27 0.800000 dot
+421.86 697.27 moveto
+421.86 678.07 lineto stroke
+3.00 setlinewidth
+425.86 697.27 moveto
+425.86 678.07 lineto stroke
+0.70 setlinewidth
+417.86 624.09 1.000000 dot
+417.86 618.09 1.000000 dot
+421.86 627.09 moveto
+421.86 615.09 lineto stroke
+3.00 setlinewidth
+425.86 627.09 moveto
+425.86 615.09 lineto stroke
+0.70 setlinewidth
+417.86 551.07 1.000000 dot
+417.86 545.07 1.000000 dot
+417.86 478.83 1.000000 dot
+417.86 472.83 1.000000 dot
+421.86 560.07 moveto
+421.86 463.83 lineto stroke
+3.00 setlinewidth
+425.86 560.07 moveto
+425.86 463.83 lineto stroke
+0.70 setlinewidth
+417.86 394.55 1.000000 dot
+417.86 388.55 1.000000 dot
+417.86 297.72 1.000000 dot
+417.86 276.90 1.000000 dot
+421.86 403.55 moveto
+421.86 261.29 lineto stroke
+3.00 setlinewidth
+425.86 403.55 moveto
+425.86 261.29 lineto stroke
+0.70 setlinewidth
+417.86 210.29 1.000000 dot
+417.86 204.29 1.000000 dot
+421.86 219.29 moveto
+421.86 195.29 lineto stroke
+3.00 setlinewidth
+425.86 219.29 moveto
+425.86 195.29 lineto stroke
+0.70 setlinewidth
+%  S_SSV
+398 linenum
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+423 linenum
+/Helvetica-Oblique findfont
+14 scalefont
+setfont
+466.96 787.40 moveto
+(-) show
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+435.17 787.40 moveto
+/Helvetica-Oblique findfont
+14 scalefont
+setfont
+(Ma) show
+/Helvetica-Oblique findfont
+14 scalefont
+setfont
+511.97 787.40 moveto
+(-) show
+/Helvetica-Oblique findfont
+14 scalefont
+setfont
+482.26 787.40 moveto
+/Ext-Helvetica-Oblique findfont
+14 scalefont
+setfont
+(f) show
+/Helvetica-Oblique findfont
+14 scalefont
+setfont
+(a) show
+/Helvetica-Oblique findfont
+14 scalefont
+setfont
+529.04 787.40 moveto
+(na) show
+441.19 822.43 1.000000 4n
+450.46 825.43 1.000000 dot
+441.19 816.43 1.000000 4n
+450.46 819.43 1.000000 dot
+434.96 816.43 moveto
+447.43 816.43 lineto stroke
+444.88 817.18 moveto
+444.88 843.43 lineto stroke
+487.32 828.43 1.000000 4n
+496.59 831.43 1.000000 dot
+487.32 822.43 1.000000 4n
+496.59 825.43 1.000000 dot
+491.01 823.18 moveto
+491.01 849.43 lineto stroke
+532.95 822.43 1.000000 4n
+542.21 825.43 1.000000 dot
+532.95 816.43 1.000000 4n
+542.21 819.43 1.000000 dot
+526.72 816.43 moveto
+539.18 816.43 lineto stroke
+536.63 817.18 moveto
+536.63 843.43 lineto stroke
+441.94 810.16 moveto
+441.95 810.31 lineto
+483.13 806.43 524.40 804.99 565.75 805.99 curveto
+607.10 806.99 648.25 810.43 689.19 816.31 curveto
+689.22 816.01 lineto
+648.34 809.33 607.20 805.50 565.79 804.49 curveto
+524.38 803.49 483.09 805.33 441.94 810.01 curveto
+fill
+/Times-Roman findfont
+14 scalefont
+setfont
+431.07 887.89 moveto
+(Cm) show
+429.19 880.03 4.80 5 3 1 2 6 [ -2 1 3 3 2 1 ] grid
+restore
+%  S_STAFF
+% staff 2
+save
+441.19 760.27 1.000000 4n
+450.46 760.27 1.000000 dot
+441.19 748.27 1.000000 4n
+450.46 748.27 1.000000 dot
+0.70 setlinewidth
+437.51 759.52 moveto
+437.51 727.27 lineto stroke
+487.32 754.27 1.000000 4n
+496.59 754.27 1.000000 dot
+487.32 748.27 1.000000 4n
+496.59 748.27 1.000000 dot
+483.64 753.52 moveto
+483.64 727.27 lineto stroke
+532.95 760.27 1.000000 4n
+542.21 760.27 1.000000 dot
+532.95 748.27 1.000000 4n
+542.21 748.27 1.000000 dot
+529.27 759.52 moveto
+529.27 727.27 lineto stroke
+441.94 766.54 moveto
+441.94 766.69 lineto
+483.09 771.38 524.38 773.21 565.79 772.21 curveto
+607.20 771.20 648.34 767.37 689.22 760.69 curveto
+689.19 760.39 lineto
+648.25 766.27 607.10 769.71 565.75 770.71 curveto
+524.40 771.71 483.13 770.27 441.95 766.39 curveto
+fill
+restore
+%  S_STAFF
+% staff 3
+save
+441.19 699.67 0.800000 4n
+433.86 699.67 0.800000 sharp
+448.61 699.67 0.800000 dot
+0.56 setlinewidth
+438.25 699.07 moveto
+438.25 682.87 lineto stroke
+487.32 702.07 0.800000 4n
+494.74 704.47 0.800000 dot
+482.34 702.07 moveto
+492.31 702.07 lineto stroke
+484.38 701.47 moveto
+484.38 685.27 lineto stroke
+532.95 699.67 0.800000 4n
+/Times-Roman findfont
+10 scalefont
+setfont
+515.68 697.15 moveto
+(\() show
+522.58 699.67 0.800000 sharp
+/Times-Roman findfont
+10 scalefont
+setfont
+526.18 697.15 moveto
+(\)) show
+540.36 699.67 0.800000 dot
+530.00 699.07 moveto
+530.00 682.87 lineto stroke
+restore
+%  S_STAFF
+% staff 4
+save
+441.19 624.09 1.000000 xnote
+450.67 624.09 1.000000 dot
+0.70 setlinewidth
+445.09 627.09 moveto
+445.09 645.09 lineto stroke
+487.32 624.09 1.000000 xnote
+496.80 624.09 1.000000 dot
+491.22 627.09 moveto
+491.22 645.09 lineto stroke
+532.95 624.09 1.000000 xnote
+536.85 627.09 moveto
+536.85 643.59 lineto stroke
+548.18 624.09 1.000000 xnote
+552.07 627.09 moveto
+552.07 643.59 lineto stroke
+564.28 624.09 1.000000 xnote
+568.18 627.09 moveto
+568.18 643.59 lineto stroke
+newpath
+536.50 645.09 moveto
+568.53 645.09 lineto
+568.53 642.09 lineto
+536.50 642.09 lineto
+closepath
+fill
+441.19 618.09 1.000000 4n
+450.67 618.09 1.000000 dot
+437.51 617.34 moveto
+437.51 597.09 lineto stroke
+487.32 618.09 1.000000 4n
+496.80 618.09 1.000000 dot
+483.64 617.34 moveto
+483.64 597.09 lineto stroke
+532.95 618.09 1.000000 4n
+542.43 618.09 1.000000 dot
+529.27 617.34 moveto
+529.27 597.09 lineto stroke
+restore
+%  S_STAFF
+% staff 5
+save
+532.95 530.07 1.000000 4n
+0.70 setlinewidth
+526.72 530.07 moveto
+539.18 530.07 lineto stroke
+529.27 529.32 moveto
+529.27 508.67 lineto stroke
+548.18 536.07 1.000000 4n
+544.49 535.32 moveto
+544.49 514.67 lineto stroke
+564.28 542.07 1.000000 4n
+560.60 541.32 moveto
+560.60 521.02 lineto stroke
+newpath
+444.53 477.21 moveto
+560.95 522.52 lineto
+560.95 519.52 lineto
+444.53 474.21 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 6
+save
+441.19 451.83 1.000000 4n
+0.70 setlinewidth
+434.96 451.83 moveto
+447.43 451.83 lineto stroke
+434.96 457.83 moveto
+447.43 457.83 lineto stroke
+444.88 452.58 moveto
+444.88 475.71 lineto stroke
+456.81 457.83 1.000000 4n
+450.58 457.83 moveto
+463.04 457.83 lineto stroke
+460.49 458.58 moveto
+460.49 481.86 lineto stroke
+471.69 463.83 1.000000 4n
+475.37 464.58 moveto
+475.37 487.72 lineto stroke
+487.32 472.83 1.000000 4n
+491.01 473.58 moveto
+491.01 493.88 lineto stroke
+502.57 478.83 1.000000 4n
+506.25 479.58 moveto
+506.25 499.88 lineto stroke
+517.88 484.83 1.000000 4n
+521.56 485.58 moveto
+521.56 505.92 lineto stroke
+restore
+%  S_STAFF
+% staff 7
+save
+441.19 406.55 1.000000 2n
+450.67 406.55 1.000000 dot
+441.19 400.55 1.000000 2n
+450.67 400.55 1.000000 dot
+441.19 394.55 1.000000 2n
+450.67 394.55 1.000000 dot
+441.19 385.55 1.000000 2n
+450.67 388.55 1.000000 dot
+441.19 373.55 1.000000 2n
+450.67 376.55 1.000000 dot
+0.70 setlinewidth
+434.75 373.55 moveto
+447.64 373.55 lineto stroke
+445.09 374.30 moveto
+445.09 427.55 lineto stroke
+532.95 406.55 1.000000 4n
+542.21 406.55 1.000000 dot
+532.95 400.55 1.000000 4n
+542.21 400.55 1.000000 dot
+532.95 394.55 1.000000 4n
+542.21 394.55 1.000000 dot
+532.95 385.55 1.000000 4n
+542.21 388.55 1.000000 dot
+532.95 373.55 1.000000 4n
+542.21 376.55 1.000000 dot
+526.72 373.55 moveto
+539.18 373.55 lineto stroke
+536.63 374.30 moveto
+536.63 427.55 lineto stroke
+534.95 368.45 moveto
+534.97 368.60 lineto
+543.73 366.33 552.62 365.19 561.67 365.19 curveto
+570.71 365.19 579.61 366.33 588.37 368.60 curveto
+588.41 368.30 lineto
+579.76 365.23 570.85 363.69 561.67 363.69 curveto
+552.49 363.69 543.58 365.23 534.93 368.30 curveto
+fill
+547.21 385.55 moveto
+547.24 385.73 lineto
+553.16 384.21 559.17 383.45 565.28 383.45 curveto
+571.40 383.45 577.41 384.21 583.33 385.73 curveto
+583.38 385.37 lineto
+577.53 383.27 571.50 382.22 565.28 382.22 curveto
+559.07 382.22 553.04 383.27 547.19 385.37 curveto
+fill
+547.21 394.55 moveto
+547.24 394.73 lineto
+553.16 393.21 559.17 392.45 565.28 392.45 curveto
+571.40 392.45 577.41 393.21 583.33 394.73 curveto
+583.38 394.37 lineto
+577.53 392.27 571.50 391.22 565.28 391.22 curveto
+559.07 391.22 553.04 392.27 547.19 394.37 curveto
+fill
+547.21 400.55 moveto
+547.24 400.73 lineto
+553.16 399.21 559.17 398.45 565.28 398.45 curveto
+571.40 398.45 577.41 399.21 583.33 400.73 curveto
+583.38 400.37 lineto
+577.53 398.27 571.50 397.22 565.28 397.22 curveto
+559.07 397.22 553.04 398.27 547.19 400.37 curveto
+fill
+547.21 411.65 moveto
+547.19 411.81 lineto
+554.17 414.33 561.38 415.58 568.80 415.58 curveto
+576.22 415.58 583.43 414.33 590.41 411.81 curveto
+590.36 411.49 lineto
+583.29 413.29 576.10 414.19 568.80 414.19 curveto
+561.50 414.19 554.31 413.29 547.24 411.49 curveto
+fill
+restore
+%  S_STAFF
+% staff 8
+save
+437.85 307.87 444.54 318.81 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+437.85 309.09 moveto
+(3) show
+437.85 297.67 444.54 308.19 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+437.85 298.68 moveto
+(4) show
+437.85 287.05 444.54 297.99 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+437.85 288.27 moveto
+(5) show
+437.85 276.64 444.54 287.58 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+437.85 277.86 moveto
+(5) show
+437.85 266.23 444.54 277.17 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+437.85 267.45 moveto
+(3) show
+529.60 307.87 536.30 318.81 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+529.60 309.09 moveto
+(3) show
+529.60 297.67 536.30 308.19 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+529.60 298.68 moveto
+(4) show
+529.60 287.05 536.30 297.99 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+529.60 288.27 moveto
+(5) show
+529.60 276.64 536.30 287.58 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+529.60 277.86 moveto
+(5) show
+529.60 266.23 536.30 277.17 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+529.60 267.45 moveto
+(3) show
+restore
+%  S_STAFF
+% staff 9
+save
+441.19 201.29 1.000000 filldiamond
+0.70 setlinewidth
+445.09 201.29 moveto
+445.09 219.99 lineto stroke
+456.81 195.29 1.000000 fillisostriangle
+460.71 192.89 moveto
+460.71 216.90 lineto stroke
+471.69 195.29 1.000000 fillisostriangle
+475.59 192.89 moveto
+475.59 213.95 lineto stroke
+487.32 207.29 1.000000 fillslashhead
+498.89 210.29 1.000000 dot
+481.34 201.89 moveto
+481.34 186.29 lineto stroke
+532.95 207.29 1.000000 fillslashhead
+544.52 210.29 1.000000 dot
+526.96 201.89 moveto
+526.96 186.29 lineto stroke
+newpath
+444.74 221.49 moveto
+475.94 215.45 lineto
+475.94 212.45 lineto
+444.74 218.49 lineto
+closepath
+fill
+restore
+%  S_BAR
+454 linenum
+0.70 setlinewidth
+581.34 846.43 moveto
+581.34 822.43 lineto stroke
+581.34 763.27 moveto
+581.34 739.27 lineto stroke
+581.34 697.27 moveto
+581.34 678.07 lineto stroke
+581.34 627.09 moveto
+581.34 615.09 lineto stroke
+581.34 560.07 moveto
+581.34 463.83 lineto stroke
+581.34 403.55 moveto
+581.34 261.29 lineto stroke
+581.34 219.29 moveto
+581.34 195.29 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+459 linenum
+/Helvetica-Oblique findfont
+14 scalefont
+setfont
+585.52 787.40 moveto
+(am) show
+/Helvetica-Oblique findfont
+14 scalefont
+setfont
+670.61 787.40 moveto
+(-) show
+/Helvetica-Oblique findfont
+14 scalefont
+setfont
+626.45 787.40 moveto
+(gr) show
+/Ext-Helvetica-Oblique findfont
+14 scalefont
+setfont
+(lF) show
+/Helvetica-Oblique findfont
+14 scalefont
+setfont
+(t) show
+/Helvetica-Oblique findfont
+14 scalefont
+setfont
+685.09 787.40 moveto
+(en,) show
+590.39 822.43 1.000000 4n
+599.65 825.43 1.000000 dot
+590.39 816.43 1.000000 4n
+599.65 819.43 1.000000 dot
+584.16 816.43 moveto
+596.62 816.43 lineto stroke
+594.07 817.18 moveto
+594.07 843.43 lineto stroke
+635.77 828.43 1.000000 4n
+645.04 831.43 1.000000 dot
+635.77 822.43 1.000000 4n
+645.04 825.43 1.000000 dot
+639.46 823.18 moveto
+639.46 849.43 lineto stroke
+689.96 828.43 1.000000 4n
+699.22 831.43 1.000000 dot
+689.96 822.43 1.000000 4n
+699.22 825.43 1.000000 dot
+693.64 823.18 moveto
+693.64 849.43 lineto stroke
+/Palatino-Italic findfont
+14 scalefont
+setfont
+newpath
+583.35 858.43 moveto
+583.35 891.02 lineto
+693.94 891.02 lineto
+693.94 858.43 lineto
+closepath
+stroke
+585.35 879.09 moveto
+(A special note, on) show
+585.35 862.71 moveto
+(two lines, in a box.) show
+restore
+%  S_STAFF
+% staff 2
+save
+590.39 760.27 1.000000 4n
+599.65 760.27 1.000000 dot
+590.39 748.27 1.000000 4n
+599.65 748.27 1.000000 dot
+0.70 setlinewidth
+586.71 759.52 moveto
+586.71 727.27 lineto stroke
+635.77 754.27 1.000000 4n
+645.04 754.27 1.000000 dot
+635.77 748.27 1.000000 4n
+645.04 748.27 1.000000 dot
+632.09 753.52 moveto
+632.09 727.27 lineto stroke
+689.96 754.27 1.000000 4n
+699.22 754.27 1.000000 dot
+689.96 748.27 1.000000 4n
+699.22 748.27 1.000000 dot
+686.28 753.52 moveto
+686.28 727.27 lineto stroke
+restore
+%  S_STAFF
+% staff 3
+save
+659.85 687.67 0.800000 measrpt
+/Times-Roman findfont
+9 scalefont
+setfont
+657.61 699.67 moveto
+(2) show
+restore
+%  S_STAFF
+% staff 4
+save
+590.39 624.09 1.000000 xnote
+599.87 624.09 1.000000 dot
+0.70 setlinewidth
+594.29 627.09 moveto
+594.29 645.09 lineto stroke
+635.77 624.09 1.000000 xnote
+645.25 624.09 1.000000 dot
+639.67 627.09 moveto
+639.67 645.09 lineto stroke
+689.96 624.09 1.000000 xnote
+693.86 627.09 moveto
+693.86 643.59 lineto stroke
+705.19 624.09 1.000000 xnote
+709.08 627.09 moveto
+709.08 643.59 lineto stroke
+721.29 624.09 1.000000 xnote
+725.19 627.09 moveto
+725.19 643.59 lineto stroke
+newpath
+693.51 645.09 moveto
+725.54 645.09 lineto
+725.54 642.09 lineto
+693.51 642.09 lineto
+closepath
+fill
+590.39 618.09 1.000000 2n
+599.87 618.09 1.000000 dot
+586.49 617.34 moveto
+586.49 597.09 lineto stroke
+689.96 618.09 1.000000 4n
+699.44 618.09 1.000000 dot
+686.28 617.34 moveto
+686.28 597.09 lineto stroke
+/Palatino-Italic findfont
+14 scalefont
+setfont
+gsave
+newpath
+1.941964 1.000000 scale
+308.62 656.08 9.99 0 360 arc
+0.514943 1.000000 scale
+2.018418 1.000000 scale
+296.93 656.08 9.49 0 360 arc
+eofill
+grestore
+584.93 651.62 moveto
+(mute) show
+restore
+%  S_STAFF
+% staff 5
+save
+restore
+%  S_STAFF
+% staff 6
+save
+590.39 551.07 1.000000 4n
+590.39 536.07 1.000000 4n
+0.70 setlinewidth
+586.71 550.32 moveto
+586.71 477.33 lineto stroke
+606.18 542.07 1.000000 4n
+606.18 493.83 1.000000 4n
+599.95 493.83 moveto
+612.41 493.83 lineto stroke
+602.50 541.32 moveto
+602.50 473.49 lineto stroke
+621.41 536.07 1.000000 4n
+621.41 484.83 1.000000 4n
+617.73 535.32 moveto
+617.73 469.79 lineto stroke
+635.77 493.83 1.000000 4n
+629.54 493.83 moveto
+642.01 493.83 lineto stroke
+635.77 478.83 1.000000 4n
+632.09 493.08 moveto
+632.09 462.33 lineto stroke
+659.57 484.83 1.000000 4n
+655.89 484.08 moveto
+655.89 462.33 lineto stroke
+674.80 478.83 1.000000 4n
+671.12 478.08 moveto
+671.12 462.33 lineto stroke
+689.96 472.83 1.000000 4n
+699.22 472.83 1.000000 dot
+693.64 473.58 moveto
+693.64 493.83 lineto stroke
+newpath
+586.36 478.83 moveto
+618.08 471.29 lineto
+618.08 468.29 lineto
+586.36 475.83 lineto
+closepath
+fill
+newpath
+631.74 463.83 moveto
+671.47 463.83 lineto
+671.47 460.83 lineto
+631.74 460.83 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 7
+save
+590.39 406.55 1.000000 4n
+599.65 406.55 1.000000 dot
+590.39 400.55 1.000000 4n
+599.65 400.55 1.000000 dot
+590.39 394.55 1.000000 4n
+599.65 394.55 1.000000 dot
+590.39 385.55 1.000000 4n
+599.65 388.55 1.000000 dot
+590.39 373.55 1.000000 4n
+599.65 376.55 1.000000 dot
+0.70 setlinewidth
+584.16 373.55 moveto
+596.62 373.55 lineto stroke
+594.07 374.30 moveto
+594.07 427.55 lineto stroke
+635.77 406.55 1.000000 2n
+645.25 406.55 1.000000 dot
+635.77 400.55 1.000000 2n
+645.25 400.55 1.000000 dot
+635.77 394.55 1.000000 2n
+645.25 394.55 1.000000 dot
+635.77 385.55 1.000000 2n
+645.25 388.55 1.000000 dot
+635.77 373.55 1.000000 2n
+645.25 376.55 1.000000 dot
+629.33 373.55 moveto
+642.22 373.55 lineto stroke
+639.67 374.30 moveto
+639.67 427.55 lineto stroke
+restore
+%  S_STAFF
+% staff 8
+save
+632.43 307.87 639.12 318.81 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+632.43 309.09 moveto
+(3) show
+632.43 297.67 639.12 308.19 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+632.43 298.68 moveto
+(4) show
+632.43 287.05 639.12 297.99 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+632.43 288.27 moveto
+(5) show
+632.43 276.64 639.12 287.58 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+632.43 277.86 moveto
+(5) show
+632.43 266.23 639.12 277.17 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+632.43 267.45 moveto
+(3) show
+restore
+%  S_STAFF
+% staff 9
+save
+659.85 207.29 1.000000 measrpt
+/Times-Roman findfont
+11 scalefont
+setfont
+657.11 222.29 moveto
+(2) show
+restore
+%  S_BAR
+476 linenum
+0.70 setlinewidth
+738.35 846.43 moveto
+738.35 822.43 lineto stroke
+738.35 763.27 moveto
+738.35 739.27 lineto stroke
+738.35 697.27 moveto
+738.35 678.07 lineto stroke
+738.35 627.09 moveto
+738.35 615.09 lineto stroke
+738.35 560.07 moveto
+738.35 463.83 lineto stroke
+738.35 403.55 moveto
+738.35 261.29 lineto stroke
+738.35 219.29 moveto
+738.35 195.29 lineto stroke
+%  S_SSV
+%  S_SSV
+%  S_SSV
+%  S_SSV
+%  S_FEED
+%  Printing header/footer
+/Times-Roman findfont
+12 scalefont
+setfont
+65.45 944.05 moveto
+(Sample Songs) show
+/Times-Roman findfont
+12 scalefont
+setfont
+366.29 944.05 moveto
+(This is the title) show
+/Times-Roman findfont
+12 scalefont
+setfont
+685.13 944.05 moveto
+(page 2 of 3) show
+/Times-Roman findfont
+12 scalefont
+setfont
+65.45 78.33 moveto
+(This is a sample remark at the bottom of the page) show
+showpage
+restore
+%%Page: 3 3
+save
+41125291 41125529 sv
+0.770000 0.770000 scale
+/Times-Roman findfont
+12 scalefont
+setfont
+364.28 930.22 moveto
+(First movement) show
+168.05 901.55 1170.70 5 1.000000 1.000000 stf
+/Helvetica-Oblique findfont
+9 scalefont
+setfont
+100.55 855.55 moveto
+(8) show
+168.05 815.56 1170.70 5 1.000000 1.000000 stf
+168.05 745.63 1170.70 1 1.000000 1.000000 stf
+168.05 638.83 1170.70 5 1.000000 1.000000 stf
+/Helvetica-Oblique findfont
+9 scalefont
+setfont
+100.55 592.83 moveto
+(8) show
+168.05 570.53 1170.70 5 1.000000 1.000000 stf
+168.05 483.17 1170.70 5 1.000000 1.000000 stf
+/Helvetica-Oblique findfont
+9 scalefont
+setfont
+100.55 437.17 moveto
+(8) show
+168.05 369.28 1170.70 6 1.735000 1.000000 stf
+168.05 289.25 1170.70 5 1.000000 1.000000 stf
+/Times-Roman findfont
+12 scalefont
+setfont
+72.08 782.52 moveto
+(Ch) show
+/Times-Roman findfont
+12 scalefont
+setfont
+65.45 528.65 moveto
+(Kbd) show
+/Times-Roman findfont
+12 scalefont
+setfont
+70.13 350.19 moveto
+(Gtr) show
+94.05 844.55 728.56 bracket
+95.55 578.83 486.53 brace
+94.05 426.17 268.25 bracket
+0.70 setlinewidth
+96.05 841.55 moveto
+96.05 205.25 lineto stroke
+338.46 842.55 362.46 204.25 whitebox
+359.46 844.55 728.56 bracket
+360.96 578.83 486.53 brace
+359.46 426.17 268.25 bracket
+362.11 841.55 moveto
+362.11 205.25 lineto stroke
+%  S_CLEFSIG
+107.84 823.55 1.000000 gclef
+108.09 749.56 1.000000 fclef
+102.05 666.13 moveto
+102.05 681.13 lineto stroke
+104.15 666.13 moveto
+104.15 681.13 lineto stroke
+107.84 560.83 1.000000 gclef
+108.09 504.53 1.000000 fclef
+107.84 405.17 1.000000 gclef
+107.84 211.25 1.000000 gclef
+121.88 829.55 1.000000 flat
+127.37 838.55 1.000000 flat
+132.85 826.55 1.000000 flat
+121.88 737.56 1.000000 flat
+127.37 746.56 1.000000 flat
+132.85 734.56 1.000000 flat
+121.88 566.83 1.000000 flat
+127.37 575.83 1.000000 flat
+132.85 563.83 1.000000 flat
+121.88 492.53 1.000000 flat
+127.37 501.53 1.000000 flat
+132.85 489.53 1.000000 flat
+121.88 411.17 1.000000 flat
+127.37 420.17 1.000000 flat
+132.85 408.17 1.000000 flat
+121.88 217.25 1.000000 flat
+127.37 226.25 1.000000 flat
+132.85 214.25 1.000000 flat
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+489 linenum
+/Helvetica-Oblique findfont
+14 scalefont
+setfont
+176.94 791.60 moveto
+(tr) show
+/Ext-Helvetica-Oblique findfont
+14 scalefont
+setfont
+(\\) show
+/Helvetica-Oblique findfont
+14 scalefont
+setfont
+(s) show
+/Helvetica-Oblique findfont
+14 scalefont
+setfont
+223.12 791.60 moveto
+(bien!) show
+182.75 829.55 1.000000 4n
+174.30 829.55 1.000000 nat
+192.02 832.55 1.000000 dot
+182.75 811.55 1.000000 4n
+173.29 811.55 1.000000 dblsharp
+192.02 814.55 1.000000 dot
+176.52 811.55 moveto
+188.98 811.55 lineto stroke
+186.43 812.30 moveto
+186.43 850.55 lineto stroke
+230.72 829.55 1.000000 2n
+240.20 832.55 1.000000 dot
+230.72 811.55 1.000000 2n
+240.20 814.55 1.000000 dot
+224.27 811.55 moveto
+237.17 811.55 lineto stroke
+234.62 812.30 moveto
+234.62 850.55 lineto stroke
+/Palatino-Italic findfont
+15 scalefont
+setfont
+266.44 854.60 moveto
+(D.C. al Coda ) show
+/Times-Roman findfont
+14 scalefont
+setfont
+175.47 887.81 moveto
+(G) show
+185.55 894.53 moveto
+/Times-Roman findfont
+9 scalefont
+setfont
+(9) show
+185.55 885.67 moveto
+(7) show
+170.75 879.95 4.80 6 0 0 0 0 [ 3 -1 0 0 0 5 ] grid
+restore
+%  S_STAFF
+% staff 2
+save
+182.75 749.56 1.000000 4n
+192.02 752.56 1.000000 dot
+182.75 731.56 1.000000 4n
+192.02 734.56 1.000000 dot
+0.70 setlinewidth
+186.43 732.31 moveto
+186.43 770.56 lineto stroke
+230.72 749.56 1.000000 2n
+240.20 752.56 1.000000 dot
+230.72 731.56 1.000000 2n
+240.20 734.56 1.000000 dot
+234.62 732.31 moveto
+234.62 770.56 lineto stroke
+restore
+%  S_STAFF
+% staff 3
+save
+restore
+%  S_STAFF
+% staff 4
+save
+182.75 691.63 1.000000 4rest
+191.05 694.63 1.000000 dot
+230.72 676.63 1.000000 4n
+239.98 676.63 1.000000 dot
+0.70 setlinewidth
+234.40 677.38 moveto
+234.40 697.63 lineto stroke
+283.91 676.63 1.000000 4n
+293.17 676.63 1.000000 dot
+287.59 677.38 moveto
+287.59 697.63 lineto stroke
+182.75 670.63 1.000000 4n
+192.02 670.63 1.000000 dot
+179.07 669.88 moveto
+179.07 649.63 lineto stroke
+230.72 655.63 1.000000 4rest
+239.02 658.63 1.000000 dot
+283.91 655.63 1.000000 4rest
+292.21 658.63 1.000000 dot
+restore
+%  S_STAFF
+% staff 5
+save
+182.75 566.83 1.000000 4n
+174.30 566.83 1.000000 nat
+199.38 569.83 1.000000 dot
+190.12 560.83 1.000000 4n
+199.38 563.83 1.000000 dot
+182.75 557.83 1.000000 4n
+199.38 557.83 1.000000 dot
+182.75 551.83 1.000000 4n
+199.38 551.83 1.000000 dot
+0.70 setlinewidth
+186.43 552.58 moveto
+186.43 587.83 lineto stroke
+230.72 566.83 1.000000 4n
+247.35 569.83 1.000000 dot
+238.08 560.83 1.000000 4n
+247.35 563.83 1.000000 dot
+230.72 557.83 1.000000 4n
+247.35 557.83 1.000000 dot
+230.72 551.83 1.000000 4n
+247.35 551.83 1.000000 dot
+234.40 552.58 moveto
+234.40 587.83 lineto stroke
+283.91 563.83 1.000000 4n
+275.45 563.83 1.000000 nat
+293.17 563.83 1.000000 dot
+283.91 557.83 1.000000 4n
+293.17 557.83 1.000000 dot
+283.91 551.83 1.000000 4n
+293.17 551.83 1.000000 dot
+287.59 552.58 moveto
+287.59 584.83 lineto stroke
+restore
+%  S_STAFF
+% staff 6
+save
+182.75 498.53 1.000000 4n
+192.02 501.53 1.000000 dot
+0.70 setlinewidth
+186.43 499.28 moveto
+186.43 519.53 lineto stroke
+230.72 495.53 1.000000 4n
+239.98 495.53 1.000000 dot
+234.40 496.28 moveto
+234.40 516.53 lineto stroke
+271.53 492.53 0.750000 gclef
+283.91 504.53 1.000000 4n
+293.17 507.53 1.000000 dot
+280.22 503.78 moveto
+280.22 483.53 lineto stroke
+restore
+%  S_STAFF
+% staff 7
+save
+156.58 426.17 0.583333 4n
+/Times-Roman findfont
+7 scalefont
+setfont
+150.92 424.40 moveto
+(\() show
+/Times-Roman findfont
+7 scalefont
+setfont
+159.93 424.40 moveto
+(\)) show
+156.58 405.17 0.583333 4n
+/Times-Roman findfont
+7 scalefont
+setfont
+150.92 403.40 moveto
+(\() show
+/Times-Roman findfont
+7 scalefont
+setfont
+159.93 403.40 moveto
+(\)) show
+182.75 429.17 1.000000 4n
+174.30 429.17 1.000000 nat
+192.02 432.17 1.000000 dot
+0.70 setlinewidth
+176.52 429.17 moveto
+188.98 429.17 lineto stroke
+182.75 408.17 1.000000 4n
+174.30 408.17 1.000000 nat
+192.02 408.17 1.000000 dot
+179.07 428.42 moveto
+179.07 387.17 lineto stroke
+230.72 426.17 1.000000 4n
+239.98 426.17 1.000000 dot
+230.72 405.17 1.000000 4n
+239.98 408.17 1.000000 dot
+227.04 425.42 moveto
+227.04 384.17 lineto stroke
+272.99 420.17 0.583333 4n
+267.65 420.17 0.583333 nat
+275.00 420.66 moveto
+275.00 435.17 lineto stroke
+276.76 432.05 0.583333 dnflag
+276.76 435.17 0.583333 dnflag
+283.91 423.17 1.000000 4n
+293.17 426.17 1.000000 dot
+280.22 422.42 moveto
+280.22 402.17 lineto stroke
+298.17 423.17 moveto
+307.17 426.17 lineto stroke
+182.75 403.07 moveto
+202.63 393.49 lineto stroke
+202.63 393.49 moveto
+223.69 400.07 lineto stroke
+184.75 434.27 moveto
+207.29 440.85 lineto stroke
+207.29 440.85 moveto
+228.72 431.27 lineto stroke
+158.58 401.57 moveto
+165.07 399.50 lineto stroke
+165.07 399.50 moveto
+170.88 403.07 lineto stroke
+157.58 433.37 moveto
+168.96 439.08 lineto stroke
+168.96 439.08 moveto
+180.75 434.27 lineto stroke
+restore
+%  S_STAFF
+% staff 8
+save
+179.40 307.42 186.10 318.37 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+179.40 308.57 moveto
+(8) show
+/Helvetica findfont
+12 scalefont
+setfont
+175.08 352.94 moveto
+(full) show
+176.06 276.19 189.45 287.14 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+176.06 277.34 moveto
+(10) show
+/Helvetica findfont
+12 scalefont
+setfont
+175.08 342.07 moveto
+(full) show
+0.70 setlinewidth
+182.75 319.37 moveto
+182.75 338.92 lineto stroke
+182.75 335.50 1.000000 uwedge
+227.37 307.42 234.07 318.37 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+227.37 308.57 moveto
+(8) show
+224.02 276.19 237.41 287.14 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+224.02 277.34 moveto
+(10) show
+182.75 338.92 moveto
+185.15 339.08 187.55 339.08 189.95 338.92 curveto
+198.81 338.35 207.66 337.58 216.33 335.49 curveto
+217.99 335.09 219.65 334.70 221.13 333.78 curveto
+225.01 331.34 228.84 328.84 230.72 324.36 curveto
+231.08 323.50 231.08 322.64 230.72 321.79 curveto
+stroke
+230.72 319.37 1.000000 wedge
+272.54 319.20 277.56 327.41 whitebox
+/Helvetica-Bold findfont
+9 scalefont
+setfont
+272.54 320.06 moveto
+(0) show
+280.56 318.05 287.25 328.56 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+280.56 319.06 moveto
+(1) show
+289.25 323.30 moveto
+298.25 326.30 lineto stroke
+restore
+%  S_STAFF
+% staff 9
+save
+503 linenum
+0.70 setlinewidth
+196.56 186.28 moveto
+335.46 186.28 lineto stroke
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+178.15 186.28 moveto
+(oo) show
+182.75 211.25 1.000000 diamond
+192.23 214.25 1.000000 dot
+186.65 211.25 moveto
+186.65 232.25 lineto stroke
+283.91 211.25 1.000000 filldiamond
+293.39 214.25 1.000000 dot
+287.80 211.25 moveto
+287.80 232.25 lineto stroke
+184.75 206.15 moveto
+184.77 206.30 lineto
+200.65 201.85 216.84 199.62 233.33 199.62 curveto
+249.82 199.62 266.01 201.85 281.88 206.30 curveto
+281.93 206.01 lineto
+266.16 200.75 249.96 198.12 233.33 198.12 curveto
+216.70 198.12 200.50 200.75 184.73 206.01 curveto
+fill
+restore
+%  S_BAR
+505 linenum
+0.70 setlinewidth
+335.11 841.55 moveto
+335.11 817.55 lineto stroke
+338.11 841.55 moveto
+338.11 817.55 lineto stroke
+335.11 755.56 moveto
+335.11 731.56 lineto stroke
+338.11 755.56 moveto
+338.11 731.56 lineto stroke
+335.11 679.63 moveto
+335.11 667.63 lineto stroke
+338.11 679.63 moveto
+338.11 667.63 lineto stroke
+335.11 578.83 moveto
+335.11 486.53 lineto stroke
+338.11 578.83 moveto
+338.11 486.53 lineto stroke
+335.11 423.17 moveto
+335.11 271.25 lineto stroke
+338.11 423.17 moveto
+338.11 271.25 lineto stroke
+335.11 229.25 moveto
+335.11 205.25 lineto stroke
+338.11 229.25 moveto
+338.11 205.25 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+restore
+%  S_STAFF
+% staff 2
+save
+restore
+%  S_STAFF
+% staff 3
+save
+restore
+%  S_STAFF
+% staff 4
+save
+restore
+%  S_STAFF
+% staff 5
+save
+restore
+%  S_STAFF
+% staff 6
+save
+restore
+%  S_STAFF
+% staff 7
+save
+restore
+%  S_STAFF
+% staff 8
+save
+restore
+%  S_STAFF
+% staff 9
+save
+restore
+%  S_BAR
+513 linenum
+0.70 setlinewidth
+%  S_SSV
+516 linenum
+%  S_CLEFSIG
+374.25 823.55 1.000000 gclef
+374.50 749.56 1.000000 fclef
+374.25 560.83 1.000000 gclef
+374.50 504.53 1.000000 fclef
+374.25 405.17 1.000000 gclef
+374.25 211.25 1.000000 gclef
+388.29 829.55 1.000000 flat
+393.78 838.55 1.000000 flat
+399.26 826.55 1.000000 flat
+388.29 737.56 1.000000 flat
+393.78 746.56 1.000000 flat
+399.26 734.56 1.000000 flat
+388.29 566.83 1.000000 flat
+393.78 575.83 1.000000 flat
+399.26 563.83 1.000000 flat
+388.29 492.53 1.000000 flat
+393.78 501.53 1.000000 flat
+399.26 489.53 1.000000 flat
+388.29 411.17 1.000000 flat
+393.78 420.17 1.000000 flat
+399.26 408.17 1.000000 flat
+388.29 217.25 1.000000 flat
+393.78 226.25 1.000000 flat
+399.26 214.25 1.000000 flat
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+434.45 823.55 1.000000 2n
+443.93 826.55 1.000000 dot
+434.45 814.55 1.000000 2n
+425.45 814.55 1.000000 flat
+443.93 814.55 1.000000 dot
+438.34 815.30 moveto
+438.34 844.55 lineto stroke
+510.12 829.55 1.000000 4n
+501.67 829.55 1.000000 nat
+510.12 823.55 1.000000 4n
+513.80 824.30 moveto
+513.80 850.55 lineto stroke
+543.54 829.55 1.000000 4n
+543.54 823.55 1.000000 4n
+547.23 824.30 moveto
+547.23 850.55 lineto stroke
+/NewCenturySchlbk-BoldItalic findfont
+11 scalefont
+setfont
+523.67 852.84 moveto
+(2) show
+506.09 856.84 moveto
+521.67 856.84 lineto stroke
+532.00 856.84 moveto
+547.58 856.84 lineto stroke
+506.09 856.84 moveto
+506.09 853.84 lineto stroke
+547.58 856.84 moveto
+547.58 853.84 lineto stroke
+/Times-Roman findfont
+14 scalefont
+setfont
+505.08 891.01 moveto
+(G) show
+498.12 883.15 4.80 5 0 0 0 0 [ 3 -1 0 0 0 3 ] grid
+/Times-Roman findfont
+14 scalefont
+setfont
+421.80 883.01 moveto
+(G) show
+436.00 883.18 1.166667 dim
+440.12 883.01 moveto
+(7) show
+422.45 875.15 4.80 5 0 0 0 0 [ 0 1 2 0 2 0 ] grid
+/Palatino-Italic findfont
+15 scalefont
+setfont
+429.45 899.74 moveto
+(Coda ) show
+/Palatino-Roman findfont
+13 scalefont
+setfont
+382.66 866.84 moveto
+392.45 866.84 1.083333 coda
+402.24 866.84 moveto
+restore
+%  S_STAFF
+% staff 2
+save
+434.45 758.56 1.000000 2n
+425.45 758.56 1.000000 flat
+443.93 758.56 1.000000 dot
+434.45 749.56 1.000000 2n
+422.47 749.56 1.000000 flat
+443.93 752.56 1.000000 dot
+0.70 setlinewidth
+430.55 757.81 moveto
+430.55 728.56 lineto stroke
+510.12 752.56 1.000000 4n
+510.12 743.56 1.000000 4n
+501.67 743.56 1.000000 nat
+/Times-Roman findfont
+12 scalefont
+setfont
+494.29 740.53 moveto
+(\() show
+/Times-Roman findfont
+12 scalefont
+setfont
+515.15 740.53 moveto
+(\)) show
+510.12 722.56 1.000000 4n
+501.67 722.56 1.000000 nat
+503.89 725.56 moveto
+516.35 725.56 lineto stroke
+513.80 723.31 moveto
+513.80 773.56 lineto stroke
+543.54 758.56 1.000000 4n
+535.09 758.56 1.000000 nat
+543.54 743.56 1.000000 4n
+539.86 757.81 moveto
+539.86 722.56 lineto stroke
+/NewCenturySchlbk-BoldItalic findfont
+11 scalefont
+setfont
+523.67 709.92 moveto
+(2) show
+506.09 712.28 moveto
+521.67 713.58 lineto stroke
+532.00 714.26 moveto
+547.58 715.56 lineto stroke
+506.09 712.28 moveto
+506.09 715.28 lineto stroke
+547.58 715.56 moveto
+547.58 718.56 lineto stroke
+restore
+%  S_STAFF
+% staff 3
+save
+restore
+%  S_STAFF
+% staff 4
+save
+restore
+%  S_STAFF
+% staff 5
+save
+434.45 620.83 1.000000 2n
+425.45 620.83 1.000000 flat
+443.93 623.83 1.000000 dot
+0.70 setlinewidth
+428.00 620.83 moveto
+440.89 620.83 lineto stroke
+428.00 614.83 moveto
+440.89 614.83 lineto stroke
+428.00 608.83 moveto
+440.89 608.83 lineto stroke
+428.00 602.83 moveto
+440.89 602.83 lineto stroke
+428.00 596.83 moveto
+440.89 596.83 lineto stroke
+428.00 590.83 moveto
+440.89 590.83 lineto stroke
+428.00 584.83 moveto
+440.89 584.83 lineto stroke
+434.45 614.83 1.000000 2n
+417.97 614.83 1.000000 flat
+443.93 617.83 1.000000 dot
+428.00 614.83 moveto
+440.89 614.83 lineto stroke
+428.00 608.83 moveto
+440.89 608.83 lineto stroke
+428.00 602.83 moveto
+440.89 602.83 lineto stroke
+428.00 596.83 moveto
+440.89 596.83 lineto stroke
+428.00 590.83 moveto
+440.89 590.83 lineto stroke
+428.00 584.83 moveto
+440.89 584.83 lineto stroke
+434.45 608.83 1.000000 2n
+443.93 611.83 1.000000 dot
+428.00 608.83 moveto
+440.89 608.83 lineto stroke
+428.00 602.83 moveto
+440.89 602.83 lineto stroke
+428.00 596.83 moveto
+440.89 596.83 lineto stroke
+428.00 590.83 moveto
+440.89 590.83 lineto stroke
+428.00 584.83 moveto
+440.89 584.83 lineto stroke
+434.45 602.83 1.000000 2n
+443.93 605.83 1.000000 dot
+428.00 602.83 moveto
+440.89 602.83 lineto stroke
+428.00 596.83 moveto
+440.89 596.83 lineto stroke
+428.00 590.83 moveto
+440.89 590.83 lineto stroke
+428.00 584.83 moveto
+440.89 584.83 lineto stroke
+438.34 603.58 moveto
+438.34 635.83 lineto stroke
+510.12 623.83 1.000000 4n
+519.39 623.83 1.000000 dot
+503.89 620.83 moveto
+516.35 620.83 lineto stroke
+503.89 614.83 moveto
+516.35 614.83 lineto stroke
+503.89 608.83 moveto
+516.35 608.83 lineto stroke
+503.89 602.83 moveto
+516.35 602.83 lineto stroke
+503.89 596.83 moveto
+516.35 596.83 lineto stroke
+503.89 590.83 moveto
+516.35 590.83 lineto stroke
+503.89 584.83 moveto
+516.35 584.83 lineto stroke
+510.12 614.83 1.000000 4n
+519.39 617.83 1.000000 dot
+503.89 614.83 moveto
+516.35 614.83 lineto stroke
+503.89 608.83 moveto
+516.35 608.83 lineto stroke
+503.89 602.83 moveto
+516.35 602.83 lineto stroke
+503.89 596.83 moveto
+516.35 596.83 lineto stroke
+503.89 590.83 moveto
+516.35 590.83 lineto stroke
+503.89 584.83 moveto
+516.35 584.83 lineto stroke
+510.12 608.83 1.000000 4n
+501.67 608.83 1.000000 nat
+519.39 611.83 1.000000 dot
+503.89 608.83 moveto
+516.35 608.83 lineto stroke
+503.89 602.83 moveto
+516.35 602.83 lineto stroke
+503.89 596.83 moveto
+516.35 596.83 lineto stroke
+503.89 590.83 moveto
+516.35 590.83 lineto stroke
+503.89 584.83 moveto
+516.35 584.83 lineto stroke
+510.12 602.83 1.000000 4n
+519.39 605.83 1.000000 dot
+503.89 602.83 moveto
+516.35 602.83 lineto stroke
+503.89 596.83 moveto
+516.35 596.83 lineto stroke
+503.89 590.83 moveto
+516.35 590.83 lineto stroke
+503.89 584.83 moveto
+516.35 584.83 lineto stroke
+513.80 603.58 moveto
+513.80 638.83 lineto stroke
+434.45 581.83 1.000000 2n
+443.93 581.83 1.000000 dot
+434.45 560.83 1.000000 2n
+443.93 557.83 1.000000 dot
+430.55 581.08 moveto
+430.55 539.83 lineto stroke
+510.12 581.83 1.000000 4n
+519.39 581.83 1.000000 dot
+510.12 560.83 1.000000 4n
+519.39 557.83 1.000000 dot
+506.44 581.08 moveto
+506.44 539.83 lineto stroke
+1.00 setlinewidth
+[0.1 5] 0 setdash
+1 setlinecap
+1 setlinejoin
+434.45 555.73 moveto
+445.63 552.30 457.07 550.59 468.77 550.59 curveto
+480.47 550.59 491.91 552.30 503.09 555.73 curveto
+stroke
+448.93 581.83 moveto
+457.75 579.13 466.78 577.77 476.01 577.77 curveto
+485.24 577.77 494.27 579.13 503.09 581.83 curveto
+stroke
+1.00 setlinewidth
+[3 3] 0 setdash
+448.93 602.83 moveto
+457.75 605.54 466.78 606.90 476.01 606.90 curveto
+485.24 606.90 494.27 605.54 503.09 602.83 curveto
+stroke
+448.93 608.83 moveto
+456.64 611.20 464.52 612.38 472.59 612.38 curveto
+480.65 612.38 488.54 611.20 496.25 608.83 curveto
+stroke
+448.93 614.83 moveto
+457.75 617.54 466.78 618.90 476.01 618.90 curveto
+485.24 618.90 494.27 617.54 503.09 614.83 curveto
+stroke
+448.93 625.93 moveto
+458.75 629.48 468.87 631.51 479.30 632.02 curveto
+489.73 632.53 500.00 631.50 510.12 628.93 curveto
+stroke
+restore
+%  S_STAFF
+% staff 6
+save
+restore
+%  S_STAFF
+% staff 7
+save
+442.24 420.17 1.000000 2n
+425.78 420.17 1.000000 nat
+451.72 420.17 1.000000 dot
+434.45 417.17 1.000000 2n
+418.61 417.17 1.000000 flat
+451.72 414.17 1.000000 dot
+434.45 405.17 1.000000 2n
+451.72 408.17 1.000000 dot
+434.45 399.17 1.000000 2n
+425.78 399.17 1.000000 nat
+451.72 402.17 1.000000 dot
+434.45 390.17 1.000000 2n
+451.72 390.17 1.000000 dot
+0.70 setlinewidth
+[] 0 setdash
+0 setlinecap
+0 setlinejoin
+428.00 393.17 moveto
+440.89 393.17 lineto stroke
+434.45 378.17 1.000000 2n
+425.78 378.17 1.000000 nat
+451.72 378.17 1.000000 dot
+428.00 381.17 moveto
+440.89 381.17 lineto stroke
+428.00 387.17 moveto
+440.89 387.17 lineto stroke
+428.00 393.17 moveto
+440.89 393.17 lineto stroke
+438.34 378.92 moveto
+438.34 441.17 lineto stroke
+newpath
+433.34 432.47 moveto
+433.34 435.47 lineto
+443.34 439.87 lineto
+443.34 436.87 lineto
+closepath
+fill
+510.12 426.17 1.000000 4n
+519.39 426.17 1.000000 dot
+510.12 411.17 1.000000 4n
+501.67 411.17 1.000000 nat
+519.39 414.17 1.000000 dot
+510.12 405.17 1.000000 4n
+519.39 408.17 1.000000 dot
+510.12 396.17 1.000000 4n
+519.39 396.17 1.000000 dot
+510.12 384.17 1.000000 4n
+519.39 384.17 1.000000 dot
+503.89 387.17 moveto
+516.35 387.17 lineto stroke
+503.89 393.17 moveto
+516.35 393.17 lineto stroke
+513.80 384.92 moveto
+513.80 447.17 lineto stroke
+restore
+%  S_STAFF
+% staff 8
+save
+431.10 317.83 437.79 328.78 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+431.10 318.98 moveto
+(0) show
+431.10 307.53 437.79 318.26 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+431.10 308.47 moveto
+(2) show
+431.10 297.01 437.79 307.96 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+431.10 298.16 moveto
+(0) show
+431.10 286.71 437.79 297.44 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+431.10 287.65 moveto
+(2) show
+431.10 276.41 437.79 286.92 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+431.10 277.42 moveto
+(1) show
+431.10 265.78 437.79 276.73 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+431.10 266.93 moveto
+(0) show
+newpath
+429.45 251.55 moveto
+429.45 254.55 lineto
+439.45 258.95 lineto
+439.45 255.95 lineto
+closepath
+fill
+506.77 317.83 513.47 328.78 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+506.77 319.06 moveto
+(3) show
+506.77 307.42 513.47 318.37 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+506.77 308.57 moveto
+(0) show
+506.77 297.01 513.47 307.96 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+506.77 298.16 moveto
+(0) show
+506.77 286.60 513.47 297.55 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+506.77 287.75 moveto
+(0) show
+506.77 265.78 513.47 276.73 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+506.77 267.01 moveto
+(3) show
+restore
+%  S_STAFF
+% staff 9
+save
+548 linenum
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+431.86 186.28 moveto
+(At) show
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+506.29 186.28 moveto
+(the) show
+434.45 211.25 1.000000 diamond
+443.93 214.25 1.000000 dot
+0.70 setlinewidth
+438.34 211.25 moveto
+438.34 232.25 lineto stroke
+510.12 217.25 1.000000 4n
+501.67 217.25 1.000000 nat
+519.39 220.25 1.000000 dot
+506.44 216.50 moveto
+506.44 196.25 lineto stroke
+restore
+%  S_BAR
+551 linenum
+0.70 setlinewidth
+573.54 841.55 moveto
+573.54 817.55 lineto stroke
+573.54 755.56 moveto
+573.54 731.56 lineto stroke
+573.54 679.63 moveto
+573.54 667.63 lineto stroke
+573.54 578.83 moveto
+573.54 486.53 lineto stroke
+573.54 423.17 moveto
+573.54 271.25 lineto stroke
+573.54 229.25 moveto
+573.54 205.25 lineto stroke
+%  S_SSV
+555 linenum
+%  S_CLEFSIG
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+577.04 829.55 moveto
+(2) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+577.04 817.53 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+586.25 825.67 moveto
+(+) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+595.95 829.55 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+595.95 817.34 moveto
+(8) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+577.04 743.56 moveto
+(2) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+577.04 731.54 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+586.25 739.68 moveto
+(+) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+595.95 743.56 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+595.95 731.35 moveto
+(8) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+577.04 673.63 moveto
+(2) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+577.04 661.61 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+586.25 669.75 moveto
+(+) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+595.95 673.63 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+595.95 661.42 moveto
+(8) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+577.04 566.83 moveto
+(2) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+577.04 554.82 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+586.25 562.96 moveto
+(+) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+595.95 566.83 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+595.95 554.63 moveto
+(8) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+577.04 498.53 moveto
+(2) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+577.04 486.52 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+586.25 494.66 moveto
+(+) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+595.95 498.53 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+595.95 486.33 moveto
+(8) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+577.04 411.17 moveto
+(2) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+577.04 399.15 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+586.25 407.29 moveto
+(+) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+595.95 411.17 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+595.95 398.96 moveto
+(8) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+577.04 217.25 moveto
+(2) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+577.04 205.24 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+586.25 213.38 moveto
+(+) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+595.95 217.25 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+595.95 205.05 moveto
+(8) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+623.87 832.55 1.000000 2n
+623.87 823.55 1.000000 2n
+623.87 817.55 1.000000 2n
+627.77 818.30 moveto
+627.77 853.55 lineto stroke
+684.61 832.55 1.000000 4n
+693.87 832.55 1.000000 dot
+684.61 823.55 1.000000 4n
+693.87 826.55 1.000000 dot
+684.61 817.55 1.000000 4n
+693.87 820.55 1.000000 dot
+688.29 818.30 moveto
+688.29 853.55 lineto stroke
+625.87 812.45 moveto
+625.89 812.60 lineto
+635.19 810.16 644.64 808.94 654.24 808.94 curveto
+663.85 808.94 673.30 810.16 682.59 812.60 curveto
+682.63 812.30 lineto
+673.45 809.06 663.98 807.44 654.24 807.44 curveto
+644.50 807.44 635.04 809.06 625.85 812.30 curveto
+fill
+630.12 823.55 moveto
+630.14 823.70 lineto
+637.92 821.72 645.82 820.74 653.85 820.74 curveto
+661.87 820.74 669.78 821.72 677.56 823.70 curveto
+677.60 823.40 lineto
+669.93 820.63 662.01 819.24 653.85 819.24 curveto
+645.69 819.24 637.77 820.63 630.10 823.40 curveto
+fill
+630.12 837.65 moveto
+630.10 837.80 lineto
+638.92 840.92 648.01 842.48 657.37 842.48 curveto
+666.72 842.48 675.81 840.92 684.63 837.80 curveto
+684.59 837.50 lineto
+675.66 839.82 666.59 840.98 657.37 840.98 curveto
+648.14 840.98 639.07 839.82 630.14 837.50 curveto
+fill
+/Palatino-Roman findfont
+14 scalefont
+setfont
+674.07 855.72 moveto
+684.61 855.72 1.166667 ferm
+695.15 855.72 moveto
+/Times-Roman findfont
+14 scalefont
+setfont
+613.75 884.01 moveto
+(Cm) show
+611.87 876.15 4.80 5 3 1 2 6 [ -2 1 3 3 2 1 ] grid
+restore
+%  S_STAFF
+% staff 2
+save
+623.87 761.56 1.000000 2n
+0.70 setlinewidth
+617.42 761.56 moveto
+630.32 761.56 lineto stroke
+623.87 752.56 1.000000 2n
+623.87 746.56 1.000000 2n
+619.97 760.81 moveto
+619.97 725.56 lineto stroke
+684.61 761.56 1.000000 4n
+693.87 764.56 1.000000 dot
+678.38 761.56 moveto
+690.84 761.56 lineto stroke
+684.61 752.56 1.000000 4n
+693.87 752.56 1.000000 dot
+684.61 746.56 1.000000 4n
+693.87 746.56 1.000000 dot
+680.93 760.81 moveto
+680.93 725.56 lineto stroke
+623.87 741.46 moveto
+623.89 741.61 lineto
+632.69 739.32 641.64 738.18 650.73 738.18 curveto
+659.81 738.18 668.76 739.32 677.56 741.61 curveto
+677.60 741.31 lineto
+668.91 738.22 659.95 736.68 650.73 736.68 curveto
+641.50 736.68 632.54 738.22 623.85 741.31 curveto
+fill
+630.12 752.56 moveto
+630.10 752.71 lineto
+637.77 755.48 645.69 756.87 653.85 756.87 curveto
+662.01 756.87 669.93 755.48 677.60 752.71 curveto
+677.56 752.41 lineto
+669.78 754.38 661.87 755.37 653.85 755.37 curveto
+645.82 755.37 637.92 754.38 630.14 752.41 curveto
+fill
+625.87 766.66 moveto
+625.85 766.81 lineto
+635.04 770.04 644.50 771.66 654.24 771.66 curveto
+663.98 771.66 673.45 770.04 682.63 766.81 curveto
+682.59 766.51 lineto
+673.30 768.95 663.85 770.16 654.24 770.16 curveto
+644.64 770.16 635.19 768.95 625.89 766.51 curveto
+fill
+/Palatino-Roman findfont
+14 scalefont
+setfont
+674.07 773.06 moveto
+684.61 773.06 1.166667 ferm
+695.15 773.06 moveto
+restore
+%  S_STAFF
+% staff 3
+save
+restore
+%  S_STAFF
+% staff 4
+save
+668.85 679.63 1.000000 1rest
+668.85 661.63 1.000000 1rest
+/Palatino-Roman findfont
+14 scalefont
+setfont
+658.30 687.86 moveto
+668.85 687.86 1.166667 ferm
+679.39 687.86 moveto
+restore
+%  S_STAFF
+% staff 5
+save
+623.87 548.83 1.000000 2n
+0.70 setlinewidth
+617.42 548.83 moveto
+630.32 548.83 lineto stroke
+627.77 549.58 moveto
+627.77 569.83 lineto stroke
+684.61 548.83 1.000000 4n
+693.87 551.83 1.000000 dot
+678.38 548.83 moveto
+690.84 548.83 lineto stroke
+688.29 549.58 moveto
+688.29 569.83 lineto stroke
+625.87 543.73 moveto
+625.89 543.88 lineto
+635.19 541.45 644.64 540.23 654.24 540.23 curveto
+663.85 540.23 673.30 541.45 682.59 543.88 curveto
+682.63 543.59 lineto
+673.45 540.35 663.98 538.73 654.24 538.73 curveto
+644.50 538.73 635.04 540.35 625.85 543.59 curveto
+fill
+/Palatino-Roman findfont
+14 scalefont
+setfont
+674.07 581.01 moveto
+684.61 581.01 1.166667 ferm
+695.15 581.01 moveto
+restore
+%  S_STAFF
+% staff 6
+save
+623.87 495.53 1.000000 2n
+0.70 setlinewidth
+627.77 496.28 moveto
+627.77 516.53 lineto stroke
+684.61 495.53 1.000000 4n
+693.87 495.53 1.000000 dot
+688.29 496.28 moveto
+688.29 516.53 lineto stroke
+625.87 490.43 moveto
+625.89 490.58 lineto
+635.19 488.15 644.64 486.93 654.24 486.93 curveto
+663.85 486.93 673.30 488.15 682.59 490.58 curveto
+682.63 490.29 lineto
+673.45 487.05 663.98 485.43 654.24 485.43 curveto
+644.50 485.43 635.04 487.05 625.85 490.29 curveto
+fill
+/Palatino-Roman findfont
+14 scalefont
+setfont
+674.07 518.71 moveto
+684.61 518.71 1.166667 ferm
+695.15 518.71 moveto
+1.00 setlinewidth
+[3 3] 0 setdash
+644.16 479.18 moveto
+726.21 479.18 lineto stroke
+726.21 479.18 moveto
+726.21 488.18 lineto stroke
+0.70 setlinewidth
+[] 0 setdash
+0 setlinecap
+0 setlinejoin
+/Palatino-Italic findfont
+12 scalefont
+setfont
+620.88 474.68 moveto
+(8va) show
+restore
+%  S_STAFF
+% staff 7
+save
+623.87 456.17 1.000000 2n
+0.70 setlinewidth
+617.42 453.17 moveto
+630.32 453.17 lineto stroke
+617.42 447.17 moveto
+630.32 447.17 lineto stroke
+617.42 441.17 moveto
+630.32 441.17 lineto stroke
+617.42 435.17 moveto
+630.32 435.17 lineto stroke
+617.42 429.17 moveto
+630.32 429.17 lineto stroke
+619.97 455.42 moveto
+619.97 411.17 lineto stroke
+684.61 456.17 1.000000 4n
+693.87 456.17 1.000000 dot
+678.38 453.17 moveto
+690.84 453.17 lineto stroke
+678.38 447.17 moveto
+690.84 447.17 lineto stroke
+678.38 441.17 moveto
+690.84 441.17 lineto stroke
+678.38 435.17 moveto
+690.84 435.17 lineto stroke
+678.38 429.17 moveto
+690.84 429.17 lineto stroke
+680.93 455.42 moveto
+680.93 411.17 lineto stroke
+625.87 461.27 moveto
+625.85 461.42 lineto
+635.04 464.65 644.50 466.27 654.24 466.27 curveto
+663.98 466.27 673.45 464.65 682.63 461.42 curveto
+682.59 461.12 lineto
+673.30 463.56 663.85 464.77 654.24 464.77 curveto
+644.64 464.77 635.19 463.56 625.89 461.12 curveto
+fill
+restore
+%  S_STAFF
+% staff 8
+save
+617.18 317.83 630.57 328.78 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+617.18 318.98 moveto
+(20) show
+restore
+%  S_STAFF
+% staff 9
+save
+573 linenum
+/Helvetica-Oblique findfont
+11 scalefont
+setfont
+618.51 186.28 moveto
+(end.) show
+623.87 220.25 1.000000 rectangle
+0.70 setlinewidth
+619.97 220.25 moveto
+619.97 199.25 lineto stroke
+684.61 220.25 1.000000 fillrectangle
+694.09 220.25 1.000000 dot
+680.71 220.25 moveto
+680.71 199.25 lineto stroke
+625.87 225.35 moveto
+625.85 225.50 lineto
+635.04 228.74 644.50 230.36 654.24 230.36 curveto
+663.98 230.36 673.45 228.74 682.63 225.50 curveto
+682.59 225.21 lineto
+673.30 227.64 663.85 228.86 654.24 228.86 curveto
+644.64 228.86 635.19 227.64 625.89 225.21 curveto
+fill
+restore
+%  S_BAR
+576 linenum
+0.70 setlinewidth
+733.20 841.55 moveto
+733.20 817.55 lineto stroke
+3.00 setlinewidth
+737.20 841.55 moveto
+737.20 817.55 lineto stroke
+0.70 setlinewidth
+733.20 755.56 moveto
+733.20 731.56 lineto stroke
+3.00 setlinewidth
+737.20 755.56 moveto
+737.20 731.56 lineto stroke
+0.70 setlinewidth
+733.20 679.63 moveto
+733.20 667.63 lineto stroke
+3.00 setlinewidth
+737.20 679.63 moveto
+737.20 667.63 lineto stroke
+0.70 setlinewidth
+733.20 578.83 moveto
+733.20 486.53 lineto stroke
+3.00 setlinewidth
+737.20 578.83 moveto
+737.20 486.53 lineto stroke
+0.70 setlinewidth
+733.20 423.17 moveto
+733.20 271.25 lineto stroke
+3.00 setlinewidth
+737.20 423.17 moveto
+737.20 271.25 lineto stroke
+0.70 setlinewidth
+733.20 229.25 moveto
+733.20 205.25 lineto stroke
+3.00 setlinewidth
+737.20 229.25 moveto
+737.20 205.25 lineto stroke
+0.70 setlinewidth
+%  S_SSV
+%  S_SSV
+%  S_SSV
+%  S_SSV
+%  Printing header/footer
+/Times-Roman findfont
+12 scalefont
+setfont
+65.45 944.05 moveto
+(Sample Songs) show
+/Times-Roman findfont
+12 scalefont
+setfont
+366.29 944.05 moveto
+(This is the title) show
+/Times-Roman findfont
+12 scalefont
+setfont
+685.13 944.05 moveto
+(page 3 of 3) show
+/Times-Roman findfont
+12 scalefont
+setfont
+65.45 78.33 moveto
+(This is a sample remark at the bottom of the page) show
+showpage
+restore
+%%Trailer
+%%DocumentFonts: /Times-Roman /Times-BoldItalic /Helvetica /Helvetica-Oblique /Helvetica-Bold /NewCenturySchlbk-Bold /NewCenturySchlbk-BoldItalic /Palatino-Roman /Palatino-Italic /Palatino-Bold /Ext-Helvetica-Oblique 
+%%Pages: 3
diff --git a/mup/docs/star.mup b/mup/docs/star.mup
new file mode 100644 (file)
index 0000000..fa3e11c
--- /dev/null
@@ -0,0 +1,211 @@
+//!Mup-Arkkra
+
+// sample of a Mup input file
+
+header
+       title (18) "The Star Spangled Banner"
+       title ital (12) "(The United States National Anthem)"
+       title (9) "Text: Francis Scott Key" "Tune: J. S. Smith"
+       title (9) ""  "arr: William J. Krauss"
+
+score
+       topmargin = 0.5
+       bottommargin = 0.5
+       leftmargin = 0.6
+       rightmargin = 0.6
+       scale = 0.7
+       packfact = 1.2
+       key = 3#
+       time = 3/4
+       staffs = 2
+       brace = 1-2
+       barstyle = 1-2
+       measnum = y
+       vscheme = 2o
+       beamstyle = 4,4,4
+       endingstyle = top
+
+staff 2
+       clef = bass
+
+define LYRICS lyrics between 1&2: @
+
+music
+       // Starts on a pickup, so use space
+       // at beginning of measure.
+       // Voices are in unison for the first
+       // few notes, so specify two voices
+       // at once.
+       1 1-2: 2s; 8.e<>; 16c;
+       2 1-2: 2s; 8.e<>; 16c;
+       LYRICS 2s; 4;           [1] "Oh_";
+       // Since the first two sections are
+       // almost the same, use a repeat
+       repeatstart
+
+       1 1: a-; c; e;
+       1 2: a-; c; b-;
+       2 1: a-; a; b;
+       2 2: a-; a; g;
+       LYRICS                  [1] "say. can you";  \
+                               [2] "stripes and bright";
+       bar
+
+       1 1: 2a; 8.c+; 16b;
+       1 2: 2c; 8.; 16;
+       2 1: 2a; 8.g; 16;
+       2 2: 2f; 8.e#; 16;
+       LYRICS                  [1] "see, by the";  \
+                               [2] "stars, through the";
+       bar
+
+       1 1: a; c; d#;
+       1 2: c; ; b-;
+       2 1: a; ; ;
+       2 2: f; ; b-;
+       LYRICS                  [1] "dawn's ear-ly";  \
+                               [2] "per-il-ous";
+       bar
+
+       1 1: e; r; 8e; ;
+       1 2: b-; r; 8b-; ;
+       2 1: g; r; 8g; ;
+       2 2: e; r; 8e; ;
+       LYRICS                  [1] "light what so";  \
+                               [2] "fight, o'er the";
+       bar
+
+       1 1: 4.c+; 8b; 4a;
+       1 2: 4.e; 8; 4;
+       2 1: 4.a; 8g; 4a;
+       2 2: 4.a-; 8b-; 4c;
+       LYRICS                  [1] "proud-ly we";  \
+                               [2] "ram-parts we";
+       bar
+
+       1 1: 2g; 8.f; 16g;
+       1 2: 2e; 8.; 16;
+       2 1: 2b; 8.; 16;
+       2 2: 2e; 8.d; 16;
+       LYRICS                  [1] "hailed, At the";  \
+                               [2] "watched, were so";
+       bar
+
+       1 1: a; ; e;
+       1 2: e; ; ;
+       2 1: a; ; e;
+       2 2: c; ; e;
+       LYRICS                  [1] "twi-light's last";  \
+                               [2] "gal-lant-ly";
+       bar ending "1."
+
+       1-2 1-2: c; 8a-; r; 8.e; 16c;
+       LYRICS                  [1] "gleam-ing, whose broad";
+       repeatend ending "2."
+
+       1 1: c; 8a-; r; 8.c+; 16;
+       1 2: c; 8a-; r; 8.e; 16;
+       2 1: c; 8a-; r; 8.a; 16;
+       2 2: c; 8a-; r; 8.a-; 16;
+       LYRICS                  [2] "stream-ing? And the";
+       bar endending
+
+       1 1: c+; d+; e+;
+       1 2: e; ; ;
+       2 1: a; b; c+;
+       2 2: a-; ; ;
+       // continue to mark as verse 2 from now on,
+       // so that the lyrics will line up properly
+       // with the lyrics of the second ending.
+       LYRICS                  [2] "rock-ets' red";
+       bar
+
+// Define a mapping, and use the chord-at-a-time input method for the
+// next several measures.  Specify the voices in bottom to top order.
+define M  [ 2 2; 2 1; 1 2; 1 1 ]  @
+
+       M: a-c+ee+; rrrr; 8a-bed+; a-aec+;
+       LYRICS                  [2] "glare, the bombs";
+       bar
+
+       M: egeb; egec+; eged+;
+       LYRICS                  [2] "burst-ing in";
+       bar
+
+       M: eged+; rrrr; eged+;
+       LYRICS                  [2] "air, gave";
+       bar
+
+       M: 4.a-aec+; 8b-geb; 4caea;
+       LYRICS                  [2] "proof through the";
+       bar
+
+       M: 2ebeg; 8.ebdf; 16ebdg;
+       LYRICS                  [2] "night that our";
+       bar
+
+       M: faca; facc; b-ab-d#;
+       LYRICS                  [2] "flag was still";
+       bar
+
+       M: egb-e; rrrr; egb-e;
+       LYRICS                  [2] "there. Oh";
+       bar
+
+       1 1: 4a; ; 8<>; g;
+       1 2: 4c; b-; 4a-;
+       2 1: e; ; ;
+       2 2: a-; b-; c;
+       LYRICS                  [2] "say, does that";
+       bar
+
+       1 1: f; ; ;
+       1 2: d; ; e;
+       2 1: a; ; a#;
+       2 2: d; ; c;
+       LYRICS                  [2] "star-span-gled";
+       bar
+
+       1 1: 4b; 8d+<>; c+; b<>; a;
+       1 2: 4d; 4f; ;
+       2 1: b; 8<>; a#; b<>; b#;
+       2 2: b-; 8<>; c; d<>; d#;
+       LYRICS                  [2] "ban-ner yet";
+       bar
+
+       mussym(12) 1-2: 2 "ferm";
+       1 1: a<>; 8g; r; e; ;
+       1 2: 4.e; 8r; e; ;
+       2 1: c+<>; 8b; r; g; ;
+       2 2: 4.e; 8r; d; ;
+       LYRICS                  [2] "wave_ o'er the";
+       bar
+
+       1 1: 4.a<>; 8b; c+; d+;
+       1 2: 4.e<>; 8; ; ;
+       2 1: 4.a<>; 8g; a; ;
+       2 2: 4.c<>; 8e; a-; b-;
+       LYRICS                  [2] "land_ of the";
+       bar
+
+       mussym(12) 1-2: 1 "ferm";
+       1 1: e+; r; 8a; b;
+       1 2: e; r; 8d; ;
+       2 1: a; r; 8a; ;
+       2 2: c; r; 8f; fn;
+       LYRICS                  [2] "free and the";
+       bar
+
+       1 1: 4.c+; 8d+; 4b;
+       1 2: 4.e; 8; 4d;
+       2 1: 4.a; 8; 4g;
+       2 2: 4.e; 8; 4;
+       LYRICS                  [2] "home of the";
+       bar
+
+       1 1: 2a; 4s;
+       1 2: 2c; 4s;
+       2 1: 2e; 4s;
+       2 2: 2a-; 4s;
+       LYRICS                  [2] "brave?";
+       endbar
diff --git a/mup/docs/star.ps b/mup/docs/star.ps
new file mode 100644 (file)
index 0000000..b53038d
--- /dev/null
@@ -0,0 +1,4854 @@
+%!PS-Adobe-1.0
+%%Creator: Mup
+%%Title: music:  from /home/johnkr/mup/5.3/doc/arkkra/star.mup
+%%CreationDate: Sat Dec 9 16:59:22 2006
+%%Pages: (atend)
+%%DocumentFonts: (atend)
+%%BoundingBox: 0 0 612 792
+%%EndComments
+% Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2004 by Arkkra Enterprises
+% All rights reserved
+
+% Mup PostScript Prolog 5.3 for use with Mup 5.3
+
+% lwid is used as the width of a standard (thin) line in the music
+% character definitions.
+/lwid 70 def
+/halflwid lwid 2 div def
+
+% Define the following for use in do_upshortnote, do_dnshortnote, and
+% do_shortrest; it has to be done outside of the music font definition.
+/utildict 10 dict def
+utildict begin
+       /setnumflags    {       /numflags       exch def } def
+       /sethooksm1     {       /hooksm1        exch def } def
+       /setoffsets     {       /offsets        exch def } def
+       /setx           {       /x              exch def } def
+       /sety           {       /y              exch def } def
+end
+
+% Define a music character font.  Each music character is defined as if it
+% were a normal ASCII character in a strange font where "A" looks like a
+% treble clef, "B" looks like a bass clef, etc.
+
+/mfont0 100 dict def
+mfont0 begin
+       /FontType 3 def
+       /FontMatrix [ .001 0 0 0.001 0 0 ] def
+       /FontBBox [ -2000 -4030 2000 4030 ] def
+       /FontName (Mfont0) def
+
+       % set up Encoding vector with standard names
+       /Encoding 256 array def
+       StandardEncoding Encoding copy
+       pop
+
+       % the following definitions are used for quarter rests
+       /topx -170 def /topy 950 def
+       /cor1x 250 def /cor1y 450 def
+       /cor2x -300 def /cor2y 200 def
+       /cor3x 250 def /cor3y -400 def
+
+       % the following definitions are used for double sharps
+       /limit 300 halflwid add def
+       /off 70 def
+       /inbendsmall limit 200 sub def
+       /inbendbig limit 20 sub def
+       /outbendsmall 100 def
+       /outbendbig outbendsmall off add def
+
+       %%%%% define routines that will be used by multiple characters %%%%%
+       /do_1n {
+               gsave
+               newpath -10 rotate 1.6 1 scale
+               0 0 325 0 360 arc               %outer ellipse
+               1 1.6 div 1 scale 10 rotate     %back to original
+               35 rotate 0.85 1.1 scale
+               0 0 275 0 360 arc               %inner ellipse
+               eofill
+               grestore
+       } def
+       /do_upflag {
+               -315 0 moveto
+               -300 100 -100 480 0 600 curveto
+               300 960 350 1500 200 1700 curveto
+               130 1700 lineto
+               350 1200 50 650 -315 600 curveto
+               fill
+       } def
+       /do_flat {
+               -250 -400 moveto        %outer edge of loop
+               500 0 350 650 -250 160 curveto
+               -250 160 lwid sub lineto %inner edge of loop
+               100 400 300 0 -250 -400 lwid add curveto
+               fill
+
+               lwid setlinewidth       %stem
+               -250 1100 moveto -250 -400 lineto stroke
+       } def
+       /do_diamond {
+               newpath
+               420 0 moveto 0 300 lineto -420 0 lineto
+               0 -300 lineto closepath
+               259 -29 moveto -41 185 lineto -259 29 lineto
+               41 -185 lineto closepath
+               eofill
+       } def
+       /do_2n {
+               gsave
+               newpath 25 rotate 1.4 1 scale
+               0 0 315 0 360 arc               %outer ellipse
+               1 1.4 div 1 scale               %back to original
+               1.3 0.5 scale
+               0 0 310 0 360 arc               %inner ellipse
+               eofill
+               grestore
+       } def
+       /do_4n {
+               gsave
+               newpath 25 rotate 1.35 1 scale
+               0 0 310 0 360 arc fill
+               grestore
+       } def
+       /do_com {
+               newpath
+               330 250 150 0 360 arc fill      %knob at upper right
+               465 300 moveto                  %outer boundary
+               410 500 200 635 0 635 curveto
+               -750 635 -750 -635 0 -635 curveto
+               350 -635 480 -300 500 -100 curveto
+               430 -100 lineto                 %inner boundary
+               380 -300 250 -565 0 -565 curveto
+               -450 -565 -450 565 0 565 curveto
+               200 565 370 350 395 300 curveto
+               fill
+       } def
+       /do_ferm {
+               0 0 800 lwid sub 0 180 arc      %inner arc
+               -800 0 lineto
+               0 270 lwid sub 800 180 0 arcn   %outer arc
+               800 0 lineto fill
+               0 120 120 0 360 arc fill        %the dot
+       } def
+       /do_mor {
+               gsave
+               0.7 1 scale     %scrunch the following horizontally
+               45 rotate       %to pretend all lines horz or vertical
+               0 1 1 {
+                       pop     %we don't need the loop variable
+                       %one half of the mordent
+                       0 40 moveto 350 40 lineto 350 -460 lineto
+                       750 -460 lineto 750 -540 lineto
+                       150 -540 lineto 150 -40 lineto
+                       0 -40 lineto fill
+                       180 rotate      %to do the other half
+               } for
+               grestore
+       } def
+       /do_turn {
+               gsave
+               0 1 1 {
+                       pop     %we don't need the loop variable
+                       0 -100 moveto   %outer boundary
+                       200 -400 625 -400 625 0 curveto
+                       625 200 500 325 300 325 curveto
+                       300 185 lineto  %inner boundary
+                       450 255 555 150 555 0 curveto
+                       555 -350 250 -250 0 100 curveto
+                       fill
+                       300 255 70 0 360 arc fill %knob on end
+                       180 rotate      %to do the other half
+               } for
+               grestore
+       } def
+
+       /do_upshortnote {
+               utildict begin
+               setnumflags             %set numflags from the stack
+               gsave
+               -330 0 translate        %half a flag width
+               do_4n                   %do a quarter note head
+               lwid setlinewidth
+               370 0 moveto
+               370 2100 numflags 2 sub flagsep mul add lineto stroke
+               670 2100 numflags 2 sub flagsep mul add translate
+               1 -1 scale              %reflect across X axis
+               0 1 numflags 1 sub {
+                       do_upflag       %do an upflag
+                       pop             %we don't need the loop variable
+                       0 flagsep translate
+               } for
+               grestore
+               end
+       } def
+
+       /do_dnshortnote {
+               utildict begin
+               setnumflags             %set numflags from the stack
+               do_4n                   %do a quarter note head
+               lwid setlinewidth
+               -370 0 moveto
+               -370 -2100 numflags 2 sub flagsep mul sub lineto stroke
+               gsave
+               -70 -2100 numflags 2 sub flagsep mul sub translate
+               0 1 numflags 1 sub {
+                       do_upflag       %do an upflag
+                       pop             %we don't need the loop variable
+                       0 flagsep translate
+               } for
+               grestore
+               end
+       } def
+
+       /do_shortrest {
+               utildict begin
+               sety setx setoffsets sethooksm1 %set variable from the stack
+               gsave
+               -105.8 offsets mul -600 offsets mul translate
+               0 1 hooksm1 {           %loop once per hook
+                       newpath
+                       1 setlinewidth
+                       gsave
+                       1 1.2 scale
+                       -150 300 1.2 div 140 0 360 arc fill     %the dot
+                       grestore
+                       lwid setlinewidth
+                       -50 700 550 255 315 arc         %rest of the hook
+                       hooksm1 lt { stroke 105.8 600 translate } if
+               } for
+               x y lineto stroke
+               grestore
+               end
+       } def
+
+
+       % subsidiary dictionary of character definitions
+       /CharStrings 128 dict def
+       CharStrings begin
+
+               /.notdef {} def
+
+               % Here are the definitions of the characters.  A stepsize here
+               % is 300 units (assuming the character is drawn at its default
+               % size).
+
+               % gclef
+               /A {
+                       newpath
+                       %start with inner curl, inside boundary
+                       -50 -300 moveto
+                       -450 600 700 700 750 0 curveto
+                       750 -800 -700 -800 -700 200 curveto
+                       -700 900 500 1400 520 2250 curveto
+                       520 2900 300 3000 200 3000 curveto
+                       100 3000 -400 2500 -200 1800 curveto
+                       350 -600 lineto
+                       720 -1600 0 -1650 -400 -1400 curveto
+
+                       %go back to start, drawing the other boundary
+                       -400 -1480 lineto
+                       0 -1700 800 -1700 430 -600 curveto
+                       -120 1800 lineto
+                       -300 2400 200 2800 250 2800 curveto
+                       400 2800 430 2700 430 2450 curveto
+                       430 1800 -900 1200 -900 300 curveto
+                       -750 -900 800 -900 850 0 curveto
+                       900 1100 -750 900 -120 -300 curveto fill
+
+                       %circle at the bottom
+                       -300 -1250 250 0 360 arc fill
+               } def
+
+               % fclef
+               /B {
+                       newpath
+                       %start with outside boundary, at bottom
+                       -1000 -1700 moveto
+                       100 -1100 500 -600 450 0 curveto
+                       450 850 -1100 850 -950 0 curveto
+
+                       %go back to start, drawing the other boundary
+                       -880 0 lineto
+                       -920 400 -600 560 -300 560 curveto
+                       0 560 150 400 150 0 curveto
+                       150 -400 100 -900 -1000 -1620 curveto fill
+
+                       %circle at the left
+                       newpath
+                       -700 0 250 0 360 arc fill
+
+                       %do the two dots after the main curve
+                       700 -300 100 0 360 arc fill
+                       700 300 100 0 360 arc fill
+               } def
+
+               % cclef
+               /C {
+                       gsave
+                       %do upper curved part, then scale to do mirror image
+                       0 1 1 {
+                               pop     %we don't need the loop variable
+                               %outer boundary of curve
+                               -170 0 moveto 100 300 lineto
+                               400 -200 750 300 750 650 curveto
+                               750 1100 450 1235 250 1235 curveto
+                               0 1235 -143 1100 -143 950 curveto
+
+                               %inner boundary of curve
+                               0 950 lineto
+                               0 1100 30 1165 250 1165 curveto
+                               300 1165 450 1100 450 650 curveto
+                               450 400 400 -100 100 400 curveto
+                               -270 0 lineto fill
+                               %stroke
+                               %-270 0 moveto 100 400 lineto
+                               %400 -100 450 400 450 650 curveto
+                               %450 1100 300 1165 250 1165 curveto
+                               %30 1165 0 1100 0 950 curveto
+                               %stroke
+
+                               %elliptical ball at end of curve
+                               gsave
+                               1.3 1 scale
+                               10 950 120 0 360 arc fill
+                               grestore
+                               1 -1 scale      %reflect across X axis
+                       } for
+                       grestore
+
+                       % two vertical lines on the left
+                       300 setlinewidth -600 -1200 halflwid sub moveto
+                       -600 1200 halflwid add lineto stroke
+                       lwid setlinewidth -300 -1200 halflwid sub moveto
+                       -300 1200 halflwid add lineto stroke
+               } def
+
+               % dblwhole
+               /D {
+                       do_1n           %do a whole note
+                       lwid setlinewidth
+                       -490 -600 moveto -490 600 lineto stroke
+                       490 -600 moveto 490 600 lineto stroke
+               } def
+
+               % 1n
+               /E {
+                       do_1n           %do a whole note
+               } def
+
+               % 2n
+               /F {
+                       do_2n           %do a half note
+               } def
+
+               % 4n
+               /G {
+                       do_4n           %do a quarter note head
+               } def
+
+               % upflag
+               /H {
+                       do_upflag               %do an upflag
+               } def
+
+               % dnflag
+               /I {
+                       gsave
+                       1 -1 scale      %reflect across X axis
+                       do_upflag               %do an upflag
+                       grestore
+               } def
+
+               % dwhrest
+               /J {
+                       300 setlinewidth
+                       0 0 moveto 0 600 lineto stroke
+               } def
+
+               % 1rest
+               /K {
+                       lwid setlinewidth
+                       -750 600 moveto 750 600 lineto stroke
+                       300 setlinewidth
+                       -400 450 moveto 400 450 lineto stroke
+               } def
+
+               % 2rest
+               /L {
+                       lwid setlinewidth
+                       -750 0 moveto 750 0 lineto stroke
+                       300 setlinewidth
+                       -400 150 moveto 400 150 lineto stroke
+               } def
+
+               % 4rest
+               /M {
+                       newpath
+                       cor3x cor3y halflwid add moveto
+                       %-400 -200 -450 -650 50 -950 lwid add curveto
+                       -450 -50 -450 -650 50 -950 lwid add curveto
+                       -150 -650 -100 -250 cor3x cor3y halflwid sub curveto
+                       fill
+
+                       cor1x cor1y moveto cor1x 200 sub cor1y 200 add lineto
+                       cor2x cor2y lineto cor2x 200 add cor2y 200 sub lineto
+                       fill
+
+                       lwid setlinewidth
+                       topx topy moveto cor1x cor1y lineto stroke
+                       cor2x cor2y moveto cor3x cor3y lineto stroke
+               } def
+
+               % 8rest
+               /N {
+                       0 0 0 -600 do_shortrest
+               } def
+
+               % 16rest
+               /O {
+                       1 1 100 -1200 do_shortrest
+               } def
+
+               % 32rest
+               /P {
+                       2 1 0 -1800 do_shortrest
+               } def
+
+               % 64rest
+               /Q {
+                       3 2 -80 -2100 do_shortrest
+               } def
+
+               % 128rest
+               /R {
+                       4 2 -150 -2700 do_shortrest
+               } def
+
+               % 256rest
+               /S {
+                       5 3 -280 -3300 do_shortrest
+               } def
+
+               % dot
+               /T {
+                       newpath
+                       0 0 120 0 360 arc fill
+               } def
+
+               % nat
+               /U {
+                       % fill crossbars so that we can do parallelograms
+                       -235 -470 moveto -235 -270 lineto
+                       235 -130 lineto 235 -330 lineto fill
+                       -235 130 moveto -235 330 lineto
+                       235 470 lineto 235 270 lineto fill
+
+                       % vertical strokes
+                       lwid setlinewidth
+                       -200 -380 moveto -200 850 lineto stroke
+                       200 -850 moveto 200 380 lineto stroke
+               } def
+
+               % sharp
+               /V {
+                       % fill crossbars so that we can do parallelograms
+                       -325 -480 moveto -325 -280 lineto
+                       325 -120 lineto 325 -320 lineto fill
+                       -325 120 moveto -325 320 lineto
+                       325 480 lineto 325 280 lineto fill
+
+                       % vertical strokes
+                       lwid setlinewidth
+                       -150 -930 moveto -150 880 lineto stroke
+                       150 -880 moveto 150 930 lineto stroke
+               } def
+
+               % flat
+               /W {
+                       do_flat         %do a flat
+               } def
+
+               % dblsharp
+               /X {
+                       gsave
+                       0 1 3 {         %loop once for each of 4 sticks
+                               pop     %we don't need the loop variable
+                               0 off neg moveto
+                               outbendbig outbendsmall lineto
+                               inbendbig inbendsmall lineto
+                               limit limit lineto
+                               inbendsmall inbendbig lineto
+                               outbendsmall outbendbig lineto
+                               off neg 0 lineto
+                               fill
+                               -90 rotate
+                       } for
+                       grestore
+               } def
+
+               % dblflat
+               /Y {
+                       -290 580 290 {  %loop once for each flat
+
+                               gsave
+                               1 setlinewidth
+                               0 translate     %translate left/right (loop var)
+                               do_flat         %do a flat
+                               grestore
+
+                       } for
+               } def
+
+               % xnote
+               /Z {
+                       gsave
+                       1.15 1 scale 120 setlinewidth 1 setlinecap      %round
+                       -300 -300 moveto 300 300 lineto stroke
+                       -300 300 moveto 300 -300 lineto stroke
+                       grestore
+               } def
+
+               % dwhdiamond
+               /a {
+                       do_diamond      %do a diamond
+                       lwid setlinewidth
+                       -420 -600 moveto -420 600 lineto stroke
+                       420 -600 moveto 420 600 lineto stroke
+               } def
+
+               % diamond
+               /b {
+                       do_diamond      %do a diamond
+               } def
+
+               % filldiamond
+               /c {
+                       420 0 moveto 0 300 lineto
+                       -420 0 lineto 0 -300 lineto fill
+               } def
+
+               % up2n
+               /d {
+                       lwid setlinewidth
+                       380 0 moveto 380 2100 lineto stroke
+                       do_2n           %do a half note
+               } def
+
+               % dn2n
+               /e {
+                       lwid setlinewidth
+                       -380 0 moveto -380 -2100 lineto stroke
+                       do_2n           %do a half note
+               } def
+
+               % up4n
+               /f {
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       370 0 moveto 370 2100 lineto stroke
+               } def
+
+               % dn4n
+               /g {
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       -370 0 moveto -370 -2100 lineto stroke
+               } def
+
+               % up8n
+               /h {
+                       gsave
+                       -330 0 translate        % half a flag width
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       370 0 moveto 370 2100 lineto stroke
+                       670 2100 translate
+                       1 -1 scale      %reflect across X axis
+                       do_upflag               %do an upflag
+                       grestore
+               } def
+
+               % dn8n
+               /i {
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       -370 0 moveto -370 -2100 lineto stroke
+                       gsave
+                       -70 -2100 translate
+                       do_upflag               %do an upflag
+                       grestore
+               } def
+
+               % up16n
+               /j {
+                       2 do_upshortnote
+               } def
+
+               % dn16n
+               /k {
+                       2 do_dnshortnote
+               } def
+
+               % up32n
+               /l {
+                       3 do_upshortnote
+               } def
+
+               % dn32n
+               /m {
+                       3 do_dnshortnote
+               } def
+
+               % up64n
+               /n {
+                       4 do_upshortnote
+               } def
+
+               % dn64n
+               /o {
+                       4 do_dnshortnote
+               } def
+
+               % up128n
+               /p {
+                       5 do_upshortnote
+               } def
+
+               % dn128n
+               /q {
+                       5 do_dnshortnote
+               } def
+
+               % up256n
+               /r {
+                       6 do_upshortnote
+               } def
+
+               % dn256n
+               /s {
+                       6 do_dnshortnote
+               } def
+
+               % com
+               /t {
+                       do_com          %do a common time symbol
+               } def
+
+               % cut
+               /u {
+                       do_com          %do a common time symbol
+                       lwid setlinewidth
+                       0 -900 moveto 0 900 lineto stroke
+               } def
+
+               % begped
+               /v {
+                       lwid setlinewidth
+                       -200 600 moveto -200 0 lineto 200 0 lineto stroke
+               } def
+
+               % pedal
+               /w {
+                       lwid setlinewidth
+                       -500 0 moveto -450 0 lineto 0 600 lineto
+                       450 0 lineto 500 0 lineto stroke
+               } def
+
+               % endped
+               /x {
+                       lwid setlinewidth
+                       200 600 moveto 200 0 lineto -200 0 lineto stroke
+               } def
+
+               % dnbow
+               /y {
+                       lwid setlinewidth
+                       -350 0 moveto -350 900 lineto stroke
+                       350 0 moveto 350 900 lineto stroke
+                       200 setlinewidth
+                       -350 800 moveto 350 800 lineto stroke
+               } def
+
+               % upbow
+               /z {
+                       lwid setlinewidth
+                       -300 900 moveto 0 0 lineto 300 900 lineto stroke
+               } def
+
+               % wedge
+               /one {
+                       0 0 moveto -150 500 lineto 150 500 lineto fill
+               } def
+
+               % uwedge
+               /two {
+                       -150 0 moveto 150 0 lineto 0 500 lineto fill
+               } def
+
+               % ferm
+               /three {
+                       newpath
+                       do_ferm         %do a right side up fermata
+               } def
+
+               % uferm
+               /four {
+                       newpath
+                       gsave
+                       0 270 lwid sub 800 add translate %baseline at bottom
+                       180 rotate                      %upside down
+                       do_ferm         %do a right side up fermata
+                       grestore
+               } def
+
+               % sign
+               /five {
+                       gsave
+                       %do upper left curved part, upper right dot;
+                       %then rotate 180 to do other half
+                       0 1 1 {
+                               pop     %we don't need the loop variable
+                               0 100 moveto            %inner boundary
+                               -1000 300 -400 750 -200 700 curveto
+                               -200 800 lineto         %outer boundary
+                               -550 900 -1100 100 0 -100 curveto
+                               fill
+                               %dot at end of curve
+                               -200 700 100 0 360 arc fill
+                               %dot in upper right quadrant
+                               500 200 70 0 360 arc fill
+                               180 rotate
+                       } for
+                       grestore
+
+                       %slash through middle
+                       lwid setlinewidth
+                       -400 -800 moveto 400 800 lineto stroke
+               } def
+
+               % coda
+               /six {
+                       newpath
+                       gsave
+                       0.6 1 scale
+                       0 0 550 0 360 arc       %outside boundary
+                       1 0.6 div 1 scale       %back to original
+                       0.9 1 scale
+                       0 0 650 0 360 arc       %inside boundary
+                       eofill
+                       grestore
+                       lwid setlinewidth
+                       0 -850 moveto 0 850 lineto stroke
+                       -800 0 moveto 800 0 lineto stroke
+               } def
+
+               % mor
+               /seven {
+                       do_mor          %do a mordent
+               } def
+
+               % invmor
+               /eight {
+                       do_mor          %do a mordent
+                       lwid setlinewidth
+                       0 -450 moveto 0 450 lineto stroke
+               } def
+
+               % turn
+               /nine {
+                       do_turn         %do a turn
+               } def
+
+               % invturn
+               /zero {
+                       gsave
+                       1 -1 scale      %reflect across X axis
+                       do_turn         %do a turn
+                       grestore
+               } def
+
+               % acc_gt
+               /numbersign {
+                       lwid setlinewidth
+                       -500 300 moveto 500 0 lineto -500 -300 lineto stroke
+               } def
+
+               % acc_hat
+               /dollar {
+                       newpath
+                       -365 0 moveto 0 860 lineto 365 0 lineto
+                       150 0 lineto -75 530 lineto -300 0 lineto fill
+               } def
+
+               % acc_uhat
+               /quotedbl {
+                       newpath
+                       365 860 moveto 0 0 lineto -365 860 lineto
+                       -150 860 lineto 75 330 lineto 300 860 lineto fill
+               } def
+
+               % tr
+               /asterisk {
+                       %vertical bar of t
+                       -350 1000 moveto -550 200 lineto
+                       -612.5 -50 -212.5 -50 -160 200 curveto
+                       -230 200 lineto
+                       -300 50 -420 50 -400 200 curveto
+                       -200 1000 lineto fill
+
+                       %crossbar of t and vertical bar of r
+                       -700 600 moveto -160 600 lineto
+                       20 600 30 520 60 440 curveto
+                       -50 0 lineto 70 0 lineto 180 440 lineto
+                       190 480 100 670 -150 670 curveto
+                       -690 670 lineto fill
+
+                       %horizontal curve of r
+                       100 480 moveto
+                       300 630 450 700 650 550 curveto
+                       560 480 lineto
+                       450 630 300 560 100 390 curveto
+                       fill
+
+                       %knob at end of r
+                       600 460 100 0 360 arc fill
+               } def
+
+               % leg
+               /comma {
+                       100 setlinewidth
+                       -400 0 moveto 400 0 lineto stroke
+               } def
+
+               % rr
+               /hyphen {
+                       100 setlinewidth
+                       -400 0 moveto 0 1000 lineto stroke
+                       0 0 moveto 400 1000 lineto stroke
+               } def
+
+               % measrpt
+               /period {
+                       newpath -450 400 150 0 360 arc fill
+                       newpath 450 -400 150 0 360 arc fill
+                       200 setlinewidth
+                       -550 -600 moveto 550 600 lineto stroke
+               } def
+
+               % copyright
+               /slash {
+                       lwid setlinewidth
+                       newpath 0 400 400 0 360 arc stroke
+                       newpath 0 400 200 45 315 arc stroke
+               } def
+
+               % dim
+               /quoteleft {
+                       50 setlinewidth
+                       newpath 0 640 220 0 360 arc stroke
+               } def
+
+               % halfdim
+               /quoteright {
+                       50 setlinewidth
+                       newpath 0 640 220 0 360 arc stroke
+                       newpath -340 300 moveto 340 980 lineto stroke
+               } def
+
+               % triangle
+               /asciicircum {
+                       50 setlinewidth
+                       newpath -340 -10 moveto 0 710 lineto
+                       340 -10 lineto closepath stroke
+               } def
+
+               % qwhrest
+               /ampersand {
+                       300 setlinewidth
+                       0 -600 moveto 0 600 lineto stroke
+               } def
+
+               % ll1rest
+               /exclam {
+                       310 setlinewidth
+                       -400 455 moveto 400 450 lineto stroke
+               } def
+
+               % ll2rest
+               /at {
+                       310 setlinewidth
+                       -400 145 moveto 400 150 lineto stroke
+               } def
+       end
+
+       /BuildChar {
+
+               exch begin
+               Encoding exch get
+
+               dup
+               Mcbbox0 exch get
+               aload pop setcachedevice
+
+               CharStrings exch get
+               exec
+               end
+       } def
+end
+
+
+% Define another music character font, since there are too many to fit in one
+% font.  It works the same way as the first one.
+
+/mfont1 100 dict def
+mfont1 begin
+       /FontType 3 def
+       /FontMatrix [ .001 0 0 0.001 0 0 ] def
+       /FontBBox [ -2000 -4030 2000 4030 ] def
+       /FontName (Mfont1) def
+
+       % set up Encoding vector with standard names
+       /Encoding 256 array def
+       StandardEncoding Encoding copy
+       pop
+
+       %%%%% define routines that will be used by multiple characters %%%%%
+
+       /do_dwh_bars {
+               % the two bars surrounding a double whole note
+               lwid setlinewidth
+               -420 -600 moveto -420 600 lineto stroke
+               420 -600 moveto 420 600 lineto stroke
+       } def
+       /do_righttriangle {
+               newpath
+               420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto
+               350 150 moveto -140 150 lineto 350 -213 lineto
+               eofill
+       } def
+       /do_fillrighttriangle {
+               newpath
+               420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto
+               fill
+       } def
+       /do_rectangle {
+               newpath
+               420 270 moveto -420 270 lineto -420 -270 lineto 420 -270 lineto
+               350 150 moveto -350 150 lineto -350 -150 lineto 350 -150 lineto
+               eofill
+       } def
+       /do_isostriangle {
+               newpath
+               0 300 moveto -420 -270 lineto 420 -270 lineto
+               0 182 moveto -245 -150 lineto 245 -150 lineto
+               eofill
+       } def
+       /do_piewedge {
+               newpath
+               0 -300 moveto 0 -244 514 35 145 arc
+               0 -209 moveto 0 -244 394 43 137 arc
+               eofill
+       } def
+       /do_semicircle {
+               newpath
+               gsave
+               1 1.357 scale 420 199 moveto 0 199 420 180 360 arc
+               1 1.09 scale 350 111 moveto 0 199 350 194.1 345.9 arc
+               eofill
+               grestore
+       } def
+       /do_slashhead {
+               newpath
+               lwid setlinewidth
+               -620 -530 moveto -480 -670 lineto 620 530 lineto 480 670 lineto
+               closepath stroke
+       } def
+
+       % subsidiary dictionary of character definitions
+       /CharStrings 128 dict def
+       CharStrings begin
+
+               /.notdef {} def
+
+               % Here are the definitions of the characters.  A stepsize here
+               % is 300 units (assuming the character is drawn at its default
+               % size).
+
+               % dwhrighttriangle
+               /A {
+                       do_righttriangle
+                       do_dwh_bars
+               } def
+
+               % righttriangle
+               /B {
+                       do_righttriangle
+               } def
+
+               % fillrighttriangle
+               /C {
+                       newpath
+                       420 270 moveto -420 270 lineto 350 -300 lineto
+                       420 -300 lineto
+                       fill
+               } def
+
+               % udwhrighttriangle
+               /D {
+                       gsave
+                       180 rotate
+                       do_righttriangle
+                       do_dwh_bars
+                       grestore
+               } def
+
+               % urighttriangle
+               /E {
+                       gsave
+                       180 rotate
+                       do_righttriangle
+                       grestore
+               } def
+
+               % ufillrighttriangle
+               /F {
+                       gsave
+                       180 rotate
+                       do_fillrighttriangle
+                       grestore
+               } def
+
+               % dwhrectangle
+               /G {
+                       do_rectangle
+                       do_dwh_bars
+               } def
+
+               % rectangle
+               /H {
+                       do_rectangle
+               } def
+
+               % fillrectangle
+               /I {
+                       newpath
+                       420 270 moveto -420 270 lineto -420 -270 lineto
+                       420 -270 lineto
+                       fill
+               } def
+
+               % dwhisostriangle
+               /J {
+                       do_isostriangle
+                       do_dwh_bars
+               } def
+
+               % isostriangle
+               /K {
+                       do_isostriangle
+               } def
+
+               % fillisostriangle
+               /L {
+                       newpath
+                       0 300 moveto -420 -270 lineto 420 -270 lineto
+                       fill
+               } def
+
+               % dwhpiewedge
+               /M {
+                       do_piewedge
+                       do_dwh_bars
+               } def
+
+               % piewedge
+               /N {
+                       do_piewedge
+               } def
+
+               % fillpiewedge
+               /O {
+                       newpath
+                       0 -300 moveto 0 -244 514 35 145 arc
+                       fill
+               } def
+
+               % dwhsemicircle
+               /P {
+                       do_semicircle
+                       do_dwh_bars
+               } def
+
+               % semicircle
+               /Q {
+                       do_semicircle
+               } def
+
+               % fillsemicircle
+               /R {
+                       newpath
+                       gsave
+                       1 570 420 div scale
+                       420 199 moveto 0 199 420 180 360 arc
+                       fill
+                       grestore
+               } def
+
+               % dwhslashhead
+               /S {
+                       do_slashhead
+                       lwid setlinewidth
+                       -650 -600 moveto -650 600 lineto stroke
+                       650 -600 moveto 650 600 lineto stroke
+               } def
+
+               % slashhead
+               /T {
+                       do_slashhead
+               } def
+
+               % fillslashhead
+               /U {
+                       newpath
+                       200 setlinewidth
+                       -550 -600 moveto 550 600 lineto stroke
+               } def
+
+               % blankhead
+               /V {
+                       %print nothing
+               } def
+       end
+
+       /BuildChar {
+
+               exch begin
+               Encoding exch get
+
+               dup
+               Mcbbox1 exch get
+               aload pop setcachedevice
+
+               CharStrings exch get
+               exec
+               end
+       } def
+end
+
+
+% General routines for printing any music character, invoked by each music
+% character's specific routine below.  The scaling factor (default 1) needs
+% to be multiplied by 10 to get the actual size.  These routines restore the
+% preexisting current font when they are done.
+
+/printmchar0 {
+       gsave
+       /musicchar exch def
+       /Mfont0 findfont exch 10 mul scalefont setfont moveto 
+       musicchar show
+       grestore
+} def
+/printmchar1 {
+       gsave
+       /musicchar exch def
+       /Mfont1 findfont exch 10 mul scalefont setfont moveto 
+       musicchar show
+       grestore
+} def
+
+% Define each music character name to be a routine that prints the character.
+% Each character is to be invoked as in this example:
+%      100 200 1 gclef         % at (100, 200), scale to default size & print
+
+/gclef                 { (A) printmchar0 } def
+/fclef                 { (B) printmchar0 } def
+/cclef                 { (C) printmchar0 } def
+/dblwhole              { (D) printmchar0 } def
+/1n                    { (E) printmchar0 } def
+/2n                    { (F) printmchar0 } def
+/4n                    { (G) printmchar0 } def
+/upflag                        { (H) printmchar0 } def
+/dnflag                        { (I) printmchar0 } def
+/dwhrest               { (J) printmchar0 } def
+/1rest                 { (K) printmchar0 } def
+/2rest                 { (L) printmchar0 } def
+/4rest                 { (M) printmchar0 } def
+/8rest                 { (N) printmchar0 } def
+/16rest                        { (O) printmchar0 } def
+/32rest                        { (P) printmchar0 } def
+/64rest                        { (Q) printmchar0 } def
+/128rest               { (R) printmchar0 } def
+/256rest               { (S) printmchar0 } def
+/dot                   { (T) printmchar0 } def
+/nat                   { (U) printmchar0 } def
+/sharp                 { (V) printmchar0 } def
+/flat                  { (W) printmchar0 } def
+/dblsharp              { (X) printmchar0 } def
+/dblflat               { (Y) printmchar0 } def
+/xnote                 { (Z) printmchar0 } def
+/dwhdiamond            { (a) printmchar0 } def
+/diamond               { (b) printmchar0 } def
+/filldiamond           { (c) printmchar0 } def
+/up2n                  { (d) printmchar0 } def
+/dn2n                  { (e) printmchar0 } def
+/up4n                  { (f) printmchar0 } def
+/dn4n                  { (g) printmchar0 } def
+/up8n                  { (h) printmchar0 } def
+/dn8n                  { (i) printmchar0 } def
+/up16n                 { (j) printmchar0 } def
+/dn16n                 { (k) printmchar0 } def
+/up32n                 { (l) printmchar0 } def
+/dn32n                 { (m) printmchar0 } def
+/up64n                 { (n) printmchar0 } def
+/dn64n                 { (o) printmchar0 } def
+/up128n                        { (p) printmchar0 } def
+/dn128n                        { (q) printmchar0 } def
+/up256n                        { (r) printmchar0 } def
+/dn256n                        { (s) printmchar0 } def
+/com                   { (t) printmchar0 } def
+/cut                   { (u) printmchar0 } def
+/begped                        { (v) printmchar0 } def
+/pedal                 { (w) printmchar0 } def
+/endped                        { (x) printmchar0 } def
+/dnbow                 { (y) printmchar0 } def
+/upbow                 { (z) printmchar0 } def
+/wedge                 { (1) printmchar0 } def
+/uwedge                        { (2) printmchar0 } def
+/ferm                  { (3) printmchar0 } def
+/uferm                 { (4) printmchar0 } def
+/sign                  { (5) printmchar0 } def
+/coda                  { (6) printmchar0 } def
+/mor                   { (7) printmchar0 } def
+/invmor                        { (8) printmchar0 } def
+/turn                  { (9) printmchar0 } def
+/invturn               { (0) printmchar0 } def
+/acc_gt                        { (#) printmchar0 } def
+/acc_hat               { ($) printmchar0 } def
+/acc_uhat              { (") printmchar0 } def
+/tr                    { (*) printmchar0 } def
+/leg                   { (,) printmchar0 } def
+/rr                    { (-) printmchar0 } def
+/measrpt               { (.) printmchar0 } def
+/copyright             { (/) printmchar0 } def
+/dim                   { (`) printmchar0 } def
+/halfdim               { (') printmchar0 } def
+/triangle              { (^) printmchar0 } def
+/qwhrest               { (&) printmchar0 } def
+/ll1rest               { (!) printmchar0 } def
+/ll2rest               { (@) printmchar0 } def
+/dwhrighttriangle      { (A) printmchar1 } def
+/righttriangle         { (B) printmchar1 } def
+/fillrighttriangle     { (C) printmchar1 } def
+/udwhrighttriangle     { (D) printmchar1 } def
+/urighttriangle                { (E) printmchar1 } def
+/ufillrighttriangle    { (F) printmchar1 } def
+/dwhrectangle          { (G) printmchar1 } def
+/rectangle             { (H) printmchar1 } def
+/fillrectangle         { (I) printmchar1 } def
+/dwhisostriangle       { (J) printmchar1 } def
+/isostriangle          { (K) printmchar1 } def
+/fillisostriangle      { (L) printmchar1 } def
+/dwhpiewedge           { (M) printmchar1 } def
+/piewedge              { (N) printmchar1 } def
+/fillpiewedge          { (O) printmchar1 } def
+/dwhsemicircle         { (P) printmchar1 } def
+/semicircle            { (Q) printmchar1 } def
+/fillsemicircle                { (R) printmchar1 } def
+/dwhslashhead          { (S) printmchar1 } def
+/slashhead             { (T) printmchar1 } def
+/fillslashhead         { (U) printmchar1 } def
+/blankhead             { (V) printmchar1 } def
+
+
+% Define routines for Mup output other than music characters.
+
+/stepsize 3 def           % define a step size as 3 points (at default magnification)
+
+% x1 y1 x2 lines dist staffscale staff
+%              draw a staff starting at x1, y1 and extending to x2 with "lines"
+%              lines, 2*dist*stepsize apart, scaled by staffscale
+/staff {
+       /staffscale exch def
+       /dist exch def
+       /lines exch def
+       /x2 exch def
+       /y1 exch def
+       /x1 exch def
+       0.7 staffscale mul sb setlinewidth
+       1 lines sub  2  lines 1 sub {   % loop from bottom line to top line
+               dup stepsize mul staffscale mul dist mul y1 add x1 exch moveto
+               stepsize mul staffscale mul dist mul y1 add x2 exch lineto stroke
+       } for
+} def
+
+% x y1 y2 bracket      draw a bracket; y1 is the top
+/bracket {
+       /y2 exch def
+       /y1 exch def
+       /x exch def
+       gsave
+       3 setlinewidth
+       x 2 sub y1 1 add moveto
+       x 2 sub y2 1 sub lineto
+       stroke
+       x 2 sub y1 1 add moveto
+       x 1 sub y1 1 add   x 3 add y1 1 add   x 5 add y1 6 add   curveto
+       x 6 add y1 5 add lineto
+       x 5 add y1 2 add   x 1 add y1 2 sub   x 2 sub y1 2 sub   curveto
+       fill
+       x 2 sub y2 1 sub moveto
+       x 1 sub y2 1 sub   x 3 add y2 1 sub   x 5 add y2 6 sub   curveto
+       x 6 add y2 5 sub lineto
+       x 5 add y2 2 sub   x 1 add y2 2 add   x 2 sub y2 2 add   curveto
+       fill
+       grestore
+} def
+
+% x y1 y2 brace                draw a brace; y1 is the top
+/brace {
+       /y2 exch def
+       /y1 exch def
+       /x exch def
+       gsave
+       x 9 sub y1 y2 add 2 div translate
+       /topy y1 y2 sub 2 div 1 sub def
+       0 1 1 {
+               pop
+               %0 topy moveto 0 0 lineto stroke
+               0 0 moveto
+               16 topy 0.2 mul   -11 topy 0.6 mul   8 topy   curveto
+               8.7 topy lineto
+               -7 topy 0.7 mul   20 topy 0.3 mul   1 0   curveto
+               fill
+               1 -1 scale      % flip to do bottom half
+       } for
+       grestore
+} def
+
+% endx endy wavy staffscale    draw a wavy line from current point to here,
+%                              scaled by staffscale
+/wavy {
+       /staffscale exch def
+       /endy exch def          % define the end point of the line
+       /endx exch def
+       currentpoint            % line starts at current point
+       /begy exch def          % define the beginning point of the line
+       /begx exch def
+       gsave
+       /dx endx begx sub def   % find delta x and delta y
+       /dy endy begy sub def
+       /r dx dx mul dy dy mul add sqrt def     % hypotenuse
+       /theta dy dx atan def                   % angle with positive x axis
+       begx begy translate     % change axes so that we can draw the line
+       theta rotate            %   from (0, 0) to (r, 0)
+       staffscale staffscale scale     % scale everything by staffscale
+       /scaledr r staffscale div def   % but scale r in reverse to keep length
+
+       % Each outer loop draws one cycle of the squiggle.  It continues until
+       % we are at or beyond the desired end point.
+       0 0 moveto
+       0 6 scaledr {
+               gsave
+               % first loop draws left half of squiggle; second draws right
+               0 1 1 {
+                       0.0 0.4 moveto
+                       2.0 1.9 3.4 2.3 3.9 0.0 curveto
+                       2.1 0.0 lineto
+                       1.9 0.8 1.4 0.7 0.0 -0.4 curveto
+                       fill
+                       pop 180 rotate -6 0 translate
+               } for
+               grestore
+
+               pop 6 0 translate       % shift axes right one squiggle
+       } for
+
+       grestore
+} def
+
+% x y space frets fretno numvert curvel curver [ f1 f2 f3 ... ] grid
+%                              print a guitar grid diagram
+/grid {
+       /grid_positions exch def % 0="o", -1="x", -2=nothing, positive=dot
+       /curver exch def        % right string for curve, 0 if none
+       /curvel exch def        % left string for curve, 0 if none
+       /numvert exch def       % vertical position to print fretno, 0 if none
+       /fretno exch def        % fret no. to print at right, 0 if none
+       /frets exch def         % number of fret lines
+       /space exch def         % points between two neighboring lines
+       /y exch def             % y coord of top fret line
+       /x exch def             % x coord of left strings
+
+       gsave
+       /strings grid_positions length def      % number of strings
+       /lmarky 0.4 space mul y add def         % lowest Y of a "o" or "x"
+       space 10 div setlinewidth
+       2 setlinecap
+
+       % draw the lines of the grid
+       0  1  strings 1 sub {   % loop from left string to right string
+               dup space mul x add y moveto
+               space mul x add frets 1 sub space mul y exch sub lineto stroke
+       } for
+       0  -1  1 frets sub {    % loop from top fret (nut) to bottom fret
+               dup space mul y add x exch moveto
+               space mul y add strings 1 sub space mul x add exch lineto stroke
+       } for
+
+       % draw the curved line if there is one
+       curvel 0 gt {
+               % within strings curvel to curver, find smallest positive fret
+               /minfret 1000 def
+               curvel 1 curver {
+                       /strno exch def
+                       /grid_p grid_positions strno 1 sub get def
+                       grid_p 0 gt grid_p minfret lt and {
+                               /minfret grid_p def
+                       } if
+               } for
+
+               % if curve goes above top fret, other marks must be higher
+               minfret 1 eq {
+                       /hmarky 1.2 space mul y add def
+               } {
+                       /hmarky lmarky def
+               } ifelse
+
+               /strdiff curver curvel sub def
+               space 8 div setlinewidth
+
+               % set endpoint coords of curve; higher if curve is short
+               /curvex1 curvel 1 sub space mul x add def
+               /curvex2 curver 1 sub space mul x add def
+               /curvey 1 minfret sub space mul y add def
+               strdiff 3 lt {
+                       /curvey 0.2 strdiff div space mul curvey add def
+               } if
+
+               % move to left end, set other points, draw curve
+               curvex1 curvey moveto
+
+               curvex1 curvex2 curvex1 sub 3 div add
+               curvey space 0.4 strdiff sqrt mul mul add
+
+               curvex2 curvex2 curvex1 sub 3 div sub
+               curvey space 0.4 strdiff sqrt mul mul add
+
+               curvex2 curvey curveto stroke
+       } if
+
+       space 10 div setlinewidth
+
+       % draw dots and x and o marks
+       0  1  strings 1 sub {   % loop from left string to right string
+               /strno exch def % first string is 0
+               /grid_p grid_positions strno get def
+               /strx strno space mul x add def
+
+               % set Y of mark higher if curved line covers this string
+               strno 1 add curvel ge  strno 1 add curver le  and {
+                       /marky hmarky def
+               } {
+                       /marky lmarky def
+               } ifelse
+
+               grid_p -1 eq {          % draw an X above the string
+                       /xhwid space 3 div def
+                       strx xhwid sub marky xhwid sub moveto
+                       strx xhwid add marky xhwid add lineto stroke
+                       strx xhwid sub marky xhwid add moveto
+                       strx xhwid add marky xhwid sub lineto stroke
+               } if
+               grid_p 0 eq {           % draw a circle above the string
+                       strx marky space 0.3 mul 0 360 arc stroke
+               } if
+               grid_p 1 ge {           % draw a dot by the proper fret
+                       strx y grid_p space mul sub space 3 div add
+                       space 3 div 0 360 arc fill
+               } if
+       } for
+
+       % print "X fr" if requested
+       fretno 0 gt {
+               /Palatino-Roman findfont space 1.9 mul scalefont setfont
+               x strings 0.5 sub space mul add
+               y space numvert 0.3 add mul sub moveto
+               fretno 2 string cvs show ( fr) show
+       } if
+       grestore
+} def
+
+% x1 y1 x2 y2 whitebox         draw a white rectangle with opposite
+%                              corners of (x1,y1) and (x2,y2)
+/whitebox {
+       /y2 exch def
+       /x2 exch def
+       /y1 exch def
+       /x1 exch def
+       1.0 setgray
+       newpath
+       x1 y1 moveto
+       x1 y2 lineto
+       x2 y2 lineto
+       x2 y1 lineto
+       closepath
+       fill
+       stroke
+       0.0 setgray
+} def
+
+
+/LineNum 0 def
+/InputFile (unknown) def
+
+% n linenum
+/linenum {
+       /LineNum exch def
+} def
+
+% (inputfilename) inputfile
+/inputfile {
+       /InputFile exch def
+} def
+
+% find size of Encoding and make a dictionary
+% that size for bounding box information
+mfont0 begin
+/dictsize Encoding length def
+mfont0 /Mcbbox0 dictsize dict put
+
+% temporarily redefine printmchar0 to get code
+5 dict begin
+/printmchar0 { {} forall } def
+
+Mcbbox0 Encoding 128rest get [ 1140.0 0 -515.0 -1515.0 615.0 1685.0 ] put
+Mcbbox0 Encoding 16rest get [ 830.0 0 -415.0 -1215.0 405.0 485.0 ] put
+Mcbbox0 Encoding 1n get [ 1080.0 0 -535.0 -335.0 535.0 345.0 ] put
+Mcbbox0 Encoding 1rest get [ 1540.0 0 -765.0 -5.0 765.0 645.0 ] put
+Mcbbox0 Encoding 256rest get [ 1250.0 0 -625.0 -2115.0 615.0 1685.0 ] put
+Mcbbox0 Encoding 2n get [ 880.0 0 -435.0 -345.0 435.0 355.0 ] put
+Mcbbox0 Encoding 2rest get [ 1540.0 0 -765.0 -45.0 765.0 315.0 ] put
+Mcbbox0 Encoding 32rest get [ 940.0 0 -415.0 -1215.0 515.0 1085.0 ] put
+Mcbbox0 Encoding 4n get [ 840.0 0 -415.0 -335.0 415.0 345.0 ] put
+Mcbbox0 Encoding 4rest get [ 650.0 0 -345.0 -885.0 295.0 985.0 ] put
+Mcbbox0 Encoding 64rest get [ 1040.0 0 -515.0 -1515.0 515.0 1085.0 ] put
+Mcbbox0 Encoding 8rest get [ 750.0 0 -305.0 -615.0 435.0 485.0 ] put
+Mcbbox0 Encoding acc_gt get [ 1170.0 0 -525.0 -335.0 635.0 345.0 ] put
+Mcbbox0 Encoding acc_hat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put
+Mcbbox0 Encoding acc_uhat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put
+Mcbbox0 Encoding begped get [ 470.0 0 -245.0 -45.0 215.0 615.0 ] put
+Mcbbox0 Encoding cclef get [ 1540.0 0 -765.0 -1245.0 765.0 1255.0 ] put
+Mcbbox0 Encoding coda get [ 1640.0 0 -815.0 -855.0 815.0 865.0 ] put
+Mcbbox0 Encoding com get [ 1100.0 0 -575.0 -635.0 515.0 655.0 ] put
+Mcbbox0 Encoding copyright get [ 920.0 0 -455.0 -45.0 455.0 855.0 ] put
+Mcbbox0 Encoding cut get [ 1100.0 0 -575.0 -905.0 515.0 915.0 ] put
+Mcbbox0 Encoding dblflat get [ 1170.0 0 -595.0 -405.0 565.0 1115.0 ] put
+Mcbbox0 Encoding dblsharp get [ 720.0 0 -355.0 -345.0 355.0 355.0 ] put
+Mcbbox0 Encoding dblwhole get [ 1090.0 0 -535.0 -605.0 545.0 615.0 ] put
+Mcbbox0 Encoding diamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put
+Mcbbox0 Encoding dim get [ 540.0 0 -265.0 -5.0 265.0 905.0 ] put
+Mcbbox0 Encoding dn128n get [ 840.0 0 -415.0 -3545.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn16n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn256n get [ 840.0 0 -415.0 -3965.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn2n get [ 880.0 0 -435.0 -2105.0 435.0 355.0 ] put
+Mcbbox0 Encoding dn32n get [ 840.0 0 -415.0 -2585.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn4n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn64n get [ 840.0 0 -415.0 -3065.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn8n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put
+Mcbbox0 Encoding dnbow get [ 810.0 0 -395.0 -5.0 405.0 915.0 ] put
+Mcbbox0 Encoding dnflag get [ 640.0 0 -335.0 -1705.0 295.0 15.0 ] put
+Mcbbox0 Encoding dot get [ 280.0 0 -135.0 -125.0 135.0 135.0 ] put
+Mcbbox0 Encoding dwhdiamond get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox0 Encoding dwhrest get [ 340.0 0 -165.0 -5.0 165.0 615.0 ] put
+Mcbbox0 Encoding endped get [ 480.0 0 -215.0 -45.0 255.0 615.0 ] put
+Mcbbox0 Encoding fclef get [ 1840.0 0 -1015.0 -1705.0 815.0 655.0 ] put
+Mcbbox0 Encoding ferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put
+Mcbbox0 Encoding filldiamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put
+Mcbbox0 Encoding flat get [ 580.0 0 -295.0 -405.0 275.0 1115.0 ] put
+Mcbbox0 Encoding gclef get [ 1790.0 0 -915.0 -1605.0 865.0 3015.0 ] put
+Mcbbox0 Encoding halfdim get [ 760.0 0 -375.0 -5.0 375.0 1015.0 ] put
+Mcbbox0 Encoding invmor get [ 1320.0 0 -655.0 -455.0 655.0 465.0 ] put
+Mcbbox0 Encoding invturn get [ 1300.0 0 -645.0 -335.0 645.0 345.0 ] put
+Mcbbox0 Encoding leg get [ 840.0 0 -415.0 -55.0 415.0 65.0 ] put
+Mcbbox0 Encoding ll1rest get [ 840.0 0 -415.0 -5.0 415.0 625.0 ] put
+Mcbbox0 Encoding ll2rest get [ 840.0 0 -415.0 -15.0 415.0 315.0 ] put
+Mcbbox0 Encoding measrpt get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put
+Mcbbox0 Encoding mor get [ 1320.0 0 -655.0 -285.0 655.0 295.0 ] put
+Mcbbox0 Encoding nat get [ 520.0 0 -255.0 -855.0 255.0 865.0 ] put
+Mcbbox0 Encoding pedal get [ 1040.0 0 -515.0 -45.0 515.0 675.0 ] put
+Mcbbox0 Encoding qwhrest get [ 340.0 0 -165.0 -605.0 165.0 615.0 ] put
+Mcbbox0 Encoding rr get [ 940.0 0 -465.0 -25.0 465.0 1035.0 ] put
+Mcbbox0 Encoding sharp get [ 700.0 0 -345.0 -935.0 345.0 945.0 ] put
+Mcbbox0 Encoding sign get [ 1340.0 0 -665.0 -825.0 665.0 835.0 ] put
+Mcbbox0 Encoding tr get [ 1440.0 0 -715.0 -5.0 715.0 1015.0 ] put
+Mcbbox0 Encoding triangle get [ 800.0 0 -395.0 -45.0 395.0 785.0 ] put
+Mcbbox0 Encoding turn get [ 1300.0 0 -645.0 -325.0 645.0 345.0 ] put
+Mcbbox0 Encoding uferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put
+Mcbbox0 Encoding up128n get [ 1390.0 0 -745.0 -335.0 635.0 3555.0 ] put
+Mcbbox0 Encoding up16n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put
+Mcbbox0 Encoding up256n get [ 1390.0 0 -745.0 -335.0 635.0 3975.0 ] put
+Mcbbox0 Encoding up2n get [ 880.0 0 -435.0 -345.0 435.0 2115.0 ] put
+Mcbbox0 Encoding up32n get [ 1390.0 0 -745.0 -335.0 635.0 2595.0 ] put
+Mcbbox0 Encoding up4n get [ 850.0 0 -415.0 -335.0 425.0 2115.0 ] put
+Mcbbox0 Encoding up64n get [ 1390.0 0 -745.0 -335.0 635.0 3075.0 ] put
+Mcbbox0 Encoding up8n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put
+Mcbbox0 Encoding upbow get [ 720.0 0 -355.0 -115.0 355.0 925.0 ] put
+Mcbbox0 Encoding upflag get [ 640.0 0 -335.0 -5.0 295.0 1715.0 ] put
+Mcbbox0 Encoding uwedge get [ 340.0 0 -165.0 -5.0 165.0 505.0 ] put
+Mcbbox0 Encoding wedge get [ 340.0 0 -165.0 5.0 165.0 515.0 ] put
+Mcbbox0 Encoding xnote get [ 880.0 0 -435.0 -365.0 435.0 375.0 ] put
+
+end
+end
+
+/Mfont0 mfont0 definefont
+
+
+% find size of Encoding and make a dictionary
+% that size for bounding box information
+mfont1 begin
+/dictsize Encoding length def
+mfont1 /Mcbbox1 dictsize dict put
+
+% temporarily redefine printmchar1 to get code
+5 dict begin
+/printmchar1 { {} forall } def
+
+Mcbbox1 Encoding blankhead get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put
+Mcbbox1 Encoding dwhisostriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhpiewedge get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhrectangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhsemicircle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhslashhead get [ 1410.0 0 -695.0 -725.0 705.0 735.0 ] put
+Mcbbox1 Encoding fillisostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+Mcbbox1 Encoding fillpiewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillrectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillrighttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillsemicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillslashhead get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put
+Mcbbox1 Encoding isostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+Mcbbox1 Encoding piewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding rectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put
+Mcbbox1 Encoding righttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding semicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding slashhead get [ 1380.0 0 -685.0 -725.0 685.0 735.0 ] put
+Mcbbox1 Encoding udwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding ufillrighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+Mcbbox1 Encoding urighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+
+end
+end
+
+/Mfont1 mfont1 definefont
+
+/makeExtEncoding {
+       /extendedencoding 256 array def
+       StandardEncoding extendedencoding copy
+       extendedencoding 32 /exclamdown put
+       extendedencoding 33 /cent put
+       extendedencoding 34 /sterling put
+       extendedencoding 35 /yen put
+       extendedencoding 36 /quotedblleft put
+       extendedencoding 37 /guillemotleft put
+       extendedencoding 38 /guillemotright put
+       extendedencoding 39 /guilsinglleft put
+       extendedencoding 40 /guilsinglright put
+       extendedencoding 41 /dagger put
+       extendedencoding 42 /daggerdbl put
+       extendedencoding 43 /bullet put
+       extendedencoding 44 /quotedblbase put
+       extendedencoding 45 /quotedblright put
+       extendedencoding 46 /questiondown put
+       extendedencoding 47 /grave put
+       extendedencoding 48 /acute put
+       extendedencoding 49 /macron put
+       extendedencoding 50 /breve put
+       extendedencoding 51 /dotaccent put
+       extendedencoding 52 /dieresis put
+       extendedencoding 53 /ring put
+       extendedencoding 54 /cedilla put
+       extendedencoding 55 /hungarumlaut put
+       extendedencoding 56 /ogonek put
+       extendedencoding 57 /caron put
+       extendedencoding 58 /emdash put
+       extendedencoding 59 /AE put
+       extendedencoding 60 /ae put
+       extendedencoding 61 /ordfeminine put
+       extendedencoding 62 /ordmasculine put
+       extendedencoding 63 /Lslash put
+       extendedencoding 64 /lslash put
+       extendedencoding 65 /Oslash put
+       extendedencoding 66 /oslash put
+       extendedencoding 67 /OE put
+       extendedencoding 68 /oe put
+       extendedencoding 69 /dotlessi put
+       extendedencoding 70 /germandbls put
+       extendedencoding 71 /Aacute put
+       extendedencoding 72 /aacute put
+       extendedencoding 73 /Acircumflex put
+       extendedencoding 74 /acircumflex put
+       extendedencoding 75 /Adieresis put
+       extendedencoding 76 /adieresis put
+       extendedencoding 77 /Agrave put
+       extendedencoding 78 /agrave put
+       extendedencoding 79 /Aring put
+       extendedencoding 80 /aring put
+       extendedencoding 81 /Atilde put
+       extendedencoding 82 /atilde put
+       extendedencoding 83 /Ccedilla put
+       extendedencoding 84 /ccedilla put
+       extendedencoding 85 /Eacute put
+       extendedencoding 86 /eacute put
+       extendedencoding 87 /Ecircumflex put
+       extendedencoding 88 /ecircumflex put
+       extendedencoding 89 /Edieresis put
+       extendedencoding 90 /edieresis put
+       extendedencoding 91 /Egrave put
+       extendedencoding 92 /egrave put
+       extendedencoding 93 /Iacute put
+       extendedencoding 94 /iacute put
+       extendedencoding 95 /Icircumflex put
+       extendedencoding 96 /icircumflex put
+       extendedencoding 97 /Idieresis put
+       extendedencoding 98 /idieresis put
+       extendedencoding 99 /Igrave put
+       extendedencoding 100 /igrave put
+       extendedencoding 101 /Ntilde put
+       extendedencoding 102 /ntilde put
+       extendedencoding 103 /Oacute put
+       extendedencoding 104 /oacute put
+       extendedencoding 105 /Ocircumflex put
+       extendedencoding 106 /ocircumflex put
+       extendedencoding 107 /Odieresis put
+       extendedencoding 108 /odieresis put
+       extendedencoding 109 /Ograve put
+       extendedencoding 110 /ograve put
+       extendedencoding 111 /Otilde put
+       extendedencoding 112 /otilde put
+       extendedencoding 113 /Scaron put
+       extendedencoding 114 /scaron put
+       extendedencoding 115 /Uacute put
+       extendedencoding 116 /uacute put
+       extendedencoding 117 /Ucircumflex put
+       extendedencoding 118 /ucircumflex put
+       extendedencoding 119 /Udieresis put
+       extendedencoding 120 /udieresis put
+       extendedencoding 121 /Ugrave put
+       extendedencoding 122 /ugrave put
+       extendedencoding 123 /Ydieresis put
+       extendedencoding 124 /ydieresis put
+       extendedencoding 125 /Zcaron put
+       extendedencoding 126 /zcaron put
+       extendedencoding 127 /space put
+} def
+
+/makeExtendedFont {
+       findfont
+       dup length dict /newdict exch def
+       { 1 index /FID ne
+               { newdict 3 1 roll put }
+               { pop pop }
+               ifelse
+       } forall
+       newdict /Encoding extendedencoding put
+       newdict /UniqueID newdict /UniqueID get 1 add put
+       newdict definefont pop
+} def
+/flagsep 1.60 300 mul def       % 1.60 stepsizes
+/scv 147460 def /sf 962 string def
+/fa {/p 0 def /chr exch -3 bitshift 127 and def {sf exch p add dup /p exch def chr put} forall} def
+[ 74 62 70 54 29 55 36 37 19 26 45 40 41 50 45 52 19 73 11 68 ] 1567304784 fa
+[ 961 ] 1341740116 fa
+[ 12 4 5 4 4 2 4 3 3 7 7 3 5 5 4 5 4 2 5 3 ] 1969419526 fa
+[ 96 4 4 3 2 4 11 2 6 23 13 16 8 3 28 13 8 3 6 11 ] 387152134 fa
+[ 268 4 13 12 5 4 4 5 4 5 3 2 4 3 4 8 3 3 9 2 ] 305899779 fa
+[ 369 3 4 9 3 3 9 2 4 3 4 7 4 4 4 9 5 3 5 4 ] 477458695 fa
+[ 498 4 36 4 37 4 42 4 4 37 4 4 35 4 4 5 13 3 4 4 ] 1130513667 fa
+[ 759 3 5 33 4 5 9 29 5 4 3 5 4 4 5 4 4 5 4 3 ] 1205319942 fa
+[ 902 8 4 2 3 4 3 4 4 3 2 3 9 ] 1708988675 fa
+[ 468 6 4 10 3 30 5 3 24 40 4 3 3 3 3 8 23 1 1 1 ] 123455756 fa
+[ 664 23 4 2 13 66 4 5 9 ] 2061720845 fa
+[ 795 ] 1622189328 fa
+[ 463 45 40 41 50 45 84 ] 304180545 fa
+[ 494 40 41 49 45 43 84 ] 251711819 fa
+[ 149 203 37 144 ] 358262127 fa
+[ 456 142 52 ] 95949173 fa
+[ 0 13 13 10 65 36 6 26 38 17 13 53 4 13 13 25 36 183 7 140 ] 1751712121 fa
+[ 839 5 13 12 13 13 48 ] 1943250302 fa
+[ 30 164 254 7 42 4 36 4 18 1 18 4 46 3 1 41 4 39 4 41 ] 499619205 fa
+[ 798 1 3 1 ] 1277775234 fa
+[ 76 32 135 79 99 8 246 43 30 160 ] 734015880 fa
+[ 265 70 36 12 25 87 4 36 4 37 4 46 4 41 43 83 4 83 41 3 ] 1546658194 fa
+[ 193 49 180 8 17 134 ] 831070621 fa
+[ 353 366 ] 1033403809 fa
+[ 266 1 190 39 40 41 50 45 43 45 ] 1758436783 fa
+[ 423 8 109 ] 508918194 fa
+[ 328 6 30 6 31 6 269 ] 212071871 fa
+[ 390 357 2 ] 1671244225 fa
+[ 500 ] 347047368 fa
+[ 558 ] 1276946910 fa
+[ 651 ] 2109048312 fa
+[ 644 ] 1914352160 fa
+[ 520 ] 471204394 fa
+[ 512 5 2 ] 1930983991 fa
+[ 665 ] 154021439 fa
+[ 513 ] 777103941 fa
+[ 514 ] 260959830 fa
+[ 530 239 ] 1284535922 fa
+[ 510 ] 1982423675 fa
+[ 150 ] 1969948305 fa
+[ 511 7 134 ] 1407991454 fa
+[ 144 371 ] 1896661664 fa
+[ 464 52 ] 1444653737 fa
+[ 509 81 ] 1712172720 fa
+[ 110 11 32 24 22 18 40 12 54 7 17 19 18 19 22 13 377 94 9 11 ] 889612 fa
+[ 954 ] 1802916616 fa
+[ 80 146 51 78 37 84 8 8 73 5 44 45 33 9 73 9 130 9 11 12 ] 1808121621 fa
+[ 19 42 3 22 8 82 63 23 25 13 8 5 176 248 40 73 12 13 13 12 ] 1752602397 fa
+[ 22 10 37 42 1 2 19 26 6 38 17 13 38 11 21 13 16 9 27 9 ] 1598682919 fa
+[ 405 9 13 46 49 50 50 213 18 12 13 13 12 45 10 ] 160257827 fa
+[ 1 8 8 6 10 10 16 11 14 8 23 19 13 19 13 7 15 3 9 8 ] 882894639 fa
+[ 234 40 9 15 6 7 6 25 36 37 19 6 47 16 40 41 50 45 43 6 ] 185215791 fa
+[ 733 19 37 16 12 13 3 3 12 6 6 6 7 6 7 6 6 6 45 10 ] 1706915629 fa
+[ 24 10 37 45 2 17 5 1 15 4 7 5 8 8 17 17 13 11 8 26 ] 1713964852 fa
+[ 284 21 13 25 18 18 19 18 28 1 7 28 2 4 106 24 3 2 32 36 ] 1218620208 fa
+[ 695 62 1 7 13 1 7 2 37 4 8 5 13 12 13 13 12 45 5 1 ] 1317868340 fa
+[ 960 ] 75399990 fa
+[ 45 9 155 6 245 68 21 98 60 109 ] 1430691640 fa
+[ 20 27 15 25 8 33 173 13 45 37 83 170 5 34 8 115 40 12 13 13 ] 841629509 fa
+[ 901 ] 422446918 fa
+[ 27 25 37 13 3 40 12 73 49 77 4 33 4 68 89 219 21 27 3 4 ] 560155470 fa
+[ 466 6 135 41 7 6 36 6 89 ] 803193686 fa
+[ 42 80 1 55 80 1 80 36 37 155 1 263 40 65 ] 189315943 fa
+[ 6 31 36 9 43 21 6 185 36 37 210 ] 1031359337 fa
+[ 44 9 101 4 4 20 8 80 3 23 30 5 19 17 20 17 15 7 7 36 ] 586694517 fa
+[ 552 22 20 16 3 55 42 31 10 33 ] 343336822 fa
+[ 7 4 54 54 10 22 10 20 8 8 53 5 226 12 115 38 17 42 26 13 ] 1808462718 fa
+[ 780 32 ] 847653755 fa
+[ 3 63 31 408 18 4 18 6 22 13 15 3 32 9 17 4 15 5 18 4 ] 1627872128 fa
+[ 724 83 7 ] 1643402114 fa
+[ 228 296 8 25 39 16 159 14 34 ] 670118796 fa
+[ 2 2 47 69 19 34 23 20 35 5 187 10 51 2 38 2 39 2 48 2 ] 888380310 fa
+[ 680 2 41 2 2 5 13 11 10 40 2 50 80 ] 1392580498 fa
+[ 14 25 10 7 22 49 21 22 1 4 10 23 4 13 15 5 16 15 12 3 ] 2114772893 fa
+[ 295 30 24 9 28 9 23 19 13 1 8 24 67 16 3 30 3 3 53 9 ] 453068702 fa
+[ 694 6 9 20 11 23 1 23 23 22 8 5 1 24 41 9 11 4 5 1 ] 1393470366 fa
+[ 944 8 ] 1770206109 fa
+[ 10 5 25 6 4 7 42 39 25 20 4 4 7 2 14 17 126 5 32 5 ] 113705892 fa
+[ 442 25 4 6 114 27 38 42 32 25 20 47 19 112 ] 998588323 fa
+[ 79 19 131 109 36 37 74 70 1 59 8 34 3 25 5 9 3 80 11 27 ] 1221405612 fa
+[ 912 9 11 ] 273962927 fa
+[ 8 230 25 23 6 17 130 31 61 64 16 127 32 ] 1881483187 fa
+[ 130 683 ] 1406620603 fa
+[ 18 10 32 25 5 3 10 3 143 50 13 9 61 93 86 1 1 180 48 58 ] 1980878788 fa
+[ 861 13 9 4 12 8 17 3 ] 1447963591 fa
+[ 67 143 8 128 115 435 19 2 ] 477757388 fa
+[ 490 35 ] 1151262673 fa
+[ 5 70 67 32 37 16 14 7 27 18 142 301 17 90 103 ] 1523362782 fa
+[ 117 14 33 38 17 13 20 26 3 453 89 3 8 113 10 ] 1908448236 fa
+sf cvx exec
+%%EndProlog
+%%Page: 1 1
+save
+1216322504 1216321786 sv
+0.700000 0.700000 scale
+%  S_SSV
+(/home/johnkr/mup/5.3/doc/arkkra/star.mup) inputfile
+12 linenum
+%  S_SSV
+29 linenum
+%  S_FEED
+252.00 1502.60 812.57 5 1.000000 1.000000 stf
+252.00 1393.03 812.57 5 1.000000 1.000000 stf
+107.50 1010.60 877.03 brace
+0.70 setlinewidth
+108.00 1010.60 moveto
+108.00 877.03 lineto stroke
+%  S_CLEFSIG
+119.79 992.60 1.000000 gclef
+120.05 895.03 1.000000 fclef
+134.41 1010.60 1.000000 sharp
+141.05 1001.60 1.000000 sharp
+147.69 1013.60 1.000000 sharp
+134.41 895.03 1.000000 sharp
+141.05 886.03 1.000000 sharp
+147.69 898.03 1.000000 sharp
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+154.01 998.60 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+154.01 986.58 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+154.01 889.03 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+154.01 877.02 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+41 linenum
+195.97 942.88 moveto
+218.78 942.88 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+175.38 942.88 moveto
+(Oh) show
+180.53 986.60 1.000000 4n
+189.79 989.60 1.000000 dot
+184.21 987.35 moveto
+184.21 1005.39 lineto stroke
+214.75 980.60 1.000000 4n
+208.52 980.60 moveto
+220.98 980.60 lineto stroke
+218.43 981.35 moveto
+218.43 999.39 lineto stroke
+newpath
+183.86 1006.89 moveto
+218.78 1000.89 lineto
+218.78 997.89 lineto
+183.86 1003.89 lineto
+closepath
+fill
+newpath
+218.08 995.89 moveto
+210.02 997.31 lineto
+210.02 994.31 lineto
+218.08 992.89 lineto
+closepath
+fill
+180.53 986.60 1.000000 4n
+189.79 989.60 1.000000 dot
+176.85 985.85 moveto
+176.85 967.81 lineto stroke
+214.75 980.60 1.000000 4n
+208.52 980.60 moveto
+220.98 980.60 lineto stroke
+211.07 979.85 moveto
+211.07 961.81 lineto stroke
+newpath
+176.50 969.31 moveto
+211.42 963.31 lineto
+211.42 960.31 lineto
+176.50 966.31 lineto
+closepath
+fill
+newpath
+210.72 968.31 moveto
+202.66 969.72 lineto
+202.66 966.72 lineto
+210.72 965.31 lineto
+closepath
+fill
+180.53 981.50 moveto
+180.61 981.69 lineto
+184.68 979.23 189.03 977.49 193.68 976.46 curveto
+198.32 975.44 203.00 975.19 207.73 975.71 curveto
+207.72 975.29 lineto
+202.95 974.22 198.18 974.21 193.41 975.26 curveto
+188.64 976.32 184.32 978.33 180.45 981.31 curveto
+fill
+194.79 991.70 moveto
+194.80 991.93 lineto
+198.45 992.99 202.09 992.97 205.73 991.88 curveto
+209.37 990.79 212.41 988.79 214.87 985.90 curveto
+214.63 985.50 lineto
+211.93 987.92 208.84 989.65 205.37 990.69 curveto
+201.90 991.73 198.37 991.99 194.79 991.47 curveto
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+180.53 892.03 1.000000 4n
+189.79 892.03 1.000000 dot
+0.70 setlinewidth
+184.21 892.78 moveto
+184.21 910.83 lineto stroke
+214.75 886.03 1.000000 4n
+218.43 886.78 moveto
+218.43 904.82 lineto stroke
+newpath
+183.86 912.33 moveto
+218.78 906.33 lineto
+218.78 903.33 lineto
+183.86 909.33 lineto
+closepath
+fill
+newpath
+218.08 901.32 moveto
+210.02 902.74 lineto
+210.02 899.74 lineto
+218.08 898.32 lineto
+closepath
+fill
+180.53 892.03 1.000000 4n
+189.79 892.03 1.000000 dot
+176.85 891.28 moveto
+176.85 873.24 lineto stroke
+214.75 886.03 1.000000 4n
+211.07 885.28 moveto
+211.07 867.24 lineto stroke
+newpath
+176.50 874.74 moveto
+211.42 868.74 lineto
+211.42 865.74 lineto
+176.50 871.74 lineto
+closepath
+fill
+newpath
+210.72 873.74 moveto
+202.66 875.15 lineto
+202.66 872.15 lineto
+210.72 870.74 lineto
+closepath
+fill
+180.53 886.93 moveto
+180.61 887.13 lineto
+184.68 884.66 189.03 882.92 193.68 881.90 curveto
+198.32 880.87 203.00 880.62 207.73 881.14 curveto
+207.72 880.72 lineto
+202.95 879.65 198.18 879.64 193.41 880.69 curveto
+188.64 881.75 184.32 883.76 180.45 886.74 curveto
+fill
+194.79 897.13 moveto
+194.80 897.36 lineto
+198.45 898.42 202.09 898.41 205.73 897.31 curveto
+209.37 896.22 212.41 894.22 214.87 891.33 curveto
+214.63 890.93 lineto
+211.93 893.35 208.84 895.08 205.37 896.12 curveto
+201.90 897.17 198.37 897.43 194.79 896.90 curveto
+fill
+restore
+%  S_BAR
+44 linenum
+239.31 1001.60 1.000000 dot
+239.31 995.60 1.000000 dot
+239.31 892.03 1.000000 dot
+239.31 886.03 1.000000 dot
+0.70 setlinewidth
+236.31 1010.60 moveto
+236.31 877.03 lineto stroke
+3.00 setlinewidth
+232.31 1010.60 moveto
+232.31 877.03 lineto stroke
+0.70 setlinewidth
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+46 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+248.23 942.88 moveto
+(say.) show
+/Times-Roman findfont
+12 scalefont
+setfont
+292.86 942.88 moveto
+(can) show
+/Times-Roman findfont
+12 scalefont
+setfont
+335.46 942.88 moveto
+(you) show
+46 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+245.17 929.56 moveto
+(stripes) show
+/Times-Roman findfont
+12 scalefont
+setfont
+292.70 929.56 moveto
+(and) show
+/Times-Roman findfont
+12 scalefont
+setfont
+332.82 929.56 moveto
+(bright) show
+252.98 974.60 1.000000 4n
+246.75 974.60 moveto
+259.21 974.60 lineto stroke
+246.75 980.60 moveto
+259.21 980.60 lineto stroke
+256.66 975.35 moveto
+256.66 998.60 lineto stroke
+297.02 980.60 1.000000 4n
+290.79 980.60 moveto
+303.25 980.60 lineto stroke
+300.70 981.35 moveto
+300.70 1001.60 lineto stroke
+339.94 986.60 1.000000 4n
+343.63 987.35 moveto
+343.63 1007.60 lineto stroke
+252.98 974.60 1.000000 4n
+246.75 974.60 moveto
+259.21 974.60 lineto stroke
+246.75 980.60 moveto
+259.21 980.60 lineto stroke
+249.30 973.85 moveto
+249.30 953.60 lineto stroke
+297.02 980.60 1.000000 4n
+290.79 980.60 moveto
+303.25 980.60 lineto stroke
+293.34 979.85 moveto
+293.34 959.60 lineto stroke
+339.94 977.60 1.000000 4n
+333.71 980.60 moveto
+346.18 980.60 lineto stroke
+336.26 976.85 moveto
+336.26 956.60 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+252.98 880.03 1.000000 4n
+0.70 setlinewidth
+256.66 880.78 moveto
+256.66 901.03 lineto stroke
+297.02 901.03 1.000000 4n
+300.70 901.78 moveto
+300.70 922.03 lineto stroke
+339.94 904.03 1.000000 4n
+343.63 904.78 moveto
+343.63 925.03 lineto stroke
+252.98 880.03 1.000000 4n
+249.30 879.28 moveto
+249.30 859.03 lineto stroke
+297.02 901.03 1.000000 4n
+293.34 900.28 moveto
+293.34 880.03 lineto stroke
+339.94 898.03 1.000000 4n
+336.26 897.28 moveto
+336.26 877.03 lineto stroke
+restore
+%  S_BAR
+53 linenum
+0.70 setlinewidth
+382.54 1010.60 moveto
+382.54 877.03 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+54 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+394.16 942.88 moveto
+(see,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+463.54 942.88 moveto
+(by) show
+/Times-Roman findfont
+12 scalefont
+setfont
+499.31 942.88 moveto
+(the) show
+54 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+392.51 929.56 moveto
+(stars,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+457.24 929.56 moveto
+(through) show
+/Times-Roman findfont
+12 scalefont
+setfont
+499.31 929.56 moveto
+(the) show
+398.75 995.60 1.000000 2n
+402.65 996.35 moveto
+402.65 1016.60 lineto stroke
+466.53 1001.60 1.000000 4n
+475.79 1001.60 1.000000 dot
+470.21 1002.35 moveto
+470.21 1020.77 lineto stroke
+502.96 998.60 1.000000 4n
+506.64 999.35 moveto
+506.64 1017.77 lineto stroke
+newpath
+469.86 1022.27 moveto
+506.99 1019.27 lineto
+506.99 1016.27 lineto
+469.86 1019.27 lineto
+closepath
+fill
+newpath
+506.29 1014.27 moveto
+498.23 1014.93 lineto
+498.23 1011.93 lineto
+506.29 1011.27 lineto
+closepath
+fill
+398.75 980.60 1.000000 2n
+392.31 980.60 moveto
+405.20 980.60 lineto stroke
+394.86 979.85 moveto
+394.86 959.60 lineto stroke
+466.53 980.60 1.000000 4n
+475.79 977.60 1.000000 dot
+460.29 980.60 moveto
+472.76 980.60 lineto stroke
+462.84 979.85 moveto
+462.84 961.10 lineto stroke
+502.96 980.60 1.000000 4n
+496.73 980.60 moveto
+509.19 980.60 lineto stroke
+499.28 979.85 moveto
+499.28 961.10 lineto stroke
+newpath
+462.49 962.60 moveto
+499.63 962.60 lineto
+499.63 959.60 lineto
+462.49 959.60 lineto
+closepath
+fill
+newpath
+498.93 967.60 moveto
+490.87 967.60 lineto
+490.87 964.60 lineto
+498.93 964.60 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+398.75 901.03 1.000000 2n
+0.70 setlinewidth
+402.65 901.78 moveto
+402.65 922.03 lineto stroke
+466.53 898.03 1.000000 4n
+475.79 898.03 1.000000 dot
+470.21 898.78 moveto
+470.21 917.53 lineto stroke
+502.96 898.03 1.000000 4n
+506.64 898.78 moveto
+506.64 917.53 lineto stroke
+newpath
+469.86 919.03 moveto
+506.99 919.03 lineto
+506.99 916.03 lineto
+469.86 916.03 lineto
+closepath
+fill
+newpath
+506.29 914.03 moveto
+498.23 914.03 lineto
+498.23 911.03 lineto
+506.29 911.03 lineto
+closepath
+fill
+398.75 895.03 1.000000 2n
+394.86 894.28 moveto
+394.86 874.03 lineto stroke
+466.53 892.03 1.000000 4n
+457.17 892.03 1.000000 sharp
+475.79 892.03 1.000000 dot
+462.84 891.28 moveto
+462.84 872.53 lineto stroke
+502.96 892.03 1.000000 4n
+499.28 891.28 moveto
+499.28 872.53 lineto stroke
+newpath
+462.49 874.03 moveto
+499.63 874.03 lineto
+499.63 871.03 lineto
+462.49 871.03 lineto
+closepath
+fill
+newpath
+498.93 879.03 moveto
+490.87 879.03 lineto
+490.87 876.03 lineto
+498.93 876.03 lineto
+closepath
+fill
+restore
+%  S_BAR
+61 linenum
+0.70 setlinewidth
+520.01 1010.60 moveto
+520.01 877.03 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+62 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+524.95 942.88 moveto
+(dawn's) show
+/Times-Roman findfont
+12 scalefont
+setfont
+602.20 942.88 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+572.65 942.88 moveto
+(ear) show
+/Times-Roman findfont
+12 scalefont
+setfont
+620.13 942.88 moveto
+(ly) show
+62 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+557.85 929.56 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+528.79 929.56 moveto
+(per) show
+/Times-Roman findfont
+12 scalefont
+setfont
+598.29 929.56 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+574.65 929.56 moveto
+(il) show
+/Times-Roman findfont
+12 scalefont
+setfont
+618.30 929.56 moveto
+(ous) show
+533.59 995.60 1.000000 4n
+537.28 996.35 moveto
+537.28 1016.60 lineto stroke
+577.30 980.60 1.000000 4n
+571.06 980.60 moveto
+583.53 980.60 lineto stroke
+580.98 981.35 moveto
+580.98 1001.60 lineto stroke
+622.46 983.60 1.000000 4n
+613.10 983.60 1.000000 sharp
+626.14 984.35 moveto
+626.14 1004.60 lineto stroke
+533.59 980.60 1.000000 4n
+527.36 980.60 moveto
+539.83 980.60 lineto stroke
+529.91 979.85 moveto
+529.91 959.60 lineto stroke
+577.30 980.60 1.000000 4n
+571.06 980.60 moveto
+583.53 980.60 lineto stroke
+573.61 979.85 moveto
+573.61 959.60 lineto stroke
+622.46 977.60 1.000000 4n
+616.22 980.60 moveto
+628.69 980.60 lineto stroke
+618.77 976.85 moveto
+618.77 956.60 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+533.59 901.03 1.000000 4n
+0.70 setlinewidth
+537.28 901.78 moveto
+537.28 922.03 lineto stroke
+577.30 901.03 1.000000 4n
+580.98 901.78 moveto
+580.98 922.03 lineto stroke
+622.46 901.03 1.000000 4n
+626.14 901.78 moveto
+626.14 922.03 lineto stroke
+533.59 895.03 1.000000 4n
+529.91 894.28 moveto
+529.91 874.03 lineto stroke
+577.30 895.03 1.000000 4n
+573.61 894.28 moveto
+573.61 874.03 lineto stroke
+622.46 883.03 1.000000 4n
+618.77 882.28 moveto
+618.77 862.03 lineto stroke
+restore
+%  S_BAR
+69 linenum
+0.70 setlinewidth
+663.57 1010.60 moveto
+663.57 877.03 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+70 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+672.07 942.88 moveto
+(light) show
+/Times-Roman findfont
+12 scalefont
+setfont
+752.92 942.88 moveto
+(what) show
+/Times-Roman findfont
+12 scalefont
+setfont
+783.82 942.88 moveto
+(so) show
+70 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+671.15 929.56 moveto
+(fight,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+753.93 929.56 moveto
+(o'er) show
+/Times-Roman findfont
+12 scalefont
+setfont
+782.83 929.56 moveto
+(the) show
+677.54 986.60 1.000000 4n
+681.22 987.35 moveto
+681.22 1007.60 lineto stroke
+721.69 1010.60 1.000000 4rest
+758.73 986.60 1.000000 4n
+762.42 987.35 moveto
+762.42 1006.10 lineto stroke
+786.49 986.60 1.000000 4n
+790.17 987.35 moveto
+790.17 1006.10 lineto stroke
+newpath
+762.07 1007.60 moveto
+790.52 1007.60 lineto
+790.52 1004.60 lineto
+762.07 1004.60 lineto
+closepath
+fill
+677.54 977.60 1.000000 4n
+671.31 980.60 moveto
+683.77 980.60 lineto stroke
+673.86 976.85 moveto
+673.86 956.60 lineto stroke
+721.69 968.60 1.000000 4rest
+758.73 977.60 1.000000 4n
+752.50 980.60 moveto
+764.97 980.60 lineto stroke
+755.05 976.85 moveto
+755.05 958.10 lineto stroke
+786.49 977.60 1.000000 4n
+780.25 980.60 moveto
+792.72 980.60 lineto stroke
+782.80 976.85 moveto
+782.80 958.10 lineto stroke
+newpath
+754.70 959.60 moveto
+783.15 959.60 lineto
+783.15 956.60 lineto
+754.70 956.60 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+677.54 898.03 1.000000 4n
+0.70 setlinewidth
+681.22 898.78 moveto
+681.22 919.03 lineto stroke
+721.69 907.03 1.000000 4rest
+758.73 898.03 1.000000 4n
+762.42 898.78 moveto
+762.42 917.53 lineto stroke
+786.49 898.03 1.000000 4n
+790.17 898.78 moveto
+790.17 917.53 lineto stroke
+newpath
+762.07 919.03 moveto
+790.52 919.03 lineto
+790.52 916.03 lineto
+762.07 916.03 lineto
+closepath
+fill
+677.54 892.03 1.000000 4n
+673.86 891.28 moveto
+673.86 871.03 lineto stroke
+721.69 877.03 1.000000 4rest
+758.73 892.03 1.000000 4n
+755.05 891.28 moveto
+755.05 872.53 lineto stroke
+786.49 892.03 1.000000 4n
+782.80 891.28 moveto
+782.80 872.53 lineto stroke
+newpath
+754.70 874.03 moveto
+783.15 874.03 lineto
+783.15 871.03 lineto
+754.70 871.03 lineto
+closepath
+fill
+restore
+%  S_BAR
+77 linenum
+0.70 setlinewidth
+812.22 1010.60 moveto
+812.22 877.03 lineto stroke
+%  S_FEED
+215.71 1309.03 812.57 5 1.000000 1.000000 stf
+/Times-Roman findfont
+11 scalefont
+setfont
+76.21 831.03 moveto
+(5) show
+215.71 1196.34 812.57 5 1.000000 1.000000 stf
+71.21 817.03 680.34 brace
+71.71 817.03 moveto
+71.71 680.34 lineto stroke
+512.40 831.03 moveto
+512.40 842.03 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+515.40 832.03 moveto
+(1.) show
+512.40 842.03 moveto
+663.97 842.03 lineto stroke
+663.97 842.03 moveto
+663.97 831.03 lineto stroke
+667.97 831.03 moveto
+667.97 842.03 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+670.97 832.03 moveto
+(2.) show
+667.97 842.03 moveto
+810.22 842.03 lineto stroke
+%  S_CLEFSIG
+83.51 799.03 1.000000 gclef
+83.76 698.34 1.000000 fclef
+98.12 817.03 1.000000 sharp
+104.76 808.03 1.000000 sharp
+111.40 820.03 1.000000 sharp
+98.12 698.34 1.000000 sharp
+104.76 689.34 1.000000 sharp
+111.40 701.34 1.000000 sharp
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+78 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+170.50 746.26 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+130.63 746.26 moveto
+(proud) show
+/Times-Roman findfont
+12 scalefont
+setfont
+185.51 746.26 moveto
+(ly) show
+/Times-Roman findfont
+12 scalefont
+setfont
+214.49 746.26 moveto
+(we) show
+78 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+165.30 732.94 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+132.94 732.94 moveto
+(ram) show
+/Times-Roman findfont
+12 scalefont
+setfont
+182.01 732.94 moveto
+(parts) show
+/Times-Roman findfont
+12 scalefont
+setfont
+214.49 732.94 moveto
+(we) show
+138.59 808.03 1.000000 4n
+147.85 808.03 1.000000 dot
+142.27 808.78 moveto
+142.27 829.03 lineto stroke
+187.83 805.03 1.000000 4n
+191.51 805.78 moveto
+191.51 826.03 lineto stroke
+194.53 826.03 1.000000 dnflag
+217.98 802.03 1.000000 4n
+221.67 802.78 moveto
+221.67 823.03 lineto stroke
+138.59 793.03 1.000000 4n
+147.85 790.03 1.000000 dot
+134.91 792.28 moveto
+134.91 772.03 lineto stroke
+187.83 793.03 1.000000 4n
+184.15 792.28 moveto
+184.15 772.03 lineto stroke
+187.17 772.03 1.000000 upflag
+217.98 793.03 1.000000 4n
+214.30 792.28 moveto
+214.30 772.03 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+138.59 704.34 1.000000 4n
+147.85 707.34 1.000000 dot
+0.70 setlinewidth
+142.27 705.09 moveto
+142.27 725.34 lineto stroke
+187.83 701.34 1.000000 4n
+191.51 702.09 moveto
+191.51 722.34 lineto stroke
+194.53 722.34 1.000000 dnflag
+217.98 704.34 1.000000 4n
+221.67 705.09 moveto
+221.67 725.34 lineto stroke
+138.59 683.34 1.000000 4n
+147.85 683.34 1.000000 dot
+134.91 682.59 moveto
+134.91 662.34 lineto stroke
+187.83 686.34 1.000000 4n
+184.15 685.59 moveto
+184.15 665.34 lineto stroke
+187.17 665.34 1.000000 upflag
+217.98 689.34 1.000000 4n
+214.30 688.59 moveto
+214.30 668.34 lineto stroke
+restore
+%  S_BAR
+85 linenum
+0.70 setlinewidth
+255.25 817.03 moveto
+255.25 680.34 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+86 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+265.25 746.26 moveto
+(hailed,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+334.23 746.26 moveto
+(At) show
+/Times-Roman findfont
+12 scalefont
+setfont
+363.54 746.26 moveto
+(the) show
+86 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+262.58 732.94 moveto
+(watched,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+331.41 732.94 moveto
+(were) show
+/Times-Roman findfont
+12 scalefont
+setfont
+364.53 732.94 moveto
+(so) show
+273.31 799.03 1.000000 2n
+277.21 799.78 moveto
+277.21 820.03 lineto stroke
+333.54 796.03 1.000000 4n
+350.17 796.03 1.000000 dot
+337.22 796.78 moveto
+337.22 815.89 lineto stroke
+367.20 799.03 1.000000 4n
+370.88 799.78 moveto
+370.88 818.89 lineto stroke
+newpath
+336.87 817.39 moveto
+371.23 820.39 lineto
+371.23 817.39 lineto
+336.87 814.39 lineto
+closepath
+fill
+newpath
+370.53 815.39 moveto
+362.46 814.67 lineto
+362.46 811.67 lineto
+370.53 812.39 lineto
+closepath
+fill
+273.31 793.03 1.000000 2n
+269.41 792.28 moveto
+269.41 772.03 lineto stroke
+340.90 793.03 1.000000 4n
+350.17 790.03 1.000000 dot
+337.22 792.28 moveto
+337.22 773.53 lineto stroke
+367.20 793.03 1.000000 4n
+363.51 792.28 moveto
+363.51 773.53 lineto stroke
+newpath
+336.87 775.03 moveto
+363.86 775.03 lineto
+363.86 772.03 lineto
+336.87 772.03 lineto
+closepath
+fill
+newpath
+363.16 780.03 moveto
+355.10 780.03 lineto
+355.10 777.03 lineto
+363.16 777.03 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+273.31 707.34 1.000000 2n
+0.70 setlinewidth
+277.21 708.09 moveto
+277.21 728.34 lineto stroke
+337.22 707.34 1.000000 4n
+346.49 707.34 1.000000 dot
+340.90 708.09 moveto
+340.90 726.84 lineto stroke
+367.20 707.34 1.000000 4n
+370.88 708.09 moveto
+370.88 726.84 lineto stroke
+newpath
+340.55 728.34 moveto
+371.23 728.34 lineto
+371.23 725.34 lineto
+340.55 725.34 lineto
+closepath
+fill
+newpath
+370.53 723.34 moveto
+362.46 723.34 lineto
+362.46 720.34 lineto
+370.53 720.34 lineto
+closepath
+fill
+273.31 695.34 1.000000 2n
+269.41 694.59 moveto
+269.41 674.34 lineto stroke
+337.22 692.34 1.000000 4n
+346.49 689.34 1.000000 dot
+333.54 691.59 moveto
+333.54 672.84 lineto stroke
+367.20 692.34 1.000000 4n
+363.51 691.59 moveto
+363.51 672.84 lineto stroke
+newpath
+333.19 674.34 moveto
+363.86 674.34 lineto
+363.86 671.34 lineto
+333.19 671.34 lineto
+closepath
+fill
+newpath
+363.16 679.34 moveto
+355.10 679.34 lineto
+355.10 676.34 lineto
+363.16 676.34 lineto
+closepath
+fill
+restore
+%  S_BAR
+93 linenum
+0.70 setlinewidth
+383.09 817.03 moveto
+383.09 680.34 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+94 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+412.73 746.26 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+389.54 746.26 moveto
+(twi) show
+/Times-Roman findfont
+12 scalefont
+setfont
+423.66 746.26 moveto
+(light's) show
+/Times-Roman findfont
+12 scalefont
+setfont
+468.64 746.26 moveto
+(last) show
+94 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+413.57 732.94 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+389.70 732.94 moveto
+(gal) show
+/Times-Roman findfont
+12 scalefont
+setfont
+455.61 732.94 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+425.82 732.94 moveto
+(lant) show
+/Times-Roman findfont
+12 scalefont
+setfont
+470.47 732.94 moveto
+(ly) show
+394.35 802.03 1.000000 4n
+398.03 802.78 moveto
+398.03 823.03 lineto stroke
+431.29 802.03 1.000000 4n
+434.97 802.78 moveto
+434.97 823.03 lineto stroke
+472.80 793.03 1.000000 4n
+476.48 793.78 moveto
+476.48 814.03 lineto stroke
+394.35 793.03 1.000000 4n
+390.67 792.28 moveto
+390.67 772.03 lineto stroke
+431.29 793.03 1.000000 4n
+427.61 792.28 moveto
+427.61 772.03 lineto stroke
+472.80 793.03 1.000000 4n
+469.11 792.28 moveto
+469.11 772.03 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+394.35 704.34 1.000000 4n
+0.70 setlinewidth
+398.03 705.09 moveto
+398.03 725.34 lineto stroke
+431.29 704.34 1.000000 4n
+434.97 705.09 moveto
+434.97 725.34 lineto stroke
+472.80 695.34 1.000000 4n
+476.48 696.09 moveto
+476.48 716.34 lineto stroke
+394.35 689.34 1.000000 4n
+390.67 688.59 moveto
+390.67 668.34 lineto stroke
+431.29 689.34 1.000000 4n
+427.61 688.59 moveto
+427.61 668.34 lineto stroke
+472.80 695.34 1.000000 4n
+469.11 694.59 moveto
+469.11 674.34 lineto stroke
+restore
+%  S_BAR
+100 linenum
+0.70 setlinewidth
+510.40 817.03 moveto
+510.40 680.34 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+102 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+549.46 746.26 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+515.31 746.26 moveto
+(gleam) show
+/Times-Roman findfont
+12 scalefont
+setfont
+557.30 746.26 moveto
+(ing,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+597.13 746.26 moveto
+(whose) show
+/Times-Roman findfont
+12 scalefont
+setfont
+630.75 746.26 moveto
+(broad) show
+523.62 787.03 1.000000 4n
+517.39 787.03 moveto
+529.85 787.03 lineto stroke
+527.30 787.78 moveto
+527.30 808.03 lineto stroke
+561.88 781.03 1.000000 4n
+555.64 781.03 moveto
+568.11 781.03 lineto stroke
+555.64 787.03 moveto
+568.11 787.03 lineto stroke
+565.56 781.78 moveto
+565.56 805.03 lineto stroke
+568.58 805.03 1.000000 dnflag
+584.77 817.03 1.000000 8rest
+604.78 793.03 1.000000 4n
+614.04 796.03 1.000000 dot
+608.46 793.78 moveto
+608.46 811.79 lineto stroke
+637.56 787.03 1.000000 4n
+631.33 787.03 moveto
+643.79 787.03 lineto stroke
+641.24 787.78 moveto
+641.24 805.79 lineto stroke
+newpath
+608.11 813.29 moveto
+641.59 807.29 lineto
+641.59 804.29 lineto
+608.11 810.29 lineto
+closepath
+fill
+newpath
+640.89 802.29 moveto
+632.83 803.77 lineto
+632.83 800.77 lineto
+640.89 799.29 lineto
+closepath
+fill
+523.62 787.03 1.000000 4n
+517.39 787.03 moveto
+529.85 787.03 lineto stroke
+519.94 786.28 moveto
+519.94 766.03 lineto stroke
+561.88 781.03 1.000000 4n
+555.64 781.03 moveto
+568.11 781.03 lineto stroke
+555.64 787.03 moveto
+568.11 787.03 lineto stroke
+558.19 780.28 moveto
+558.19 760.03 lineto stroke
+561.22 760.03 1.000000 upflag
+584.77 763.03 1.000000 8rest
+604.78 793.03 1.000000 4n
+614.04 796.03 1.000000 dot
+601.10 792.28 moveto
+601.10 774.27 lineto stroke
+637.56 787.03 1.000000 4n
+631.33 787.03 moveto
+643.79 787.03 lineto stroke
+633.88 786.28 moveto
+633.88 768.27 lineto stroke
+newpath
+600.75 775.77 moveto
+634.23 769.77 lineto
+634.23 766.77 lineto
+600.75 772.77 lineto
+closepath
+fill
+newpath
+633.53 774.77 moveto
+625.46 776.25 lineto
+625.46 773.25 lineto
+633.53 771.77 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+523.62 689.34 1.000000 4n
+0.70 setlinewidth
+527.30 690.09 moveto
+527.30 710.34 lineto stroke
+561.88 683.34 1.000000 4n
+565.56 684.09 moveto
+565.56 704.34 lineto stroke
+568.58 704.34 1.000000 dnflag
+584.77 710.34 1.000000 8rest
+604.78 695.34 1.000000 4n
+614.04 695.34 1.000000 dot
+608.46 696.09 moveto
+608.46 714.10 lineto stroke
+637.56 689.34 1.000000 4n
+641.24 690.09 moveto
+641.24 708.10 lineto stroke
+newpath
+608.11 715.60 moveto
+641.59 709.60 lineto
+641.59 706.60 lineto
+608.11 712.60 lineto
+closepath
+fill
+newpath
+640.89 704.60 moveto
+632.83 706.07 lineto
+632.83 703.07 lineto
+640.89 701.60 lineto
+closepath
+fill
+523.62 689.34 1.000000 4n
+519.94 688.59 moveto
+519.94 668.34 lineto stroke
+561.88 683.34 1.000000 4n
+558.19 682.59 moveto
+558.19 662.34 lineto stroke
+561.22 662.34 1.000000 upflag
+584.77 668.34 1.000000 8rest
+604.78 695.34 1.000000 4n
+614.04 695.34 1.000000 dot
+601.10 694.59 moveto
+601.10 676.57 lineto stroke
+637.56 689.34 1.000000 4n
+633.88 688.59 moveto
+633.88 670.57 lineto stroke
+newpath
+600.75 678.07 moveto
+634.23 672.07 lineto
+634.23 669.07 lineto
+600.75 675.07 lineto
+closepath
+fill
+newpath
+633.53 677.07 moveto
+625.46 678.55 lineto
+625.46 675.55 lineto
+633.53 674.07 lineto
+closepath
+fill
+restore
+%  S_BAR
+104 linenum
+661.97 808.03 1.000000 dot
+661.97 802.03 1.000000 dot
+661.97 695.34 1.000000 dot
+661.97 689.34 1.000000 dot
+0.70 setlinewidth
+665.97 817.03 moveto
+665.97 680.34 lineto stroke
+3.00 setlinewidth
+669.97 817.03 moveto
+669.97 680.34 lineto stroke
+0.70 setlinewidth
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+106 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+710.73 732.94 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+675.03 732.94 moveto
+(stream) show
+/Times-Roman findfont
+12 scalefont
+setfont
+717.47 732.94 moveto
+(ing?) show
+/Times-Roman findfont
+12 scalefont
+setfont
+761.54 732.94 moveto
+(And) show
+/Times-Roman findfont
+12 scalefont
+setfont
+792.68 732.94 moveto
+(the) show
+684.01 787.03 1.000000 4n
+677.78 787.03 moveto
+690.24 787.03 lineto stroke
+687.69 787.78 moveto
+687.69 808.03 lineto stroke
+722.62 781.03 1.000000 4n
+716.38 781.03 moveto
+728.85 781.03 lineto stroke
+716.38 787.03 moveto
+728.85 787.03 lineto stroke
+726.30 781.78 moveto
+726.30 805.03 lineto stroke
+729.32 805.03 1.000000 dnflag
+745.53 817.03 1.000000 8rest
+766.69 808.03 1.000000 4n
+775.95 808.03 1.000000 dot
+770.37 808.78 moveto
+770.37 827.53 lineto stroke
+796.33 808.03 1.000000 4n
+800.01 808.78 moveto
+800.01 827.53 lineto stroke
+newpath
+770.02 829.03 moveto
+800.36 829.03 lineto
+800.36 826.03 lineto
+770.02 826.03 lineto
+closepath
+fill
+newpath
+799.66 824.03 moveto
+791.60 824.03 lineto
+791.60 821.03 lineto
+799.66 821.03 lineto
+closepath
+fill
+684.01 787.03 1.000000 4n
+677.78 787.03 moveto
+690.24 787.03 lineto stroke
+680.33 786.28 moveto
+680.33 766.03 lineto stroke
+722.62 781.03 1.000000 4n
+716.38 781.03 moveto
+728.85 781.03 lineto stroke
+716.38 787.03 moveto
+728.85 787.03 lineto stroke
+718.93 780.28 moveto
+718.93 760.03 lineto stroke
+721.96 760.03 1.000000 upflag
+745.53 763.03 1.000000 8rest
+766.69 793.03 1.000000 4n
+775.95 790.03 1.000000 dot
+763.01 792.28 moveto
+763.01 773.53 lineto stroke
+796.33 793.03 1.000000 4n
+792.65 792.28 moveto
+792.65 773.53 lineto stroke
+newpath
+762.66 775.03 moveto
+793.00 775.03 lineto
+793.00 772.03 lineto
+762.66 772.03 lineto
+closepath
+fill
+newpath
+792.30 780.03 moveto
+784.24 780.03 lineto
+784.24 777.03 lineto
+792.30 777.03 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+684.01 689.34 1.000000 4n
+0.70 setlinewidth
+687.69 690.09 moveto
+687.69 710.34 lineto stroke
+722.62 683.34 1.000000 4n
+726.30 684.09 moveto
+726.30 704.34 lineto stroke
+729.32 704.34 1.000000 dnflag
+745.53 704.34 1.000000 8rest
+766.69 704.34 1.000000 4n
+775.95 707.34 1.000000 dot
+770.37 705.09 moveto
+770.37 723.84 lineto stroke
+796.33 704.34 1.000000 4n
+800.01 705.09 moveto
+800.01 723.84 lineto stroke
+newpath
+770.02 725.34 moveto
+800.36 725.34 lineto
+800.36 722.34 lineto
+770.02 722.34 lineto
+closepath
+fill
+newpath
+799.66 720.34 moveto
+791.60 720.34 lineto
+791.60 717.34 lineto
+799.66 717.34 lineto
+closepath
+fill
+684.01 689.34 1.000000 4n
+680.33 688.59 moveto
+680.33 668.34 lineto stroke
+722.62 683.34 1.000000 4n
+718.93 682.59 moveto
+718.93 662.34 lineto stroke
+721.96 662.34 1.000000 upflag
+745.53 668.34 1.000000 8rest
+766.69 683.34 1.000000 4n
+775.95 683.34 1.000000 dot
+763.01 682.59 moveto
+763.01 663.84 lineto stroke
+796.33 683.34 1.000000 4n
+792.65 682.59 moveto
+792.65 663.84 lineto stroke
+newpath
+762.66 665.34 moveto
+793.00 665.34 lineto
+793.00 662.34 lineto
+762.66 662.34 lineto
+closepath
+fill
+newpath
+792.30 670.34 moveto
+784.24 670.34 lineto
+784.24 667.34 lineto
+792.30 667.34 lineto
+closepath
+fill
+restore
+%  S_BAR
+111 linenum
+0.70 setlinewidth
+812.22 817.03 moveto
+812.22 680.34 lineto stroke
+%  S_FEED
+215.71 1112.34 812.57 5 1.000000 1.000000 stf
+/Times-Roman findfont
+11 scalefont
+setfont
+76.21 634.34 moveto
+(10) show
+215.71 1025.09 812.57 5 1.000000 1.000000 stf
+71.21 620.34 509.09 brace
+71.71 620.34 moveto
+71.71 509.09 lineto stroke
+%  S_CLEFSIG
+83.51 602.34 1.000000 gclef
+83.76 527.09 1.000000 fclef
+98.12 620.34 1.000000 sharp
+104.76 611.34 1.000000 sharp
+111.40 623.34 1.000000 sharp
+98.12 527.09 1.000000 sharp
+104.76 518.09 1.000000 sharp
+111.40 530.09 1.000000 sharp
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+113 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+159.96 564.62 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+129.45 564.62 moveto
+(rock) show
+/Times-Roman findfont
+12 scalefont
+setfont
+172.23 564.62 moveto
+(ets') show
+/Times-Roman findfont
+12 scalefont
+setfont
+214.63 564.62 moveto
+(red) show
+135.75 611.34 1.000000 4n
+139.43 612.09 moveto
+139.43 632.34 lineto stroke
+176.55 614.34 1.000000 4n
+180.23 615.09 moveto
+180.23 635.34 lineto stroke
+218.45 617.34 1.000000 4n
+222.13 618.09 moveto
+222.13 638.34 lineto stroke
+135.75 596.34 1.000000 4n
+132.07 595.59 moveto
+132.07 575.34 lineto stroke
+176.55 596.34 1.000000 4n
+172.86 595.59 moveto
+172.86 575.34 lineto stroke
+218.45 596.34 1.000000 4n
+214.77 595.59 moveto
+214.77 575.34 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+135.75 533.09 1.000000 4n
+0.70 setlinewidth
+139.43 533.84 moveto
+139.43 554.09 lineto stroke
+176.55 536.09 1.000000 4n
+180.23 536.84 moveto
+180.23 557.09 lineto stroke
+218.45 539.09 1.000000 4n
+212.22 539.09 moveto
+224.68 539.09 lineto stroke
+222.13 539.84 moveto
+222.13 560.09 lineto stroke
+135.75 512.09 1.000000 4n
+132.07 511.34 moveto
+132.07 491.09 lineto stroke
+176.55 512.09 1.000000 4n
+172.86 511.34 moveto
+172.86 491.09 lineto stroke
+218.45 512.09 1.000000 4n
+214.77 511.34 moveto
+214.77 491.09 lineto stroke
+restore
+%  S_BAR
+122 linenum
+0.70 setlinewidth
+257.45 620.34 moveto
+257.45 509.09 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+127 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+264.47 564.62 moveto
+(glare,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+344.84 564.62 moveto
+(the) show
+/Times-Roman findfont
+12 scalefont
+setfont
+363.46 564.62 moveto
+(bombs) show
+271.21 617.34 1.000000 4n
+274.89 618.09 moveto
+274.89 638.34 lineto stroke
+313.19 620.34 1.000000 4rest
+348.49 614.34 1.000000 4n
+352.18 615.09 moveto
+352.18 633.31 lineto stroke
+371.45 611.34 1.000000 4n
+375.13 612.09 moveto
+375.13 630.31 lineto stroke
+newpath
+351.83 634.81 moveto
+375.48 631.81 lineto
+375.48 628.81 lineto
+351.83 631.81 lineto
+closepath
+fill
+271.21 596.34 1.000000 4n
+267.52 595.59 moveto
+267.52 575.34 lineto stroke
+313.19 596.34 1.000000 4rest
+348.49 596.34 1.000000 4n
+344.81 595.59 moveto
+344.81 576.84 lineto stroke
+371.45 596.34 1.000000 4n
+367.77 595.59 moveto
+367.77 576.84 lineto stroke
+newpath
+344.46 578.34 moveto
+368.12 578.34 lineto
+368.12 575.34 lineto
+344.46 575.34 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+271.21 539.09 1.000000 4n
+0.70 setlinewidth
+264.97 539.09 moveto
+277.44 539.09 lineto stroke
+274.89 539.84 moveto
+274.89 560.09 lineto stroke
+313.19 533.09 1.000000 4rest
+348.49 536.09 1.000000 4n
+352.18 536.84 moveto
+352.18 555.06 lineto stroke
+371.45 533.09 1.000000 4n
+375.13 533.84 moveto
+375.13 552.06 lineto stroke
+newpath
+351.83 556.56 moveto
+375.48 553.56 lineto
+375.48 550.56 lineto
+351.83 553.56 lineto
+closepath
+fill
+271.21 512.09 1.000000 4n
+267.52 511.34 moveto
+267.52 491.09 lineto stroke
+313.19 509.09 1.000000 4rest
+348.49 512.09 1.000000 4n
+344.81 511.34 moveto
+344.81 492.59 lineto stroke
+371.45 512.09 1.000000 4n
+367.77 511.34 moveto
+367.77 492.59 lineto stroke
+newpath
+344.46 494.09 moveto
+368.12 494.09 lineto
+368.12 491.09 lineto
+344.46 491.09 lineto
+closepath
+fill
+restore
+%  S_BAR
+130 linenum
+0.70 setlinewidth
+398.93 620.34 moveto
+398.93 509.09 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+131 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+437.54 564.62 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+404.82 564.62 moveto
+(burst) show
+/Times-Roman findfont
+12 scalefont
+setfont
+449.35 564.62 moveto
+(ing) show
+/Times-Roman findfont
+12 scalefont
+setfont
+493.24 564.62 moveto
+(in) show
+411.79 608.34 1.000000 4n
+415.47 609.09 moveto
+415.47 629.34 lineto stroke
+453.17 611.34 1.000000 4n
+456.85 612.09 moveto
+456.85 632.34 lineto stroke
+495.57 614.34 1.000000 4n
+499.25 615.09 moveto
+499.25 635.34 lineto stroke
+411.79 596.34 1.000000 4n
+408.11 595.59 moveto
+408.11 575.34 lineto stroke
+453.17 596.34 1.000000 4n
+449.49 595.59 moveto
+449.49 575.34 lineto stroke
+495.57 596.34 1.000000 4n
+491.88 595.59 moveto
+491.88 575.34 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+411.79 530.09 1.000000 4n
+0.70 setlinewidth
+415.47 530.84 moveto
+415.47 551.09 lineto stroke
+453.17 530.09 1.000000 4n
+456.85 530.84 moveto
+456.85 551.09 lineto stroke
+495.57 530.09 1.000000 4n
+499.25 530.84 moveto
+499.25 551.09 lineto stroke
+411.79 524.09 1.000000 4n
+408.11 523.34 moveto
+408.11 503.09 lineto stroke
+453.17 524.09 1.000000 4n
+449.49 523.34 moveto
+449.49 503.09 lineto stroke
+495.57 524.09 1.000000 4n
+491.88 523.34 moveto
+491.88 503.09 lineto stroke
+restore
+%  S_BAR
+134 linenum
+0.70 setlinewidth
+533.82 620.34 moveto
+533.82 509.09 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+135 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+543.38 564.62 moveto
+(air,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+621.21 564.62 moveto
+(gave) show
+547.29 614.34 1.000000 4n
+550.97 615.09 moveto
+550.97 635.34 lineto stroke
+587.76 620.34 1.000000 4rest
+626.86 614.34 1.000000 4n
+630.54 615.09 moveto
+630.54 635.34 lineto stroke
+547.29 596.34 1.000000 4n
+543.61 595.59 moveto
+543.61 575.34 lineto stroke
+587.76 596.34 1.000000 4rest
+626.86 596.34 1.000000 4n
+623.18 595.59 moveto
+623.18 575.34 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+547.29 530.09 1.000000 4n
+0.70 setlinewidth
+550.97 530.84 moveto
+550.97 551.09 lineto stroke
+587.76 539.09 1.000000 4rest
+626.86 530.09 1.000000 4n
+630.54 530.84 moveto
+630.54 551.09 lineto stroke
+547.29 524.09 1.000000 4n
+543.61 523.34 moveto
+543.61 503.09 lineto stroke
+587.76 509.09 1.000000 4rest
+626.86 524.09 1.000000 4n
+623.18 523.34 moveto
+623.18 503.09 lineto stroke
+restore
+%  S_BAR
+138 linenum
+0.70 setlinewidth
+666.78 620.34 moveto
+666.78 509.09 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+139 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+674.29 564.62 moveto
+(proof) show
+/Times-Roman findfont
+12 scalefont
+setfont
+723.20 564.62 moveto
+(through) show
+/Times-Roman findfont
+12 scalefont
+setfont
+769.65 564.62 moveto
+(the) show
+680.75 611.34 1.000000 4n
+690.01 611.34 1.000000 dot
+684.43 612.09 moveto
+684.43 632.34 lineto stroke
+732.49 608.34 1.000000 4n
+736.17 609.09 moveto
+736.17 629.34 lineto stroke
+739.20 629.34 1.000000 dnflag
+773.30 605.34 1.000000 4n
+776.99 606.09 moveto
+776.99 626.34 lineto stroke
+680.75 596.34 1.000000 4n
+690.01 593.34 1.000000 dot
+677.07 595.59 moveto
+677.07 575.34 lineto stroke
+732.49 596.34 1.000000 4n
+728.81 595.59 moveto
+728.81 575.34 lineto stroke
+731.83 575.34 1.000000 upflag
+773.30 596.34 1.000000 4n
+769.62 595.59 moveto
+769.62 575.34 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+680.75 533.09 1.000000 4n
+690.01 536.09 1.000000 dot
+0.70 setlinewidth
+684.43 533.84 moveto
+684.43 554.09 lineto stroke
+732.49 530.09 1.000000 4n
+736.17 530.84 moveto
+736.17 551.09 lineto stroke
+739.20 551.09 1.000000 dnflag
+773.30 533.09 1.000000 4n
+776.99 533.84 moveto
+776.99 554.09 lineto stroke
+680.75 512.09 1.000000 4n
+690.01 512.09 1.000000 dot
+677.07 511.34 moveto
+677.07 491.09 lineto stroke
+732.49 515.09 1.000000 4n
+728.81 514.34 moveto
+728.81 494.09 lineto stroke
+731.83 494.09 1.000000 upflag
+773.30 518.09 1.000000 4n
+769.62 517.34 moveto
+769.62 497.09 lineto stroke
+restore
+%  S_BAR
+142 linenum
+0.70 setlinewidth
+812.22 620.34 moveto
+812.22 509.09 lineto stroke
+%  S_FEED
+215.71 941.09 812.57 5 1.000000 1.000000 stf
+/Times-Roman findfont
+11 scalefont
+setfont
+76.21 463.09 moveto
+(15) show
+215.71 844.77 812.57 5 1.000000 1.000000 stf
+71.21 449.09 328.77 brace
+71.71 449.09 moveto
+71.71 328.77 lineto stroke
+%  S_CLEFSIG
+83.51 431.09 1.000000 gclef
+83.76 346.77 1.000000 fclef
+98.12 449.09 1.000000 sharp
+104.76 440.09 1.000000 sharp
+111.40 452.09 1.000000 sharp
+98.12 346.77 1.000000 sharp
+104.76 337.77 1.000000 sharp
+111.40 349.77 1.000000 sharp
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+143 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+134.40 381.37 moveto
+(night) show
+/Times-Roman findfont
+12 scalefont
+setfont
+202.88 381.37 moveto
+(that) show
+/Times-Roman findfont
+12 scalefont
+setfont
+234.86 381.37 moveto
+(our) show
+140.54 431.09 1.000000 2n
+144.44 431.84 moveto
+144.44 452.09 lineto stroke
+207.36 428.09 1.000000 4n
+216.62 428.09 1.000000 dot
+211.04 428.84 moveto
+211.04 447.97 lineto stroke
+238.84 431.09 1.000000 4n
+242.52 431.84 moveto
+242.52 450.97 lineto stroke
+newpath
+210.69 449.47 moveto
+242.87 452.47 lineto
+242.87 449.47 lineto
+210.69 446.47 lineto
+closepath
+fill
+newpath
+242.17 447.47 moveto
+234.11 446.70 lineto
+234.11 443.70 lineto
+242.17 444.47 lineto
+closepath
+fill
+140.54 425.09 1.000000 2n
+136.64 424.34 moveto
+136.64 404.09 lineto stroke
+207.36 422.09 1.000000 4n
+216.62 422.09 1.000000 dot
+203.68 421.34 moveto
+203.68 402.59 lineto stroke
+238.84 422.09 1.000000 4n
+235.16 421.34 moveto
+235.16 402.59 lineto stroke
+newpath
+203.33 404.09 moveto
+235.51 404.09 lineto
+235.51 401.09 lineto
+203.33 401.09 lineto
+closepath
+fill
+newpath
+234.81 409.09 moveto
+226.74 409.09 lineto
+226.74 406.09 lineto
+234.81 406.09 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+140.54 355.77 1.000000 2n
+0.70 setlinewidth
+144.44 356.52 moveto
+144.44 376.77 lineto stroke
+207.36 355.77 1.000000 4n
+216.62 355.77 1.000000 dot
+211.04 356.52 moveto
+211.04 375.27 lineto stroke
+238.84 355.77 1.000000 4n
+242.52 356.52 moveto
+242.52 375.27 lineto stroke
+newpath
+210.69 376.77 moveto
+242.87 376.77 lineto
+242.87 373.77 lineto
+210.69 373.77 lineto
+closepath
+fill
+newpath
+242.17 371.77 moveto
+234.11 371.77 lineto
+234.11 368.77 lineto
+242.17 368.77 lineto
+closepath
+fill
+140.54 343.77 1.000000 2n
+136.64 343.02 moveto
+136.64 322.77 lineto stroke
+207.36 343.77 1.000000 4n
+216.62 343.77 1.000000 dot
+203.68 343.02 moveto
+203.68 324.27 lineto stroke
+238.84 343.77 1.000000 4n
+235.16 343.02 moveto
+235.16 324.27 lineto stroke
+newpath
+203.33 325.77 moveto
+235.51 325.77 lineto
+235.51 322.77 lineto
+203.33 322.77 lineto
+closepath
+fill
+newpath
+234.81 330.77 moveto
+226.74 330.77 lineto
+226.74 327.77 lineto
+234.81 327.77 lineto
+closepath
+fill
+restore
+%  S_BAR
+146 linenum
+0.70 setlinewidth
+255.78 449.09 moveto
+255.78 328.77 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+147 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+262.95 381.37 moveto
+(flag) show
+/Times-Roman findfont
+12 scalefont
+setfont
+303.16 381.37 moveto
+(was) show
+/Times-Roman findfont
+12 scalefont
+setfont
+347.89 381.37 moveto
+(still) show
+267.60 434.09 1.000000 4n
+271.28 434.84 moveto
+271.28 455.09 lineto stroke
+307.83 419.09 1.000000 4n
+301.59 419.09 moveto
+314.06 419.09 lineto stroke
+311.51 419.84 moveto
+311.51 440.09 lineto stroke
+352.38 422.09 1.000000 4n
+343.02 422.09 1.000000 sharp
+356.06 422.84 moveto
+356.06 443.09 lineto stroke
+267.60 419.09 1.000000 4n
+261.37 419.09 moveto
+273.83 419.09 lineto stroke
+263.92 418.34 moveto
+263.92 398.09 lineto stroke
+307.83 419.09 1.000000 4n
+301.59 419.09 moveto
+314.06 419.09 lineto stroke
+304.14 418.34 moveto
+304.14 398.09 lineto stroke
+352.38 416.09 1.000000 4n
+346.14 419.09 moveto
+358.61 419.09 lineto stroke
+348.69 415.34 moveto
+348.69 395.09 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+267.60 352.77 1.000000 4n
+0.70 setlinewidth
+271.28 353.52 moveto
+271.28 373.77 lineto stroke
+307.83 352.77 1.000000 4n
+311.51 353.52 moveto
+311.51 373.77 lineto stroke
+352.38 352.77 1.000000 4n
+356.06 353.52 moveto
+356.06 373.77 lineto stroke
+267.60 346.77 1.000000 4n
+263.92 346.02 moveto
+263.92 325.77 lineto stroke
+307.83 346.77 1.000000 4n
+304.14 346.02 moveto
+304.14 325.77 lineto stroke
+352.38 334.77 1.000000 4n
+348.69 334.02 moveto
+348.69 313.77 lineto stroke
+restore
+%  S_BAR
+150 linenum
+0.70 setlinewidth
+392.85 449.09 moveto
+392.85 328.77 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+151 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+400.10 381.37 moveto
+(there.) show
+/Times-Roman findfont
+12 scalefont
+setfont
+487.90 381.37 moveto
+(Oh) show
+406.84 425.09 1.000000 4n
+410.52 425.84 moveto
+410.52 446.09 lineto stroke
+450.19 449.09 1.000000 4rest
+491.56 425.09 1.000000 4n
+495.24 425.84 moveto
+495.24 446.09 lineto stroke
+406.84 416.09 1.000000 4n
+400.60 419.09 moveto
+413.07 419.09 lineto stroke
+403.15 415.34 moveto
+403.15 395.09 lineto stroke
+450.19 407.09 1.000000 4rest
+491.56 416.09 1.000000 4n
+485.32 419.09 moveto
+497.79 419.09 lineto stroke
+487.87 415.34 moveto
+487.87 395.09 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+406.84 349.77 1.000000 4n
+0.70 setlinewidth
+410.52 350.52 moveto
+410.52 370.77 lineto stroke
+450.19 358.77 1.000000 4rest
+491.56 349.77 1.000000 4n
+495.24 350.52 moveto
+495.24 370.77 lineto stroke
+406.84 343.77 1.000000 4n
+403.15 343.02 moveto
+403.15 322.77 lineto stroke
+450.19 328.77 1.000000 4rest
+491.56 343.77 1.000000 4n
+487.87 343.02 moveto
+487.87 322.77 lineto stroke
+restore
+%  S_BAR
+154 linenum
+0.70 setlinewidth
+531.61 449.09 moveto
+531.61 328.77 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+155 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+538.55 381.37 moveto
+(say,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+579.19 381.37 moveto
+(does) show
+/Times-Roman findfont
+12 scalefont
+setfont
+619.89 381.37 moveto
+(that) show
+543.30 434.09 1.000000 4n
+546.98 434.84 moveto
+546.98 455.09 lineto stroke
+584.68 434.09 1.000000 4n
+588.37 434.84 moveto
+588.37 455.09 lineto stroke
+624.37 434.09 1.000000 4n
+628.06 434.84 moveto
+628.06 453.13 lineto stroke
+650.59 431.09 1.000000 4n
+654.27 431.84 moveto
+654.27 450.13 lineto stroke
+newpath
+627.71 454.63 moveto
+654.62 451.63 lineto
+654.62 448.63 lineto
+627.71 451.63 lineto
+closepath
+fill
+543.30 419.09 1.000000 4n
+537.07 419.09 moveto
+549.53 419.09 lineto stroke
+539.62 418.34 moveto
+539.62 398.09 lineto stroke
+584.68 416.09 1.000000 4n
+578.45 419.09 moveto
+590.92 419.09 lineto stroke
+581.00 415.34 moveto
+581.00 395.09 lineto stroke
+624.37 413.09 1.000000 4n
+618.14 413.09 moveto
+630.61 413.09 lineto stroke
+618.14 419.09 moveto
+630.61 419.09 lineto stroke
+620.69 412.34 moveto
+620.69 392.09 lineto stroke
+630.41 439.19 moveto
+630.38 439.42 lineto
+633.76 441.00 637.30 441.52 640.99 440.97 curveto
+644.68 440.42 647.91 438.90 650.68 436.40 curveto
+650.50 435.97 lineto
+647.55 437.96 644.32 439.22 640.80 439.74 curveto
+637.29 440.27 633.83 440.00 630.43 438.96 curveto
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+543.30 343.77 1.000000 4n
+0.70 setlinewidth
+546.98 344.52 moveto
+546.98 364.77 lineto stroke
+584.68 343.77 1.000000 4n
+588.37 344.52 moveto
+588.37 364.77 lineto stroke
+624.37 343.77 1.000000 4n
+628.06 344.52 moveto
+628.06 364.77 lineto stroke
+543.30 331.77 1.000000 4n
+539.62 331.02 moveto
+539.62 310.77 lineto stroke
+584.68 334.77 1.000000 4n
+581.00 334.02 moveto
+581.00 313.77 lineto stroke
+624.37 337.77 1.000000 4n
+620.69 337.02 moveto
+620.69 316.77 lineto stroke
+restore
+%  S_BAR
+161 linenum
+0.70 setlinewidth
+674.88 449.09 moveto
+674.88 328.77 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+162 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+708.09 381.37 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+681.59 381.37 moveto
+(star) show
+/Times-Roman findfont
+12 scalefont
+setfont
+752.77 381.37 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+720.31 381.37 moveto
+(span) show
+/Times-Roman findfont
+12 scalefont
+setfont
+766.27 381.37 moveto
+(gled) show
+686.90 428.09 1.000000 4n
+690.58 428.84 moveto
+690.58 449.09 lineto stroke
+726.79 428.09 1.000000 4n
+730.48 428.84 moveto
+730.48 449.09 lineto stroke
+767.73 428.09 1.000000 4n
+771.42 428.84 moveto
+771.42 449.09 lineto stroke
+686.90 422.09 1.000000 4n
+683.22 421.34 moveto
+683.22 401.09 lineto stroke
+726.79 422.09 1.000000 4n
+723.11 421.34 moveto
+723.11 401.09 lineto stroke
+775.10 425.09 1.000000 4n
+771.42 424.34 moveto
+771.42 404.09 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+686.90 352.77 1.000000 4n
+0.70 setlinewidth
+690.58 353.52 moveto
+690.58 373.77 lineto stroke
+726.79 352.77 1.000000 4n
+730.48 353.52 moveto
+730.48 373.77 lineto stroke
+771.42 352.77 1.000000 4n
+762.06 352.77 1.000000 sharp
+775.10 353.52 moveto
+775.10 373.77 lineto stroke
+686.90 340.77 1.000000 4n
+683.22 340.02 moveto
+683.22 319.77 lineto stroke
+726.79 340.77 1.000000 4n
+723.11 340.02 moveto
+723.11 319.77 lineto stroke
+771.42 337.77 1.000000 4n
+767.73 337.02 moveto
+767.73 316.77 lineto stroke
+restore
+%  S_BAR
+168 linenum
+0.70 setlinewidth
+812.22 449.09 moveto
+812.22 328.77 lineto stroke
+%  S_FEED
+215.71 760.77 812.57 5 1.000000 1.000000 stf
+/Times-Roman findfont
+11 scalefont
+setfont
+76.21 282.77 moveto
+(20) show
+215.71 658.50 812.57 5 1.000000 1.000000 stf
+71.21 268.77 142.50 brace
+71.71 268.77 moveto
+71.71 142.50 lineto stroke
+%  S_CLEFSIG
+83.51 250.77 1.000000 gclef
+83.76 160.50 1.000000 fclef
+98.12 268.77 1.000000 sharp
+104.76 259.77 1.000000 sharp
+111.40 271.77 1.000000 sharp
+98.12 160.50 1.000000 sharp
+104.76 151.50 1.000000 sharp
+111.40 163.50 1.000000 sharp
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+169 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+151.54 207.05 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+128.56 207.05 moveto
+(ban) show
+/Times-Roman findfont
+12 scalefont
+setfont
+160.23 207.05 moveto
+(ner) show
+/Times-Roman findfont
+12 scalefont
+setfont
+206.13 207.05 moveto
+(yet) show
+133.87 256.77 1.000000 4n
+137.56 257.52 moveto
+137.56 277.77 lineto stroke
+164.05 262.77 1.000000 4n
+167.73 263.52 moveto
+167.73 281.85 lineto stroke
+192.78 259.77 1.000000 4n
+196.46 260.52 moveto
+196.46 278.85 lineto stroke
+209.78 256.77 1.000000 4n
+213.46 257.52 moveto
+213.46 275.95 lineto stroke
+247.99 253.77 1.000000 4n
+251.67 254.52 moveto
+251.67 272.95 lineto stroke
+newpath
+167.38 283.35 moveto
+196.81 280.35 lineto
+196.81 277.35 lineto
+167.38 280.35 lineto
+closepath
+fill
+newpath
+213.11 277.45 moveto
+252.02 274.45 lineto
+252.02 271.45 lineto
+213.11 274.45 lineto
+closepath
+fill
+133.87 241.77 1.000000 4n
+130.19 241.02 moveto
+130.19 220.77 lineto stroke
+164.05 247.77 1.000000 4n
+160.37 247.02 moveto
+160.37 226.77 lineto stroke
+209.78 247.77 1.000000 4n
+206.10 247.02 moveto
+206.10 226.77 lineto stroke
+215.81 261.87 moveto
+215.80 262.07 lineto
+221.16 263.65 226.63 264.19 232.21 263.67 curveto
+237.78 263.15 243.06 261.61 248.04 259.06 curveto
+247.94 258.68 lineto
+242.84 260.68 237.55 261.94 232.09 262.45 curveto
+226.63 262.96 221.21 262.70 215.83 261.67 curveto
+fill
+170.08 267.87 moveto
+170.06 268.09 lineto
+173.85 269.68 177.79 270.20 181.86 269.66 curveto
+185.94 269.12 189.61 267.59 192.86 265.08 curveto
+192.70 264.66 lineto
+189.29 266.65 185.62 267.91 181.70 268.43 curveto
+177.78 268.95 173.92 268.69 170.10 267.64 curveto
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+133.87 169.50 1.000000 4n
+0.70 setlinewidth
+137.56 170.25 moveto
+137.56 190.50 lineto stroke
+164.05 169.50 1.000000 4n
+167.73 170.25 moveto
+167.73 188.57 lineto stroke
+192.78 166.50 1.000000 4n
+183.43 166.50 1.000000 sharp
+196.46 167.25 moveto
+196.46 185.57 lineto stroke
+209.78 169.50 1.000000 4n
+213.46 170.25 moveto
+213.46 189.00 lineto stroke
+247.99 169.50 1.000000 4n
+238.64 169.50 1.000000 sharp
+251.67 170.25 moveto
+251.67 189.00 lineto stroke
+newpath
+167.38 190.07 moveto
+196.81 187.07 lineto
+196.81 184.07 lineto
+167.38 187.07 lineto
+closepath
+fill
+newpath
+213.11 190.50 moveto
+252.02 190.50 lineto
+252.02 187.50 lineto
+213.11 187.50 lineto
+closepath
+fill
+133.87 148.50 1.000000 4n
+130.19 147.75 moveto
+130.19 127.50 lineto stroke
+164.05 148.50 1.000000 4n
+160.37 147.75 moveto
+160.37 128.57 lineto stroke
+192.78 151.50 1.000000 4n
+189.10 150.75 moveto
+189.10 131.57 lineto stroke
+209.78 154.50 1.000000 4n
+206.10 153.75 moveto
+206.10 135.00 lineto stroke
+247.99 154.50 1.000000 4n
+230.00 154.50 1.000000 sharp
+244.31 153.75 moveto
+244.31 135.00 lineto stroke
+newpath
+160.02 130.07 moveto
+189.45 133.07 lineto
+189.45 130.07 lineto
+160.02 127.07 lineto
+closepath
+fill
+newpath
+205.75 136.50 moveto
+244.66 136.50 lineto
+244.66 133.50 lineto
+205.75 133.50 lineto
+closepath
+fill
+209.78 149.40 moveto
+209.87 149.63 lineto
+211.90 148.09 214.18 147.32 216.73 147.32 curveto
+219.27 147.32 221.56 148.09 223.59 149.63 curveto
+223.77 149.16 lineto
+221.87 147.10 219.53 146.07 216.73 146.07 curveto
+213.93 146.07 211.58 147.10 209.69 149.16 curveto
+fill
+164.05 143.40 moveto
+164.07 143.62 lineto
+167.72 142.58 171.42 142.32 175.18 142.84 curveto
+178.94 143.36 182.43 144.61 185.66 146.61 curveto
+185.83 146.18 lineto
+182.77 143.67 179.27 142.15 175.35 141.61 curveto
+171.43 141.07 167.65 141.59 164.02 143.17 curveto
+fill
+215.81 174.60 moveto
+215.78 174.79 lineto
+220.95 176.87 226.33 177.91 231.90 177.91 curveto
+237.48 177.91 242.85 176.87 248.02 174.79 curveto
+247.96 174.40 lineto
+242.71 175.92 237.36 176.68 231.90 176.68 curveto
+226.44 176.68 221.09 175.92 215.84 174.40 curveto
+fill
+170.08 174.60 moveto
+170.06 174.82 lineto
+173.85 176.40 177.79 176.93 181.86 176.39 curveto
+185.94 175.85 189.61 174.32 192.86 171.81 curveto
+192.70 171.38 lineto
+189.29 173.38 185.62 174.64 181.70 175.16 curveto
+177.78 175.68 173.92 175.41 170.10 174.37 curveto
+fill
+restore
+%  S_BAR
+175 linenum
+0.70 setlinewidth
+267.65 268.77 moveto
+267.65 142.50 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+177 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+273.37 207.05 moveto
+(wave) show
+/Times-Roman findfont
+12 scalefont
+setfont
+342.95 207.05 moveto
+(o'er) show
+/Times-Roman findfont
+12 scalefont
+setfont
+367.81 207.05 moveto
+(the) show
+281.18 253.77 1.000000 4n
+284.86 254.52 moveto
+284.86 274.77 lineto stroke
+311.60 250.77 1.000000 4n
+315.28 251.52 moveto
+315.28 271.77 lineto stroke
+318.31 271.77 1.000000 dnflag
+330.83 268.77 1.000000 8rest
+347.75 244.77 1.000000 4n
+351.44 245.52 moveto
+351.44 264.27 lineto stroke
+371.47 244.77 1.000000 4n
+375.15 245.52 moveto
+375.15 264.27 lineto stroke
+newpath
+351.09 265.77 moveto
+375.50 265.77 lineto
+375.50 262.77 lineto
+351.09 262.77 lineto
+closepath
+fill
+281.18 244.77 1.000000 4n
+290.45 241.77 1.000000 dot
+277.50 244.02 moveto
+277.50 223.77 lineto stroke
+330.83 226.77 1.000000 8rest
+347.75 244.77 1.000000 4n
+344.07 244.02 moveto
+344.07 225.27 lineto stroke
+371.47 244.77 1.000000 4n
+367.78 244.02 moveto
+367.78 225.27 lineto stroke
+newpath
+343.72 226.77 moveto
+368.13 226.77 lineto
+368.13 223.77 lineto
+343.72 223.77 lineto
+closepath
+fill
+287.21 258.87 moveto
+287.19 259.09 lineto
+291.27 260.67 295.47 261.19 299.81 260.66 curveto
+304.15 260.13 308.10 258.60 311.67 256.08 curveto
+311.53 255.66 lineto
+307.81 257.66 303.85 258.92 299.66 259.43 curveto
+295.47 259.95 291.33 259.69 287.23 258.65 curveto
+fill
+/Times-Roman findfont
+12 scalefont
+setfont
+302.57 273.78 moveto
+311.60 273.78 1.000000 ferm
+320.64 273.78 moveto
+restore
+%  S_STAFF
+% staff 2
+save
+281.18 172.50 1.000000 4n
+0.70 setlinewidth
+274.95 172.50 moveto
+287.41 172.50 lineto stroke
+284.86 173.25 moveto
+284.86 193.50 lineto stroke
+311.60 169.50 1.000000 4n
+315.28 170.25 moveto
+315.28 190.50 lineto stroke
+318.31 190.50 1.000000 dnflag
+330.83 172.50 1.000000 8rest
+347.75 163.50 1.000000 4n
+351.44 164.25 moveto
+351.44 183.00 lineto stroke
+371.47 163.50 1.000000 4n
+375.15 164.25 moveto
+375.15 183.00 lineto stroke
+newpath
+351.09 184.50 moveto
+375.50 184.50 lineto
+375.50 181.50 lineto
+351.09 181.50 lineto
+closepath
+fill
+281.18 157.50 1.000000 4n
+290.45 157.50 1.000000 dot
+277.50 156.75 moveto
+277.50 136.50 lineto stroke
+330.83 142.50 1.000000 8rest
+347.75 154.50 1.000000 4n
+344.07 153.75 moveto
+344.07 135.00 lineto stroke
+371.47 154.50 1.000000 4n
+367.78 153.75 moveto
+367.78 135.00 lineto stroke
+newpath
+343.72 136.50 moveto
+368.13 136.50 lineto
+368.13 133.50 lineto
+343.72 133.50 lineto
+closepath
+fill
+287.21 177.60 moveto
+287.19 177.82 lineto
+291.27 179.40 295.47 179.92 299.81 179.39 curveto
+304.15 178.86 308.10 177.33 311.67 174.80 curveto
+311.53 174.39 lineto
+307.81 176.39 303.85 177.65 299.66 178.16 curveto
+295.47 178.68 291.33 178.42 287.23 177.38 curveto
+fill
+/Times-Roman findfont
+12 scalefont
+setfont
+302.57 192.50 moveto
+311.60 192.50 1.000000 ferm
+320.64 192.50 moveto
+restore
+%  S_BAR
+183 linenum
+0.70 setlinewidth
+392.12 268.77 moveto
+392.12 142.50 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+184 linenum
+425.08 207.05 moveto
+451.12 207.05 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+398.51 207.05 moveto
+(land) show
+/Times-Roman findfont
+12 scalefont
+setfont
+462.92 207.05 moveto
+(of) show
+/Times-Roman findfont
+12 scalefont
+setfont
+480.90 207.05 moveto
+(the) show
+405.15 253.77 1.000000 4n
+414.41 253.77 1.000000 dot
+408.83 254.52 moveto
+408.83 274.77 lineto stroke
+447.09 256.77 1.000000 4n
+450.77 257.52 moveto
+450.77 277.77 lineto stroke
+453.79 277.77 1.000000 dnflag
+465.41 259.77 1.000000 4n
+469.09 260.52 moveto
+469.09 279.90 lineto stroke
+484.55 262.77 1.000000 4n
+488.24 263.52 moveto
+488.24 282.90 lineto stroke
+newpath
+468.74 281.40 moveto
+488.59 284.40 lineto
+488.59 281.40 lineto
+468.74 278.40 lineto
+closepath
+fill
+405.15 244.77 1.000000 4n
+414.41 241.77 1.000000 dot
+401.47 244.02 moveto
+401.47 223.77 lineto stroke
+447.09 244.77 1.000000 4n
+443.40 244.02 moveto
+443.40 223.77 lineto stroke
+446.43 223.77 1.000000 upflag
+465.41 244.77 1.000000 4n
+461.73 244.02 moveto
+461.73 225.27 lineto stroke
+484.55 244.77 1.000000 4n
+480.87 244.02 moveto
+480.87 225.27 lineto stroke
+newpath
+461.38 226.77 moveto
+481.22 226.77 lineto
+481.22 223.77 lineto
+461.38 223.77 lineto
+closepath
+fill
+405.15 239.67 moveto
+405.18 239.86 lineto
+410.89 238.34 416.69 237.58 422.60 237.58 curveto
+428.51 237.58 434.32 238.34 440.03 239.86 curveto
+440.08 239.48 lineto
+434.44 237.40 428.61 236.36 422.60 236.36 curveto
+416.59 236.36 410.76 237.40 405.12 239.48 curveto
+fill
+419.41 258.87 moveto
+419.35 259.07 lineto
+423.52 261.61 428.04 263.14 432.89 263.66 curveto
+437.75 264.19 442.48 263.66 447.10 262.08 curveto
+447.07 261.66 lineto
+442.43 262.69 437.75 262.95 433.03 262.44 curveto
+428.30 261.93 423.78 260.67 419.48 258.67 curveto
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+405.15 166.50 1.000000 4n
+414.41 169.50 1.000000 dot
+0.70 setlinewidth
+408.83 167.25 moveto
+408.83 187.50 lineto stroke
+447.09 163.50 1.000000 4n
+450.77 164.25 moveto
+450.77 184.50 lineto stroke
+453.79 184.50 1.000000 dnflag
+465.41 166.50 1.000000 4n
+469.09 167.25 moveto
+469.09 186.00 lineto stroke
+484.55 166.50 1.000000 4n
+488.24 167.25 moveto
+488.24 186.00 lineto stroke
+newpath
+468.74 187.50 moveto
+488.59 187.50 lineto
+488.59 184.50 lineto
+468.74 184.50 lineto
+closepath
+fill
+405.15 151.50 1.000000 4n
+414.41 151.50 1.000000 dot
+401.47 150.75 moveto
+401.47 130.50 lineto stroke
+447.09 157.50 1.000000 4n
+443.40 156.75 moveto
+443.40 136.50 lineto stroke
+446.43 136.50 1.000000 upflag
+465.41 145.50 1.000000 4n
+461.73 144.75 moveto
+461.73 125.36 lineto stroke
+484.55 148.50 1.000000 4n
+480.87 147.75 moveto
+480.87 128.36 lineto stroke
+newpath
+461.38 126.86 moveto
+481.22 129.86 lineto
+481.22 126.86 lineto
+461.38 123.86 lineto
+closepath
+fill
+405.15 146.40 moveto
+405.15 146.58 lineto
+411.11 146.07 417.05 146.32 422.96 147.34 curveto
+428.86 148.35 434.54 150.10 439.99 152.57 curveto
+440.11 152.22 lineto
+434.82 149.19 429.17 147.17 423.16 146.13 curveto
+417.15 145.10 411.15 145.13 405.15 146.21 curveto
+fill
+419.41 171.60 moveto
+419.40 171.81 lineto
+424.02 173.39 428.75 173.92 433.61 173.39 curveto
+438.46 172.87 442.98 171.33 447.15 168.80 curveto
+447.02 168.39 lineto
+442.72 170.40 438.20 171.66 433.47 172.17 curveto
+428.75 172.68 424.07 172.42 419.43 171.39 curveto
+fill
+restore
+%  S_BAR
+190 linenum
+0.70 setlinewidth
+505.20 268.77 moveto
+505.20 142.50 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+192 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+512.28 207.05 moveto
+(free) show
+/Times-Roman findfont
+12 scalefont
+setfont
+573.45 207.05 moveto
+(and) show
+/Times-Roman findfont
+12 scalefont
+setfont
+603.21 207.05 moveto
+(the) show
+516.92 265.77 1.000000 4n
+520.61 266.52 moveto
+520.61 286.77 lineto stroke
+549.57 268.77 1.000000 4rest
+577.77 253.77 1.000000 4n
+581.45 254.52 moveto
+581.45 273.68 lineto stroke
+606.86 256.77 1.000000 4n
+610.54 257.52 moveto
+610.54 276.68 lineto stroke
+newpath
+581.10 275.18 moveto
+610.89 278.18 lineto
+610.89 275.18 lineto
+581.10 272.18 lineto
+closepath
+fill
+516.92 244.77 1.000000 4n
+513.24 244.02 moveto
+513.24 223.77 lineto stroke
+549.57 238.77 1.000000 4rest
+577.77 241.77 1.000000 4n
+574.08 241.02 moveto
+574.08 222.27 lineto stroke
+606.86 241.77 1.000000 4n
+603.18 241.02 moveto
+603.18 222.27 lineto stroke
+newpath
+573.73 223.77 moveto
+603.53 223.77 lineto
+603.53 220.77 lineto
+573.73 220.77 lineto
+closepath
+fill
+/Times-Roman findfont
+12 scalefont
+setfont
+507.89 288.78 moveto
+516.92 288.78 1.000000 ferm
+525.96 288.78 moveto
+restore
+%  S_STAFF
+% staff 2
+save
+516.92 166.50 1.000000 4n
+0.70 setlinewidth
+520.61 167.25 moveto
+520.61 187.50 lineto stroke
+549.57 178.50 1.000000 4rest
+577.77 166.50 1.000000 4n
+581.45 167.25 moveto
+581.45 186.00 lineto stroke
+606.86 166.50 1.000000 4n
+610.54 167.25 moveto
+610.54 186.00 lineto stroke
+newpath
+581.10 187.50 moveto
+610.89 187.50 lineto
+610.89 184.50 lineto
+581.10 184.50 lineto
+closepath
+fill
+516.92 151.50 1.000000 4n
+513.24 150.75 moveto
+513.24 130.50 lineto stroke
+549.57 142.50 1.000000 4rest
+577.77 160.50 1.000000 4n
+574.08 159.75 moveto
+574.08 141.00 lineto stroke
+606.86 160.50 1.000000 4n
+598.41 160.50 1.000000 nat
+603.18 159.75 moveto
+603.18 141.00 lineto stroke
+newpath
+573.73 142.50 moveto
+603.53 142.50 lineto
+603.53 139.50 lineto
+573.73 139.50 lineto
+closepath
+fill
+/Times-Roman findfont
+12 scalefont
+setfont
+507.89 189.50 moveto
+516.92 189.50 1.000000 ferm
+525.96 189.50 moveto
+restore
+%  S_BAR
+198 linenum
+0.70 setlinewidth
+627.51 268.77 moveto
+627.51 142.50 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+199 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+633.72 207.05 moveto
+(home) show
+/Times-Roman findfont
+12 scalefont
+setfont
+679.95 207.05 moveto
+(of) show
+/Times-Roman findfont
+12 scalefont
+setfont
+700.20 207.05 moveto
+(the) show
+640.38 259.77 1.000000 4n
+649.64 259.77 1.000000 dot
+644.06 260.52 moveto
+644.06 280.77 lineto stroke
+682.43 262.77 1.000000 4n
+686.11 263.52 moveto
+686.11 283.77 lineto stroke
+689.14 283.77 1.000000 dnflag
+703.85 256.77 1.000000 4n
+707.53 257.52 moveto
+707.53 277.77 lineto stroke
+640.38 244.77 1.000000 4n
+649.64 241.77 1.000000 dot
+636.70 244.02 moveto
+636.70 223.77 lineto stroke
+682.43 244.77 1.000000 4n
+678.75 244.02 moveto
+678.75 223.77 lineto stroke
+681.77 223.77 1.000000 upflag
+703.85 241.77 1.000000 4n
+700.17 241.02 moveto
+700.17 220.77 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+640.38 166.50 1.000000 4n
+649.64 169.50 1.000000 dot
+0.70 setlinewidth
+644.06 167.25 moveto
+644.06 187.50 lineto stroke
+682.43 166.50 1.000000 4n
+686.11 167.25 moveto
+686.11 187.50 lineto stroke
+689.14 187.50 1.000000 dnflag
+703.85 163.50 1.000000 4n
+707.53 164.25 moveto
+707.53 184.50 lineto stroke
+640.38 157.50 1.000000 4n
+649.64 157.50 1.000000 dot
+636.70 156.75 moveto
+636.70 136.50 lineto stroke
+682.43 157.50 1.000000 4n
+678.75 156.75 moveto
+678.75 136.50 lineto stroke
+681.77 136.50 1.000000 upflag
+703.85 157.50 1.000000 4n
+700.17 156.75 moveto
+700.17 136.50 lineto stroke
+restore
+%  S_BAR
+205 linenum
+0.70 setlinewidth
+735.86 268.77 moveto
+735.86 142.50 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+206 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+744.15 207.05 moveto
+(brave?) show
+752.13 253.77 1.000000 2n
+756.03 254.52 moveto
+756.03 274.77 lineto stroke
+752.13 238.77 1.000000 2n
+745.68 238.77 moveto
+758.58 238.77 lineto stroke
+748.23 238.02 moveto
+748.23 217.77 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+752.13 157.50 1.000000 2n
+0.70 setlinewidth
+756.03 158.25 moveto
+756.03 178.50 lineto stroke
+752.13 145.50 1.000000 2n
+748.23 144.75 moveto
+748.23 124.50 lineto stroke
+restore
+%  S_BAR
+211 linenum
+0.70 setlinewidth
+807.07 268.77 moveto
+807.07 142.50 lineto stroke
+3.00 setlinewidth
+811.07 268.77 moveto
+811.07 142.50 lineto stroke
+0.70 setlinewidth
+%  Printing header/footer
+/Times-Roman findfont
+18 scalefont
+setfont
+342.53 1065.42 moveto
+(The Star Spangled Banner) show
+/Times-Italic findfont
+12 scalefont
+setfont
+348.37 1052.60 moveto
+(\(The United States National Anthem\)) show
+/Times-Roman findfont
+9 scalefont
+setfont
+61.71 1042.99 moveto
+(Text: Francis Scott Key) show
+/Times-Roman findfont
+9 scalefont
+setfont
+750.26 1042.99 moveto
+(Tune: J. S. Smith) show
+/Times-Roman findfont
+9 scalefont
+setfont
+61.71 1033.38 moveto
+/Times-Roman findfont
+9 scalefont
+setfont
+733.19 1033.38 moveto
+(arr: William J. Krauss) show
+showpage
+restore
+%%Trailer
+%%DocumentFonts: /Times-Roman /Times-Italic /NewCenturySchlbk-Bold 
+%%Pages: 1
diff --git a/mup/docs/template.mup b/mup/docs/template.mup
new file mode 100644 (file)
index 0000000..aa12d23
--- /dev/null
@@ -0,0 +1,142 @@
+//!Mup-Arkkra
+// This is a Mup input file template.
+// Lines starting with // are "comments" that are here for your benefit.
+// You can remove them without affecting the output.
+
+/////////////////////////////////////////////////////////////////////////
+//             things to go on the top of the first page
+top
+
+       //               centered title.
+       // The number in parentheses is the text point size.
+       // Make it bigger if you want a bigger title or smaller if you
+       // want a smaller title
+       title (18) "Replace this with the title of your song"
+
+       //              subtitle
+       // If you want a subtitle, remove the // from the beginning
+       // of the next line and fill in the appropriate subtitle text
+       // title (14) "Replace this with the subtitle"
+
+       //              composer info
+       // The first pair of double quotes enclose what to left justify,
+       // the second encloses what to right justify.
+       // If you want more than one line, add similar lines of input
+       title   ""   "Replace this with composer info"
+
+
+/////////////////////////////////////////////////////////////////////////
+//             things to go on the bottom on the first page
+bottom
+       // If you want a copyright notice, remove the //
+       // from the next line and edit in the appropriate information
+       // title "\(copyright) Copyright  Replace this with year and name"
+
+
+/////////////////////////////////////////////////////////////////////////
+//             things to go on the top of pages other than the first
+top2
+       // This example will give a centered page number between dashes.
+       // You can customize as you wish.
+       title "- \% -"
+
+
+/////////////////////////////////////////////////////////////////////////
+//             things to go at the bottom of pages other than the first
+bottom2
+       // if you want things printed at the bottom of pages of than
+       // the first page, place them here
+
+
+/////////////////////////////////////////////////////////////////////////
+//             score-wide parameters
+//
+// You may or may not need to change some items in this section
+//
+// The values given as examples are the default values that Mup uses
+// if you don't specify anything for them
+score
+       //      time signature. Can be cut, com,
+       //      or two numbers with a / between them
+       time = 4/4
+
+       //      key signature. Value is a number from 0 to 7
+       //      followed by # or & for number of sharps or flats.
+       key = 0#
+
+       //      how many staffs. Can be a number from 1 to 40
+       staffs = 1
+
+       //      clef. Can be treble, treble8, 8treble, frenchviolin,
+       //      soprano, mezzosoprano, alto, tenor, baritone, or bass
+       clef = treble
+
+       // Note: there are many more parameters that can be set,
+       // but they are not included in this simple template.
+       // There are parameters to set margins, control how things
+       // are laid out on the page, transpositions value, font and size
+       // for text and lyrics, etc
+
+
+/////////////////////////////////////////////////////////////////////////
+//     You can set some parameters for specific staffs,
+//     to override the score-wide parameters. For example,
+//     if you specify staffs = 2 in the score-wide parameters above,
+//     and want to use bass clef on staff 2, even though the score-wide
+//     clef parameter is set to treble, you can do
+//             staff 2
+//                     clef = bass
+
+
+/////////////////////////////////////////////////////////////////////////
+//             music input starts here
+music
+
+
+// For each measure, you enter one line of input for each staff,
+// then indicate what kind of barline to print.
+// The following specifies that staff 1 contains a measure of rest
+// and that an ordinary bar line is to be used at the end of the measure.
+
+1: mr;
+bar
+
+// Usually, a measure of input for one staff consists of one or more chords
+// Each chord is specified by
+//     time_value notes ;
+// where time_value is something like
+//     4       for a quarter note
+//     8       for an eighth note
+//     4.      for a dotted-quarter note
+// etc and notes is a list of one or more notes, specified as a pitch from
+// a to g, optionally followed by an accidental (#, &, x, &&, or n for sharp,
+// flat, double sharp, double flat, or natural respectively).
+// Examples:
+//     4c;
+//     2. ceg;
+//     16 f#;
+//     1 d b&;
+// (Spaces are optional, you can put them in if you want, but don't have to)
+//
+// So a complete measure might look something like:
+//     1: 4e; 4d; 2c;
+//     bar
+//
+// If you want a note in a different octave than the default octave
+// (the octave from middle-C up for treble clef,
+// or the octave below middle-C for bass clef),
+// you can add a + for each octave to go up or - for each octave to go down.
+// For example:
+//     1: c+; gc+e+; a&-; f#---;
+//
+// There are many other things you can specify, such as ties, slurs, grace
+// notes, etc, and there are also many shortcuts you can use to save typing.
+// Consult the Mup documentation for more details.
+
+// Other bar types you may want to use are
+//     repeatstart
+//     repeatend
+//     repeatboth
+//     dblbar
+//     endbar
+//     invisbar
diff --git a/mup/docs/uguide.ps b/mup/docs/uguide.ps
new file mode 100644 (file)
index 0000000..8bc10a7
--- /dev/null
@@ -0,0 +1,30255 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.17.2
+%%CreationDate: Mon Dec  4 22:55:33 2006
+%%DocumentNeededResources: font Times-BoldItalic
+%%+ font Times-Roman
+%%+ font Times-Bold
+%%+ font Courier
+%%+ font Times-Italic
+%%+ font AvantGarde-Book
+%%+ font AvantGarde-Demi
+%%+ font AvantGarde-BookOblique
+%%+ font AvantGarde-DemiOblique
+%%+ font Bookman-Light
+%%+ font Bookman-Demi
+%%+ font Bookman-LightItalic
+%%+ font Bookman-DemiItalic
+%%+ font Courier-Bold
+%%+ font Courier-Oblique
+%%+ font Courier-BoldOblique
+%%+ font Helvetica
+%%+ font Helvetica-Bold
+%%+ font Helvetica-Oblique
+%%+ font Helvetica-BoldOblique
+%%+ font NewCenturySchlbk-Roman
+%%+ font NewCenturySchlbk-Bold
+%%+ font NewCenturySchlbk-Italic
+%%+ font NewCenturySchlbk-BoldItalic
+%%+ font Palatino-Roman
+%%+ font Palatino-Bold
+%%+ font Palatino-Italic
+%%+ font Palatino-BoldItalic
+%%DocumentSuppliedResources: file mugex102.ps
+%%+ file mugex101.ps
+%%+ file mugex100.ps
+%%+ file mugex99.ps
+%%+ file mugex98.ps
+%%+ file mugex97.ps
+%%+ file mugex96.ps
+%%+ file mugex95.ps
+%%+ file mugex94.ps
+%%+ file mugex93.ps
+%%+ file mugex92.ps
+%%+ file mugex91.ps
+%%+ file mugex90.ps
+%%+ file mugex89.ps
+%%+ file mugex88.ps
+%%+ file mugex87.ps
+%%+ file mugex86.ps
+%%+ file mugex85.ps
+%%+ file mugex84.ps
+%%+ file mugex83.ps
+%%+ file mugex82.ps
+%%+ file mugex81.ps
+%%+ file mugex80.ps
+%%+ file mugex79.ps
+%%+ file mugex78.ps
+%%+ file mugex77.ps
+%%+ file mugex76.ps
+%%+ file mugex75.ps
+%%+ file mugex74.ps
+%%+ file mugex73.ps
+%%+ file mugex72.ps
+%%+ file mugex71.ps
+%%+ file mugex70.ps
+%%+ file mugex69.ps
+%%+ file mugex68.ps
+%%+ file mugex67.ps
+%%+ file mugex66.ps
+%%+ file mugex65.ps
+%%+ file extchar.ps
+%%+ file muschar.ps
+%%+ file mugex64.ps
+%%+ file mugex63.ps
+%%+ file mugex62.ps
+%%+ file mugex61.ps
+%%+ file mugex60.ps
+%%+ file mugex59.ps
+%%+ file mugex58.ps
+%%+ file mugex57.ps
+%%+ file mugex56.ps
+%%+ file mugex55.ps
+%%+ file mugex54.ps
+%%+ file mugex53.ps
+%%+ file mugex52.ps
+%%+ file mugex51.ps
+%%+ file mugex50.ps
+%%+ file mugex49.ps
+%%+ file mugex48.ps
+%%+ file mugex47.ps
+%%+ file mugex46.ps
+%%+ file mugex45.ps
+%%+ file mugex44.ps
+%%+ file mugex43.ps
+%%+ file mugex42.ps
+%%+ file mugex41.ps
+%%+ file mugex40.ps
+%%+ file mugex39.ps
+%%+ file mugex38.ps
+%%+ file mugex37.ps
+%%+ file mugex36.ps
+%%+ file mugex35.ps
+%%+ file mugex34.ps
+%%+ file mugex33.ps
+%%+ file mugex32.ps
+%%+ file mugex31.ps
+%%+ file mugex30.ps
+%%+ file mugex29.ps
+%%+ file mugex28.ps
+%%+ file mugex27.ps
+%%+ file mugex26.ps
+%%+ file mugex25.ps
+%%+ file mugex24.ps
+%%+ file mugex23.ps
+%%+ file mugex22.ps
+%%+ file mugex21.ps
+%%+ file mugex20.ps
+%%+ file mugex19.ps
+%%+ file mugex18.ps
+%%+ file mugex17.ps
+%%+ file mugex16.ps
+%%+ file mugex15.ps
+%%+ file mugex14.ps
+%%+ file mugex13.ps
+%%+ file mugex12.ps
+%%+ file mugex11.ps
+%%+ file mugex10.ps
+%%+ file mugex9.ps
+%%+ file mugex8.ps
+%%+ file mugex7.ps
+%%+ file mugex6.ps
+%%+ file mugex5.ps
+%%+ file mugex4.ps
+%%+ file mugex3.ps
+%%+ file mugex2.ps
+%%+ file mugex1.ps
+%%+ procset grops 1.17 2
+%%Pages: 172
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+% Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2004 by Arkkra Enterprises
+% All rights reserved
+
+% Mup PostScript Prolog 5.3 for use with Mup 5.3
+
+% lwid is used as the width of a standard (thin) line in the music
+% character definitions.
+/lwid 70 def
+/halflwid lwid 2 div def
+
+% Define the following for use in do_upshortnote, do_dnshortnote, and
+% do_shortrest; it has to be done outside of the music font definition.
+/utildict 10 dict def
+utildict begin
+       /setnumflags    {       /numflags       exch def } def
+       /sethooksm1     {       /hooksm1        exch def } def
+       /setoffsets     {       /offsets        exch def } def
+       /setx           {       /x              exch def } def
+       /sety           {       /y              exch def } def
+end
+
+% Define a music character font.  Each music character is defined as if it
+% were a normal ASCII character in a strange font where "A" looks like a
+% treble clef, "B" looks like a bass clef, etc.
+
+/mfont0 100 dict def
+mfont0 begin
+       /FontType 3 def
+       /FontMatrix [ .001 0 0 0.001 0 0 ] def
+       /FontBBox [ -2000 -4030 2000 4030 ] def
+       /FontName (Mfont0) def
+
+       % set up Encoding vector with standard names
+       /Encoding 256 array def
+       StandardEncoding Encoding copy
+       pop
+
+       % the following definitions are used for quarter rests
+       /topx -170 def /topy 950 def
+       /cor1x 250 def /cor1y 450 def
+       /cor2x -300 def /cor2y 200 def
+       /cor3x 250 def /cor3y -400 def
+
+       % the following definitions are used for double sharps
+       /limit 300 halflwid add def
+       /off 70 def
+       /inbendsmall limit 200 sub def
+       /inbendbig limit 20 sub def
+       /outbendsmall 100 def
+       /outbendbig outbendsmall off add def
+
+       %%%%% define routines that will be used by multiple characters %%%%%
+       /do_1n {
+               gsave
+               newpath -10 rotate 1.6 1 scale
+               0 0 325 0 360 arc               %outer ellipse
+               1 1.6 div 1 scale 10 rotate     %back to original
+               35 rotate 0.85 1.1 scale
+               0 0 275 0 360 arc               %inner ellipse
+               eofill
+               grestore
+       } def
+       /do_upflag {
+               -315 0 moveto
+               -300 100 -100 480 0 600 curveto
+               300 960 350 1500 200 1700 curveto
+               130 1700 lineto
+               350 1200 50 650 -315 600 curveto
+               fill
+       } def
+       /do_flat {
+               -250 -400 moveto        %outer edge of loop
+               500 0 350 650 -250 160 curveto
+               -250 160 lwid sub lineto %inner edge of loop
+               100 400 300 0 -250 -400 lwid add curveto
+               fill
+
+               lwid setlinewidth       %stem
+               -250 1100 moveto -250 -400 lineto stroke
+       } def
+       /do_diamond {
+               newpath
+               420 0 moveto 0 300 lineto -420 0 lineto
+               0 -300 lineto closepath
+               259 -29 moveto -41 185 lineto -259 29 lineto
+               41 -185 lineto closepath
+               eofill
+       } def
+       /do_2n {
+               gsave
+               newpath 25 rotate 1.4 1 scale
+               0 0 315 0 360 arc               %outer ellipse
+               1 1.4 div 1 scale               %back to original
+               1.3 0.5 scale
+               0 0 310 0 360 arc               %inner ellipse
+               eofill
+               grestore
+       } def
+       /do_4n {
+               gsave
+               newpath 25 rotate 1.35 1 scale
+               0 0 310 0 360 arc fill
+               grestore
+       } def
+       /do_com {
+               newpath
+               330 250 150 0 360 arc fill      %knob at upper right
+               465 300 moveto                  %outer boundary
+               410 500 200 635 0 635 curveto
+               -750 635 -750 -635 0 -635 curveto
+               350 -635 480 -300 500 -100 curveto
+               430 -100 lineto                 %inner boundary
+               380 -300 250 -565 0 -565 curveto
+               -450 -565 -450 565 0 565 curveto
+               200 565 370 350 395 300 curveto
+               fill
+       } def
+       /do_ferm {
+               0 0 800 lwid sub 0 180 arc      %inner arc
+               -800 0 lineto
+               0 270 lwid sub 800 180 0 arcn   %outer arc
+               800 0 lineto fill
+               0 120 120 0 360 arc fill        %the dot
+       } def
+       /do_mor {
+               gsave
+               0.7 1 scale     %scrunch the following horizontally
+               45 rotate       %to pretend all lines horz or vertical
+               0 1 1 {
+                       pop     %we don't need the loop variable
+                       %one half of the mordent
+                       0 40 moveto 350 40 lineto 350 -460 lineto
+                       750 -460 lineto 750 -540 lineto
+                       150 -540 lineto 150 -40 lineto
+                       0 -40 lineto fill
+                       180 rotate      %to do the other half
+               } for
+               grestore
+       } def
+       /do_turn {
+               gsave
+               0 1 1 {
+                       pop     %we don't need the loop variable
+                       0 -100 moveto   %outer boundary
+                       200 -400 625 -400 625 0 curveto
+                       625 200 500 325 300 325 curveto
+                       300 185 lineto  %inner boundary
+                       450 255 555 150 555 0 curveto
+                       555 -350 250 -250 0 100 curveto
+                       fill
+                       300 255 70 0 360 arc fill %knob on end
+                       180 rotate      %to do the other half
+               } for
+               grestore
+       } def
+
+       /do_upshortnote {
+               utildict begin
+               setnumflags             %set numflags from the stack
+               gsave
+               -330 0 translate        %half a flag width
+               do_4n                   %do a quarter note head
+               lwid setlinewidth
+               370 0 moveto
+               370 2100 numflags 2 sub flagsep mul add lineto stroke
+               670 2100 numflags 2 sub flagsep mul add translate
+               1 -1 scale              %reflect across X axis
+               0 1 numflags 1 sub {
+                       do_upflag       %do an upflag
+                       pop             %we don't need the loop variable
+                       0 flagsep translate
+               } for
+               grestore
+               end
+       } def
+
+       /do_dnshortnote {
+               utildict begin
+               setnumflags             %set numflags from the stack
+               do_4n                   %do a quarter note head
+               lwid setlinewidth
+               -370 0 moveto
+               -370 -2100 numflags 2 sub flagsep mul sub lineto stroke
+               gsave
+               -70 -2100 numflags 2 sub flagsep mul sub translate
+               0 1 numflags 1 sub {
+                       do_upflag       %do an upflag
+                       pop             %we don't need the loop variable
+                       0 flagsep translate
+               } for
+               grestore
+               end
+       } def
+
+       /do_shortrest {
+               utildict begin
+               sety setx setoffsets sethooksm1 %set variable from the stack
+               gsave
+               -105.8 offsets mul -600 offsets mul translate
+               0 1 hooksm1 {           %loop once per hook
+                       newpath
+                       1 setlinewidth
+                       gsave
+                       1 1.2 scale
+                       -150 300 1.2 div 140 0 360 arc fill     %the dot
+                       grestore
+                       lwid setlinewidth
+                       -50 700 550 255 315 arc         %rest of the hook
+                       hooksm1 lt { stroke 105.8 600 translate } if
+               } for
+               x y lineto stroke
+               grestore
+               end
+       } def
+
+
+       % subsidiary dictionary of character definitions
+       /CharStrings 128 dict def
+       CharStrings begin
+
+               /.notdef {} def
+
+               % Here are the definitions of the characters.  A stepsize here
+               % is 300 units (assuming the character is drawn at its default
+               % size).
+
+               % gclef
+               /A {
+                       newpath
+                       %start with inner curl, inside boundary
+                       -50 -300 moveto
+                       -450 600 700 700 750 0 curveto
+                       750 -800 -700 -800 -700 200 curveto
+                       -700 900 500 1400 520 2250 curveto
+                       520 2900 300 3000 200 3000 curveto
+                       100 3000 -400 2500 -200 1800 curveto
+                       350 -600 lineto
+                       720 -1600 0 -1650 -400 -1400 curveto
+
+                       %go back to start, drawing the other boundary
+                       -400 -1480 lineto
+                       0 -1700 800 -1700 430 -600 curveto
+                       -120 1800 lineto
+                       -300 2400 200 2800 250 2800 curveto
+                       400 2800 430 2700 430 2450 curveto
+                       430 1800 -900 1200 -900 300 curveto
+                       -750 -900 800 -900 850 0 curveto
+                       900 1100 -750 900 -120 -300 curveto fill
+
+                       %circle at the bottom
+                       -300 -1250 250 0 360 arc fill
+               } def
+
+               % fclef
+               /B {
+                       newpath
+                       %start with outside boundary, at bottom
+                       -1000 -1700 moveto
+                       100 -1100 500 -600 450 0 curveto
+                       450 850 -1100 850 -950 0 curveto
+
+                       %go back to start, drawing the other boundary
+                       -880 0 lineto
+                       -920 400 -600 560 -300 560 curveto
+                       0 560 150 400 150 0 curveto
+                       150 -400 100 -900 -1000 -1620 curveto fill
+
+                       %circle at the left
+                       newpath
+                       -700 0 250 0 360 arc fill
+
+                       %do the two dots after the main curve
+                       700 -300 100 0 360 arc fill
+                       700 300 100 0 360 arc fill
+               } def
+
+               % cclef
+               /C {
+                       gsave
+                       %do upper curved part, then scale to do mirror image
+                       0 1 1 {
+                               pop     %we don't need the loop variable
+                               %outer boundary of curve
+                               -170 0 moveto 100 300 lineto
+                               400 -200 750 300 750 650 curveto
+                               750 1100 450 1235 250 1235 curveto
+                               0 1235 -143 1100 -143 950 curveto
+
+                               %inner boundary of curve
+                               0 950 lineto
+                               0 1100 30 1165 250 1165 curveto
+                               300 1165 450 1100 450 650 curveto
+                               450 400 400 -100 100 400 curveto
+                               -270 0 lineto fill
+                               %stroke
+                               %-270 0 moveto 100 400 lineto
+                               %400 -100 450 400 450 650 curveto
+                               %450 1100 300 1165 250 1165 curveto
+                               %30 1165 0 1100 0 950 curveto
+                               %stroke
+
+                               %elliptical ball at end of curve
+                               gsave
+                               1.3 1 scale
+                               10 950 120 0 360 arc fill
+                               grestore
+                               1 -1 scale      %reflect across X axis
+                       } for
+                       grestore
+
+                       % two vertical lines on the left
+                       300 setlinewidth -600 -1200 halflwid sub moveto
+                       -600 1200 halflwid add lineto stroke
+                       lwid setlinewidth -300 -1200 halflwid sub moveto
+                       -300 1200 halflwid add lineto stroke
+               } def
+
+               % dblwhole
+               /D {
+                       do_1n           %do a whole note
+                       lwid setlinewidth
+                       -490 -600 moveto -490 600 lineto stroke
+                       490 -600 moveto 490 600 lineto stroke
+               } def
+
+               % 1n
+               /E {
+                       do_1n           %do a whole note
+               } def
+
+               % 2n
+               /F {
+                       do_2n           %do a half note
+               } def
+
+               % 4n
+               /G {
+                       do_4n           %do a quarter note head
+               } def
+
+               % upflag
+               /H {
+                       do_upflag               %do an upflag
+               } def
+
+               % dnflag
+               /I {
+                       gsave
+                       1 -1 scale      %reflect across X axis
+                       do_upflag               %do an upflag
+                       grestore
+               } def
+
+               % dwhrest
+               /J {
+                       300 setlinewidth
+                       0 0 moveto 0 600 lineto stroke
+               } def
+
+               % 1rest
+               /K {
+                       lwid setlinewidth
+                       -750 600 moveto 750 600 lineto stroke
+                       300 setlinewidth
+                       -400 450 moveto 400 450 lineto stroke
+               } def
+
+               % 2rest
+               /L {
+                       lwid setlinewidth
+                       -750 0 moveto 750 0 lineto stroke
+                       300 setlinewidth
+                       -400 150 moveto 400 150 lineto stroke
+               } def
+
+               % 4rest
+               /M {
+                       newpath
+                       cor3x cor3y halflwid add moveto
+                       %-400 -200 -450 -650 50 -950 lwid add curveto
+                       -450 -50 -450 -650 50 -950 lwid add curveto
+                       -150 -650 -100 -250 cor3x cor3y halflwid sub curveto
+                       fill
+
+                       cor1x cor1y moveto cor1x 200 sub cor1y 200 add lineto
+                       cor2x cor2y lineto cor2x 200 add cor2y 200 sub lineto
+                       fill
+
+                       lwid setlinewidth
+                       topx topy moveto cor1x cor1y lineto stroke
+                       cor2x cor2y moveto cor3x cor3y lineto stroke
+               } def
+
+               % 8rest
+               /N {
+                       0 0 0 -600 do_shortrest
+               } def
+
+               % 16rest
+               /O {
+                       1 1 100 -1200 do_shortrest
+               } def
+
+               % 32rest
+               /P {
+                       2 1 0 -1800 do_shortrest
+               } def
+
+               % 64rest
+               /Q {
+                       3 2 -80 -2100 do_shortrest
+               } def
+
+               % 128rest
+               /R {
+                       4 2 -150 -2700 do_shortrest
+               } def
+
+               % 256rest
+               /S {
+                       5 3 -280 -3300 do_shortrest
+               } def
+
+               % dot
+               /T {
+                       newpath
+                       0 0 120 0 360 arc fill
+               } def
+
+               % nat
+               /U {
+                       % fill crossbars so that we can do parallelograms
+                       -235 -470 moveto -235 -270 lineto
+                       235 -130 lineto 235 -330 lineto fill
+                       -235 130 moveto -235 330 lineto
+                       235 470 lineto 235 270 lineto fill
+
+                       % vertical strokes
+                       lwid setlinewidth
+                       -200 -380 moveto -200 850 lineto stroke
+                       200 -850 moveto 200 380 lineto stroke
+               } def
+
+               % sharp
+               /V {
+                       % fill crossbars so that we can do parallelograms
+                       -325 -480 moveto -325 -280 lineto
+                       325 -120 lineto 325 -320 lineto fill
+                       -325 120 moveto -325 320 lineto
+                       325 480 lineto 325 280 lineto fill
+
+                       % vertical strokes
+                       lwid setlinewidth
+                       -150 -930 moveto -150 880 lineto stroke
+                       150 -880 moveto 150 930 lineto stroke
+               } def
+
+               % flat
+               /W {
+                       do_flat         %do a flat
+               } def
+
+               % dblsharp
+               /X {
+                       gsave
+                       0 1 3 {         %loop once for each of 4 sticks
+                               pop     %we don't need the loop variable
+                               0 off neg moveto
+                               outbendbig outbendsmall lineto
+                               inbendbig inbendsmall lineto
+                               limit limit lineto
+                               inbendsmall inbendbig lineto
+                               outbendsmall outbendbig lineto
+                               off neg 0 lineto
+                               fill
+                               -90 rotate
+                       } for
+                       grestore
+               } def
+
+               % dblflat
+               /Y {
+                       -290 580 290 {  %loop once for each flat
+
+                               gsave
+                               1 setlinewidth
+                               0 translate     %translate left/right (loop var)
+                               do_flat         %do a flat
+                               grestore
+
+                       } for
+               } def
+
+               % xnote
+               /Z {
+                       gsave
+                       1.15 1 scale 120 setlinewidth 1 setlinecap      %round
+                       -300 -300 moveto 300 300 lineto stroke
+                       -300 300 moveto 300 -300 lineto stroke
+                       grestore
+               } def
+
+               % dwhdiamond
+               /a {
+                       do_diamond      %do a diamond
+                       lwid setlinewidth
+                       -420 -600 moveto -420 600 lineto stroke
+                       420 -600 moveto 420 600 lineto stroke
+               } def
+
+               % diamond
+               /b {
+                       do_diamond      %do a diamond
+               } def
+
+               % filldiamond
+               /c {
+                       420 0 moveto 0 300 lineto
+                       -420 0 lineto 0 -300 lineto fill
+               } def
+
+               % up2n
+               /d {
+                       lwid setlinewidth
+                       380 0 moveto 380 2100 lineto stroke
+                       do_2n           %do a half note
+               } def
+
+               % dn2n
+               /e {
+                       lwid setlinewidth
+                       -380 0 moveto -380 -2100 lineto stroke
+                       do_2n           %do a half note
+               } def
+
+               % up4n
+               /f {
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       370 0 moveto 370 2100 lineto stroke
+               } def
+
+               % dn4n
+               /g {
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       -370 0 moveto -370 -2100 lineto stroke
+               } def
+
+               % up8n
+               /h {
+                       gsave
+                       -330 0 translate        % half a flag width
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       370 0 moveto 370 2100 lineto stroke
+                       670 2100 translate
+                       1 -1 scale      %reflect across X axis
+                       do_upflag               %do an upflag
+                       grestore
+               } def
+
+               % dn8n
+               /i {
+                       do_4n           %do a quarter note head
+                       lwid setlinewidth
+                       -370 0 moveto -370 -2100 lineto stroke
+                       gsave
+                       -70 -2100 translate
+                       do_upflag               %do an upflag
+                       grestore
+               } def
+
+               % up16n
+               /j {
+                       2 do_upshortnote
+               } def
+
+               % dn16n
+               /k {
+                       2 do_dnshortnote
+               } def
+
+               % up32n
+               /l {
+                       3 do_upshortnote
+               } def
+
+               % dn32n
+               /m {
+                       3 do_dnshortnote
+               } def
+
+               % up64n
+               /n {
+                       4 do_upshortnote
+               } def
+
+               % dn64n
+               /o {
+                       4 do_dnshortnote
+               } def
+
+               % up128n
+               /p {
+                       5 do_upshortnote
+               } def
+
+               % dn128n
+               /q {
+                       5 do_dnshortnote
+               } def
+
+               % up256n
+               /r {
+                       6 do_upshortnote
+               } def
+
+               % dn256n
+               /s {
+                       6 do_dnshortnote
+               } def
+
+               % com
+               /t {
+                       do_com          %do a common time symbol
+               } def
+
+               % cut
+               /u {
+                       do_com          %do a common time symbol
+                       lwid setlinewidth
+                       0 -900 moveto 0 900 lineto stroke
+               } def
+
+               % begped
+               /v {
+                       lwid setlinewidth
+                       -200 600 moveto -200 0 lineto 200 0 lineto stroke
+               } def
+
+               % pedal
+               /w {
+                       lwid setlinewidth
+                       -500 0 moveto -450 0 lineto 0 600 lineto
+                       450 0 lineto 500 0 lineto stroke
+               } def
+
+               % endped
+               /x {
+                       lwid setlinewidth
+                       200 600 moveto 200 0 lineto -200 0 lineto stroke
+               } def
+
+               % dnbow
+               /y {
+                       lwid setlinewidth
+                       -350 0 moveto -350 900 lineto stroke
+                       350 0 moveto 350 900 lineto stroke
+                       200 setlinewidth
+                       -350 800 moveto 350 800 lineto stroke
+               } def
+
+               % upbow
+               /z {
+                       lwid setlinewidth
+                       -300 900 moveto 0 0 lineto 300 900 lineto stroke
+               } def
+
+               % wedge
+               /one {
+                       0 0 moveto -150 500 lineto 150 500 lineto fill
+               } def
+
+               % uwedge
+               /two {
+                       -150 0 moveto 150 0 lineto 0 500 lineto fill
+               } def
+
+               % ferm
+               /three {
+                       newpath
+                       do_ferm         %do a right side up fermata
+               } def
+
+               % uferm
+               /four {
+                       newpath
+                       gsave
+                       0 270 lwid sub 800 add translate %baseline at bottom
+                       180 rotate                      %upside down
+                       do_ferm         %do a right side up fermata
+                       grestore
+               } def
+
+               % sign
+               /five {
+                       gsave
+                       %do upper left curved part, upper right dot;
+                       %then rotate 180 to do other half
+                       0 1 1 {
+                               pop     %we don't need the loop variable
+                               0 100 moveto            %inner boundary
+                               -1000 300 -400 750 -200 700 curveto
+                               -200 800 lineto         %outer boundary
+                               -550 900 -1100 100 0 -100 curveto
+                               fill
+                               %dot at end of curve
+                               -200 700 100 0 360 arc fill
+                               %dot in upper right quadrant
+                               500 200 70 0 360 arc fill
+                               180 rotate
+                       } for
+                       grestore
+
+                       %slash through middle
+                       lwid setlinewidth
+                       -400 -800 moveto 400 800 lineto stroke
+               } def
+
+               % coda
+               /six {
+                       newpath
+                       gsave
+                       0.6 1 scale
+                       0 0 550 0 360 arc       %outside boundary
+                       1 0.6 div 1 scale       %back to original
+                       0.9 1 scale
+                       0 0 650 0 360 arc       %inside boundary
+                       eofill
+                       grestore
+                       lwid setlinewidth
+                       0 -850 moveto 0 850 lineto stroke
+                       -800 0 moveto 800 0 lineto stroke
+               } def
+
+               % mor
+               /seven {
+                       do_mor          %do a mordent
+               } def
+
+               % invmor
+               /eight {
+                       do_mor          %do a mordent
+                       lwid setlinewidth
+                       0 -450 moveto 0 450 lineto stroke
+               } def
+
+               % turn
+               /nine {
+                       do_turn         %do a turn
+               } def
+
+               % invturn
+               /zero {
+                       gsave
+                       1 -1 scale      %reflect across X axis
+                       do_turn         %do a turn
+                       grestore
+               } def
+
+               % acc_gt
+               /numbersign {
+                       lwid setlinewidth
+                       -500 300 moveto 500 0 lineto -500 -300 lineto stroke
+               } def
+
+               % acc_hat
+               /dollar {
+                       newpath
+                       -365 0 moveto 0 860 lineto 365 0 lineto
+                       150 0 lineto -75 530 lineto -300 0 lineto fill
+               } def
+
+               % acc_uhat
+               /quotedbl {
+                       newpath
+                       365 860 moveto 0 0 lineto -365 860 lineto
+                       -150 860 lineto 75 330 lineto 300 860 lineto fill
+               } def
+
+               % tr
+               /asterisk {
+                       %vertical bar of t
+                       -350 1000 moveto -550 200 lineto
+                       -612.5 -50 -212.5 -50 -160 200 curveto
+                       -230 200 lineto
+                       -300 50 -420 50 -400 200 curveto
+                       -200 1000 lineto fill
+
+                       %crossbar of t and vertical bar of r
+                       -700 600 moveto -160 600 lineto
+                       20 600 30 520 60 440 curveto
+                       -50 0 lineto 70 0 lineto 180 440 lineto
+                       190 480 100 670 -150 670 curveto
+                       -690 670 lineto fill
+
+                       %horizontal curve of r
+                       100 480 moveto
+                       300 630 450 700 650 550 curveto
+                       560 480 lineto
+                       450 630 300 560 100 390 curveto
+                       fill
+
+                       %knob at end of r
+                       600 460 100 0 360 arc fill
+               } def
+
+               % leg
+               /comma {
+                       100 setlinewidth
+                       -400 0 moveto 400 0 lineto stroke
+               } def
+
+               % rr
+               /hyphen {
+                       100 setlinewidth
+                       -400 0 moveto 0 1000 lineto stroke
+                       0 0 moveto 400 1000 lineto stroke
+               } def
+
+               % measrpt
+               /period {
+                       newpath -450 400 150 0 360 arc fill
+                       newpath 450 -400 150 0 360 arc fill
+                       200 setlinewidth
+                       -550 -600 moveto 550 600 lineto stroke
+               } def
+
+               % copyright
+               /slash {
+                       lwid setlinewidth
+                       newpath 0 400 400 0 360 arc stroke
+                       newpath 0 400 200 45 315 arc stroke
+               } def
+
+               % dim
+               /quoteleft {
+                       50 setlinewidth
+                       newpath 0 640 220 0 360 arc stroke
+               } def
+
+               % halfdim
+               /quoteright {
+                       50 setlinewidth
+                       newpath 0 640 220 0 360 arc stroke
+                       newpath -340 300 moveto 340 980 lineto stroke
+               } def
+
+               % triangle
+               /asciicircum {
+                       50 setlinewidth
+                       newpath -340 -10 moveto 0 710 lineto
+                       340 -10 lineto closepath stroke
+               } def
+
+               % qwhrest
+               /ampersand {
+                       300 setlinewidth
+                       0 -600 moveto 0 600 lineto stroke
+               } def
+
+               % ll1rest
+               /exclam {
+                       310 setlinewidth
+                       -400 455 moveto 400 450 lineto stroke
+               } def
+
+               % ll2rest
+               /at {
+                       310 setlinewidth
+                       -400 145 moveto 400 150 lineto stroke
+               } def
+       end
+
+       /BuildChar {
+
+               exch begin
+               Encoding exch get
+
+               dup
+               Mcbbox0 exch get
+               aload pop setcachedevice
+
+               CharStrings exch get
+               exec
+               end
+       } def
+end
+
+
+% Define another music character font, since there are too many to fit in one
+% font.  It works the same way as the first one.
+
+/mfont1 100 dict def
+mfont1 begin
+       /FontType 3 def
+       /FontMatrix [ .001 0 0 0.001 0 0 ] def
+       /FontBBox [ -2000 -4030 2000 4030 ] def
+       /FontName (Mfont1) def
+
+       % set up Encoding vector with standard names
+       /Encoding 256 array def
+       StandardEncoding Encoding copy
+       pop
+
+       %%%%% define routines that will be used by multiple characters %%%%%
+
+       /do_dwh_bars {
+               % the two bars surrounding a double whole note
+               lwid setlinewidth
+               -420 -600 moveto -420 600 lineto stroke
+               420 -600 moveto 420 600 lineto stroke
+       } def
+       /do_righttriangle {
+               newpath
+               420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto
+               350 150 moveto -140 150 lineto 350 -213 lineto
+               eofill
+       } def
+       /do_fillrighttriangle {
+               newpath
+               420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto
+               fill
+       } def
+       /do_rectangle {
+               newpath
+               420 270 moveto -420 270 lineto -420 -270 lineto 420 -270 lineto
+               350 150 moveto -350 150 lineto -350 -150 lineto 350 -150 lineto
+               eofill
+       } def
+       /do_isostriangle {
+               newpath
+               0 300 moveto -420 -270 lineto 420 -270 lineto
+               0 182 moveto -245 -150 lineto 245 -150 lineto
+               eofill
+       } def
+       /do_piewedge {
+               newpath
+               0 -300 moveto 0 -244 514 35 145 arc
+               0 -209 moveto 0 -244 394 43 137 arc
+               eofill
+       } def
+       /do_semicircle {
+               newpath
+               gsave
+               1 1.357 scale 420 199 moveto 0 199 420 180 360 arc
+               1 1.09 scale 350 111 moveto 0 199 350 194.1 345.9 arc
+               eofill
+               grestore
+       } def
+       /do_slashhead {
+               newpath
+               lwid setlinewidth
+               -620 -530 moveto -480 -670 lineto 620 530 lineto 480 670 lineto
+               closepath stroke
+       } def
+
+       % subsidiary dictionary of character definitions
+       /CharStrings 128 dict def
+       CharStrings begin
+
+               /.notdef {} def
+
+               % Here are the definitions of the characters.  A stepsize here
+               % is 300 units (assuming the character is drawn at its default
+               % size).
+
+               % dwhrighttriangle
+               /A {
+                       do_righttriangle
+                       do_dwh_bars
+               } def
+
+               % righttriangle
+               /B {
+                       do_righttriangle
+               } def
+
+               % fillrighttriangle
+               /C {
+                       newpath
+                       420 270 moveto -420 270 lineto 350 -300 lineto
+                       420 -300 lineto
+                       fill
+               } def
+
+               % udwhrighttriangle
+               /D {
+                       gsave
+                       180 rotate
+                       do_righttriangle
+                       do_dwh_bars
+                       grestore
+               } def
+
+               % urighttriangle
+               /E {
+                       gsave
+                       180 rotate
+                       do_righttriangle
+                       grestore
+               } def
+
+               % ufillrighttriangle
+               /F {
+                       gsave
+                       180 rotate
+                       do_fillrighttriangle
+                       grestore
+               } def
+
+               % dwhrectangle
+               /G {
+                       do_rectangle
+                       do_dwh_bars
+               } def
+
+               % rectangle
+               /H {
+                       do_rectangle
+               } def
+
+               % fillrectangle
+               /I {
+                       newpath
+                       420 270 moveto -420 270 lineto -420 -270 lineto
+                       420 -270 lineto
+                       fill
+               } def
+
+               % dwhisostriangle
+               /J {
+                       do_isostriangle
+                       do_dwh_bars
+               } def
+
+               % isostriangle
+               /K {
+                       do_isostriangle
+               } def
+
+               % fillisostriangle
+               /L {
+                       newpath
+                       0 300 moveto -420 -270 lineto 420 -270 lineto
+                       fill
+               } def
+
+               % dwhpiewedge
+               /M {
+                       do_piewedge
+                       do_dwh_bars
+               } def
+
+               % piewedge
+               /N {
+                       do_piewedge
+               } def
+
+               % fillpiewedge
+               /O {
+                       newpath
+                       0 -300 moveto 0 -244 514 35 145 arc
+                       fill
+               } def
+
+               % dwhsemicircle
+               /P {
+                       do_semicircle
+                       do_dwh_bars
+               } def
+
+               % semicircle
+               /Q {
+                       do_semicircle
+               } def
+
+               % fillsemicircle
+               /R {
+                       newpath
+                       gsave
+                       1 570 420 div scale
+                       420 199 moveto 0 199 420 180 360 arc
+                       fill
+                       grestore
+               } def
+
+               % dwhslashhead
+               /S {
+                       do_slashhead
+                       lwid setlinewidth
+                       -650 -600 moveto -650 600 lineto stroke
+                       650 -600 moveto 650 600 lineto stroke
+               } def
+
+               % slashhead
+               /T {
+                       do_slashhead
+               } def
+
+               % fillslashhead
+               /U {
+                       newpath
+                       200 setlinewidth
+                       -550 -600 moveto 550 600 lineto stroke
+               } def
+
+               % blankhead
+               /V {
+                       %print nothing
+               } def
+       end
+
+       /BuildChar {
+
+               exch begin
+               Encoding exch get
+
+               dup
+               Mcbbox1 exch get
+               aload pop setcachedevice
+
+               CharStrings exch get
+               exec
+               end
+       } def
+end
+
+
+% General routines for printing any music character, invoked by each music
+% character's specific routine below.  The scaling factor (default 1) needs
+% to be multiplied by 10 to get the actual size.  These routines restore the
+% preexisting current font when they are done.
+
+/printmchar0 {
+       gsave
+       /musicchar exch def
+       /Mfont0 findfont exch 10 mul scalefont setfont moveto 
+       musicchar show
+       grestore
+} def
+/printmchar1 {
+       gsave
+       /musicchar exch def
+       /Mfont1 findfont exch 10 mul scalefont setfont moveto 
+       musicchar show
+       grestore
+} def
+
+% Define each music character name to be a routine that prints the character.
+% Each character is to be invoked as in this example:
+%      100 200 1 gclef         % at (100, 200), scale to default size & print
+
+/gclef                 { (A) printmchar0 } def
+/fclef                 { (B) printmchar0 } def
+/cclef                 { (C) printmchar0 } def
+/dblwhole              { (D) printmchar0 } def
+/1n                    { (E) printmchar0 } def
+/2n                    { (F) printmchar0 } def
+/4n                    { (G) printmchar0 } def
+/upflag                        { (H) printmchar0 } def
+/dnflag                        { (I) printmchar0 } def
+/dwhrest               { (J) printmchar0 } def
+/1rest                 { (K) printmchar0 } def
+/2rest                 { (L) printmchar0 } def
+/4rest                 { (M) printmchar0 } def
+/8rest                 { (N) printmchar0 } def
+/16rest                        { (O) printmchar0 } def
+/32rest                        { (P) printmchar0 } def
+/64rest                        { (Q) printmchar0 } def
+/128rest               { (R) printmchar0 } def
+/256rest               { (S) printmchar0 } def
+/dot                   { (T) printmchar0 } def
+/nat                   { (U) printmchar0 } def
+/sharp                 { (V) printmchar0 } def
+/flat                  { (W) printmchar0 } def
+/dblsharp              { (X) printmchar0 } def
+/dblflat               { (Y) printmchar0 } def
+/xnote                 { (Z) printmchar0 } def
+/dwhdiamond            { (a) printmchar0 } def
+/diamond               { (b) printmchar0 } def
+/filldiamond           { (c) printmchar0 } def
+/up2n                  { (d) printmchar0 } def
+/dn2n                  { (e) printmchar0 } def
+/up4n                  { (f) printmchar0 } def
+/dn4n                  { (g) printmchar0 } def
+/up8n                  { (h) printmchar0 } def
+/dn8n                  { (i) printmchar0 } def
+/up16n                 { (j) printmchar0 } def
+/dn16n                 { (k) printmchar0 } def
+/up32n                 { (l) printmchar0 } def
+/dn32n                 { (m) printmchar0 } def
+/up64n                 { (n) printmchar0 } def
+/dn64n                 { (o) printmchar0 } def
+/up128n                        { (p) printmchar0 } def
+/dn128n                        { (q) printmchar0 } def
+/up256n                        { (r) printmchar0 } def
+/dn256n                        { (s) printmchar0 } def
+/com                   { (t) printmchar0 } def
+/cut                   { (u) printmchar0 } def
+/begped                        { (v) printmchar0 } def
+/pedal                 { (w) printmchar0 } def
+/endped                        { (x) printmchar0 } def
+/dnbow                 { (y) printmchar0 } def
+/upbow                 { (z) printmchar0 } def
+/wedge                 { (1) printmchar0 } def
+/uwedge                        { (2) printmchar0 } def
+/ferm                  { (3) printmchar0 } def
+/uferm                 { (4) printmchar0 } def
+/sign                  { (5) printmchar0 } def
+/coda                  { (6) printmchar0 } def
+/mor                   { (7) printmchar0 } def
+/invmor                        { (8) printmchar0 } def
+/turn                  { (9) printmchar0 } def
+/invturn               { (0) printmchar0 } def
+/acc_gt                        { (#) printmchar0 } def
+/acc_hat               { ($) printmchar0 } def
+/acc_uhat              { (") printmchar0 } def
+/tr                    { (*) printmchar0 } def
+/leg                   { (,) printmchar0 } def
+/rr                    { (-) printmchar0 } def
+/measrpt               { (.) printmchar0 } def
+/copyright             { (/) printmchar0 } def
+/dim                   { (`) printmchar0 } def
+/halfdim               { (') printmchar0 } def
+/triangle              { (^) printmchar0 } def
+/qwhrest               { (&) printmchar0 } def
+/ll1rest               { (!) printmchar0 } def
+/ll2rest               { (@) printmchar0 } def
+/dwhrighttriangle      { (A) printmchar1 } def
+/righttriangle         { (B) printmchar1 } def
+/fillrighttriangle     { (C) printmchar1 } def
+/udwhrighttriangle     { (D) printmchar1 } def
+/urighttriangle                { (E) printmchar1 } def
+/ufillrighttriangle    { (F) printmchar1 } def
+/dwhrectangle          { (G) printmchar1 } def
+/rectangle             { (H) printmchar1 } def
+/fillrectangle         { (I) printmchar1 } def
+/dwhisostriangle       { (J) printmchar1 } def
+/isostriangle          { (K) printmchar1 } def
+/fillisostriangle      { (L) printmchar1 } def
+/dwhpiewedge           { (M) printmchar1 } def
+/piewedge              { (N) printmchar1 } def
+/fillpiewedge          { (O) printmchar1 } def
+/dwhsemicircle         { (P) printmchar1 } def
+/semicircle            { (Q) printmchar1 } def
+/fillsemicircle                { (R) printmchar1 } def
+/dwhslashhead          { (S) printmchar1 } def
+/slashhead             { (T) printmchar1 } def
+/fillslashhead         { (U) printmchar1 } def
+/blankhead             { (V) printmchar1 } def
+
+
+% Define routines for Mup output other than music characters.
+
+/stepsize 3 def           % define a step size as 3 points (at default magnification)
+
+% x1 y1 x2 lines dist staffscale staff
+%              draw a staff starting at x1, y1 and extending to x2 with "lines"
+%              lines, 2*dist*stepsize apart, scaled by staffscale
+/staff {
+       /staffscale exch def
+       /dist exch def
+       /lines exch def
+       /x2 exch def
+       /y1 exch def
+       /x1 exch def
+       0.7 staffscale mul sb setlinewidth
+       1 lines sub  2  lines 1 sub {   % loop from bottom line to top line
+               dup stepsize mul staffscale mul dist mul y1 add x1 exch moveto
+               stepsize mul staffscale mul dist mul y1 add x2 exch lineto stroke
+       } for
+} def
+
+% x y1 y2 bracket      draw a bracket; y1 is the top
+/bracket {
+       /y2 exch def
+       /y1 exch def
+       /x exch def
+       gsave
+       3 setlinewidth
+       x 2 sub y1 1 add moveto
+       x 2 sub y2 1 sub lineto
+       stroke
+       x 2 sub y1 1 add moveto
+       x 1 sub y1 1 add   x 3 add y1 1 add   x 5 add y1 6 add   curveto
+       x 6 add y1 5 add lineto
+       x 5 add y1 2 add   x 1 add y1 2 sub   x 2 sub y1 2 sub   curveto
+       fill
+       x 2 sub y2 1 sub moveto
+       x 1 sub y2 1 sub   x 3 add y2 1 sub   x 5 add y2 6 sub   curveto
+       x 6 add y2 5 sub lineto
+       x 5 add y2 2 sub   x 1 add y2 2 add   x 2 sub y2 2 add   curveto
+       fill
+       grestore
+} def
+
+% x y1 y2 brace                draw a brace; y1 is the top
+/brace {
+       /y2 exch def
+       /y1 exch def
+       /x exch def
+       gsave
+       x 9 sub y1 y2 add 2 div translate
+       /topy y1 y2 sub 2 div 1 sub def
+       0 1 1 {
+               pop
+               %0 topy moveto 0 0 lineto stroke
+               0 0 moveto
+               16 topy 0.2 mul   -11 topy 0.6 mul   8 topy   curveto
+               8.7 topy lineto
+               -7 topy 0.7 mul   20 topy 0.3 mul   1 0   curveto
+               fill
+               1 -1 scale      % flip to do bottom half
+       } for
+       grestore
+} def
+
+% endx endy wavy staffscale    draw a wavy line from current point to here,
+%                              scaled by staffscale
+/wavy {
+       /staffscale exch def
+       /endy exch def          % define the end point of the line
+       /endx exch def
+       currentpoint            % line starts at current point
+       /begy exch def          % define the beginning point of the line
+       /begx exch def
+       gsave
+       /dx endx begx sub def   % find delta x and delta y
+       /dy endy begy sub def
+       /r dx dx mul dy dy mul add sqrt def     % hypotenuse
+       /theta dy dx atan def                   % angle with positive x axis
+       begx begy translate     % change axes so that we can draw the line
+       theta rotate            %   from (0, 0) to (r, 0)
+       staffscale staffscale scale     % scale everything by staffscale
+       /scaledr r staffscale div def   % but scale r in reverse to keep length
+
+       % Each outer loop draws one cycle of the squiggle.  It continues until
+       % we are at or beyond the desired end point.
+       0 0 moveto
+       0 6 scaledr {
+               gsave
+               % first loop draws left half of squiggle; second draws right
+               0 1 1 {
+                       0.0 0.4 moveto
+                       2.0 1.9 3.4 2.3 3.9 0.0 curveto
+                       2.1 0.0 lineto
+                       1.9 0.8 1.4 0.7 0.0 -0.4 curveto
+                       fill
+                       pop 180 rotate -6 0 translate
+               } for
+               grestore
+
+               pop 6 0 translate       % shift axes right one squiggle
+       } for
+
+       grestore
+} def
+
+% x y space frets fretno numvert curvel curver [ f1 f2 f3 ... ] grid
+%                              print a guitar grid diagram
+/grid {
+       /grid_positions exch def % 0="o", -1="x", -2=nothing, positive=dot
+       /curver exch def        % right string for curve, 0 if none
+       /curvel exch def        % left string for curve, 0 if none
+       /numvert exch def       % vertical position to print fretno, 0 if none
+       /fretno exch def        % fret no. to print at right, 0 if none
+       /frets exch def         % number of fret lines
+       /space exch def         % points between two neighboring lines
+       /y exch def             % y coord of top fret line
+       /x exch def             % x coord of left strings
+
+       gsave
+       /strings grid_positions length def      % number of strings
+       /lmarky 0.4 space mul y add def         % lowest Y of a "o" or "x"
+       space 10 div setlinewidth
+       2 setlinecap
+
+       % draw the lines of the grid
+       0  1  strings 1 sub {   % loop from left string to right string
+               dup space mul x add y moveto
+               space mul x add frets 1 sub space mul y exch sub lineto stroke
+       } for
+       0  -1  1 frets sub {    % loop from top fret (nut) to bottom fret
+               dup space mul y add x exch moveto
+               space mul y add strings 1 sub space mul x add exch lineto stroke
+       } for
+
+       % draw the curved line if there is one
+       curvel 0 gt {
+               % within strings curvel to curver, find smallest positive fret
+               /minfret 1000 def
+               curvel 1 curver {
+                       /strno exch def
+                       /grid_p grid_positions strno 1 sub get def
+                       grid_p 0 gt grid_p minfret lt and {
+                               /minfret grid_p def
+                       } if
+               } for
+
+               % if curve goes above top fret, other marks must be higher
+               minfret 1 eq {
+                       /hmarky 1.2 space mul y add def
+               } {
+                       /hmarky lmarky def
+               } ifelse
+
+               /strdiff curver curvel sub def
+               space 8 div setlinewidth
+
+               % set endpoint coords of curve; higher if curve is short
+               /curvex1 curvel 1 sub space mul x add def
+               /curvex2 curver 1 sub space mul x add def
+               /curvey 1 minfret sub space mul y add def
+               strdiff 3 lt {
+                       /curvey 0.2 strdiff div space mul curvey add def
+               } if
+
+               % move to left end, set other points, draw curve
+               curvex1 curvey moveto
+
+               curvex1 curvex2 curvex1 sub 3 div add
+               curvey space 0.4 strdiff sqrt mul mul add
+
+               curvex2 curvex2 curvex1 sub 3 div sub
+               curvey space 0.4 strdiff sqrt mul mul add
+
+               curvex2 curvey curveto stroke
+       } if
+
+       space 10 div setlinewidth
+
+       % draw dots and x and o marks
+       0  1  strings 1 sub {   % loop from left string to right string
+               /strno exch def % first string is 0
+               /grid_p grid_positions strno get def
+               /strx strno space mul x add def
+
+               % set Y of mark higher if curved line covers this string
+               strno 1 add curvel ge  strno 1 add curver le  and {
+                       /marky hmarky def
+               } {
+                       /marky lmarky def
+               } ifelse
+
+               grid_p -1 eq {          % draw an X above the string
+                       /xhwid space 3 div def
+                       strx xhwid sub marky xhwid sub moveto
+                       strx xhwid add marky xhwid add lineto stroke
+                       strx xhwid sub marky xhwid add moveto
+                       strx xhwid add marky xhwid sub lineto stroke
+               } if
+               grid_p 0 eq {           % draw a circle above the string
+                       strx marky space 0.3 mul 0 360 arc stroke
+               } if
+               grid_p 1 ge {           % draw a dot by the proper fret
+                       strx y grid_p space mul sub space 3 div add
+                       space 3 div 0 360 arc fill
+               } if
+       } for
+
+       % print "X fr" if requested
+       fretno 0 gt {
+               /Palatino-Roman findfont space 1.9 mul scalefont setfont
+               x strings 0.5 sub space mul add
+               y space numvert 0.3 add mul sub moveto
+               fretno 2 string cvs show ( fr) show
+       } if
+       grestore
+} def
+
+% x1 y1 x2 y2 whitebox         draw a white rectangle with opposite
+%                              corners of (x1,y1) and (x2,y2)
+/whitebox {
+       /y2 exch def
+       /x2 exch def
+       /y1 exch def
+       /x1 exch def
+       1.0 setgray
+       newpath
+       x1 y1 moveto
+       x1 y2 lineto
+       x2 y2 lineto
+       x2 y1 lineto
+       closepath
+       fill
+       stroke
+       0.0 setgray
+} def
+
+
+/LineNum 0 def
+/InputFile (unknown) def
+
+% n linenum
+/linenum {
+       /LineNum exch def
+} def
+
+% (inputfilename) inputfile
+/inputfile {
+       /InputFile exch def
+} def
+
+% find size of Encoding and make a dictionary
+% that size for bounding box information
+mfont0 begin
+/dictsize Encoding length def
+mfont0 /Mcbbox0 dictsize dict put
+
+% temporarily redefine printmchar0 to get code
+5 dict begin
+/printmchar0 { {} forall } def
+
+Mcbbox0 Encoding 128rest get [ 1140.0 0 -515.0 -1515.0 615.0 1685.0 ] put
+Mcbbox0 Encoding 16rest get [ 830.0 0 -415.0 -1215.0 405.0 485.0 ] put
+Mcbbox0 Encoding 1n get [ 1080.0 0 -535.0 -335.0 535.0 345.0 ] put
+Mcbbox0 Encoding 1rest get [ 1540.0 0 -765.0 -5.0 765.0 645.0 ] put
+Mcbbox0 Encoding 256rest get [ 1250.0 0 -625.0 -2115.0 615.0 1685.0 ] put
+Mcbbox0 Encoding 2n get [ 880.0 0 -435.0 -345.0 435.0 355.0 ] put
+Mcbbox0 Encoding 2rest get [ 1540.0 0 -765.0 -45.0 765.0 315.0 ] put
+Mcbbox0 Encoding 32rest get [ 940.0 0 -415.0 -1215.0 515.0 1085.0 ] put
+Mcbbox0 Encoding 4n get [ 840.0 0 -415.0 -335.0 415.0 345.0 ] put
+Mcbbox0 Encoding 4rest get [ 650.0 0 -345.0 -885.0 295.0 985.0 ] put
+Mcbbox0 Encoding 64rest get [ 1040.0 0 -515.0 -1515.0 515.0 1085.0 ] put
+Mcbbox0 Encoding 8rest get [ 750.0 0 -305.0 -615.0 435.0 485.0 ] put
+Mcbbox0 Encoding acc_gt get [ 1170.0 0 -525.0 -335.0 635.0 345.0 ] put
+Mcbbox0 Encoding acc_hat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put
+Mcbbox0 Encoding acc_uhat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put
+Mcbbox0 Encoding begped get [ 470.0 0 -245.0 -45.0 215.0 615.0 ] put
+Mcbbox0 Encoding cclef get [ 1540.0 0 -765.0 -1245.0 765.0 1255.0 ] put
+Mcbbox0 Encoding coda get [ 1640.0 0 -815.0 -855.0 815.0 865.0 ] put
+Mcbbox0 Encoding com get [ 1100.0 0 -575.0 -635.0 515.0 655.0 ] put
+Mcbbox0 Encoding copyright get [ 920.0 0 -455.0 -45.0 455.0 855.0 ] put
+Mcbbox0 Encoding cut get [ 1100.0 0 -575.0 -905.0 515.0 915.0 ] put
+Mcbbox0 Encoding dblflat get [ 1170.0 0 -595.0 -405.0 565.0 1115.0 ] put
+Mcbbox0 Encoding dblsharp get [ 720.0 0 -355.0 -345.0 355.0 355.0 ] put
+Mcbbox0 Encoding dblwhole get [ 1090.0 0 -535.0 -605.0 545.0 615.0 ] put
+Mcbbox0 Encoding diamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put
+Mcbbox0 Encoding dim get [ 540.0 0 -265.0 -5.0 265.0 905.0 ] put
+Mcbbox0 Encoding dn128n get [ 840.0 0 -415.0 -3545.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn16n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn256n get [ 840.0 0 -415.0 -3965.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn2n get [ 880.0 0 -435.0 -2105.0 435.0 355.0 ] put
+Mcbbox0 Encoding dn32n get [ 840.0 0 -415.0 -2585.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn4n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn64n get [ 840.0 0 -415.0 -3065.0 415.0 345.0 ] put
+Mcbbox0 Encoding dn8n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put
+Mcbbox0 Encoding dnbow get [ 810.0 0 -395.0 -5.0 405.0 915.0 ] put
+Mcbbox0 Encoding dnflag get [ 640.0 0 -335.0 -1705.0 295.0 15.0 ] put
+Mcbbox0 Encoding dot get [ 280.0 0 -135.0 -125.0 135.0 135.0 ] put
+Mcbbox0 Encoding dwhdiamond get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox0 Encoding dwhrest get [ 340.0 0 -165.0 -5.0 165.0 615.0 ] put
+Mcbbox0 Encoding endped get [ 480.0 0 -215.0 -45.0 255.0 615.0 ] put
+Mcbbox0 Encoding fclef get [ 1840.0 0 -1015.0 -1705.0 815.0 655.0 ] put
+Mcbbox0 Encoding ferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put
+Mcbbox0 Encoding filldiamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put
+Mcbbox0 Encoding flat get [ 580.0 0 -295.0 -405.0 275.0 1115.0 ] put
+Mcbbox0 Encoding gclef get [ 1790.0 0 -915.0 -1605.0 865.0 3015.0 ] put
+Mcbbox0 Encoding halfdim get [ 760.0 0 -375.0 -5.0 375.0 1015.0 ] put
+Mcbbox0 Encoding invmor get [ 1320.0 0 -655.0 -455.0 655.0 465.0 ] put
+Mcbbox0 Encoding invturn get [ 1300.0 0 -645.0 -335.0 645.0 345.0 ] put
+Mcbbox0 Encoding leg get [ 840.0 0 -415.0 -55.0 415.0 65.0 ] put
+Mcbbox0 Encoding ll1rest get [ 840.0 0 -415.0 -5.0 415.0 625.0 ] put
+Mcbbox0 Encoding ll2rest get [ 840.0 0 -415.0 -15.0 415.0 315.0 ] put
+Mcbbox0 Encoding measrpt get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put
+Mcbbox0 Encoding mor get [ 1320.0 0 -655.0 -285.0 655.0 295.0 ] put
+Mcbbox0 Encoding nat get [ 520.0 0 -255.0 -855.0 255.0 865.0 ] put
+Mcbbox0 Encoding pedal get [ 1040.0 0 -515.0 -45.0 515.0 675.0 ] put
+Mcbbox0 Encoding qwhrest get [ 340.0 0 -165.0 -605.0 165.0 615.0 ] put
+Mcbbox0 Encoding rr get [ 940.0 0 -465.0 -25.0 465.0 1035.0 ] put
+Mcbbox0 Encoding sharp get [ 700.0 0 -345.0 -935.0 345.0 945.0 ] put
+Mcbbox0 Encoding sign get [ 1340.0 0 -665.0 -825.0 665.0 835.0 ] put
+Mcbbox0 Encoding tr get [ 1440.0 0 -715.0 -5.0 715.0 1015.0 ] put
+Mcbbox0 Encoding triangle get [ 800.0 0 -395.0 -45.0 395.0 785.0 ] put
+Mcbbox0 Encoding turn get [ 1300.0 0 -645.0 -325.0 645.0 345.0 ] put
+Mcbbox0 Encoding uferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put
+Mcbbox0 Encoding up128n get [ 1390.0 0 -745.0 -335.0 635.0 3555.0 ] put
+Mcbbox0 Encoding up16n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put
+Mcbbox0 Encoding up256n get [ 1390.0 0 -745.0 -335.0 635.0 3975.0 ] put
+Mcbbox0 Encoding up2n get [ 880.0 0 -435.0 -345.0 435.0 2115.0 ] put
+Mcbbox0 Encoding up32n get [ 1390.0 0 -745.0 -335.0 635.0 2595.0 ] put
+Mcbbox0 Encoding up4n get [ 850.0 0 -415.0 -335.0 425.0 2115.0 ] put
+Mcbbox0 Encoding up64n get [ 1390.0 0 -745.0 -335.0 635.0 3075.0 ] put
+Mcbbox0 Encoding up8n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put
+Mcbbox0 Encoding upbow get [ 720.0 0 -355.0 -115.0 355.0 925.0 ] put
+Mcbbox0 Encoding upflag get [ 640.0 0 -335.0 -5.0 295.0 1715.0 ] put
+Mcbbox0 Encoding uwedge get [ 340.0 0 -165.0 -5.0 165.0 505.0 ] put
+Mcbbox0 Encoding wedge get [ 340.0 0 -165.0 5.0 165.0 515.0 ] put
+Mcbbox0 Encoding xnote get [ 880.0 0 -435.0 -365.0 435.0 375.0 ] put
+
+end
+end
+
+/Mfont0 mfont0 definefont
+
+
+% find size of Encoding and make a dictionary
+% that size for bounding box information
+mfont1 begin
+/dictsize Encoding length def
+mfont1 /Mcbbox1 dictsize dict put
+
+% temporarily redefine printmchar1 to get code
+5 dict begin
+/printmchar1 { {} forall } def
+
+Mcbbox1 Encoding blankhead get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put
+Mcbbox1 Encoding dwhisostriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhpiewedge get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhrectangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhsemicircle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding dwhslashhead get [ 1410.0 0 -695.0 -725.0 705.0 735.0 ] put
+Mcbbox1 Encoding fillisostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+Mcbbox1 Encoding fillpiewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillrectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillrighttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillsemicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding fillslashhead get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put
+Mcbbox1 Encoding isostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+Mcbbox1 Encoding piewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding rectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put
+Mcbbox1 Encoding righttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding semicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put
+Mcbbox1 Encoding slashhead get [ 1380.0 0 -685.0 -725.0 685.0 735.0 ] put
+Mcbbox1 Encoding udwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put
+Mcbbox1 Encoding ufillrighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+Mcbbox1 Encoding urighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put
+
+end
+end
+
+/Mfont1 mfont1 definefont
+
+/makeExtEncoding {
+       /extendedencoding 256 array def
+       StandardEncoding extendedencoding copy
+       extendedencoding 32 /exclamdown put
+       extendedencoding 33 /cent put
+       extendedencoding 34 /sterling put
+       extendedencoding 35 /yen put
+       extendedencoding 36 /quotedblleft put
+       extendedencoding 37 /guillemotleft put
+       extendedencoding 38 /guillemotright put
+       extendedencoding 39 /guilsinglleft put
+       extendedencoding 40 /guilsinglright put
+       extendedencoding 41 /dagger put
+       extendedencoding 42 /daggerdbl put
+       extendedencoding 43 /bullet put
+       extendedencoding 44 /quotedblbase put
+       extendedencoding 45 /quotedblright put
+       extendedencoding 46 /questiondown put
+       extendedencoding 47 /grave put
+       extendedencoding 48 /acute put
+       extendedencoding 49 /macron put
+       extendedencoding 50 /breve put
+       extendedencoding 51 /dotaccent put
+       extendedencoding 52 /dieresis put
+       extendedencoding 53 /ring put
+       extendedencoding 54 /cedilla put
+       extendedencoding 55 /hungarumlaut put
+       extendedencoding 56 /ogonek put
+       extendedencoding 57 /caron put
+       extendedencoding 58 /emdash put
+       extendedencoding 59 /AE put
+       extendedencoding 60 /ae put
+       extendedencoding 61 /ordfeminine put
+       extendedencoding 62 /ordmasculine put
+       extendedencoding 63 /Lslash put
+       extendedencoding 64 /lslash put
+       extendedencoding 65 /Oslash put
+       extendedencoding 66 /oslash put
+       extendedencoding 67 /OE put
+       extendedencoding 68 /oe put
+       extendedencoding 69 /dotlessi put
+       extendedencoding 70 /germandbls put
+       extendedencoding 71 /Aacute put
+       extendedencoding 72 /aacute put
+       extendedencoding 73 /Acircumflex put
+       extendedencoding 74 /acircumflex put
+       extendedencoding 75 /Adieresis put
+       extendedencoding 76 /adieresis put
+       extendedencoding 77 /Agrave put
+       extendedencoding 78 /agrave put
+       extendedencoding 79 /Aring put
+       extendedencoding 80 /aring put
+       extendedencoding 81 /Atilde put
+       extendedencoding 82 /atilde put
+       extendedencoding 83 /Ccedilla put
+       extendedencoding 84 /ccedilla put
+       extendedencoding 85 /Eacute put
+       extendedencoding 86 /eacute put
+       extendedencoding 87 /Ecircumflex put
+       extendedencoding 88 /ecircumflex put
+       extendedencoding 89 /Edieresis put
+       extendedencoding 90 /edieresis put
+       extendedencoding 91 /Egrave put
+       extendedencoding 92 /egrave put
+       extendedencoding 93 /Iacute put
+       extendedencoding 94 /iacute put
+       extendedencoding 95 /Icircumflex put
+       extendedencoding 96 /icircumflex put
+       extendedencoding 97 /Idieresis put
+       extendedencoding 98 /idieresis put
+       extendedencoding 99 /Igrave put
+       extendedencoding 100 /igrave put
+       extendedencoding 101 /Ntilde put
+       extendedencoding 102 /ntilde put
+       extendedencoding 103 /Oacute put
+       extendedencoding 104 /oacute put
+       extendedencoding 105 /Ocircumflex put
+       extendedencoding 106 /ocircumflex put
+       extendedencoding 107 /Odieresis put
+       extendedencoding 108 /odieresis put
+       extendedencoding 109 /Ograve put
+       extendedencoding 110 /ograve put
+       extendedencoding 111 /Otilde put
+       extendedencoding 112 /otilde put
+       extendedencoding 113 /Scaron put
+       extendedencoding 114 /scaron put
+       extendedencoding 115 /Uacute put
+       extendedencoding 116 /uacute put
+       extendedencoding 117 /Ucircumflex put
+       extendedencoding 118 /ucircumflex put
+       extendedencoding 119 /Udieresis put
+       extendedencoding 120 /udieresis put
+       extendedencoding 121 /Ugrave put
+       extendedencoding 122 /ugrave put
+       extendedencoding 123 /Ydieresis put
+       extendedencoding 124 /ydieresis put
+       extendedencoding 125 /Zcaron put
+       extendedencoding 126 /zcaron put
+       extendedencoding 127 /space put
+} def
+
+/makeExtendedFont {
+       findfont
+       dup length dict /newdict exch def
+       { 1 index /FID ne
+               { newdict 3 1 roll put }
+               { pop pop }
+               ifelse
+       } forall
+       newdict /Encoding extendedencoding put
+       newdict /UniqueID newdict /UniqueID get 1 add put
+       newdict definefont pop
+} def
+/flagsep 1.60 300 mul def       % 1.60 stepsizes
+/scv 149508 def /sf 962 string def
+/fa {/p 0 def /chr exch -3 bitshift 127 and def {sf exch p add dup /p exch def chr put} forall} def
+[ 74 62 70 54 29 55 36 37 19 26 45 40 41 50 45 52 19 73 11 68 ] 1567304784 fa
+[ 961 ] 1341740116 fa
+[ 12 4 5 4 4 2 4 3 3 7 7 3 5 5 4 5 4 2 5 3 ] 1969419526 fa
+[ 96 4 4 3 2 4 11 2 6 23 13 16 8 3 28 13 8 3 6 11 ] 387152134 fa
+[ 268 4 13 12 5 4 4 5 4 5 3 2 4 3 4 8 3 3 9 2 ] 305899779 fa
+[ 369 3 4 9 3 3 9 2 4 3 4 7 4 4 4 9 5 3 5 4 ] 477458695 fa
+[ 498 4 36 4 37 4 42 4 4 37 4 4 35 4 4 5 13 3 4 4 ] 1130513667 fa
+[ 759 3 5 33 4 5 9 29 5 4 3 5 4 4 5 4 4 5 4 3 ] 1205319942 fa
+[ 902 8 4 2 3 4 3 4 4 3 2 3 9 ] 1708988675 fa
+[ 468 6 4 10 3 30 5 3 24 40 4 3 3 3 3 8 23 1 1 1 ] 123455756 fa
+[ 664 23 4 2 13 66 4 5 9 ] 2061720845 fa
+[ 795 ] 1622189328 fa
+[ 463 45 40 41 50 45 84 ] 304180545 fa
+[ 494 40 41 49 45 43 84 ] 251711819 fa
+[ 149 203 37 144 ] 358262127 fa
+[ 456 142 52 ] 95949173 fa
+[ 0 13 13 10 65 36 6 26 38 17 13 53 4 13 13 25 36 183 7 140 ] 1751712121 fa
+[ 839 5 13 12 13 13 48 ] 1943250302 fa
+[ 30 164 254 7 42 4 36 4 18 1 18 4 46 3 1 41 4 39 4 41 ] 499619205 fa
+[ 798 1 3 1 ] 1277775234 fa
+[ 76 32 135 79 99 8 246 43 30 160 ] 734015880 fa
+[ 265 70 36 12 25 87 4 36 4 37 4 46 4 41 43 83 4 83 41 3 ] 1546658194 fa
+[ 193 49 180 8 17 134 ] 831070621 fa
+[ 353 366 ] 1033403809 fa
+[ 266 1 190 39 40 41 50 45 43 45 ] 1758436783 fa
+[ 423 8 109 ] 508918194 fa
+[ 328 6 30 6 31 6 269 ] 212071871 fa
+[ 390 357 2 ] 1671244225 fa
+[ 500 ] 347047368 fa
+[ 558 ] 1276946910 fa
+[ 651 ] 2109048312 fa
+[ 644 ] 1914352160 fa
+[ 520 ] 471204394 fa
+[ 512 5 2 ] 1930983991 fa
+[ 665 ] 154021439 fa
+[ 513 ] 777103941 fa
+[ 514 ] 260959830 fa
+[ 530 239 ] 1284535922 fa
+[ 510 ] 1982423675 fa
+[ 150 ] 1969948305 fa
+[ 511 7 134 ] 1407991454 fa
+[ 144 371 ] 1896661664 fa
+[ 464 52 ] 1444653737 fa
+[ 509 81 ] 1712172720 fa
+[ 110 11 32 24 22 18 40 12 54 7 17 19 18 19 22 13 377 94 9 11 ] 889612 fa
+[ 954 ] 1802916616 fa
+[ 80 146 51 78 37 84 8 8 73 5 44 45 33 9 73 9 130 9 11 12 ] 1808121621 fa
+[ 19 42 3 22 8 82 63 23 25 13 8 5 176 248 40 73 12 13 13 12 ] 1752602397 fa
+[ 22 10 37 42 1 2 19 26 6 38 17 13 38 11 21 13 16 9 27 9 ] 1598682919 fa
+[ 405 9 13 46 49 50 50 213 18 12 13 13 12 45 10 ] 160257827 fa
+[ 1 8 8 6 10 10 16 11 14 8 23 19 13 19 13 7 15 3 9 8 ] 882894639 fa
+[ 234 40 9 15 6 7 6 25 36 37 19 6 47 16 40 41 50 45 43 6 ] 185215791 fa
+[ 733 19 37 16 12 13 3 3 12 6 6 6 7 6 7 6 6 6 45 10 ] 1706915629 fa
+[ 24 10 37 45 2 17 5 1 15 4 7 5 8 8 17 17 13 11 8 26 ] 1713964852 fa
+[ 284 21 13 25 18 18 19 18 28 1 7 28 2 4 106 24 3 2 32 36 ] 1218620208 fa
+[ 695 62 1 7 13 1 7 2 37 4 8 5 13 12 13 13 12 45 5 1 ] 1317868340 fa
+[ 960 ] 75399990 fa
+[ 45 9 155 6 245 68 21 98 60 109 ] 1430691640 fa
+[ 20 27 15 25 8 33 173 13 45 37 83 170 5 34 8 115 40 12 13 13 ] 841629509 fa
+[ 901 ] 422446918 fa
+[ 27 25 37 13 3 40 12 73 49 77 4 33 4 68 89 219 21 27 3 4 ] 560155470 fa
+[ 466 6 135 41 7 6 36 6 89 ] 803193686 fa
+[ 42 80 1 55 80 1 80 36 37 155 1 263 40 65 ] 189315943 fa
+[ 6 31 36 9 43 21 6 185 36 37 210 ] 1031359337 fa
+[ 44 9 101 4 4 20 8 80 3 23 30 5 19 17 20 17 15 7 7 36 ] 586694517 fa
+[ 552 22 20 16 3 55 42 31 10 33 ] 343336822 fa
+[ 7 4 54 54 10 22 10 20 8 8 53 5 226 12 115 38 17 42 26 13 ] 1808462718 fa
+[ 780 32 ] 847653755 fa
+[ 3 63 31 408 18 4 18 6 22 13 15 3 32 9 17 4 15 5 18 4 ] 1627872128 fa
+[ 724 83 7 ] 1643402114 fa
+[ 228 296 8 25 39 16 159 14 34 ] 670118796 fa
+[ 2 2 47 69 19 34 23 20 35 5 187 10 51 2 38 2 39 2 48 2 ] 888380310 fa
+[ 680 2 41 2 2 5 13 11 10 40 2 50 80 ] 1392580498 fa
+[ 14 25 10 7 22 49 21 22 1 4 10 23 4 13 15 5 16 15 12 3 ] 2114772893 fa
+[ 295 30 24 9 28 9 23 19 13 1 8 24 67 16 3 30 3 3 53 9 ] 453068702 fa
+[ 694 6 9 20 11 23 1 23 23 22 8 5 1 24 41 9 11 4 5 1 ] 1393470366 fa
+[ 944 8 ] 1770206109 fa
+[ 10 5 25 6 4 7 42 39 25 20 4 4 7 2 14 17 126 5 32 5 ] 113705892 fa
+[ 442 25 4 6 114 27 38 42 32 25 20 47 19 112 ] 998588323 fa
+[ 79 19 131 109 36 37 74 70 1 59 8 34 3 25 5 9 3 80 11 27 ] 1221405612 fa
+[ 912 9 11 ] 273962927 fa
+[ 8 230 25 23 6 17 130 31 61 64 16 127 32 ] 1881483187 fa
+[ 130 683 ] 1406620603 fa
+[ 18 10 32 25 5 3 10 3 143 50 13 9 61 93 86 1 1 180 48 58 ] 1980878788 fa
+[ 861 13 9 4 12 8 17 3 ] 1447963591 fa
+[ 67 143 8 128 115 435 19 2 ] 477757388 fa
+[ 490 35 ] 1151262673 fa
+[ 5 70 67 32 37 16 14 7 27 18 142 301 17 90 103 ] 1523362782 fa
+[ 117 14 33 38 17 13 20 26 3 453 89 3 8 113 10 ] 1908448236 fa
+sf cvx exec
+%%BeginResource: procset grops 1.17 2
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/MANUAL{
+statusdict begin/manualfeed true store end
+}bind def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-BoldItalic
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Courier
+%%IncludeResource: font Times-Italic
+%%IncludeResource: font AvantGarde-Book
+%%IncludeResource: font AvantGarde-Demi
+%%IncludeResource: font AvantGarde-BookOblique
+%%IncludeResource: font AvantGarde-DemiOblique
+%%IncludeResource: font Bookman-Light
+%%IncludeResource: font Bookman-Demi
+%%IncludeResource: font Bookman-LightItalic
+%%IncludeResource: font Bookman-DemiItalic
+%%IncludeResource: font Courier-Bold
+%%IncludeResource: font Courier-Oblique
+%%IncludeResource: font Courier-BoldOblique
+%%IncludeResource: font Helvetica
+%%IncludeResource: font Helvetica-Bold
+%%IncludeResource: font Helvetica-Oblique
+%%IncludeResource: font Helvetica-BoldOblique
+%%IncludeResource: font NewCenturySchlbk-Roman
+%%IncludeResource: font NewCenturySchlbk-Bold
+%%IncludeResource: font NewCenturySchlbk-Italic
+%%IncludeResource: font NewCenturySchlbk-BoldItalic
+%%IncludeResource: font Palatino-Roman
+%%IncludeResource: font Palatino-Bold
+%%IncludeResource: font Palatino-Italic
+%%IncludeResource: font Palatino-BoldItalic
+grops begin/DEFS 52 dict def DEFS begin/u{.001 mul}bind def end/RES 72
+def/PL PLG def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
+/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
+/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
+/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
+/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
+/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
+/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
+/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
+/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
+/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
+/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
+/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
+/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
+/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
+/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
+/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
+/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
+/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
+/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
+/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
+/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
+/Palatino-BoldItalic@0 ENC0/Palatino-BoldItalic RE/Palatino-Italic@0
+ENC0/Palatino-Italic RE/Palatino-Bold@0 ENC0/Palatino-Bold RE
+/Palatino-Roman@0 ENC0/Palatino-Roman RE/NewCenturySchlbk-BoldItalic@0
+ENC0/NewCenturySchlbk-BoldItalic RE/NewCenturySchlbk-Italic@0 ENC0
+/NewCenturySchlbk-Italic RE/NewCenturySchlbk-Bold@0 ENC0
+/NewCenturySchlbk-Bold RE/NewCenturySchlbk-Roman@0 ENC0
+/NewCenturySchlbk-Roman RE/Helvetica-BoldOblique@0 ENC0
+/Helvetica-BoldOblique RE/Helvetica-Oblique@0 ENC0/Helvetica-Oblique RE
+/Helvetica-Bold@0 ENC0/Helvetica-Bold RE/Helvetica@0 ENC0/Helvetica RE
+/Courier-BoldOblique@0 ENC0/Courier-BoldOblique RE/Courier-Oblique@0
+ENC0/Courier-Oblique RE/Courier-Bold@0 ENC0/Courier-Bold RE
+/Bookman-DemiItalic@0 ENC0/Bookman-DemiItalic RE/Bookman-LightItalic@0
+ENC0/Bookman-LightItalic RE/Bookman-Demi@0 ENC0/Bookman-Demi RE
+/Bookman-Light@0 ENC0/Bookman-Light RE/AvantGarde-DemiOblique@0 ENC0
+/AvantGarde-DemiOblique RE/AvantGarde-BookOblique@0 ENC0
+/AvantGarde-BookOblique RE/AvantGarde-Demi@0 ENC0/AvantGarde-Demi RE
+/AvantGarde-Book@0 ENC0/AvantGarde-Book RE/Times-Italic@0 ENC0
+/Times-Italic RE/Courier@0 ENC0/Courier RE/Times-Bold@0 ENC0/Times-Bold
+RE/Times-Roman@0 ENC0/Times-Roman RE/Times-BoldItalic@0 ENC0
+/Times-BoldItalic RE
+%%EndProlog
+%%Page: T-1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+69.336 164 EBEGIN
+0 0.15 0.65 setrgbcolor
+EEND/F0 24/Times-BoldItalic@0 SF 6(Mup)273.996 196 S -2 4
+(Music Publisher)194.652 228 T -2 4(User's Guide)217.344 260 T 69.336
+364 EBEGIN
+0 0 0 setrgbcolor
+EEND 232 702 176 176 -61 61 221.336 440.6 PBEGIN
+%%BeginDocument: mugex1.ps
+%%BoundingBox: 232 702 408 763
+save
+1445575900 1445576686 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+684.29 1163.00 900.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+264.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+292.78 719.00 1.000000 4n
+0.70 setlinewidth
+296.46 719.75 moveto
+296.46 740.00 lineto stroke
+320.08 716.00 1.000000 4n
+323.76 716.75 moveto
+323.76 737.00 lineto stroke
+351.62 713.00 1.000000 2n
+345.17 713.00 moveto
+358.07 713.00 lineto stroke
+355.52 713.75 moveto
+355.52 734.00 lineto stroke
+restore
+%  S_BAR
+5 linenum
+0.70 setlinewidth
+395.65 743.00 moveto
+395.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 638.6 EBEGIN
+0 0.15 0.65 setrgbcolor
+EEND/F0 14/Times-Roman@0 SF(Mup V)256.478 670.6 Q(ersion 5.3)-1.554 E
+69.336 694.6 EBEGIN
+0 0 0 setrgbcolor
+EEND EP
+%%Page: T-2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF(Mup Music Publisher User')69.336 420 Q 2.5(sG)
+-.55 G(uide \212 Mup V)-2.5 E(ersion 5.3)-1.11 E 5.208<a943>69.336 438 S
+(op)-5.208 E 2.708(yright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 200\
+2, 2003, 2004, 2005, 2006 by Arkkra)-.1 F(Enterprises)69.336 450 Q
+(All rights reserv)69.336 468 Q(ed.)-.15 E -.35(Tr)69.336 492 S .721
+(ademarks: All brand names and product names included in this User').35
+F 3.221(sG)-.55 G .721(uide are trademarks, re)-3.221 F(gistered)-.15 E
+(trademarks, or trade names of their respecti)69.336 504 Q .3 -.15(ve h)
+-.25 H(olders.).15 E 69.336 528 EBEGIN
+%-marker1-
+EEND EP
+%%Page: i 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF(CONTENTS)259.226 96 Q(1.)69.336 144 Q(INTR)
+86.836 144 Q(ODUCTION)-.4 E 7.5(.......................................\
+.......................................................................\
+............... 1)173.836 144 R(2.)69.336 162 Q(MUP B)86.836 162 Q
+(ASICS)-.35 E 7.5(.....................................................\
+.......................................................................\
+........ 2)156.336 162 R(2.1)86.836 174 Q(Notes and chords)114.336 174 Q
+7.5(...................................................................\
+.................................................. 2)193.836 174 R(2.2)
+86.836 186 Q -.15(Pa)114.336 186 S(rameters).15 E 7.5(.................\
+.......................................................................\
+....................................... 3)168.836 186 R(2.3)86.836 198 Q
+-.15(Pa)114.336 198 S(ge headers and footers).15 E 7.5(................\
+.......................................................................\
+................. 5)226.336 198 R(2.4)86.836 210 Q -.55(Ly)114.336 210 S
+(rics).55 E 7.5(.......................................................\
+.......................................................................\
+........ 5)151.336 210 R(2.5)86.836 222 Q(Miscellaneous)114.336 222 Q
+7.5(...................................................................\
+...................................................... 5)183.836 222 R
+(2.6)86.836 234 Q(Displaying, printing, and playing music)114.336 234 Q
+7.5(...................................................................\
+.............. 6)283.836 234 R(3.)69.336 252 Q -.4(RU)86.836 252 S
+(NNING MUP).4 E 7.5(...................................................\
+.......................................................................\
+..... 7)168.836 252 R(3.1)86.836 264 Q(Mupmate)114.336 264 Q 7.5(......\
+.......................................................................\
+.................................................... 7)163.836 264 R
+(3.2)86.836 276 Q(Mup Options)114.336 276 Q 7.5(.......................\
+.......................................................................\
+............................. 7)178.836 276 R(3.3)86.836 288 Q
+(Mupdisp and Mupprnt utility programs)114.336 288 Q 7.5(...............\
+................................................................. 11)
+281.336 288 R(4.)69.336 306 Q(MUP FILE STR)86.836 306 Q(UCTURE)-.4 E 7.5
+(......................................................................\
+......................................... 13)203.836 306 R(4.1)86.836
+318 Q(Mup General Syntax)114.336 318 Q 7.5(............................\
+.......................................................................\
+.......... 13)208.836 318 R(4.2)86.836 330 Q(Conte)114.336 330 Q(xts)
+-.15 E 7.5(............................................................\
+.................................................................... 14)
+161.336 330 R(5.)69.336 348 Q -.35(BA)86.836 348 S(SIC ST).35 E(AND)-.93
+E(ARD MUSIC NO)-.4 E -.93(TA)-.4 G(TION)-.18 E 7.5(....................\
+................................................................. 15)
+268.836 348 R(5.1)86.836 360 Q(Specifying chords)114.336 360 Q 7.5(....\
+.......................................................................\
+...................................... 15)198.836 360 R(5.1.1)114.336
+372 Q(Staf)144.336 372 Q 2.5(fa)-.25 G(nd v)-2.5 E(oice)-.2 E 7.5(.....\
+.......................................................................\
+.............................. 15)216.336 372 R(5.1.2)114.336 384 Q
+(Chord duration information)144.336 384 Q 7.5(.........................\
+............................................................. 15)266.336
+384 R(5.1.3)114.336 396 Q(Notes, rests, or spaces)144.336 396 Q 7.5(...\
+.......................................................................\
+..................... 16)243.836 396 R(5.1.3.1)144.336 408 Q
+(Measure duration)181.836 408 Q(17)7.5 E(5.1.3.2)144.336 420 Q 5
+(Accidentals 17)181.836 420 R(5.1.3.3)144.336 432 Q(Octa)181.836 432 Q
+5.3 -.15(ve 1)-.2 H(7).15 E(5.1.4)114.336 444 Q(Shorthand notations)
+144.336 444 Q 7.5(.....................................................\
+............................................. 18)236.336 444 R(5.1.5)
+114.336 456 Q(Note attrib)144.336 456 Q(utes)-.2 E 7.5(................\
+.......................................................................\
+.................... 19)213.836 456 R(5.1.5.1)144.336 468 Q
+(Small note head)181.836 468 Q(19)7.5 E(5.1.5.2)144.336 480 Q(Note tie)
+181.836 480 Q(19)7.5 E(5.1.5.3)144.336 492 Q 5(Slurs 20)181.836 492 R
+(5.1.5.4)144.336 504 Q(Head shape)181.836 504 Q(20)7.5 E(5.1.5.5)144.336
+516 Q(Note location tag)181.836 516 Q(21)7.5 E(5.1.6)114.336 528 Q
+(Chord attrib)144.336 528 Q(utes)-.2 E 7.5(............................\
+.......................................................................\
+..... 21)221.336 528 R(5.1.6.1)144.336 540 Q(Chord style)181.836 540 Q
+(21)7.5 E(5.1.6.2)144.336 552 Q(Head shape)181.836 552 Q(22)7.5 E
+(5.1.6.3)144.336 564 Q(Symbols to be printed with a chord)181.836 564 Q
+(22)7.5 E(5.1.6.4)144.336 576 Q 5(Slashes 22)181.836 576 R(5.1.6.5)
+144.336 588 Q(Stem direction)181.836 588 Q(22)7.5 E(5.1.6.6)144.336 600
+Q(Stem len)181.836 600 Q(23)7.5 E(5.1.6.7)144.336 612 Q -.15(Pa)181.836
+612 S 5(dding 23).15 F(5.1.6.8)144.336 624 Q(Chord location tag)181.836
+624 Q(23)7.5 E(5.1.6.9)144.336 636 Q(Horizontal of)181.836 636 Q 5
+(fset 23)-.25 F(5.1.6.10)144.336 648 Q(Rest distance)181.836 648 Q(24)
+7.5 E(5.1.6.11)144.336 660 Q(Repeated attrib)181.836 660 Q 5(utes 24)-.2
+F(5.1.7)114.336 672 Q(Mid-measure parameter changes)144.336 672 Q 7.5(.\
+.......................................................................\
+...... 25)286.336 672 R(5.1.8)114.336 684 Q(Cross-staf)144.336 684 Q 2.5
+(fs)-.25 G(tems)-2.5 E 7.5(............................................\
+........................................................... 25)223.836
+684 R(5.1.9)114.336 696 Q(Inter)144.336 696 Q(-chord attrib)-.2 E(utes)
+-.2 E 7.5(.............................................................\
+.................................... 26)238.836 696 R(5.1.9.1)144.336
+708 Q(Chord ties)181.836 708 Q(26)7.5 E(5.1.9.2)144.336 720 Q
+(Chord slurs)181.836 720 Q(27)7.5 E(i)283.946 768 Q EP
+%%Page: ii 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF(5.1.9.3)144.336 96 Q(Custom beaming)181.836 96 Q
+(27)7.5 E(5.1.9.4)144.336 108 Q(Cross-staf)181.836 108 Q 2.5(fb)-.25 G 5
+(eams 31)-2.5 F(5.1.9.5)144.336 120 Q 5(Alternation 32)181.836 120 R
+(5.1.9.6)144.336 132 Q 5(Slope 32)181.836 132 R(5.1.10)114.336 144 Q
+-.45(Tu)144.336 144 S(plets).45 E 7.5(.................................\
+.......................................................................\
+.............. 33)186.336 144 R(5.2)86.836 156 Q
+(Chord-at-a-time input style)114.336 156 Q 7.5(........................\
+.......................................................................\
+.... 34)233.836 156 R(5.3)86.836 168 Q(Bar lines)114.336 168 Q 7.5(....\
+.......................................................................\
+..................................................... 37)161.336 168 R
+(5.3.1)114.336 180 Q(Bar line padding)144.336 180 Q 7.5(...............\
+.......................................................................\
+.................. 39)221.336 180 R(5.3.2)114.336 192 Q
+(Bar line location tag)144.336 192 Q 7.5(..............................\
+.................................................................... 39)
+236.336 192 R(5.3.3)114.336 204 Q(Endings)144.336 204 Q 7.5(...........\
+.......................................................................\
+................................... 40)188.836 204 R(5.3.4)114.336 216 Q
+(Rehearsal marks)144.336 216 Q 7.5(....................................\
+.................................................................... 40)
+221.336 216 R(5.3.5)114.336 228 Q(Setting the measure number)144.336 228
+Q 7.5(.................................................................\
+..................... 41)266.336 228 R(5.3.6)114.336 240 Q
+(Setting rehearsal letter or number)144.336 240 Q 7.5(.................\
+............................................................ 41)288.836
+240 R(5.3.7)114.336 252 Q(Hiding time/k)144.336 252 Q .3 -.15(ey s)-.1 H
+(ignature and clef changes).15 E 7.5
+(............................................................. 41)
+328.836 252 R(5.4)86.836 264 Q(Multirest)114.336 264 Q 7.5(............\
+.......................................................................\
+............................................. 42)161.336 264 R(5.5)
+86.836 276 Q -.55(Ly)114.336 276 S(rics).55 E 7.5(.....................\
+.......................................................................\
+........................................ 43)151.336 276 R(6.)69.336 294
+Q -.93(TA)86.836 294 S(BLA).93 E(TURE NO)-1.11 E -.93(TA)-.4 G(TION)-.18
+E 7.5(.................................................................\
+............................................. 50)206.336 294 R(6.1)
+86.836 306 Q(Specifying a tablature staf)114.336 306 Q(f)-.25 E 7.5(...\
+.......................................................................\
+......................... 50)233.836 306 R(6.2)86.836 318 Q
+(Music input on tablature staf)114.336 318 Q(fs)-.25 E 7.5(............\
+.......................................................................\
+........... 51)246.336 318 R(6.3)86.836 330 Q(Chord attrib)114.336 330 Q
+(utes)-.2 E 7.5(.......................................................\
+............................................................. 52)191.336
+330 R(6.4)86.836 342 Q -.35(Ti)114.336 342 S(es).35 E 7.5(.............\
+.......................................................................\
+.................................................... 52)141.336 342 R
+(6.5)86.836 354 Q(Slides)114.336 354 Q 7.5(............................\
+.......................................................................\
+.................................. 52)148.836 354 R(6.6)86.836 366 Q
+(Bends)114.336 366 Q 7.5(..............................................\
+.......................................................................\
+............... 53)151.336 366 R(6.7)86.836 378 Q(Miscellaneous)114.336
+378 Q 7.5(.............................................................\
+.......................................................... 54)183.836
+378 R(7.)69.336 396 Q(SHAPED NO)86.836 396 Q(TES)-.4 E 7.5(............\
+.......................................................................\
+......................................... 56)171.336 396 R(7.1)86.836
+408 Q(Headshapes conte)114.336 408 Q(xt)-.15 E 7.5(....................\
+.......................................................................\
+................... 56)206.336 408 R(7.2)86.836 420 Q
+(Noteheads parameter)114.336 420 Q 7.5(................................\
+.......................................................................\
+..... 57)211.336 420 R(7.3)86.836 432 Q(Ov)114.336 432 Q
+(erriding chord note heads)-.15 E 7.5(.................................\
+................................................................ 58)
+238.836 432 R(7.4)86.836 444 Q(Ov)114.336 444 Q(erriding indi)-.15 E
+(vidual note heads)-.25 E 7.5(.........................................\
+................................................. 59)256.336 444 R(7.5)
+86.836 456 Q(Putting it all together to use shaped notes)114.336 456 Q
+7.5(...................................................................\
+......... 59)291.336 456 R(8.)69.336 474 Q(TEXT STRINGS)86.836 474 Q 7.5
+(......................................................................\
+....................................................... 63)168.836 474 R
+(8.1)86.836 486 Q(Special characters)114.336 486 Q 7.5(................\
+.......................................................................\
+.......................... 63)198.836 486 R(8.2)86.836 498 Q -.15(Fo)
+114.336 498 S(nt and size changes).15 E 7.5(...........................\
+.......................................................................\
+......... 68)213.836 498 R(8.3)86.836 510 Q(Horizontal and v)114.336 510
+Q(ertical motion)-.15 E 7.5(...........................................\
+.................................................. 69)248.836 510 R(8.4)
+86.836 522 Q(Piled te)114.336 522 Q
+(xt, for superscripts, subscripts, etc.)-.15 E 7.5(....................\
+....................................................... 69)293.836 522 R
+(8.5)86.836 534 Q(Slash through number)114.336 534 Q 7.5(..............\
+.......................................................................\
+...................... 70)213.836 534 R(8.6)86.836 546 Q(Box)114.336 546
+Q(ed or circled te)-.15 E(xt)-.15 E 7.5(...............................\
+.......................................................................\
+....... 70)208.836 546 R(9.)69.336 564 Q(TEMPO, D)86.836 564 Q(YN)-.55 E
+(AMIC MARKS, ORN)-.35 E(AMENTS, ETC.)-.35 E 7.5
+(.................................................................. 71)
+316.336 564 R(9.1)86.836 576 Q(General information)114.336 576 Q 7.5(..\
+.......................................................................\
+..................................... 71)206.336 576 R(9.2)86.836 588 Q
+-1.25 -.7(Te x)114.336 588 T(t).7 E 7.5(...............................\
+.......................................................................\
+................................. 74)143.836 588 R(9.2.1)114.336 600 Q
+(Chord, analysis, \214gured bass, and dynamics)144.336 600 Q 7.5
+(............................................................ 74)331.336
+600 R(9.3)86.836 612 Q(Grids)114.336 612 Q 7.5(........................\
+.......................................................................\
+...................................... 76)148.836 612 R(9.4)86.836 624 Q
+(Mussym)114.336 624 Q 7.5(.............................................\
+.......................................................................\
+............. 77)158.836 624 R(9.5)86.836 636 Q(Phrase marks)114.336 636
+Q 7.5(.................................................................\
+........................................................ 78)178.836 636
+R(9.6)86.836 648 Q(Crescendo and decrescendo marks)114.336 648 Q 7.5(..\
+.......................................................................\
+.............. 79)263.836 648 R(9.7)86.836 660 Q(Octa)114.336 660 Q .3
+-.15(ve m)-.2 H(arks).15 E 7.5(........................................\
+.......................................................................\
+......... 80)181.336 660 R(9.8)86.836 672 Q(Piano pedal marks)114.336
+672 Q 7.5(.............................................................\
+.................................................... 81)198.836 672 R
+(9.9)86.836 684 Q(Rolls)114.336 684 Q 7.5(.............................\
+.......................................................................\
+.................................. 81)146.336 684 R(10.)69.336 702 Q
+-1.04 -.93(TA G)86.836 702 T(S, PRINTING, LINES, AND CUR).93 E(VES)-.8 E
+7.5(...................................................................\
+............... 84)276.336 702 R(10.1)86.836 714 Q(Location tags)114.336
+714 Q 7.5(.............................................................\
+............................................................ 84)178.836
+714 R(ii)282.556 768 Q EP
+%%Page: iii 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF(10.2)86.836 96 Q(Printing commands)114.336 96 Q
+7.5(...................................................................\
+............................................ 86)203.836 96 R(10.3)86.836
+108 Q(Including ra)114.336 108 Q 2.5(wP)-.15 G(ostScript)-2.5 E 7.5(...\
+.......................................................................\
+............................. 89)223.836 108 R(10.4)86.836 120 Q
+(Lines and curv)114.336 120 Q(es)-.15 E 7.5(...........................\
+.......................................................................\
+................. 90)193.836 120 R(11.)69.336 138 Q(MISCELLANEOUS FEA)
+86.836 138 Q(TURES)-1.11 E 7.5(........................................\
+........................................................... 93)233.836
+138 R(11.1)86.836 150 Q(Ne)114.336 150 Q(wscore and ne)-.25 E(wpage)-.25
+E 7.5(.................................................................\
+........................................ 93)218.836 150 R(11.2)86.836
+162 Q(Headers and footers)114.336 162 Q 7.5(...........................\
+.......................................................................\
+............ 93)206.336 162 R(11.3)86.836 174 Q(Macros)114.336 174 Q 7.5
+(......................................................................\
+............................................................ 95)156.336
+174 R(11.3.1)114.336 186 Q(Simple Macros \(without parameters\))144.336
+186 Q 7.5(.............................................................\
+........... 95)301.336 186 R(11.3.2)114.336 198 Q
+(Macros with parameters)144.336 198 Q 7.5(.............................\
+............................................................... 96)
+251.336 198 R(11.3.3)114.336 210 Q(Generalized conditionals)144.336 210
+Q 7.5(.................................................................\
+......................... 98)256.336 210 R(11.4)86.836 222 Q(Include)
+114.336 222 Q 7.5(.....................................................\
+.......................................................................\
+.... 100)156.336 222 R(11.5)86.836 234 Q(Installing other fonts)114.336
+234 Q 7.5(.............................................................\
+.............................................. 100)208.836 234 R(12.)
+69.336 252 Q -.92(PA)86.836 252 S(RAMETERS).92 E 7.5(..................\
+.......................................................................\
+.................................... 102)163.836 252 R(13.)69.336 270 Q
+(HINTS)86.836 270 Q 7.5(...............................................\
+.......................................................................\
+...................... 129)126.336 270 R(13.1)86.836 282 Q(Deb)114.336
+282 Q(ugging)-.2 E 7.5(................................................\
+.......................................................................\
+.... 129)168.836 282 R(13.2)86.836 294 Q(Adjusting Output)114.336 294 Q
+7.5(...................................................................\
+............................................. 129)196.336 294 R(13.3)
+86.836 306 Q(Special uses of in)114.336 306 Q(visbar)-.4 E 7.5(........\
+.......................................................................\
+........................ 129)218.836 306 R(13.4)86.836 318 Q(Chant)
+114.336 318 Q 7.5(.....................................................\
+.......................................................................\
+....... 131)148.836 318 R(13.5)86.836 330 Q -.15(Fo)114.336 330 S
+(rcing shared noteheads).15 E 7.5(.....................................\
+.............................................................. 134)
+228.836 330 R(13.6)86.836 342 Q(Manually placed tuplet numbers)114.336
+342 Q 7.5(.............................................................\
+............................ 135)253.836 342 R(13.7)86.836 354 Q
+(Manual placement of notes)114.336 354 Q 7.5(..........................\
+.......................................................................\
+ 135)233.836 354 R(13.8)86.836 366 Q(Brack)114.336 366 Q
+(eting notes across staf)-.1 E(fs)-.25 E 7.5(..........................\
+................................................................... 136)
+243.836 366 R(13.9)86.836 378 Q(Cross-bar beaming)114.336 378 Q 7.5(...\
+.......................................................................\
+.................................... 138)201.336 378 R(13.10)86.836 390
+Q(Mix)114.336 390 Q(ed time signatures)-.15 E 7.5(.....................\
+.......................................................................\
+............. 138)213.836 390 R(13.11)86.836 402 Q(Dif)114.336 402 Q
+(ferent mar)-.25 E(gins for odd/e)-.18 E -.15(ve)-.25 G 2.5(np).15 G
+(ages)-2.5 E 7.5(......................................................\
+........................... 140)273.836 402 R(13.12)86.836 414 Q
+(Marking complicated tempo changes)114.336 414 Q 7.5(..................\
+............................................................... 140)
+273.836 414 R(13.13)86.836 426 Q(Placing se)114.336 426 Q -.15(ve)-.25 G
+(ral songs on one page).15 E 7.5(......................................\
+................................................ 141)261.336 426 R
+(13.14)86.836 438 Q(Cadenzas)114.336 438 Q 7.5(........................\
+.......................................................................\
+.............................. 143)163.836 438 R(13.15)86.836 450 Q -.35
+(Tr)114.336 450 S(ansposition).35 E 7.5(...............................\
+.......................................................................\
+................ 143)181.336 450 R(13.16)86.836 462 Q(Placing v)114.336
+462 Q(erses belo)-.15 E 2.5(wt)-.25 G(he scores)-2.5 E 7.5(............\
+.......................................................................\
+....... 145)251.336 462 R(13.17)86.836 474 Q(Automatic piano reduction)
+114.336 474 Q 7.5(.....................................................\
+............................................ 145)233.836 474 R(13.18)
+86.836 486 Q(Diagonal slash marks)114.336 486 Q 7.5(...................\
+.......................................................................\
+................ 147)211.336 486 R(13.19)86.836 498 Q(Breath marks)
+114.336 498 Q 7.5(.....................................................\
+.................................................................. 148)
+178.836 498 R(13.20)86.836 510 Q(Or)114.336 510 Q -.05(ga)-.18 G 2.5(np)
+.05 G(edal heel and toe marks)-2.5 E 7.5(..............................\
+............................................................ 148)251.336
+510 R(13.21)86.836 522 Q(Generating blank staf)114.336 522 Q 2.5(fp)-.25
+G(aper)-2.5 E 7.5(.....................................................\
+.......................................... 149)238.836 522 R(13.22)
+86.836 534 Q(Con)114.336 534 Q -.15(ve)-.4 G
+(rting Mup \214les to other formats).15 E 7.5(.........................\
+....................................................... 149)276.336 534
+R(14.)69.336 552 Q(MIDI OUTPUT)86.836 552 Q 7.5(.......................\
+.......................................................................\
+............................... 150)163.836 552 R(15.)69.336 570 Q
+(CONCLUSION)86.836 570 Q 7.5(..........................................\
+.......................................................................\
+............. 155)161.336 570 R(iii)281.166 768 Q EP
+%%Page: iv 6
+save
+mark
+200 200 moveto
+/TimesRoman findfont 10 scalefont setfont ([This page intentionally left blank]) show
+cleartomark
+showpage
+restore
+%%Page: 1 7
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 16/Times-Bold@0 SF(Mup \212 Music Publisher)201.104 96 Q(User')
+240.968 120 Q 4(sG)-.592 G(uide)-4 E 69.336 163.001 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(1. INTR)73.086 163.001 R(ODUCTION)-.45 E
+69.336 181.001 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.805
+(The music publisher program called "Mup" tak)73.641 181.001 R 1.804
+(es a te)-.1 F 1.804(xt \214le describing music as input, and generates)
+-.15 F .606(PostScript* output for printing that music.)69.336 193.001 R
+.607(The input \214le can be created using your f)5.606 F -.2(avo)-.1 G
+.607(rite te).2 F .607(xt editor)-.15 F 3.107(,o)-.4 G(r)-3.107 E 1.147
+(with the help of the companion Mupmate program, or generated from an)
+69.336 205.001 R 3.647(yo)-.15 G 1.147(ther source, such as another)
+-3.647 F 1.193(program. The input must be written in a special language\
+ designed especially for describing music. The)69.336 217.001 R
+(majority of the Mup User')69.336 229.001 Q 2.5(sG)-.55 G(uide is the e)
+-2.5 E(xplanation of this language and ho)-.15 E 2.5(wt)-.25 G 2.5(ou)
+-2.5 G(se it.)-2.5 E 2.272(Mup has the po)69.336 247.001 R 2.271
+(wer to print almost an)-.25 F 4.771(yk)-.15 G 2.271(ind of music, e)
+-4.771 F -.15(ve)-.25 G 2.271(rything from a single melody line to full)
+.15 F .214(orchestral or choral scores complete with tempo and dynamic \
+marks. In addition to standard 5-line staf)69.336 259.001 R .215(fs, it)
+-.25 F 1.08(can handle 1-line staf)69.336 271.001 R 1.079(fs \(typicall\
+y used for percussion\), and tablature notation \(typically used for gu\
+itar\).)-.25 F .155(Because Mup can do so much, it tak)69.336 283.001 R
+.156(es a while to master its entire language. Ho)-.1 F(we)-.25 E -.15
+(ve)-.25 G .956 -.4(r, i).15 H 2.656(th).4 G .156(as b)-2.656 F .156
+(uilt-in def)-.2 F(ault)-.1 E -.25(va)69.336 295.001 S .962
+(lues for man).25 F 3.462(yt)-.15 G .962(hings, so that you can start u\
+sing it for simple songs after learning just the basics, then)-3.462 F
+.979(learn the more complicated features as you need them.)69.336
+307.001 R .979(Mup also has an option to produce output in the)5.979 F
+(standard Musical Instrument Digital Interf)69.336 319.001 Q
+(ace \(MIDI\) format.)-.1 E 1.532(Mup is share)69.336 337.001 R -.1(wa)
+-.25 G 1.532(re. That means you may try it out before b).1 F 1.531
+(uying it, and that you may mak)-.2 F 4.031(ec)-.1 G 1.531(opies for)
+-4.031 F .918(others, b)69.336 349.001 R .918(ut an)-.2 F .918
+(yone who w)-.15 F .919(ants to k)-.1 F .919
+(eep and use Mup must pay a share)-.1 F -.1(wa)-.25 G .919(re re).1 F
+.919(gistration fee. Running Mup)-.15 F 1.245
+(with the -r option \(or /r option for MS-DOS** or W)69.336 361.001 R
+(indo)-.4 E 1.245(ws**\) will print the re)-.25 F 1.244
+(gistration form, with the)-.15 F(rele)69.336 373.001 Q -.25(va)-.25 G
+.458(nt information.).25 F .459
+(Or if you are using Mupmate, the menu-dri)5.458 F -.15(ve)-.25 G 2.959
+(ni).15 G(nterf)-2.959 E .459(ace on top of Mup, you can get)-.1 F .7
+(the re)69.336 385.001 R .7(gistration form from the Con\214g Menu.)-.15
+F(An)5.699 E .699(yone may do)-.15 F .699(wnload an unre)-.25 F .699
+(gistered cop)-.15 F 3.199(yo)-.1 G 3.199(fM)-3.199 G .699(up via ftp)
+-3.199 F 1.566(from ftp.arkkra.com or via a W)69.336 397.001 R 1.566
+(eb bro)-.8 F 1.566(wser from www)-.25 F 4.066(.arkkra.com. Music)-.65 F
+1.567(generated by an unre)4.066 F(gistered)-.15 E(cop)69.336 409.001 Q
+3.436(yo)-.1 G 3.436(fM)-3.436 G .936
+(up will include a notice stating the program is unre)-3.436 F .935
+(gistered, b)-.15 F .935(ut all the features of a re)-.2 F(gistered)-.15
+E(cop)69.336 421.001 Q 2.5(ya)-.1 G(re included.)-2.5 E .654(The User')
+69.336 439.001 R 3.154(sG)-.55 G .654(uide be)-3.154 F .654
+(gins by introducing the basics and describing the general frame)-.15 F
+-.1(wo)-.25 G .654(rk of the language.).1 F 1.148(Then it gi)69.336
+451.001 R -.15(ve)-.25 G 3.648(sd).15 G 1.148
+(etailed information about all the features of Mup.)-3.648 F 1.147
+(Appendix A gi)6.148 F -.15(ve)-.25 G 3.647(sas).15 G 1.147
+(ample input \214le.)-3.647 F .517(There is a Quick Reference a)69.336
+463.001 R -.25(va)-.2 G .517
+(ilable that may be useful for jogging your memory after you').25 F .818
+-.15(ve h)-.5 H .518(ad a little).15 F -.15(ex)69.336 475.001 S
+(perience using Mup.).15 E(This User')69.336 493.001 Q 2.5(sG)-.55 G
+(uide is for Mup v)-2.5 E(ersion 5.3.)-.15 E .32 LW 73.336 693 69.336
+693 DL 77.336 693 73.336 693 DL 81.336 693 77.336 693 DL 85.336 693
+81.336 693 DL 89.336 693 85.336 693 DL 93.336 693 89.336 693 DL 97.336
+693 93.336 693 DL 101.336 693 97.336 693 DL 105.336 693 101.336 693 DL
+109.336 693 105.336 693 DL 113.336 693 109.336 693 DL 117.336 693
+113.336 693 DL 121.336 693 117.336 693 DL 125.336 693 121.336 693 DL
+129.336 693 125.336 693 DL 133.336 693 129.336 693 DL 137.336 693
+133.336 693 DL 141.336 693 137.336 693 DL 145.336 693 141.336 693 DL
+149.336 693 145.336 693 DL/F1 8/Times-Roman@0 SF(*)69.336 710 Q
+(PostScript is a trademark of Adobe Systems Incorporated)90.595 710 Q
+(**)69.336 727 Q(MS-DOS and W)90.595 727 Q(indo)-.32 E
+(ws are trademarks of Microsoft Corporation)-.2 E/F2 9/Times-Roman@0 SF
+2.25<a943>98.474 744 S(op)-2.25 E(yright 1995, 1996, 1997, 1998, 1999, \
+2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises)-.09 E EP
+%%Page: 2 8
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-2-)277.006 48 S 69.336 103 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(2. MUP)73.086 103 R -.45(BA)3.75 G(SICS)
+.45 E 69.336 121 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .689
+(This section introduces the Mup language, gi)72.525 121 R .689
+(ving some simple e)-.25 F .689(xamples to gi)-.15 F .989 -.15(ve y)-.25
+H .689(ou the \215a).15 F -.2(vo)-.2 G 3.189(ro).2 G 3.188(faM)-3.189 G
+(up)-3.188 E(input \214le.)69.336 133 Q
+(Subsequent sections will go into greater detail.)5 E 69.336 151 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(2.1 Notes)72.836 151 R(and chords)3.5 E
+69.336 169 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.449(Music is described one measure at a t\
+ime. Each note is speci\214ed by its pitch v)73.285 169 R 1.449
+(alue, "a" to "g." As an)-.25 F -.15(ex)69.336 181 S
+(ample, the \214rst measure of "Three Blind Mice" can be described lik)
+.15 E 2.5(et)-.1 G(his:)-2.5 E/F1 10/Courier@0 SF 18(1: 4e;)105.336 199
+R(4d; 2c;)6 E 199.836 208.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 176 0 rlineto 0 61 neg rlineto closepath stroke grestore
+EEND 232 702 176 176 -61 61 198.836 269.6 PBEGIN
+%%BeginDocument: mugex2.ps
+%%BoundingBox: 232 702 408 763
+save
+192278223 192278013 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+612.29 1235.00 756.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+264.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+292.78 719.00 1.000000 4n
+0.70 setlinewidth
+296.46 719.75 moveto
+296.46 740.00 lineto stroke
+320.08 716.00 1.000000 4n
+323.76 716.75 moveto
+323.76 737.00 lineto stroke
+351.62 713.00 1.000000 2n
+345.17 713.00 moveto
+358.07 713.00 lineto stroke
+355.52 713.75 moveto
+355.52 734.00 lineto stroke
+restore
+%  S_BAR
+5 linenum
+0.70 setlinewidth
+395.65 743.00 moveto
+395.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .734(The "1:" at the be)69.336 283.6 R
+.733
+(ginning of the line tells Mup that we are describing the notes on staf)
+-.15 F 3.233(fn)-.25 G .733(umber 1. In this)-3.233 F -.15(ve)69.336
+295.6 S .902(ry simple e).15 F .902(xample, we only ha)-.15 F 1.202 -.15
+(ve o)-.2 H .902(ne staf).15 F .902(f, b)-.25 F .902(ut later we')-.2 F
+.902(ll do songs with more than one.)-.1 F .903(Each staf)5.902 F 3.403
+(fo)-.25 G(f)-3.403 E(each measure is normally put on a separate line.)
+69.336 307.6 Q .079
+(The \214rst three notes of "Three Blind Mice" are E, D, and C. F)69.336
+325.6 R .078(or Mup input, these pitches are gi)-.15 F -.15(ve)-.25 G
+2.578(ni).15 G 2.578(nl)-2.578 G -.25(ow)-2.578 G(er).25 E .878
+(case to a)69.336 337.6 R -.2(vo)-.2 G .878(id ha).2 F .878
+(ving to use the shift k)-.2 F -.15(ey)-.1 G 3.378(.N)-.5 G 3.378(oo)
+-3.378 G(cta)-3.378 E 1.178 -.15(ve i)-.2 H .878(nformation w).15 F .879
+(as speci\214ed in this simple e)-.1 F .879(xample, so)-.15 F(Mup w)
+69.336 349.6 Q(ould use its def)-.1 E(ault, which in this case w)-.1 E
+(ould be the octa)-.1 E .3 -.15(ve b)-.2 H -.15(eg).15 G
+(inning with middle C.).15 E 1.25(The \214rst tw)69.336 367.6 R 3.749
+(on)-.1 G 1.249
+(otes are quarter notes, and the last note is a half note. T)-3.749 F
+1.249(ime v)-.35 F 1.249(alues of notes are gi)-.25 F -.15(ve)-.25 G
+3.749(na).15 G(s)-3.749 E(sho)69.336 379.6 Q(wn in the e)-.25 E
+(xample. A quarter note is mark)-.15 E
+(ed by a 4, a half note by 2, a sixteenth note by a 16, etc.)-.1 E 2.856
+(As)69.336 397.6 S .356
+(emicolon is used to separate chords. In this simple e)-2.856 F .356
+(xample, each chord has only a single note in it, b)-.15 F(ut)-.2 E
+(it is possible to ha)69.336 409.6 Q .3 -.15(ve l)-.2 H
+(ots of notes in one chord.).15 E .201
+(At the end of each measure, we ha)69.336 427.6 R .501 -.15(ve t)-.2 H
+2.701(ot).15 G .201(ell Mup what kind of bar line to dra)-2.701 F 1.501
+-.65(w. T)-.15 H .2(he standard bar line is just).65 F(called "bar)
+69.336 439.6 Q(." So a complete description of the \214rst measure w)
+-.55 E(ould be:)-.1 E/F1 10/Courier@0 SF 18(1: 4e;)105.336 457.6 R
+(4d; 2c;)6 E(bar)105.336 469.6 Q F0 2.52 -.8(To s)69.336 495.6 T -2.25
+-.2(av e).8 H .92(typing, Mup allo)3.62 F .921(ws a lot of shortcuts. O\
+ne such shortcut is that it assumes that unless you tell it)-.25 F .447
+(otherwise, each note in the measure is lik)69.336 507.6 R 2.947(et)-.1
+G .447(he note before. Y)-2.947 F .446(ou can lea)-1.1 F .746 -.15(ve o)
+-.2 H .446(ut the second 4, because if you).15 F(don')69.336 519.6 Q 2.5
+(ts)-.18 G(pecify a time v)-2.5 E
+(alue, Mup will assume the note is the same length as the pre)-.25 E
+(vious note.)-.25 E .984(The same sort of idea w)69.336 537.6 R .985(or\
+ks with pitches. The third measure of "Three Blind Mice" could be state\
+d lik)-.1 F(e)-.1 E(this:)69.336 549.6 Q F1(1: 4g;8f;;2e;)105.336 567.6
+Q(bar)105.336 579.6 Q 127.836 589.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 320 0 rlineto 0 61 neg rlineto closepath stroke grestore
+EEND 160 702 320 320 -61 61 126.836 650.2 PBEGIN
+%%BeginDocument: mugex3.ps
+%%BoundingBox: 160 702 480 763
+save
+192278223 192278013 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+540.29 1235.00 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+226.78 725.00 1.000000 4n
+0.70 setlinewidth
+230.46 725.75 moveto
+230.46 746.00 lineto stroke
+284.75 722.00 1.000000 4n
+288.43 722.75 moveto
+288.43 743.00 lineto stroke
+291.46 743.00 1.000000 dnflag
+321.07 722.00 1.000000 4n
+324.76 722.75 moveto
+324.76 743.00 lineto stroke
+327.78 743.00 1.000000 dnflag
+368.33 719.00 1.000000 2n
+372.23 719.75 moveto
+372.23 740.00 lineto stroke
+restore
+%  S_BAR
+5 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .18
+(The third note has no information gi)69.336 664.2 R -.15(ve)-.25 G 2.68
+(na).15 G 2.68(ta)-2.68 G .18(ll in this e)-2.68 F .18
+(xample\212there is only a semicolon. In this case, Mup)-.15 F .312
+(will get both pitch and time v)69.336 676.2 R .312(alue from the pre)
+-.25 F .313(vious note, so the actual third note in this measure w)-.25
+F .313(ould be)-.1 F(an eighth note with pitch F)69.336 688.2 Q(.)-.8 E
+-1.1(Yo)69.336 706.2 S 3.01(um)1.1 G .51(ay ha)-3.01 F .81 -.15(ve n)-.2
+H .51(oticed that this e).15 F .51(xample doesn')-.15 F 3.009(th)-.18 G
+-2.25 -.2(av e)-3.009 H .509(spaces between chords.)3.209 F .509
+(There are only a fe)5.509 F 3.009(wp)-.25 G(laces)-3.009 E .386
+(where the Mup language requires you to put spaces.)69.336 718.2 R(Ho)
+5.386 E(we)-.25 E -.15(ve)-.25 G 1.186 -.4(r, y).15 H .386(ou can al).4
+F -.1(wa)-.1 G .386(ys put some in other places to).1 F(mak)69.336 730.2
+Q 2.5(et)-.1 G(hings easier to read.)-2.5 E EP
+%%Page: 3 9
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-3-)277.006 48 S 69.336 102 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(2.2 P)72.836 102 R(arameters)-.14 E
+69.336 120 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .806(Printed music contains a lot more than\
+ just notes and bar lines. Among other things, each staf)72.643 120 R
+3.306(fn)-.25 G(ormally)-3.306 E(be)69.336 132 Q .289
+(gins with a clef, k)-.15 F .589 -.15(ey s)-.1 H .289
+(ignature, and time signature. Mup pro).15 F .29(vides def)-.15 F .29
+(ault v)-.1 F .29(alues for these, which you can)-.25 F .399(then o)
+69.336 144 R -.15(ve)-.15 G .399(rride if you w).15 F .399
+(ant something dif)-.1 F .399(ferent. In the e)-.25 F .399(xamples so f)
+-.15 F(ar)-.1 E 2.899(,w)-.4 G 2.899(ed)-2.899 G(idn')-2.899 E 2.899(to)
+-.18 G -.15(ve)-3.049 G .398(rride an).15 F .398(ything, so Mup)-.15 F
+-.1(wo)69.336 156 S .818(uld assume its def).1 F .818(ault v)-.1 F .818
+(alues, which are treble clef, a k)-.25 F 1.118 -.15(ey s)-.1 H .819
+(ignature with no sharps or \215ats, and a time).15 F(signature of 4/4.)
+69.336 168 Q 1.073
+(There is a long list of "parameters" that can be set.)69.336 186 R
+1.073(Things lik)6.073 F 3.572(ec)-.1 G 1.072(lef and k)-3.572 F 1.372
+-.15(ey s)-.1 H 1.072(ignature are among them.).15 F -.15(Pa)69.336 198
+S(rameters can be changed with a line of the form:).15 E/F1 10
+/Times-Italic@0 SF(par)105.336 216 Q(ameter_name)-.15 E/F2 10/Courier@0
+SF(=)A F1(value)A F0 -.15(Fo)69.336 236 S 4.125(re).15 G 1.625
+(xample, suppose we ha)-4.275 F 1.925 -.15(ve a s)-.2 H 1.625
+(ong written in 6/8 time in the k).15 F 1.926 -.15(ey o)-.1 H 4.126(fDm)
+.15 G(ajor)-4.126 E 6.626(.W)-.55 G 4.126(ec)-7.426 G 1.626(an con)
+-4.126 F 1.926 -.15(vey t)-.4 H(his).15 E(information to Mup lik)69.336
+248 Q 2.5(et)-.1 G(his:)-2.5 E F2(score)105.336 266 Q(time=6/8)117.336
+278 Q(key=2#)117.336 290 Q(music)105.336 314 Q(1: 4d;8e;4f;8d;)117.336
+326 Q(bar)117.336 338 Q 127.836 347.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 320 0 rlineto 0 61 neg rlineto closepath stroke grestore
+EEND 160 702 320 320 -61 61 126.836 408.6 PBEGIN
+%%BeginDocument: mugex4.ps
+%%BoundingBox: 160 702 480 763
+save
+192278223 192278013 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+540.29 1235.00 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+206.19 743.00 1.000000 sharp
+212.83 734.00 1.000000 sharp
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+219.15 731.00 moveto
+(6) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+219.15 718.79 moveto
+(8) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+254.35 716.00 1.000000 4n
+0.70 setlinewidth
+258.04 716.75 moveto
+258.04 737.00 lineto stroke
+318.35 719.00 1.000000 4n
+322.03 719.75 moveto
+322.03 740.00 lineto stroke
+325.06 740.00 1.000000 dnflag
+364.23 722.00 1.000000 4n
+367.91 722.75 moveto
+367.91 743.00 lineto stroke
+429.07 716.00 1.000000 4n
+432.75 716.75 moveto
+432.75 737.00 lineto stroke
+435.77 737.00 1.000000 dnflag
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF(Note that in this e)69.336 428.6 Q
+(xample, the k)-.15 E .3 -.15(ey w)-.1 H(as speci\214ed as tw).05 E 2.5
+(os)-.1 G 2.5(harps. Y)-2.5 F(ou can also specify the k)-1.1 E .3 -.15
+(ey b)-.1 H 2.5(yn).15 G(ame:)-2.5 E/F1 10/Courier@0 SF(key = d major)
+117.336 446.6 Q F0 1.359(These parameters gi)69.336 472.6 R 1.659 -.15
+(ve a ve)-.25 H 1.359(ry dif).15 F 1.359
+(ferent sort of information than the notes of a measure, so the)-.25 F
+3.859(yg)-.15 G 3.859(oi)-3.859 G 3.858(na)-3.859 G 1.208
+(separate section of the input \214le.)69.336 484.6 R 1.209(Each sectio\
+n of the \214le describes information for a speci\214c "conte)6.209 F
+(xt.")-.15 E .097(Information about musical notes is gi)69.336 496.6 R
+-.15(ve)-.25 G 2.597(ni).15 G 2.597(n")-2.597 G .097(music" conte)-2.597
+F .096(xt, while things that apply in general to the whole)-.15 F .723
+(score are gi)69.336 508.6 R -.15(ve)-.25 G 3.224(ni).15 G 3.224(n")
+-3.224 G .724(score" conte)-3.224 F 3.224(xt. Once)-.15 F .724
+(you start a measure in music conte)3.224 F .724(xt, you ha)-.15 F 1.024
+-.15(ve t)-.2 H 3.224(oc).15 G .724(omplete that)-3.224 F .654
+(measure before switching to another conte)69.336 520.6 R .654(xt, b)
+-.15 F .654(ut otherwise you can pretty much change from one conte)-.2 F
+(xt)-.15 E .394(to another as necessary)69.336 532.6 R 5.394(.E)-.65 G
+.394(ach ne)-5.394 F 2.894(wc)-.25 G(onte)-2.894 E .395
+(xt section is headed by its name \(e.g., "music" or "score"\).)-.15 F
+.395(At the)5.395 F(be)69.336 544.6 Q(ginning of input, music conte)-.15
+E(xt is assumed.)-.15 E(Here is a more complicated e)69.336 562.6 Q
+(xample:)-.15 E F1(score)105.336 580.6 Q(staffs=2)141.336 592.6 Q
+(key=3&)141.336 604.6 Q(time=2/4)141.336 616.6 Q(music)105.336 640.6 Q
+(1: ceg;;)105.336 652.6 Q(2: 2c;)105.336 664.6 Q(bar)105.336 676.6 Q EP
+%%Page: 4 10
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-4-)277.006 48 S 163.836 96 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 115 rlineto 248 0 rlineto 0 115 neg rlineto closepath stroke grestore
+EEND 200 648 248 248 -115 115 162.836 211 PBEGIN
+%%BeginDocument: mugex5.ps
+%%BoundingBox: 200 648 448 763
+save
+192278223 192278013 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+576.29 1235.00 792.00 5 1.000000 1.000000 stf
+576.29 1181.00 792.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+216.29 743.00 moveto
+216.29 665.00 lineto stroke
+%  S_CLEFSIG
+228.08 725.00 1.000000 gclef
+228.08 671.00 1.000000 gclef
+241.62 731.00 1.000000 flat
+247.10 740.00 1.000000 flat
+252.59 728.00 1.000000 flat
+241.62 677.00 1.000000 flat
+247.10 686.00 1.000000 flat
+252.59 674.00 1.000000 flat
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+258.34 731.00 moveto
+(2) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+258.34 718.98 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+258.34 677.00 moveto
+(2) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+258.34 664.98 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+294.15 725.00 1.000000 4n
+294.15 719.00 1.000000 4n
+294.15 713.00 1.000000 4n
+287.92 713.00 moveto
+300.38 713.00 lineto stroke
+297.83 713.75 moveto
+297.83 746.00 lineto stroke
+367.17 725.00 1.000000 4n
+367.17 719.00 1.000000 4n
+367.17 713.00 1.000000 4n
+360.93 713.00 moveto
+373.40 713.00 lineto stroke
+370.85 713.75 moveto
+370.85 746.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+294.15 659.00 1.000000 2n
+0.70 setlinewidth
+287.70 659.00 moveto
+300.60 659.00 lineto stroke
+298.05 659.75 moveto
+298.05 680.00 lineto stroke
+restore
+%  S_BAR
+12 linenum
+0.70 setlinewidth
+431.65 743.00 moveto
+431.65 719.00 lineto stroke
+431.65 689.00 moveto
+431.65 665.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF 1.142(This e)69.336 225 R 1.141(xample \
+starts by setting some parameters. First it states that this piece of m\
+usic should be printed)-.15 F 1.069(with tw)69.336 237 R 3.569(os)-.1 G
+(taf)-3.569 E 1.069(fs, instead of the def)-.25 F 1.069
+(ault of only one. Then it gi)-.1 F -.15(ve)-.25 G 3.569(sak).15 G 1.369
+-.15(ey s)-3.669 H 1.069(ignature. Since there is no "\215at").15 F .214
+(symbol on a standard computer k)69.336 249 R -.15(ey)-.1 G .214
+(board, Mup uses the "&" symbol for \215at.).15 F .214
+(The time signature is then set)5.214 F(to 2/4.)69.336 261 Q(Ne)69.336
+279 Q .545(xt we \214nd the k)-.15 F -.15(ey)-.1 G -.1(wo).15 G .546
+(rd "music," which indicates the end of parameters and the be).1 F .546
+(ginning of the music.)-.15 F .196(Data is gi)69.336 291 R -.15(ve)-.25
+G 2.696(nf).15 G .196(or both staf)-2.696 F 2.696(f1a)-.25 G .196
+(nd staf)-2.696 F 2.696(f2)-.25 G 5.196(.S)-2.696 G(taf)-5.196 E 2.696
+(f1h)-.25 G .196(as tw)-2.696 F 2.696(oc)-.1 G .196
+(hords in the measure. The \214rst is a C minor triad)-2.696 F(\(it')
+69.336 303 Q 3.408(sm)-.55 G .908(inor since the k)-3.408 F 1.208 -.15
+(ey i)-.1 H 3.408(st).15 G .908(hree \215ats\). No time v)-3.408 F .908
+(alue is speci\214ed for this chord. Since it is the v)-.25 F .909
+(ery \214rst)-.15 F .281(chord of the piece, Mup cannot use the pre)
+69.336 315 R .281(vious chord')-.25 F 2.781(st)-.55 G .281(ime v)-2.781
+F .281(alue, because there is no pre)-.25 F .281(vious chord.)-.25 F(In)
+5.281 E .273(this case, Mup f)69.336 327 R .274(alls back to using the \
+denominator \(bottom number\) of the time signature, so the chord is a)
+-.1 F 1.027(quarter note. Incidentally)69.336 339 R 3.527(,i)-.65 G
+3.527(fM)-3.527 G 1.027(up has to back up to pre)-3.527 F 1.026
+(vious notes to deduce pitch and/or time v)-.25 F 1.026(alues, it)-.25 F
+.009(only goes back as f)69.336 351 R .009(ar as the be)-.1 F .01
+(ginning of the current measure. That means the def)-.15 F .01
+(ault time v)-.1 F .01(alue for the \214rst)-.25 F .308(chord of e)
+69.336 363 R -.15(ve)-.25 G .308(ry measure in this piece w).15 F .308
+(ould be quarter note.)-.1 F .308(The second chord on staf)5.308 F 2.807
+(f1i)-.25 G 2.807(st)-2.807 G .307(he same as the)-2.807 F
+(\214rst, since only a semicolon is speci\214ed.)69.336 375 Q(Staf)
+69.336 393 Q 3.116(f2h)-.25 G .617
+(as only a single chord, consisting of a half note with pitch C.)-3.116
+F .617(Mup checks to mak)5.617 F 3.117(es)-.1 G .617(ure the time)-3.117
+F -.25(va)69.336 405 S .305(lues on each staf).25 F 2.805(fa)-.25 G .304
+(dd up to the time signature\212no more or less\212and will print an er\
+ror message if the)-2.805 F(y)-.15 E(don')69.336 417 Q 2.761(t. If)-.18
+F .261(you ha)2.761 F .561 -.15(ve s)-.2 H .261(omething lik).15 F -5.26
+2.761(ea ")-.1 H .262(pickup" measure, which doesn')-2.761 F 2.762(ta)
+-.18 G .262(dd up to the time signature, you can)-2.762 F(specify "spac\
+e" rather than a chord, to account for the rest of the time.)69.336 429
+Q .768(Some parameters can be set on a per)69.336 447 R(-staf)-.2 E
+3.268(fb)-.25 G .768
+(asis as well as for the entire score. Mup also allo)-3.268 F .768
+(ws for up to)-.25 F .06(three independent v)69.336 459 R .06
+(oices on each staf)-.2 F .06(f, and each v)-.25 F .061(oice can ha)-.2
+F .361 -.15(ve p)-.2 H .061(arameters set that apply to only that v).15
+F(oice.)-.2 E 1.972 -.8(To g)69.336 471 T .372(et the v).8 F .372
+(alue of a parameter)-.25 F 2.872(,M)-.4 G .372(up al)-2.872 F -.1(wa)
+-.1 G .372
+(ys starts at the most speci\214c place it could be de\214ned and w).1 F
+(orks)-.1 E(to)69.336 483 Q -.1(wa)-.25 G .048
+(rd the most general. In other w).1 F .048
+(ords, it will \214rst see if the parameter is set for the current v)-.1
+F .049(oice. If not, it)-.2 F .438
+(will see if it is set for the current staf)69.336 495 R .437
+(f. If not, it will use the v)-.25 F .437
+(alue set for the entire score. Staf)-.25 F 2.937(fp)-.25 G(arameters)
+-2.937 E(are set in "staf)69.336 507 Q(f" conte)-.25 E(xt, and v)-.15 E
+(oice parameters are set in "v)-.2 E(oice" conte)-.2 E 2.5(xt. As)-.15 F
+(an e)2.5 E(xample:)-.15 E/F1 10/Courier@0 SF(score)105.336 525 Q
+(staffs=3)141.336 537 Q(key=1&)141.336 549 Q(staff 2)105.336 561 Q
+(key=2&)141.336 573 Q(clef=bass)141.336 585 Q(music)105.336 597 Q
+(1: 2f;a;)105.336 609 Q(2: 2c;f;)105.336 621 Q(3: 1f;)105.336 633 Q(bar)
+105.336 645 Q EP
+%%Page: 5 11
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-5-)277.006 48 S 127.836 96 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 169 rlineto 320 0 rlineto 0 169 neg rlineto closepath stroke grestore
+EEND 160 594 320 320 -169 169 126.836 265 PBEGIN
+%%BeginDocument: mugex6.ps
+%%BoundingBox: 160 594 480 763
+save
+192278223 192278013 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_SSV
+7 linenum
+%  S_FEED
+540.29 1235.00 828.00 5 1.000000 1.000000 stf
+540.29 1181.00 828.00 5 1.000000 1.000000 stf
+540.29 1127.00 828.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+180.29 743.00 moveto
+180.29 611.00 lineto stroke
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+192.33 683.00 1.000000 fclef
+192.08 617.00 1.000000 gclef
+206.12 731.00 1.000000 flat
+206.12 671.00 1.000000 flat
+211.61 680.00 1.000000 flat
+206.12 623.00 1.000000 flat
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+246.97 722.00 1.000000 2n
+250.87 722.75 moveto
+250.87 743.00 lineto stroke
+362.76 728.00 1.000000 2n
+366.66 728.75 moveto
+366.66 749.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+246.97 674.00 1.000000 2n
+0.70 setlinewidth
+250.87 674.75 moveto
+250.87 695.00 lineto stroke
+362.76 683.00 1.000000 2n
+358.86 682.25 moveto
+358.86 662.00 lineto stroke
+restore
+%  S_STAFF
+% staff 3
+save
+246.97 614.00 1.000000 1n
+restore
+%  S_BAR
+14 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+467.65 689.00 moveto
+467.65 665.00 lineto stroke
+467.65 635.00 moveto
+467.65 611.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF(Staf)69.336 279 Q 2.553(f2w)-.25 G .053
+(ill ha)-2.553 F .353 -.15(ve t)-.2 H .254 -.1(wo \215).15 H .054
+(ats, whereas the other staf).1 F .054(fs will ha)-.25 F .354 -.15(ve o)
+-.2 H .054(ne \215at.).15 F(Staf)5.054 E 2.554(f2w)-.25 G .054
+(ill use the bass clef, whereas)-2.554 F 1.58(the other staf)69.336 291
+R 1.58(fs will use treble clef \(since that is the def)-.25 F 1.579
+(ault when none is speci\214ed\).)-.1 F 1.579(All the a)6.579 F -.25(va)
+-.2 G(ilable).25 E .139(parameters are listed later in this User')69.336
+303 R 2.639(sG)-.55 G .139
+(uide, along with information about whether the)-2.639 F 2.64(yc)-.15 G
+.14(an be set for an)-2.64 F(indi)69.336 315 Q(vidual staf)-.25 E 2.5
+(fo)-.25 G 2.5(rv)-2.5 G(oice, or just for the score as a whole.)-2.7 E
+69.336 333 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(2.3 P)72.836 333 R(age headers and f)-.14
+E(ooters)-.35 E 69.336 351 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .271(Mup allo)72.107 351 R .27(ws you to sp\
+ecify a header and/or footer to put on the \214rst page, as well as a h\
+eader and/or footer)-.25 F 1.119(to use on subsequent pages. These can \
+include a page number that will be incremented automatically as)69.336
+363 R .507(pages are printed. The headers and footers can be customized\
+ as you lik)69.336 375 R .506(e, with dif)-.1 F .506
+(ferent fonts and sizes of)-.25 F(te)69.336 387 Q .16(xt and items cent\
+ered or left or right justi\214ed. There is also a shortcut "title" com\
+mand that can be used to)-.15 F(create a canned format title. F)69.336
+399 Q(or e)-.15 E(xample:)-.15 E/F1 10/Courier@0 SF
+(title "Three Blind Mice")105.336 417 Q F0
+(will create a centered title. Y)69.336 437 Q
+(ou can also get left and right justi\214ed titles.)-1.1 E 69.336 455
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(2.4 L)72.836 455 R(yrics)-.77 E 69.336
+473 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF -1.1(Yo)73.323 473 S 3.987(uc)1.1 G 1.487
+(an specify lyrics for as man)-3.987 F 3.987(yv)-.15 G 1.487
+(erses as you lik)-4.137 F 1.487(e. The)-.1 F 3.987(ya)-.15 G 1.487
+(re speci\214ed some)-3.987 F 1.487(what lik)-.25 F 3.986(en)-.1 G 1.486
+(otes. As an)-3.986 F -.15(ex)69.336 485 S(ample:).15 E/F1 10/Courier@0
+SF(1: 4e;d;2c;)105.336 503 Q(lyrics 1: 4;;2; "Three blind mice,";)
+105.336 515 Q(bar)105.336 527 Q 127.836 536.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 73 rlineto 320 0 rlineto 0 73 neg rlineto closepath stroke grestore
+EEND 160 690 320 320 -73 73 126.836 609.6 PBEGIN
+%%BeginDocument: mugex7.ps
+%%BoundingBox: 160 690 480 763
+save
+192278223 192278013 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+540.29 1235.00 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+218.74 698.90 moveto
+(Three) show
+/Times-Roman findfont
+12 scalefont
+setfont
+285.23 698.90 moveto
+(blind) show
+/Times-Roman findfont
+12 scalefont
+setfont
+358.27 698.90 moveto
+(mice,) show
+225.72 719.00 1.000000 4n
+0.70 setlinewidth
+229.40 719.75 moveto
+229.40 740.00 lineto stroke
+291.37 716.00 1.000000 4n
+295.05 716.75 moveto
+295.05 737.00 lineto stroke
+364.86 713.00 1.000000 2n
+358.41 713.00 moveto
+371.30 713.00 lineto stroke
+368.75 713.75 moveto
+368.75 734.00 lineto stroke
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .748(This e)69.336 623.6 R .749
+(xample describes the lyrics to go with staf)-.15 F 3.249(f1)-.25 G
+3.249(.T)-3.249 G .749(here are three lyric syllables, ha)-3.249 F .749
+(ving time v)-.2 F .749(alues of)-.25 F 3.054
+(quarter note, quarter note, and half note.)69.336 635.6 R 3.054
+(The actual syllables are gi)8.054 F -.15(ve)-.25 G 5.554(ni).15 G 3.054
+(nside the double quotes.)-5.554 F(Incidentally)69.336 647.6 Q 2.794(,s)
+-.65 G .294(ince in this e)-2.794 F .294(xample the time v)-.15 F .295
+(alues for the lyrics are the same as those of the notes, the time)-.25
+F -.25(va)69.336 659.6 S .6(lues don').25 F 3.1(ta)-.18 G .6
+(ctually need to be speci\214ed; if no lyrics time v)-3.1 F .599
+(alues are gi)-.25 F -.15(ve)-.25 G .599(n, Mup assumes the).15 F 3.099
+(ym)-.15 G .599(atch the)-3.099 F(note time v)69.336 671.6 Q(alues.)-.25
+E 69.336 689.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(2.5 Miscellaneous)72.836 689.6 R 69.336
+707.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .157(Mup pro)71.993 707.6 R .158(vides a w)
+-.15 F .158(ay to print arbitrary te)-.1 F .158(xt \(lik)-.15 F 2.658
+(e")-.1 G(alle)-2.658 E .158(gro"\) and musical symbols \(lik)-.15 F
+2.658(eaf)-.1 G .158(ermata\). It can also)-2.658 F .622(print phrase m\
+arks, piano pedal marks, etc. The placement of these items is speci\214\
+ed in terms of "counts")69.336 719.6 R(into the measure. F)69.336 731.6
+Q(or e)-.15 E(xample:)-.15 E EP
+%%Page: 6 12
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-6-)277.006 48 S/F1 10/Courier@0 SF
+(boldital below 1: 3 "mf";)105.336 96 Q 127.836 105.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 74 rlineto 320 0 rlineto 0 74 neg rlineto closepath stroke grestore
+EEND 160 689 320 320 -74 74 126.836 179.6 PBEGIN
+%%BeginDocument: mugex8.ps
+%%BoundingBox: 160 689 480 763
+save
+192278223 192278013 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+540.29 1235.00 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+227.20 719.00 1.000000 4n
+0.70 setlinewidth
+230.88 719.75 moveto
+230.88 740.00 lineto stroke
+292.98 716.00 1.000000 4n
+296.66 716.75 moveto
+296.66 737.00 lineto stroke
+363.95 713.00 1.000000 2n
+357.50 713.00 moveto
+370.40 713.00 lineto stroke
+367.85 713.75 moveto
+367.85 734.00 lineto stroke
+/Times-BoldItalic findfont
+12 scalefont
+setfont
+359.27 699.40 moveto
+(mf ) show
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-BoldItalic 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .788
+(tells Mup to print "mf" in bold-italics belo)69.336 193.6 R 3.288(ws)
+-.25 G(taf)-3.288 E 3.288(f1)-.25 G 3.288(,a)-3.288 G 3.288(tc)-3.288 G
+.788(ount 3 of the measure.)-3.288 F -1.1(Yo)5.788 G 3.288(uc)1.1 G .788
+(an also print marks)-3.288 F(associated with speci\214c chords.)69.336
+205.6 Q(All of these f)5 E(acilities are described in detail in follo)
+-.1 E(wing sections.)-.25 E 69.336 223.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(2.6 Displaying,)72.836 223.6 R
+(printing, and playing music)3.5 E 69.336 241.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(Once you ha)71.836 241.6 Q .3 -.15(ve a)-.2
+H 2.5(ni).15 G(nput \214le, you can run Mup on it to get the printed v)
+-2.5 E(ersion of the music. Entering:)-.15 E/F1 10/Courier@0 SF(mup)
+105.336 259.6 Q/F2 10/Times-Italic@0 SF(my\214le)6 E F0 1.129(from a co\
+mmand line prompt or selecting Run > Display from Mupmate will cause Mu\
+p to read)69.336 279.6 R F2(my\214le)3.628 E F0(,)A .276
+(which should contain te)69.336 291.6 R .276
+(xt in the Mup input language. If there are no errors in)-.15 F F2
+(my\214le)2.776 E F0 2.776(,P)C .277(ostScript output will)-2.776 F
+1.022(be produced, which can be displayed on the screen or printed via \
+Mupmate or other programs. Mup can)69.336 303.6 R
+(also produce MIDI output, which can then be played on your speak)69.336
+315.6 Q(ers.)-.1 E 2.322(If you are using Ghostscript, b)69.336 333.6 R
+2.322(ut without Mupmate, tw)-.2 F 4.822(ou)-.1 G 2.322
+(tility programs are included with Mup for)-4.822 F
+(displaying and printing music using Ghostscript.)69.336 345.6 Q
+(These are described in more detail in the ne)5 E(xt section.)-.15 E EP
+%%Page: 7 13
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-7-)277.006 48 S 69.336 103 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(3. R)73.086 103 R(UNNING MUP)-.45 E
+69.336 121 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .072(There are tw)71.908 121 R 2.572(ob)-.1
+G .072(asic w)-2.572 F .072(ays to run Mup: directly from a command lin\
+e or via the Mupmate program. Y)-.1 F .072(ou can)-1.1 F 1.424(use eith\
+er approach, or switch between them as you wish. The Mupmate program ju\
+st pro)69.336 133 R 1.424(vides a more)-.15 F(menu-dri)69.336 145 Q -.15
+(ve)-.25 G 2.5(ne).15 G -.4(nv)-2.5 G
+(ironment on top of the Mup program itself.).4 E -1.1(Yo)69.336 163 S
+3.596(uc)1.1 G 1.096(an create a Mup \214le using an)-3.596 F 3.596(yo)
+-.15 G 1.096(rdinary te)-3.596 F 1.096(xt editor)-.15 F 3.596(,a)-.4 G
+1.096(nd then run the Mup program on the \214le you)-3.596 F 3.614
+(created. On)69.336 175 R -.4(Wi)3.614 G(ndo).4 E 1.114
+(ws, Notepad is a typical editor choice, and on Linux, editors lik)-.25
+F 3.614(ev)-.1 G 1.115(im and emacs are)-3.614 F .451(commonly used, b)
+69.336 187 R .451(ut pretty much an)-.2 F 2.951(yt)-.15 G -.15(ex)-2.951
+G 2.951(te).15 G .451(ditor \(not w)-2.951 F .45
+(ord processor\) can be used. Man)-.1 F 2.95(yp)-.15 G .45(eople, ho)
+-2.95 F(we)-.25 E -.15(ve)-.25 G -.4(r,).15 G 1.015
+(prefer to be able to edit, display)69.336 199 R 3.515(,a)-.65 G 1.016
+(nd play from a single inte)-3.515 F 1.016
+(grated and more graphical interf)-.15 F 1.016(ace, and for)-.1 F 1.58
+(them, a helper program called "Mupmate" is pro)69.336 211 R 4.079
+(vided. The)-.15 F 1.579(Mupmate program helps lead you through)4.079 F
+(some of the steps, and you can easily access this User')69.336 223 Q
+2.5(sG)-.55 G(uide from its Help menu.)-2.5 E 69.336 241 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(3.1 Mupmate)72.836 241 R 69.336 259
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .125
+(Mupmate is currently only supported on W)71.961 259 R(indo)-.4 E .125
+(ws and Linux.)-.25 F(Ho)5.125 E(we)-.25 E -.15(ve)-.25 G .925 -.4(r, s)
+.15 H .125(ince the source code is a).4 F -.25(va)-.2 G(ilable,).25 E
+.601(and it is based on the cross-platform FL)69.336 271 R .601
+(TK toolkit, it w)-.92 F .601(ould probably be f)-.1 F .601
+(airly easy to mak)-.1 F 3.101(ei)-.1 G 3.101(tr)-3.101 G .601(un on an)
+-3.101 F(y)-.15 E(system supported by FL)69.336 283 Q(TK.)-.92 E .379
+(Once you ha)69.336 301 R .679 -.15(ve i)-.2 H .379
+(nstalled Mup and Mupmate on W).15 F(indo)-.4 E .38
+(ws, double clicking a .mup \214le in W)-.25 F(indo)-.4 E .38(ws e)-.25
+F(xplorer)-.15 E 2.049(will run Mupmate on that \214le.)69.336 313 R(Or)
+7.049 E 4.548(,y)-.4 G 2.048
+(ou can run Mupmate by going to the Start menu, and choosing)-4.548 F
+.666(Programs, then Arkkra, and then Mupmate.)69.336 325 R .667
+(If you w)5.666 F .667(ould lik)-.1 F 3.167(ea)-.1 G 3.167(ni)-3.167 G
+.667(con on the desktop, you can create one)-3.167 F .746
+(by right clicking the Mupmate choice in the Arkkra menu, choosing "cop)
+69.336 337 R .746(y", right clicking some)-.1 F .746(where on)-.25 F
+(the desktop, and choosing "paste".)69.336 349 Q .138
+(On Linux, you can just type the mupmate command in a terminal windo)
+69.336 367 R 1.438 -.65(w, o)-.25 H .139(ptionally follo).65 F .139
+(wed by the name)-.25 F(of a Mup input \214le.)69.336 379 Q
+(Or you can add mupmate to your f)5 E -.2(avo)-.1 G(rite windo).2 E 2.5
+(wm)-.25 G(anager')-2.5 E 2.5(sm)-.55 G(enus.)-2.5 E 2.246(Mupmate pro)
+69.336 397 R 2.246(vides \214v)-.15 F 4.746(et)-.15 G 2.246(op le)-4.746
+F -.15(ve)-.25 G 4.746(lm).15 G 2.246
+(enus: File, Edit, Run, Con\214g, and Help.)-4.746 F 2.246
+(The File menu pro)7.246 F(vides)-.15 E .013(commands for opening ne)
+69.336 409 R 2.513<778c>-.25 G .013(les and sa)-2.513 F .014
+(ving the \214le you are w)-.2 F .014(orking on, as well as e)-.1 F .014
+(xiting the program. The)-.15 F .8(Edit menu pro)69.336 421 R .8
+(vides the kinds of things you w)-.15 F .8(ould e)-.1 F .8
+(xpect in a editor: commands to \214nd a pattern, or \214nd)-.15 F 1.965
+(and replace; to select te)69.336 433 R 1.965(xt; to cop)-.15 F 3.265
+-.65(y, c)-.1 H 1.966
+(ut, and paste; to go to a speci\214c line; and to undo the pre).65 F
+(vious)-.25 E 1.082(operation, if you mak)69.336 445 R 3.581(eam)-.1 G
+(istak)-3.581 E 3.581(eo)-.1 G 3.581(rc)-3.581 G 1.081(hange you mind.)
+-3.581 F 1.081(The Run menu lets you set runtime options, and)6.081 F
+.126(then run the Mup program on your input in v)69.336 457 R .126
+(arious w)-.25 F .126(ays. Y)-.1 F .127
+(ou can either just generate a PostScript or MIDI)-1.1 F 2.123
+(\214le, or display the PostScript or play the MIDI.)69.336 469 R 2.123
+(The Con\214g menu lets you specify what application)7.123 F .197
+(program you w)69.336 481 R .197(ant to use to vie)-.1 F 2.697(wP)-.25 G
+.198(ostScript \214les and which you w)-2.697 F .198
+(ant to use to play MIDI \214les, and well as)-.1 F .208(specify locati\
+ons for other Mup \214les. Mupmate will try to \214nd reasonable def)
+69.336 493 R .207(ault v)-.1 F .207(alues, b)-.25 F .207(ut you may w)
+-.2 F(ant)-.1 E .215(to check that the)69.336 505 R 2.715(ya)-.15 G .215
+(re what you w)-2.715 F .215(ant, and tweak them if the)-.1 F 2.715(ya)
+-.15 G(ren')-2.715 E 2.715(t. The)-.18 F .215(Con\214g menu also pro)
+2.715 F .215(vides a w)-.15 F(ay)-.1 E .099
+(for you to \214ll in the Mup re)69.336 517 R .098
+(gistration form if you wish to send in a paper form rather than re)-.15
+F .098(gistering online)-.15 F .926
+(via credit card, as well as a place to entry the re)69.336 529 R .927
+(gistration k)-.15 F 1.227 -.15(ey y)-.1 H .927(ou will recei).15 F
+1.227 -.15(ve o)-.25 H .927(nce you ha).15 F 1.227 -.15(ve p)-.2 H 3.427
+(aid. The).15 F .089(Help menu lets you bro)69.336 541 R .089
+(wse this User')-.25 F 2.589(sG)-.55 G .089(uide, vie)-2.589 F 2.589(ws)
+-.25 G .089(ome startup hints, or see the current v)-2.589 F .088
+(ersion number of)-.15 F(Mup and Mupmate.)69.336 553 Q 1.657
+(Mupmate does not directly pro)69.336 571 R 1.658(vide a print f)-.15 F
+(acility)-.1 E 4.158(.A)-.65 G 1.658(lmost an)-4.158 F 4.158(yP)-.15 G
+1.658(ostScript vie)-4.158 F 1.658(wer already pro)-.25 F 1.658
+(vides this)-.15 F(ability)69.336 583 Q 4.153(,s)-.65 G 4.153(oy)-4.153
+G 1.653
+(ou can simply select "Display" from the Run menu and use the vie)-4.153
+F(wer')-.25 E 4.152(sp)-.55 G 1.652(rint capabilities.)-4.152 F .432(Al\
+ternately you can use "Write PostScript File" from the Run menu to crea\
+te a PostScript \214le that you can)69.336 595 R(print as you w)69.336
+607 Q(ould an)-.1 E 2.5(yo)-.15 G(ther PostScript \214le.)-2.5 E 69.336
+625 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(3.2 Mup)72.836 625 R(Options)3.5 E 69.336
+643 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .163(Mup accepts a number of options.)71.999
+643 R .163(When in)5.163 F -.2(vo)-.4 G .163
+(king Mup from a command line, the options are speci\214ed by).2 F 2.852
+(ad)69.336 655 S .352(ash follo)-2.852 F .352(wed by a letter)-.25 F
+5.352(.O)-.55 G 2.852(nW)-5.352 G(indo)-3.252 E .353
+(ws/MS-DOS systems, you can substitute a slash instead of the dash.)-.25
+F .77(If you are using Mupmate, you will use the "Set Options" form of)
+69.336 667 R 3.27(fo)-.25 G 3.27(ft)-3.27 G .77
+(he "Run" menu to set the options.)-3.27 F -1.1(Yo)69.336 679 S 3.823
+(uj)1.1 G 1.323(ust \214ll v)-3.823 F 1.324
+(alues into the form, and Mupmate will tak)-.25 F 3.824(ec)-.1 G 1.324
+(are of the details of running Mup with your)-3.824 F -.25(va)69.336 691
+S .625(lues, so you w).25 F(on')-.1 E 3.125(tu)-.18 G .625
+(se the dash and letter sho)-3.125 F .625(wn belo)-.25 F 3.124(wa)-.25 G
+3.124(ta)-3.124 G 3.124(ll. Some)-3.124 F .624
+(of the options listed belo)3.124 F 3.124(wa)-.25 G .624(re not)-3.124 F
+-.2(av)69.336 703 S .319(ailable from Mupmate, either because the)-.05 F
+2.819(ya)-.15 G .319(re meant for deb)-2.819 F .32
+(ugging, and thus not generally of interest to)-.2 F 1.443(most users, \
+or because Mupmate handles the appropriate details automatically)69.336
+715 R 6.443(.T)-.65 G 1.443(he options to the mup)-6.443 F
+(command \(in alphabetical order\) are:)69.336 727 Q EP
+%%Page: 8 14
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-8-)277.006 48 S/F1 10/Courier@0 SF
+(Command line:)69.336 96 Q/F2 10/Times-Bold@0 SF(-c)12 E/F3 10
+/Times-Italic@0 SF(N)2.5 E F1(Mupmate:)69.336 108 Q F0
+(Run > Set Options > Enable Auto Multirest and Min Measures to Combine)
+42 E 2.096(Combine consecuti)98.136 123.6 R 2.397 -.15(ve m)-.25 H 2.097
+(easures of all rests or spaces into multirests \(multiple measures of \
+rest).15 F 1.073(printed as a single measure, usually with the number o\
+f measures of rest printed abo)98.136 135.6 R 1.372 -.15(ve t)-.15 H
+1.072(he staf).15 F(f\).)-.25 E(An)98.136 147.6 Q 2.844(yt)-.15 G .344
+(ime there are)-2.844 F F3(N)2.844 E F0 .344(or more measures in a ro)
+2.844 F 2.844(wt)-.25 G .344
+(hat consist entirely of rests or spaces, the)-2.844 F 2.844(yw)-.15 G
+.344(ill be)-2.844 F .445(replaced by a multirest. The combining of mea\
+sures stops when there is a visible staf)98.136 159.6 R 2.945(ft)-.25 G
+.445(hat contains)-2.945 F .806(notes or lyrics, or that contain te)
+98.136 171.6 R .807
+(xt or musical symbols after the \214rst beat of the measure, or when)
+-.15 F 1.66(there are parameter changes on a visible staf)98.136 183.6 R
+4.16(fo)-.25 G 4.16(ri)-4.16 G 4.16(ns)-4.16 G 1.66(core conte)-4.16 F
+1.66(xt that change clef, k)-.15 F -.15(ey)-.1 G 4.16(,o)-.5 G 4.16(rt)
+-4.16 G(ime)-4.16 E 1.053
+(signature, or when there is a bar line other than an ordinary bar)
+98.136 195.6 R 6.053(.T)-.55 G 1.053(his option is most lik)-6.053 F
+1.054(ely to be)-.1 F 1.868(useful when printing a subset of staf)98.136
+207.6 R 1.868(fs, where the particular staf)-.25 F 1.868
+(f\(s\) you are printing ha)-.25 F 2.168 -.15(ve l)-.2 H(ong).15 E .158
+(periods of rests.)98.136 219.6 R .158
+(See information about the -s option and the "visible" parameter belo)
+5.158 F 3.958 -.65(w. T)-.25 H .158(his option).65 F -.15(ove)98.136
+231.6 S(rrides the restcombine parameter).15 E(.)-.55 E F1
+(Command line:)69.336 255.6 Q F2(-C)12 E F1(Mupmate:)69.336 267.6 Q F0
+(Option not a)42 E -.25(va)-.2 G(ilable \(only used for deb).25 E
+(ugging\).)-.2 E 1.578
+(This option is only used in connection with the -E option.)98.136 283.2
+R 1.578(It speci\214es that comments are to be)6.578 F
+(passed through rather than deleted.)98.136 295.2 Q F1(Command line:)
+69.336 319.2 Q F2(-d)12 E F3(N)2.5 E F1(Mupmate:)69.336 331.2 Q F0
+(Option not a)42 E -.25(va)-.2 G(ilable \(only used for deb).25 E
+(ugging\).)-.2 E .285(Print deb)98.136 346.8 R .285(ugging information.)
+-.2 F F3(N)2.785 E F0 .285(is a bitmap, so you can turn on multiple deb)
+2.785 F .285(ugging le)-.2 F -.15(ve)-.25 G .285(ls by adding).15 F .105
+(up the \215ag v)98.136 358.8 R .104(alues. F)-.25 F .104(or e)-.15 F
+.104(xample, if you w)-.15 F .104(ant to turn on both le)-.1 F -.15(ve)
+-.25 G 2.604(l2a).15 G .104(nd le)-2.604 F -.15(ve)-.25 G 2.604(l4t).15
+G(racing,)-2.604 E F3(N)2.604 E F0 -.1(wo)2.604 G .104(uld be 6).1 F
+(\(because 2+4=6\).)98.136 370.8 Q 20(1i)98.136 388.8 S
+(nput syntax/grammar analysis tracing)-20 E 20(2h)98.136 406.8 S(igh le)
+-20 E -.15(ve)-.25 G 2.5(lp).15 G(arse phase tracing)-2.5 E 20(4l)98.136
+424.8 S .5 -.25(ow l)-20 H -2.15 -.25(ev e).25 H 2.5(lp).25 G
+(arse phase tracing)-2.5 E 20(8r)98.136 442.8 S(eserv)-20 E(ed)-.15 E
+12.5(16 high)98.136 460.8 R(le)2.5 E -.15(ve)-.25 G 2.5(lp).15 G
+(lacement phase tracing)-2.5 E 12.5(32 lo)98.136 478.8 R 2.5(wl)-.25 G
+-2.15 -.25(ev e)-2.5 H 2.5(lp).25 G(lacement phase tracing)-2.5 E 12.5
+(64 reserv)98.136 496.8 R(ed)-.15 E 7.5(128 contents)98.136 514.8 R
+(of the main internal list)2.5 E 7.5(256 high)98.136 532.8 R(le)2.5 E
+-.15(ve)-.25 G 2.5(lp).15 G(rint or MIDI phase tracing)-2.5 E 7.5
+(512 lo)98.136 550.8 R 2.5(wl)-.25 G -2.15 -.25(ev e)-2.5 H 2.5(lp).25 G
+(rint or MIDI phase tracing)-2.5 E F3(N)98.136 574.8 Q F0 .487(can be s\
+peci\214ed in decimal, octal \(by using a leading zero\), or he)2.986 F
+2.987(x\()-.15 G .487(by using a leading 0x\).)-2.987 F(This)5.487 E .19
+(information is intended for deb)98.136 586.8 R .19
+(ugging of Mup itself and thus is not lik)-.2 F .19
+(ely to be of use to the a)-.1 F -.15(ve)-.2 G(rage).15 E(user)98.136
+598.8 Q 2.5(,a)-.4 G(nd is not a)-2.5 E -.25(va)-.2 G
+(ilable from Mupmate.).25 E F1(Command line:)69.336 622.8 Q F2(-D)12 E
+F3(MA)2.5 E(CR)-.3 E(O[=macr)-.4 E(o-def])-.45 E F1(Mupmate:)69.336
+634.8 Q F0(Run > Set Options > Macro De\214nitions)42 E 3.16
+(De\214ne the macro)98.136 650.4 R F3(MA)5.66 E(CR)-.3 E(O)-.4 E F0 5.66
+(.T)C 3.16
+(he macro name must consist of upper case letters, digits, and)-5.66 F
+.05(underscores, be)98.136 662.4 R .05
+(ginning with an upper case letter)-.15 F 2.55(.T)-.55 G(he)-2.55 E F3
+(macr)2.55 E(o_def)-.45 E F0 .05(is optional, and gi)2.55 F -.15(ve)-.25
+G 2.55(st).15 G .05(he te)-2.55 F .05(xt of the)-.15 F 2.764
+(macro. On UNIX, Linux, or similar systems, if it contains an)98.136
+674.4 R 5.264(yw)-.15 G 2.764(hite space or other special)-5.264 F .044
+(characters, it must be quoted. On other systems, white space may not b\
+e allo)98.136 686.4 R 2.543(wed. The)-.25 F .043(-D option can)2.543 F(\
+be speci\214ed multiple times, if you wish to de\214ne more than one ma\
+cro.)98.136 698.4 Q .32 LW 73.336 727 69.336 727 DL 77.336 727 73.336
+727 DL 81.336 727 77.336 727 DL 85.336 727 81.336 727 DL 89.336 727
+85.336 727 DL 93.336 727 89.336 727 DL 97.336 727 93.336 727 DL 101.336
+727 97.336 727 DL 105.336 727 101.336 727 DL 109.336 727 105.336 727 DL
+113.336 727 109.336 727 DL 117.336 727 113.336 727 DL 121.336 727
+117.336 727 DL 125.336 727 121.336 727 DL 129.336 727 125.336 727 DL
+133.336 727 129.336 727 DL 137.336 727 133.336 727 DL 141.336 727
+137.336 727 DL 145.336 727 141.336 727 DL 149.336 727 145.336 727 DL/F4
+8/Times-Roman@0 SF(*)69.336 744 Q(UNIX is a re)90.595 744 Q
+(gistered trademark of X/Open Compan)-.12 E 2(yL)-.12 G(imited.)-2 E EP
+%%Page: 9 15
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-9-)277.006 48 S/F1 10/Courier@0 SF
+(Command line:)69.336 96 Q/F2 10/Times-Bold@0 SF(-e)12 E/F3 10
+/Times-Italic@0 SF(err\214le)2.5 E F1(Mupmate:)69.336 108 Q F0
+(Option not needed. Mupmate automatically sa)42 E -.15(ve)-.2 G 2.5(sa)
+.15 G(nd displays error output.)-2.5 E
+(Place the error message output into)98.136 123.6 Q F3(err\214le)2.5 E
+F0(instead of writing it to the standard error output stream.)2.5 E F1
+(Command line:)69.336 147.6 Q F2(-E)12 E F1(Mupmate:)69.336 159.6 Q F0
+(Option not needed \(only used for deb)42 E(ugging\).)-.2 E 1.592
+(Rather than produce PostScript or MIDI output, just e)98.136 175.2 R
+1.592(xpand macros and includes, and write the)-.15 F .255
+(result to the standard output stream.)98.136 187.2 R .255
+(Comments in the input are deleted, unless the -C option is also)5.255 F
+(speci\214ed.)98.136 199.2 Q F1(Command line:)69.336 223.2 Q F2(-f)12 E
+F3(out\214le)2.5 E F1(Mupmate:)69.336 235.2 Q F0(Option not needed. Mup\
+mate automatically creates appropriate output \214le.)42 E
+(Place the PostScript output into)98.136 250.8 Q F3(out\214le)2.5 E F0
+(instead of writing to the standard output.)2.5 E F1(Command line:)
+69.336 274.8 Q F2(-F)12 E F1(Mupmate:)69.336 286.8 Q F0
+(Run > Write PostScript File)42 E .958(This is lik)98.136 302.4 R 3.458
+(et)-.1 G(he)-3.458 E F2(-f)3.458 E F0 .958(option, e)3.458 F .958
+(xcept the name of the output \214le is deri)-.15 F -.15(ve)-.25 G 3.459
+(df).15 G .959(rom the name of the Mup)-3.459 F 1.489(input \214le. If \
+the name of the Mup input \214le ends with a ".mup" suf)98.136 314.4 R
+1.488(\214x, the generated PostScript)-.25 F .051
+(output \214le will end with a ".ps" suf)98.136 326.4 R .051
+(\214x instead.)-.25 F .052
+(If the name of the Mup input \214le ends with a ".MUP")5.051 F(suf)
+98.136 338.4 Q .4
+(\214x, the PostScript \214le will end with a ".PS" suf)-.25 F 2.9
+(\214x. Otherwise,)-.25 F 2.9(a")2.9 G .4(.ps" suf)-2.9 F .4
+(\214x will be appended to)-.25 F 1.078(the end of the Mup input \214le\
+ name. If multiple input \214les are listed, the last is used.)98.136
+350.4 R 1.079(If none are)6.079 F(speci\214ed \(input is read from stan\
+dard input\), the name "stdin.ps" will be used for the output \214le.)
+98.136 362.4 Q F1(Command line:)69.336 386.4 Q F2(-m)12 E F3(midi\214le)
+2.5 E F1(Mupmate:)69.336 398.4 Q F0(Option not needed. Mupmate automati\
+cally creates appropriate output \214le.)42 E 3.242(Instead of generati\
+ng PostScript output, generate standard MIDI \(Musical Instrument Digit\
+al)98.136 414 R(Interf)98.136 426 Q 2.05(ace\) output, and put it in)-.1
+F F3(midi\214le)4.55 E F0 7.05(.T)C 2.05
+(his option also causes the macro "MIDI" to become)-7.05 F(de\214ned.)
+98.136 438 Q F1(Command line:)69.336 462 Q F2(-M)12 E F1(Mupmate:)69.336
+474 Q F0(Run > Write MIDI File)42 E .848(This is lik)98.136 489.6 R
+3.348(et)-.1 G(he)-3.348 E F2(-m)3.348 E F0 .848(option, e)3.348 F .848
+(xcept the name of the MIDI \214le is deri)-.15 F -.15(ve)-.25 G 3.348
+(df).15 G .848(rom the name of the Mup)-3.348 F .543(input \214le. If t\
+he name of the Mup input \214le ends with a ".mup" suf)98.136 501.6 R
+.544(\214x, the generated MIDI \214le will)-.25 F .843
+(end with a ".mid" suf)98.136 513.6 R .843(\214x instead. If the name o\
+f the Mup input \214le ends with a ".MUP" suf)-.25 F .842(\214x, the)
+-.25 F .551(MIDI \214le will end with a ".MID" suf)98.136 525.6 R 3.051
+(\214x. Otherwise,)-.25 F 3.051(a")3.051 G .551(.mid" suf)-3.051 F .551
+(\214x will be appended to the end of)-.25 F 1.445(the Mup input \214le\
+ name. If multiple input \214les are listed, the last is used.)98.136
+537.6 R 1.445(If none are speci\214ed)6.445 F(\(input is read from stan\
+dard input\), the name "stdin.mid" will be used for the MIDI \214le.)
+98.136 549.6 Q F1(Command line:)69.336 573.6 Q F2(-o)12 E F3(pa)2.5 E
+-.1(ge)-.1 G(list).1 E F1(Mupmate:)69.336 585.6 Q F0
+(Run > Set Options > P)42 E(ages to Display)-.15 E 1.173
+(Print only the pages gi)98.136 601.2 R -.15(ve)-.25 G 3.673(ni).15 G(n)
+-3.673 E F3(pa)3.673 E -.1(ge)-.1 G(list).1 E F0 3.673(.T)C(he)-3.673 E
+F3(pa)3.673 E -.1(ge)-.1 G(list).1 E F0 1.173
+(can be a comma-separated list of numbers or)3.673 F .549
+(ranges, where a range is tw)98.136 613.2 R 3.049(on)-.1 G .549
+(umbers separated by a dash. F)-3.049 F .548(or e)-.15 F .548
+(xample, -o1,7-9,12-14 w)-.15 F .548(ould print)-.1 F .23
+(pages 1, 7, 8, 9, 12, 13, and 14. Alternately)98.136 625.2 R 2.731(,t)
+-.65 G(he)-2.731 E F3(pa)2.731 E -.1(ge)-.1 G(list).1 E F0 .231
+(can be the special k)2.731 F -.15(ey)-.1 G -.1(wo).15 G .231
+(rd "odd" or "e).1 F -.15(ve)-.25 G(n").15 E .943
+(which will cause all odd or e)98.136 637.2 R -.15(ve)-.25 G 3.443(nn)
+.15 G .942(umbered pages to be printed. This may be useful if you ha)
+-3.443 F 1.242 -.15(ve a)-.2 H 1.361(printer that only mak)98.136 649.2
+R 1.361(es single-sided copies, b)-.1 F 1.362
+(ut you wish to print Mup output double-sided. Y)-.2 F(ou)-1.1 E .627
+(could print odd-numbered pages, then turn the paper o)98.136 661.2 R
+-.15(ve)-.15 G 3.127(ra).15 G .627(nd feed the pages through ag)-3.127 F
+.626(ain for the)-.05 F -2.15 -.25(ev e)98.136 673.2 T .638
+(n-numbered pages.).25 F -.15(Pa)5.638 G .638(ges will be printed in th\
+e order speci\214ed, so you can print pages in other).15 F 1.213
+(than ascending order if you wish, or e)98.136 685.2 R -.15(ve)-.25 G
+3.712(np).15 G 1.212
+(rint the same page more than once. Printing pages in)-3.712 F 1.161
+(non-ascending order is most lik)98.136 697.2 R 1.161
+(ely to be useful when printing more than one page of music on a)-.1 F
+(single ph)98.136 709.2 Q
+(ysical page, using the panelsperpage parameter)-.05 E(.)-.55 E EP
+%%Page: 10 16
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)274.506 48 S 2.5(0-)-2.5 G/F1 10
+/Courier@0 SF(Command line:)69.336 96 Q/F2 10/Times-Bold@0 SF(-p)12 E/F3
+10/Times-Italic@0 SF(N)2.5 E F1(Mupmate:)69.336 108 Q F0
+(Run > Set Options > First P)42 E(age')-.15 E 2.5(sP)-.55 G(age Number)
+-2.65 E 1.705(Start numbering pages at)98.136 123.6 R F3(N)4.205 E F0
+1.705(instead of at 1.)4.205 F 1.705
+(This can be set inside the Mup input \214le with the)6.705 F 1.364
+("\214rstpage" parameter)98.136 135.6 R 3.864(,b)-.4 G 1.364
+(ut the command line option will o)-4.064 F -.15(ve)-.15 G 1.364
+(rride the parameter).15 F 6.364(.I)-.55 G(f)-6.364 E F2(-o)3.864 E F0
+(and)3.864 E F2(-p)3.864 E F0(are)3.864 E 1.756(used together)98.136
+147.6 R 4.256(,t)-.4 G 1.756(he page numbers gi)-4.256 F -.15(ve)-.25 G
+4.256(ni).15 G 4.256(nt)-4.256 G(he)-4.256 E F2(-o)4.256 E F3(pa)A -.1
+(ge)-.1 G(list).1 E F0 1.756(must be the printed page numbers. F)4.256 F
+(or)-.15 E -.15(ex)98.136 159.6 S(ample, if you use -p10 and w).15 E
+(ant to print just the second page, you w)-.1 E
+(ould need to specify -o11.)-.1 E F1(Command line:)69.336 183.6 Q F2(-r)
+12 E F1(Mupmate:)69.336 195.6 Q F0(Con\214g > Re)42 E(gistration F)-.15
+E(orm)-.15 E(Print a cop)98.136 211.2 Q 2.5(yo)-.1 G 2.5(ft)-2.5 G
+(he Mup share)-2.5 E -.1(wa)-.25 G(re re).1 E
+(gistration form to standard output.)-.15 E F1(Command line:)69.336
+235.2 Q F2(-s)12 E F3(staf)2.5 E(\215ist)-.18 E F1(Mupmate:)69.336 247.2
+Q F0(Run > Set Options > Staf)42 E(fs to Display/Play)-.25 E .258
+(Only print the staf)98.136 262.8 R .258(fs that are included in)-.25 F
+F3(staf)2.758 E(\215ist)-.18 E F0 5.258(.T)C(he)-5.258 E F3(staf)2.758 E
+(\215ist)-.18 E F0 .259(can be a comma-separated list of staf)2.758 F(f)
+-.25 E .44(numbers or ranges, such as "1,5" or "1-3,7-8" b)98.136 274.8
+R .44(ut no spaces are allo)-.2 F .439(wed in the list.)-.25 F .439
+(If the -m or -M)5.439 F .357(option is also used, to produce MIDI outp\
+ut, this option controls which staf)98.136 286.8 R .358
+(fs are played rather than)-.25 F .917(which are printed.)98.136 298.8 R
+.917(If you w)5.917 F .916(ant only a single v)-.1 F .916
+(oice to be printed or played, you can follo)-.2 F 3.416(was)-.25 G(taf)
+-3.416 E(f)-.25 E 1.268(number or range with)98.136 310.8 R F2(v1)3.768
+E F0(or)3.768 E F2(v2)3.768 E F0(or)3.768 E F2(v3)3.768 E F0 1.268
+(to restrict to v)3.768 F 1.268(oice 1, 2 or 3 respecti)-.2 F -.15(ve)
+-.25 G(ly).15 E 3.768(,s)-.65 G 1.269(uch as "1v2" or)-3.768 F 1.054
+("1-4v1,5-6v2". Otherwise all v)98.136 322.8 R 1.053(oices on the staf)
+-.2 F 3.553(fa)-.25 G 1.053(re printed or played.)-3.553 F -1.1(Yo)6.053
+G 3.553(uc)1.1 G(an')-3.553 E 3.553(ts)-.18 G 1.053(pecify a list or)
+-3.553 F .285(range for v)98.136 334.8 R .285(oices; if you only w)-.2 F
+.285(ant to mak)-.1 F 2.785(et)-.1 G .485 -.1(wo o)-2.785 H .285
+(ut of three v).1 F .286(oices visible, you ha)-.2 F .586 -.15(ve t)-.2
+H 2.786(os).15 G .286(pecify them)-2.786 F(separately)98.136 346.8 Q 2.5
+(,l)-.65 G(ik)-2.5 E 2.5(e")-.1 G 2.5(1v2,1v3". See)-2.5 F
+(also the "visible" parameter)2.5 E(.)-.55 E F1(Command line:)69.336
+370.8 Q F2(-v)12 E F1(Mupmate:)69.336 382.8 Q F0(Help > About Mupmate)42
+E 2.663(Print the Mup v)98.136 398.4 R 2.662(ersion number)-.15 F 5.162
+(.W)-.55 G 2.662(hen in)-5.162 F -.2(vo)-.4 G -.1(ke).2 G 5.162(df).1 G
+2.662(rom command line, Mup will then e)-5.162 F 2.662(xit. This)-.15 F
+(document is for v)98.136 410.4 Q(ersion 5.3.)-.15 E F1(Command line:)
+69.336 434.4 Q F2(-x)12 E F3(M)A F2(,)A F3(N)A F1(Mupmate:)69.336 446.4
+Q F0(Run > Set Options > Extract Measures)42 E .925(Extract measures)
+98.136 462 R F3(M)3.425 E F0(through)3.425 E F3(N)3.425 E F0 .925
+(of the song. This allo)3.425 F .925
+(ws you to print or play a part of a song. The)-.25 F .79
+(comma and second v)98.136 474 R .79
+(alue are optional; if not speci\214ed, the def)-.25 F .789
+(ault is to go to the end of the piece.)-.1 F(Positi)98.136 486 Q 1.922
+-.15(ve v)-.25 H 1.623(alues specify the number of measures from the be)
+-.1 F 1.623(ginning of the piece, while ne)-.15 F -.05(ga)-.15 G(ti).05
+E -.15(ve)-.25 G -.25(va)98.136 498 S .339(lues are relati).25 F .639
+-.15(ve t)-.25 H 2.839(ot).15 G .338
+(he end, with -1 referring to the last measure of the song.)-2.839 F
+.338(So -x1,-1 means the)5.338 F 1.044(entire song, if the song doesn')
+98.136 510 R 3.544(th)-.18 G -2.25 -.2(av e)-3.544 H 3.544(ap)3.744 G
+1.044(ickup measure.)-3.544 F 1.045
+(If the song has a pickup measure, that is)6.044 F .994
+(speci\214ed by 0.)98.136 522 R .994
+(So for a song with a pickup, -x0,-1 w)5.994 F .994
+(ould mean the entire song, and -x0,0 w)-.1 F(ould)-.1 E .3
+(mean just the pickup measure.)98.136 534 R .3(As other e)5.3 F .3
+(xamples, -x-1,-1 means just the \214nal measure of the song,)-.15 F
+.405(-x2 means starting after the \214rst full measure, -x3,4 means onl\
+y measures 3 and 4, and -x6,6 means)98.136 546 R .348(just measure 6.)
+98.136 558 R .348(The starting measure is not allo)5.348 F .348
+(wed to be inside an ending.)-.25 F 2.849(Ac)5.349 G .349
+(ommon use for this)-2.849 F .45
+(option might be to generate a MIDI \214le for just a fe)98.136 570 R
+2.949(wm)-.25 G .449(easures. F)-2.949 F .449(or e)-.15 F .449
+(xample, if you were trying to)-.15 F .457(tweak tempo v)98.136 582 R
+.458(alues for a ritard in the last 2 measures of a song, you could use\
+ -x-2 to listen to just)-.25 F(those measures.)98.136 594 Q .61(When in)
+69.336 612 R -.2(vo)-.4 G -.1(ke).2 G 3.11(df).1 G .61
+(rom command line, the options, if an)-3.11 F 1.91 -.65(y, c)-.15 H .61
+(an be follo).65 F .61(wed by one or more)-.25 F F3(\214les)3.11 E F0
+.61(in the format)3.11 F .051(described in this User')69.336 624 R 2.551
+(sG)-.55 G .051(uide. If no)-2.551 F F3(\214les)2.551 E F0 .051
+(are speci\214ed, standard input is read.)2.551 F .051(If se)5.051 F
+-.15(ve)-.25 G(ral).15 E F3(\214les)2.551 E F0 .051(are listed, the)
+2.551 F(y)-.15 E .066(are ef)69.336 636 R(fecti)-.25 E -.15(ve)-.25 G
+.065(ly concatenated together and treated as one big \214le. Since ther\
+e are some things \(such as header).15 F 1.244
+(and footer\) that are only allo)69.336 648 R 1.244
+(wed to occur once, if you ha)-.25 F 1.544 -.15(ve s)-.2 H -2.15 -.25
+(ev e).15 H 1.244(ral independent pieces, Mup should be).25 F .622
+(called on each indi)69.336 660 R .622
+(vidually rather than trying to print them all with one command.)-.25 F
+.621(If a speci\214ed \214le does)5.621 F 1.956(not e)69.336 672 R 1.956
+(xist, and its name does not already end with .mup or .MUP)-.15 F 4.456
+(,t)-1.11 G 1.957(hen Mup will append .mup to the)-4.456 F
+(speci\214ed name and attempt to open that.)69.336 684 Q .139
+(If you just w)69.336 702 R .139(ant to create a PostScript output \214\
+le, for printing on a PostScript printer)-.1 F 2.638(,o)-.4 G 2.638(rv)
+-2.638 G(ie)-2.638 E .138(wing with a tool)-.25 F(such as GSvie)69.336
+714 Q 1.3 -.65(w, y)-.25 H(ou can use the -f option, as in).65 E F1
+(mup -f outfile.ps infile.mup)129.336 732 Q EP
+%%Page: 11 17
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)274.506 48 S 2.5(1-)-2.5 G 1.269
+(Or on Unix, Linux or MS-DOS command windo)69.336 96 R 2.569 -.65(w, y)
+-.25 H 1.269(ou could redirect the output into a \214le using the >).65
+F(character)69.336 108 Q 2.5(,a)-.4 G 2.5(si)-2.5 G(n:)-2.5 E/F1 10
+/Courier@0 SF(mup infile.mup > outfile.ps)129.336 126 Q F0 -.15(Fo)
+69.336 152 S 2.966(rm).15 G .466(ore deb)-2.966 F .465
+(ugging, in addition to the -d option, if the en)-.2 F .465(vironment v)
+-.4 F .465(ariable MUP_BB is set to "bcfgnsu")-.25 F 1.875(or an)69.336
+164 R 4.375(ys)-.15 G 1.876(ubset of those letters, the generated outpu\
+t will include "bounding box)-4.375 F 1.876(es" for the things Mup)-.15
+F .321(internally calls bars \(b\), chords \(c\), feeds \(f\), grpsyls \
+\(g\), header/footer and top/bottom \(h\), notes \(n\), staf)69.336 176
+R(fs)-.25 E .584(\(s\), and stuf)69.336 188 R 3.084(f\()-.25 G 3.084
+(u\). While)-3.084 F .584(this is intended for use in deb)3.084 F .584
+(ugging Mup itself, it may also help you understand)-.2 F(wh)69.336 200
+Q 4.125(yM)-.05 G 1.624(up places things the w)-4.125 F 1.624
+(ay it does, since in general, Mup only allo)-.1 F 1.624
+(ws bounding box)-.25 F 1.624(es to o)-.15 F -.15(ve)-.15 G(rlap).15 E
+.038(according to speci\214c rules. If vie)69.336 212 R .039
+(wed with a color PostScript vie)-.25 F .039
+(wer \(not mupdisp, which is co)-.25 F -.15(ve)-.15 G .039(red belo).15
+F(w\),)-.25 E(these box)69.336 224 Q(es will be in color)-.15 E(.)-.55 E
+69.336 242 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(3.3 Mupdisp)72.836 242 R(and Muppr)3.5 E
+(nt utility pr)-.21 E(ograms)-.252 E 69.336 260 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .594(If you are using Ghostscript, b)72.43
+260 R .594(ut prefer to not use Mupmate, there are tw)-.2 F 3.094(ou)-.1
+G .593(tility programs included with)-3.094 F
+(Mup for displaying and printing music.)69.336 272 Q/F1 10/Courier@0 SF
+(mupdisp)105.336 290 Q/F2 10/Times-Italic@0 SF(Mup_options my\214le)6 E
+F0(will display music to your screen, while)69.336 310 Q F1(mupprnt)
+105.336 328 Q F2(Mup_options my\214le)6 E F0 1.132
+(will print the output to your printer)69.336 348 R 6.132(.S)-.55 G
+1.133
+(ee the installation instructions for more details on con\214guring the)
+-6.132 F(Mupprnt program for your printer)69.336 360 Q(.)-.55 E(The)
+69.336 378 Q F2(Mup_options)3.018 E F0 .518(can be an)3.018 F 3.018(yo)
+-.15 G 3.018(ft)-3.018 G .518
+(he options listed in the section on "Command line ar)-3.018 F .517
+(guments" e)-.18 F .517(xcept -C,)-.15 F(-E, -f, -F)69.336 390 Q 2.5(,-)
+-.8 G(m, -M, -r)-2.5 E 2.5(,o)-.4 G 2.5(r-)-2.5 G 1.3 -.65(v, w)-2.5 H
+(hich don').65 E 2.5(ts)-.18 G
+(end PostScript output to the standard output.)-2.5 E .638
+(The Mupdisp program allo)69.336 408 R .638(ws you to vie)-.25 F 3.138
+(wp)-.25 G .638(ages in an)-3.138 F 3.138(yo)-.15 G(rder)-3.138 E 3.138
+(,w)-.4 G .639(ith either a v)-3.138 F .639
+(ersion small enough to \214t on)-.15 F .701(your screen or a near)
+69.336 420 R .701(-actual-size v)-.2 F .701
+(ersion that you can scroll if it doesn')-.15 F 3.2<748c>-.18 G 3.2(to)
+-3.2 G 3.2(ny)-3.2 G .7(our screen.)-3.2 F .7(Mupdisp will)5.7 F 1.314
+(run under MS-DOS/W)69.336 432 R(indo)-.4 E 1.314
+(ws or will run under UNIX with TERM of A)-.25 F 1.315
+(T386, linux, or xterm \(under X)-1.11 F(windo)69.336 444 Q(ws\).)-.25 E
+.11(Mupdisp be)69.336 462 R .109(gins in partial page mode, which displ\
+ays output at approximately actual size \(depending on the)-.15 F .408(\
+size of your monitor\). In this mode, it is possible that not all of th\
+e page \214ts on the screen, so the scrolling)69.336 474 R .189
+(commands can be used to mo)69.336 486 R .489 -.15(ve u)-.15 H 2.689(pa)
+.15 G .189(nd do)-2.689 F .189(wn to vie)-.25 F 2.689(wd)-.25 G(if)
+-2.689 E .188(ferent parts of the page. In full page mode, a small)-.25
+F -.15(ve)69.336 498 S .906(rsion of the entire page is displayed.).15 F
+.907(This is useful for seeing o)5.907 F -.15(ve)-.15 G .907
+(rall page layout, b).15 F .907(ut is generally too)-.2 F .735
+(small to see much detail.)69.336 510 R .735(This mode is no)5.735 F
+3.235(ws)-.25 G(ome)-3.235 E .735
+(what of a relic of the days when screens were typically)-.25 F
+(much smaller than the)69.336 522 Q 2.5(ya)-.15 G(re today)-2.5 E 2.5
+(,a)-.65 G(nd is thus becoming less useful.)-2.5 E .491
+(Once the music has been dra)69.336 540 R .491
+(wn on the screen, you can enter v)-.15 F .491(arious commands to vie)
+-.25 F 2.991(wd)-.25 G(if)-2.991 E .492(ferent pages or)-.25 F
+(parts of the current page.)69.336 552 Q(The commands are:)5 E F2(num)
+69.336 570 Q F0 22.34(<Enter> Go)B(to page number)2.5 E F2(num)2.5 E F0
+(.)A 2.5(+o)69.336 588 S 2.5(r<)-2.5 G
+(space> or <control-E> or <control-F> mo)-2.5 E .343 -.15(ve f)-.15 H
+(orw).15 E .042(ard on the page by about 1/8 of an inch \(partial page)
+-.1 F(mode only\))144.336 600 Q 2.5(-o)69.336 618 S 2.5(r<)-2.5 G
+(backspace> or <control-Y> or <control-B> mo)-2.5 E 3.026 -.15(ve b)-.15
+H(ackw).15 E 2.726(ard on the page by about 1/8 of an inch)-.1 F
+(\(partial page mode only\))144.336 630 Q 2.5(bo)69.336 648 S 2.5(r<)
+-2.5 G(control-U> or <control-P> or <upw)-2.5 E(ard-arro)-.1 E(w-k)-.25
+E -.15(ey)-.1 G 2.5(>m).15 G 2.812 -.15(ove b)-2.5 H(ackw).15 E 2.511
+(ard on the page by about an inch)-.1 F(\(partial page mode only\))
+144.336 660 Q 2.5(fo)69.336 678 S 2.5(r<)-2.5 G
+(Enter> or <control-D> or <control-N> or <do)-2.5 E(wnw)-.25 E(ard-arro)
+-.1 E(w-k)-.25 E -.15(ey)-.1 G 2.5(>m).15 G .423 -.15(ove f)-2.5 H(orw)
+.15 E .123(ard on the page by about)-.1 F
+(an inch \(partial page mode only\))144.336 690 Q 2.5(ho)69.336 708 S
+44.73 2.5(r? d)-2.5 H(isplay help screen)-2.5 E EP
+%%Page: 12 18
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)274.506 48 S 2.5(2-)-2.5 G 67.22(mt)
+69.336 96 S(oggle between partial page and full page modes.)-67.22 E 2.5
+(no)69.336 114 S 2.5(r<)-2.5 G -.15(Pa)-2.5 G(geDo).15 E(wn> go to ne)
+-.25 E(xt page)-.15 E 2.5(po)69.336 132 S 2.5(r<)-2.5 G -.15(Pa)-2.5 G
+11.38(geUp> go).15 F(to pre)2.5 E(vious page)-.25 E 2.5(qo)69.336 150 S
+2.5(rZ)-2.5 G 44.45(Zq)-2.5 G(uit)-44.45 E 71.67(rR)69.336 168 S
+(epaint the page \(useful for e)-71.67 E(xiting help page\))-.15 E 1.554
+(When in X windo)69.336 186 R 1.553
+(ws, the mouse can be used for scrolling. The left b)-.25 F 1.553
+(utton scrolls do)-.2 F(wnw)-.25 E 1.553(ard lik)-.1 F 4.053(et)-.1 G
+1.553(he f)-4.053 F(command, while the right b)69.336 198 Q
+(utton scrolls backw)-.2 E(ards lik)-.1 E 2.5(et)-.1 G(he b command.)
+-2.5 E EP
+%%Page: 13 19
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)274.506 48 S 2.5(3-)-2.5 G 69.336 103
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(4. MUP)73.086 103 R(FILE STR)3.75 E
+(UCTURE)-.45 E 69.336 121 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .283(Mup \214les do not ha)72.119 121 R .583
+-.15(ve t)-.2 H 2.783(of).15 G(ollo)-2.783 E 2.783(wa)-.25 G .583 -.15
+(ny n)-2.783 H .283(aming con).15 F -.15(ve)-.4 G .283
+(ntion, although on systems that use \214le name suf).15 F<8c78>-.25 E
+.284(es to)-.15 F .382(associate a \214le with an application, it is tr\
+aditional to use .mup for the suf)69.336 133 R 2.882(\214x. It)-.25 F
+.381(can also be useful to put a)2.882 F .313
+(special "magic string" on the \214rst line of Mup \214les.)69.336 145 R
+.313(This magic string is completely optional, b)5.313 F .313(ut ha)-.2
+F .313(ving it)-.2 F 2.725(there mak)69.336 157 R 2.725(es it easy for \
+both people and programs to identify the \214le as Mup input.)-.1 F
+2.724(The standard)7.724 F(recommended v)69.336 169 Q
+(alue for this string is:)-.25 E/F1 10/Courier@0 SF(//!Mup-Arkkra)
+105.336 187 Q F0 1.004(with e)69.336 207 R 1.004
+(xactly that spacing and capitalization.)-.15 F 1.004
+(If the \214le uses features of ne)6.004 F 1.004(wer v)-.25 F 1.004
+(ersions of Mup, and thus)-.15 F -.1(wo)69.336 219 S .327(uld not w).1 F
+.327(ork with older v)-.1 F .327
+(ersions, you can add a dash and the minimim v)-.15 F .326
+(ersion number the \214le requires,)-.15 F(as in:)69.336 231 Q F1
+(//!Mup-Arkkra-5.3)105.336 249 Q 69.336 275 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(4.1 Mup)72.836 275 R(General Syntax)3.5 E
+69.336 293 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(An)73.245 293 Q 3.909(yn)-.15 G 1.409
+(umber of spaces and tabs can be put in almost an)-3.909 F 1.41
+(ywhere e)-.15 F 1.41(xcept in the middle of a w)-.15 F 3.91(ord. Each)
+-.1 F .423(statement goes on a separate line.)69.336 305 R .423
+(If for some reason you wish to split a statement onto se)5.423 F -.15
+(ve)-.25 G .422(ral lines, each).15 F -.2(bu)69.336 317 S 2.932(tt).2 G
+.433(he last must end with a "\\" \(backslash\) character)-2.932 F 2.933
+(,t)-.4 G 2.933(ot)-2.933 G .433(ell Mup to treat the ne)-2.933 F .433
+(xt line as a continuation of)-.15 F(the current line.)69.336 329 Q
+(Blank lines can be put between statements to mak)5 E 2.5(et)-.1 G
+(hings easier to read.)-2.5 E 1.245(Comments be)69.336 347 R 1.245
+(gin with tw)-.15 F 3.744(os)-.1 G 1.244(lashes and continue to end of \
+line. All comments will be totally ignored by)-3.744 F
+(Mup, and are for your o)69.336 359 Q
+(wn use to remind yourself of something. F)-.25 E(or e)-.15 E(xample:)
+-.15 E/F1 10/Courier@0 SF
+(// Note: in some early manuscripts, this chord had an accent)105.336
+377 Q F0(Staf)69.336 403 Q
+(fs are numbered from top to bottom, starting at staf)-.25 E 2.5(f1)-.25
+G(.)-2.5 E(Se)69.336 421 Q -.15(ve)-.25 G .407(ral dif).15 F .407(feren\
+t units are used for distances. One is inches or centimeters. \(There i\
+s a units parameter that)-.25 F .624(is used to select which you w)
+69.336 433 R .624(ant to use.\) Another is "stepsizes." One stepsize is\
+ half the distance between)-.1 F(tw)69.336 445 Q 3.053(os)-.1 G(taf)
+-3.053 E 3.053(fl)-.25 G 3.053(ines. In)-3.053 F .554(the horizontal di\
+mension, "counts" are sometimes used. A "count" refers to the musical)
+3.053 F .857(duration of a note with a duration of the denominator \(bo\
+ttom number\) of the time signature.)69.336 457 R .856(The actual)5.856
+F .204(distance on the page will v)69.336 469 R .204
+(ary depending on ho)-.25 F 2.704(wM)-.25 G .205
+(up determines notes should be placed.)-2.704 F .205(When you use a)
+5.205 F 2.194(time signature with tw)69.336 481 R 4.694(oo)-.1 G 4.694
+(rm)-4.694 G 2.193(ore fractions added together)-4.694 F 4.693(,a)-.4 G
+4.693(si)-4.693 G 4.693(n3)-4.693 G 2.193
+(/4 + 3/8, the "count" is the lar)-4.693 F(gest)-.18 E(denominator)
+69.336 493 Q 2.5(,w)-.4 G(hich w)-2.5 E(ould be 8 in the e)-.1 E
+(xample just gi)-.15 E -.15(ve)-.25 G(n.).15 E 1.641(Upper and lo)69.336
+511 R 1.642(wer case letters are not interchangeable. Thus, for e)-.25 F
+1.642(xample, "SCORE" is not the same as)-.15 F("score.")69.336 523 Q
+1.365(Most lines of input end with a semicolon. There are some kinds of\
+ input that do not require an ending)69.336 541 R .324(semicolon, b)
+69.336 553 R .324(ut Mup will allo)-.2 F 2.824(ws)-.25 G .324
+(emicolons on those too, so that if you can')-2.824 F 2.825(tr)-.18 G
+.325(emember if a gi)-2.825 F -.15(ve)-.25 G 2.825(nc).15 G(ommand)
+-2.825 E 2.708(requires a semicolon or not, you can just use one an)
+69.336 565 R(yw)-.15 E(ay)-.1 E 5.208(.F)-.65 G 2.707(or the e)-5.358 F
+2.707(xamples in this User')-.15 F 5.207(sG)-.55 G(uide,)-5.207 E .968
+(semicolons are not used when the)69.336 577 R 3.468(ya)-.15 G .968
+(re not necessary)-3.468 F 3.468(.* Semicolons)-.65 F .968(are not allo)
+3.468 F .968(wed after commands that)-.25 F .605(indicate entering a ne)
+69.336 589 R 3.105(wc)-.25 G(onte)-3.105 E .605(xt \(header)-.15 F 3.105
+(,f)-.4 G(ooter)-3.105 E 3.105(,m)-.4 G .605(usic, staf)-3.105 F .605
+(f, grids, etc.\).)-.25 F 3.106(An)5.606 G -.25(ew)-3.106 G .606
+(line after those commands).25 F
+(is optional, although often a good idea for readability)69.336 601 Q(.)
+-.65 E .961(In music conte)69.336 619 R .961(xt, ne)-.15 F .961(wlines \
+are required to separate commands: music data, bar lines, rolls, comman\
+ds to)-.25 F .537
+(print strings, dynamic marks, lyrics, etc. all must each end with a ne)
+69.336 631 R .537(wline. In grids conte)-.25 F .537(xt and headshape)
+-.15 F(conte)69.336 643 Q 1.797
+(xt, each pair of strings must end with a ne)-.15 F 4.297(wline. In)-.25
+F 1.797(other conte)4.297 F 1.797(xts, there are a fe)-.15 F 4.297(wc)
+-.25 G 1.797(ases where)-4.297 F(ne)69.336 655 Q 2.763(wlines between c\
+ommands are optional, although you may wish to use them an)-.25 F(yw)
+-.15 E 2.763(ay to impro)-.1 F -.15(ve)-.15 G(readability)69.336 667 Q
+(.)-.65 E .082(Mup supports macros and conditionals \(lik)69.336 685 R
+2.582(e')-.1 G -1.95(if ')-2.582 F .082(and 'ifdef)2.582 F .082
+('\) that can be placed an).55 F .081(ywhere in input, e)-.15 F .081
+(xcept in)-.15 F(the middle of w)69.336 697 Q
+(ords, numbers, or strings; the)-.1 E 2.5(yn)-.15 G(eedn')-2.5 E 2.5(tb)
+-.18 G 2.5(eo)-2.5 G 2.5(ns)-2.5 G(eparate lines.)-2.5 E .32 LW 73.336
+716 69.336 716 DL 77.336 716 73.336 716 DL 81.336 716 77.336 716 DL
+85.336 716 81.336 716 DL 89.336 716 85.336 716 DL 93.336 716 89.336 716
+DL 97.336 716 93.336 716 DL 101.336 716 97.336 716 DL 105.336 716
+101.336 716 DL 109.336 716 105.336 716 DL 113.336 716 109.336 716 DL
+117.336 716 113.336 716 DL 121.336 716 117.336 716 DL 125.336 716
+121.336 716 DL 129.336 716 125.336 716 DL 133.336 716 129.336 716 DL
+137.336 716 133.336 716 DL 141.336 716 137.336 716 DL 145.336 716
+141.336 716 DL 149.336 716 145.336 716 DL/F2 8/Times-Roman@0 SF(*)69.336
+733 Q .005
+(The commands on which the ending semicolon is optional are: bar)90.595
+733 R 2.005(,m)-.32 G .005
+(ultirest, setting of parameters, print, left, right, center)-2.005 F
+2.005(,t)-.32 G(itle,)-2.005 E(ne)90.595 744 Q(wscore, ne)-.2 E
+(wpage, line, and curv)-.2 E
+(e. These commands are described in subsequent sections of this User')
+-.12 E 2(sG)-.44 G(uide.)-2 E EP
+%%Page: 14 20
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)274.506 48 S 2.5(4-)-2.5 G .925
+(In a number of statements, Mup e)69.336 96 R .925(xpects a te)-.15 F
+.925(xt string. All strings must be enclosed in double quotes. F)-.15 F
+(or)-.15 E -.15(ex)69.336 108 S(ample:).15 E/F1 10/Courier@0 SF
+("This is a string.")105.336 126 Q("Allegro")105.336 138 Q F0 4.092(As)
+69.336 164 S 1.592(tring can contain an)-4.092 F 4.092(yc)-.15 G 1.592
+(ombination of letters, numbers, spaces, and punctuation.)-4.092 F 1.592
+(It can also contain)6.592 F -.25(va)69.336 176 S .104(rious things tha\
+t will cause printing of special music characters, change font and size\
+, and so forth. Those).25 F(things are co)69.336 188 Q -.15(ve)-.15 G
+(red in the chapter on te).15 E(xt strings.)-.15 E 69.336 206 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(4.2 Contexts)72.836 206 R 69.336 224
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .479(There is al)72.315 224 R -.1(wa)-.1 G
+.479(ys a current Mup "conte).1 F .479(xt" that is in ef)-.15 F 2.979
+(fect. When)-.25 F .479(Mup be)2.979 F .479
+(gins reading input, it is operating)-.15 F .618(in "music" conte)69.336
+236 R .618(xt, which is where music, lyrics, barlines, and other relate\
+d things are described. Y)-.15 F .619(ou can)-1.1 F .343
+(change to another conte)69.336 248 R .343
+(xt by entering its name. A conte)-.15 F .343(xt remains in ef)-.15 F
+.343(fect until another conte)-.25 F .343(xt is named.)-.15 F(The conte)
+69.336 260 Q(xts are:)-.15 E/F1 10/Times-Bold@0 SF(header)69.336 278 Q
+F0(to de\214ne what goes at the top of the \214rst page, typically the \
+title, composer)30.56 E 2.5(,e)-.4 G(tc.)-2.5 E F1 -.25(fo)69.336 296 S
+(oter).25 E F0 .273(to de\214ne what goes at the bottom of the \214rst \
+page, typically a cop)34.71 F .274(yright notice, performance)-.1 F
+(notes, etc.)129.336 308 Q F1(header2)69.336 326 Q F0(to de\214ne what \
+is to be printed on the top of pages after the \214rst page.)25.56 E F1
+-.25(fo)69.336 344 S(oter2).25 E F0(to de\214ne what is to be printed o\
+n the bottom of pages after the \214rst page.)29.71 E F1(top)69.336 362
+Q F0 1.054(to de\214ne what is to be printed on the top of page.)46.11 F
+1.054(This gets printed belo)6.054 F 3.554(wt)-.25 G 1.053
+(he header \(or)-3.554 F .668(header2\), if an)129.336 374 R 4.468 -.65
+(y. I)-.15 H 3.168(ft).65 G .668(he output is not already at the be)
+-3.168 F .669(ginning of a ne)-.15 F 3.169(wp)-.25 G .669(age, a ne)
+-3.169 F 3.169(wp)-.25 G .669(age is)-3.169 F 2.66(started. Unlik)
+129.336 386 R 2.66(eh)-.1 G(eader)-2.66 E 2.66(,w)-.4 G .16
+(hich can only be used once, and is used only on the v)-2.66 F .16
+(ery \214rst page,)-.15 F .086
+(top can be used multiple times. In a song with multiple mo)129.336 398
+R -.15(ve)-.15 G .086(ments, you might use top to put).15 F 2.5(at)
+129.336 410 S(itle at the be)-2.5 E(ginning of each mo)-.15 E -.15(ve)
+-.15 G(ment.).15 E F1(bottom)69.336 428 Q F0 .377
+(to de\214ne what is to be printed on the bottom of page.)29.45 F .377
+(This gets printed abo)5.377 F .677 -.15(ve t)-.15 H .377
+(he footer \(or).15 F .814(footer2\), if an)129.336 440 R 4.614 -.65
+(y. I)-.15 H 3.314(ft).65 G .814(he output is not already at the be)
+-3.314 F .814(ginning of a ne)-.15 F 3.314(wp)-.25 G .815(age, a ne)
+-3.314 F 3.315(wp)-.25 G .815(age is)-3.315 F 2.823(started. Unlik)
+129.336 452 R 2.823(ef)-.1 G(ooter)-2.823 E 2.823(,w)-.4 G .323
+(hich can only be used once, and is used only on the v)-2.823 F .323
+(ery \214rst page,)-.15 F(bottom can be used multiple times.)129.336 464
+Q F1(top2)69.336 482 Q F0 1.345(to de\214ne what is to be printed on th\
+e top of pages, after the page that uses "top.")41.11 F 1.346(If the)
+6.346 F(output is not already at the be)129.336 494 Q(ginning of a ne)
+-.15 E 2.5(wp)-.25 G(age, a ne)-2.5 E 2.5(wp)-.25 G(age is started.)-2.5
+E F1(bottom2)69.336 512 Q F0 .648(to de\214ne what is to be printed on \
+the bottom of pages after the page that uses "bottom.")24.45 F(If)5.647
+E(the output is not already at the be)129.336 524 Q(ginning of a ne)-.15
+E 2.5(wp)-.25 G(age, a ne)-2.5 E 2.5(wp)-.25 G(age is started.)-2.5 E F1
+(block)69.336 542 Q F0(to de\214ne a block that contains te)36.66 E
+(xt rather than music.)-.15 E F1(scor)69.336 560 Q(e)-.18 E F0
+(to de\214ne parameters that apply to the entire score.)37.97 E F1
+(staff)69.336 578 Q/F2 10/Times-Italic@0 SF(S)2.5 E F0
+(to de\214ne parameters to be used for staf)33.62 E(f)-.25 E F2(S)2.5 E
+F0 2.5(,w)C(here)-2.5 E F2(S)2.5 E F0(is a number from 1 to 40.)2.5 E F1
+-.1(vo)69.336 596 S(ice).1 E F2 2.5(SV)2.5 G F0 .318
+(to de\214ne parameters for a particular v)19.83 F(oice)-.2 E F2(V)2.818
+E F0 .318(on staf)2.818 F(f)-.25 E F2(S)2.818 E F0 5.318(.T)C .318(he v)
+-5.318 F(oice)-.2 E F2(V)2.818 E F0 .318(can be either 1, 2, or 3.)2.818
+F F2(S)129.336 608 Q F0(is a staf)2.5 E 2.5(fn)-.25 G
+(umber from 1 to 40.)-2.5 E F1(grids)69.336 626 Q F0
+(to de\214ne grids \(typically for guitar\))38.33 E F1(headshapes)69.336
+644 Q F0 .431(to de\214ne what note head shapes to use for notes of v)
+11.1 F .431(arious durations.)-.25 F .431(This conte)5.431 F .431
+(xt is rarely)-.15 F
+(used, and is described in the chapter on shaped notes.)129.336 656 Q F1
+(music)69.336 674 Q F0 1.598(to de\214ne e)35 F -.15(ve)-.25 G 1.599(ry\
+thing else. This includes notes, lyrics, bar lines, phrase marks, tempo\
+ and).15 F(dynamic marks, etc.)129.336 686 Q 1.023(Most conte)69.336 704
+R 1.022(xts are optional. An input \214le just needs to contain either \
+at least one measure of music or at)-.15 F .11(least one block.)69.336
+716 R(The)5.11 E F1(header)2.61 E 2.61(,f)-.92 G(ooter)-2.86 E 2.61(,h)
+-.92 G(eader2,)-2.61 E F0(and)2.61 E F1 -.25(fo)2.611 G(oter2).25 E F0
+(conte)2.611 E .111(xts may be placed an)-.15 F .111
+(ywhere in the \214le, b)-.15 F(ut)-.2 E 1.208
+(each can be used only once.)69.336 728 R 1.208(The other conte)6.208 F
+1.208(xts may appear an)-.15 F 3.708(yn)-.15 G 1.208
+(umber of times in an)-3.708 F 3.708(yo)-.15 G(rder)-3.708 E 3.707(,a)
+-.4 G 1.207(nd the)-3.707 F(order in which the)69.336 740 Q 2.5(yo)-.15
+G(ccur is signi\214cant in determining the output produced.)-2.5 E EP
+%%Page: 15 21
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)274.506 48 S 2.5(5-)-2.5 G 69.336 103
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(5. B)73.086 103 R(ASIC ST)-.45 E(AND)
+-1.35 E(ARD MUSIC NO)-.525 E -1.35(TA)-.6 G(TION)-.075 E 69.336 121
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .688(Music data is gi)72.524 121 R -.15(ve)
+-.25 G 3.188(ni).15 G 3.188(nt)-3.188 G .688(he "music" conte)-3.188 F
+3.188(xt. F)-.15 F .689
+(or each measure, there is usually one line of input for each)-.15 F -.2
+(vo)69.336 133 S 3.72(ice. At).2 F 1.219(the end of the measure, the ki\
+nd of bar line to be used to end the measure is speci\214ed.)3.719 F
+(This)6.219 E 2.617
+(section describes the input for generating standard music notation.)
+69.336 145 R 2.617(Mup can also generate tablature)7.617 F
+(notation, and that is co)69.336 157 Q -.15(ve)-.15 G(red in the ne).15
+E(xt section.)-.15 E 69.336 175 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(5.1 Specifying)72.836 175 R(chords)3.5 E
+69.336 193 EBEGIN
+0 0 0 setrgbcolor
+EEND 69.336 210 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.1.1 Staf)72.586 210 R 3.25(fa)-.234
+G(nd voice)-3.25 E 69.336 222 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .843(The description of the music for one v)
+72.68 222 R .843(oice be)-.2 F .843(gins with the staf)-.15 F 3.343(fa)
+-.25 G .843(nd v)-3.343 F .843(oice number)-.2 F 3.343(,f)-.4 G(ollo)
+-3.343 E .843(wed by a colon.)-.25 F -.15(Fo)69.336 234 S 2.5(re).15 G
+(xample:)-2.65 E/F1 10/Courier@0 SF 6(31)105.336 252 S(:)-6 E F0 .917(i\
+ndicates that the remainder of the line contains musical information fo\
+r v)69.336 272 R .917(oice 1 of staf)-.2 F 3.418(f3)-.25 G 3.418(.I)
+-3.418 G 3.418(ft)-3.418 G .918(he "v)-3.418 F(oice")-.2 E
+(number is omitted, v)69.336 284 Q(oice 1 is assumed. Thus)-.2 E F1(3:)
+105.336 302 Q F0 .288(is equi)69.336 322 R -.25(va)-.25 G .288
+(lent to the pre).25 F .287(vious e)-.25 F 2.787(xample. Both)-.15 F
+.287(the staf)2.787 F 2.787(fa)-.25 G .287(nd v)-2.787 F .287
+(oice can be gi)-.2 F -.15(ve)-.25 G 2.787(na).15 G 2.787(sal)-2.787 G
+.287(ist. This may be useful if)-2.787 F(se)69.336 334 Q -.15(ve)-.25 G
+(ral staf).15 E(fs ha)-.25 E .3 -.15(ve t)-.2 H
+(he same notes, or multiple v).15 E(oices on a staf)-.2 E 2.5(fh)-.25 G
+-2.25 -.2(av e)-2.5 H(the same notes. F)2.7 E(or e)-.15 E(xample:)-.15 E
+F1(1-4 2:)105.336 352 Q(// voice 2 of staffs 1, 2, 3, and 4)72 E 66
+(1,2,4: //)105.336 364 R(voice 1 of staffs 1, 2, and 4,)6 E
+(1,3,6-7 1-2:)105.336 376 Q(// voices 1 and 2 on staffs 1, 3, 6 and 7)36
+E(5-8 1,2:)105.336 388 Q(// voices 1 and 2 on staffs 5, 6, 7, and 8)24 E
+F0 .887(If you w)69.336 414 R .887(ant notes to go to one v)-.1 F .887
+(oice on some staf)-.2 F .887(fs and a dif)-.25 F .887(ferent v)-.25 F
+.887(oice on others, this can be speci\214ed)-.2 F
+(using an ampersand. F)69.336 426 Q(or e)-.15 E(xample:)-.15 E F1 6
+(11&32)105.336 444 S(:)-6 E F0 1.547(will cause the music to go to v)
+69.336 464 R 1.547(oice 1 of staf)-.2 F 4.047(f1a)-.25 G 4.047(sw)-4.047
+G 1.547(ell as to v)-4.047 F 1.547(oice 2 of staf)-.2 F 4.047(f3)-.25 G
+4.047(.V)-4.047 G 1.547(arious styles can be)-5.157 F(combined:)69.336
+476 Q F1(// Voices 1 and 2 on staff 2,)105.336 494 Q
+(// as well as voice 2 on staff 4)105.336 506 Q
+(// and voice 1 on staffs 6, 7, and 9)105.336 518 Q 6(21)105.336 530 S
+(-2 & 4 2 & 6-7,9 1:)-6 E F0 .29(It is possible to ha)69.336 556 R .59
+-.15(ve u)-.2 H 2.79(pt).15 G 2.79(o4)-2.79 G 2.79(0s)-2.79 G(taf)-2.79
+E .29(fs and up to three v)-.25 F .29(oices per staf)-.2 F 2.79
+(f. While)-.25 F .29(there can be v)2.79 F .29(oice crossings, in)-.2 F
+.572(general v)69.336 568 R .571(oice 1 should be the "top" v)-.2 F .571
+(oice, v)-.2 F .571(oice 2 the "bottom" v)-.2 F .571(oice, and v)-.2 F
+.571(oice 3 the "middle" or "e)-.2 F(xtra")-.15 E -.2(vo)69.336 580 S
+3.434(ice. W).2 F .934(ith the \214rst tw)-.4 F 3.434(ov)-.1 G .935
+(oices, Mup tries hard to a)-3.634 F -.2(vo)-.2 G .935(id an).2 F 3.435
+(y")-.15 G .935(collisions" between notes, rests, and other)-3.435 F
+.268(things. Since v)69.336 592 R .268(oice 3 is an e)-.2 F .268(xtra v)
+-.15 F .267(oice, there are some cases when o)-.2 F -.15(ve)-.15 G .267
+(rlap with the other v).15 F .267(oices is basically)-.2 F(una)69.336
+604 Q -.2(vo)-.2 G(idable, b).2 E(ut there are some techniques discusse\
+d later that let you tweak placement when necessary)-.2 E(.)-.65 E .074
+(As an alternati)69.336 622 R .374 -.15(ve t)-.25 H 2.574(ot).15 G .074
+(his v)-2.574 F .075(oice-at-a-time input style, there is also a chord-\
+at-a-time input style, which will be)-.2 F(co)69.336 634 Q -.15(ve)-.15
+G(red later).15 E(.)-.55 E 69.336 651 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.1.2 Chor)72.586 651 R 3.25(dd)-.481
+G(ur)-3.25 E(ation information)-.195 E 69.336 663 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .513(The rest of the line contains a list o\
+f chords, with a semicolon at the end of each chord. Each chord has a)
+72.35 663 R .136(time v)69.336 675 R 2.636(alue. The)-.25 F .136(time v)
+2.636 F .137
+(alues of all the chords in the line must add up to the time signature.)
+-.25 F -.35(Ti)5.137 G .137(me v).35 F .137(alues are)-.25 F(gi)69.336
+687 Q -.15(ve)-.25 G 2.5(na).15 G 2.5(sf)-2.5 G(ollo)-2.5 E(ws:)-.25 E
+EP
+%%Page: 16 22
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)274.506 48 S 2.5(6-)-2.5 G/F1 10
+/Times-Bold@0 SF 68.055(Input Meaning)191.441 96 R .4 LW 379.231 100.5
+191.441 100.5 DL F0 18.06(1/4 quadruple)197.001 110 R(whole \(not v)2.5
+E(alid for notes\))-.25 E 18.06(1/2 double)197.001 122 R(whole)2.5 E
+24.45(1w)200.891 134 S(hole)-24.45 E 24.45(2h)200.891 146 S(alf)-24.45 E
+24.45(4q)200.891 158 S(uarter)-24.45 E 24.45(8e)200.891 170 S(ighth)
+-24.45 E 19.45(16 sixteenth)198.391 182 R 19.45(32 thirty-second)198.391
+194 R 19.45(64 sixty-fourth)198.391 206 R 16.95(128 128th)195.891 218 R
+16.95(256 256th)195.891 230 R(An)69.336 248 Q 2.692(yo)-.15 G 2.692(ft)
+-2.692 G .192(hese time v)-2.692 F .192(alues can be follo)-.25 F .192
+(wed by one or more dots, to indicate a dotted note. Each dot increases)
+-.25 F(the time v)69.336 260 Q
+(alue by 50% of the preceding note or dot.)-.25 E 1.357
+(It is also possible to specify time as tw)69.336 278 R 3.857(oo)-.1 G
+3.857(rm)-3.857 G 1.357(ore times to be added together)-3.857 F 6.357
+(.F)-.55 G 1.357(or e)-6.507 F 1.357(xample, 2+8 w)-.15 F(ould)-.1 E
+1.096(indicate the time of a half note plus the time of an eighth note,\
+ or in other w)69.336 290 R 1.096(ords, a half note tied to an)-.1 F .11
+(eighth note.)69.336 302 R .11(The e)5.11 F .111
+(xpression can also include subtractions, lik)-.15 F 2.611(e2)-.1 G .111
+(.-16. When subtractions are present, it isn')-2.611 F(t)-.18 E .933
+(clear what time v)69.336 314 R .933(alues you w)-.25 F .933
+(ant Mup to use, so it will start with the lar)-.1 F .932
+(gest possible time v)-.18 F .932(alue and add)-.25 F 1.03
+(enough additional chords to add up to the total. F)69.336 326 R 1.03
+(or e)-.15 F 1.03(xample, if you were to use 1-4, indicating a whole)
+-.15 F .11
+(note minus a quarter note, Mup will use a dotted half note, e)69.336
+338 R -.15(ve)-.25 G 2.609(nt).15 G .109
+(hough there are a number of other w)-2.609 F .109(ays to)-.1 F
+(represent that total time, such as a half note tied to a quarter note.)
+69.336 350 Q .035(If a time v)69.336 368 R .035
+(alue is not speci\214ed for the \214rst chord in a measure for a gi)
+-.25 F -.15(ve)-.25 G 2.535(nv).15 G .035(oice, the def)-2.735 F .035
+(ault timeunit v)-.1 F .035(alue is)-.25 F .217(used. Y)69.336 380 R
+.217(ou can set the def)-1.1 F .217(ault v)-.1 F .217
+(alue using the "timeunit" parameter as described in the "P)-.25 F .216
+(arameters" section.)-.15 F 1.54(If that parameter is not set, the def)
+69.336 392 R 1.541
+(ault is the denominator \(bottom number\) of the time signature.)-.1 F
+-.15(Fo)6.541 G(r).15 E(chords after the \214rst, if a time v)69.336 404
+Q(alue is not speci\214ed, the time v)-.25 E(alue for the pre)-.25 E
+(vious chord is used.)-.25 E 69.336 421 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.1.3 Notes,)72.586 421 R -.481(re)
+3.25 G(sts, or spaces).481 E 69.336 433 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .655(There are three kinds of "chords.")
+72.491 433 R .655(The \214rst type consists of one or more pitches, gi)
+5.655 F -.15(ve)-.25 G 3.155(nb).15 G 3.155(yt)-3.155 G .655
+(he letters "a")-3.155 F .493(through "g".)69.336 445 R -.15(Pa)5.493 G
+.494(rentheses can be placed around the pitch if you w).15 F .494
+(ant the note to be printed in parentheses.)-.1 F 1.792
+(\(If the pitch is modi\214ed by an accidental or octa)69.336 457 R -.15
+(ve)-.2 G 4.292(,w).15 G 1.792(hich will be discussed later)-4.292 F
+4.291(,t)-.4 G 1.791(hose must also be)-4.291 F .02
+(included inside the parentheses.\))69.336 469 R .02
+(The second is a rest, which is designated by the letter r)5.02 F 2.52
+(.T)-.55 G .02(he third type is a)-2.52 F 1.238("space," designated by \
+the letter s. Space is basically a placeholder that tak)69.336 481 R
+1.238(es up time, b)-.1 F 1.238(ut doesn')-.2 F 3.738(tp)-.18 G(rint)
+-3.738 E(an)69.336 493 Q .621(ything. It is useful when a certain v)-.15
+F .622
+(oice only has notes during part of the measure. It can also be useful)
+-.2 F(for specifying "pickup" measures to account for the time before t\
+he \214rst note in the measure. F)69.336 505 Q(or e)-.15 E(xample:)-.15
+E/F1 10/Courier@0 SF(// a pickup measure)105.336 523 Q(1: 2.s;8.c;16d;)
+105.336 535 Q(bar)105.336 547 Q(1: e;g;e;c;)105.336 559 Q(endbar)105.336
+571 Q 127.836 580.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 320 0 rlineto 0 61 neg rlineto closepath stroke grestore
+EEND 160 702 320 320 -61 61 126.836 641.6 PBEGIN
+%%BeginDocument: mugex9.ps
+%%BoundingBox: 160 702 480 763
+save
+192278223 192278013 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+540.29 1235.00 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+220.76 713.00 1.000000 4n
+230.02 716.00 1.000000 dot
+0.70 setlinewidth
+214.53 713.00 moveto
+226.99 713.00 lineto stroke
+224.44 713.75 moveto
+224.44 737.00 lineto stroke
+227.47 737.00 1.000000 dnflag
+254.11 716.00 1.000000 4n
+257.79 716.75 moveto
+257.79 737.00 lineto stroke
+260.82 732.20 1.000000 dnflag
+260.82 737.00 1.000000 dnflag
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+271.55 743.00 moveto
+271.55 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+285.84 719.00 1.000000 4n
+289.52 719.75 moveto
+289.52 740.00 lineto stroke
+330.44 725.00 1.000000 4n
+334.13 725.75 moveto
+334.13 746.00 lineto stroke
+375.05 719.00 1.000000 4n
+378.73 719.75 moveto
+378.73 740.00 lineto stroke
+420.49 713.00 1.000000 4n
+414.26 713.00 moveto
+426.72 713.00 lineto stroke
+424.17 713.75 moveto
+424.17 734.00 lineto stroke
+restore
+%  S_BAR
+7 linenum
+0.70 setlinewidth
+462.50 743.00 moveto
+462.50 719.00 lineto stroke
+3.00 setlinewidth
+466.50 743.00 moveto
+466.50 719.00 lineto stroke
+0.70 setlinewidth
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .072(If all v)69.336 661.6 R .072
+(oices contain spaces, no space is actually tak)-.2 F .072
+(en up on output.)-.1 F .072(Most of the time, this will be what you)
+5.072 F -.1(wa)69.336 673.6 S .062(nt. F).1 F .062(or e)-.15 F .062(xam\
+ple, when you are using space for a pickup, the space is just to add up\
+ to a measure, and you)-.15 F(don')69.336 685.6 Q 3.169(tw)-.18 G .669
+(ant an)-3.269 F 3.169(ya)-.15 G .669(ctual blank space at the be)-3.169
+F .669(ginning of the piece. Once in a while, ho)-.15 F(we)-.25 E -.15
+(ve)-.25 G 1.469 -.4(r, y).15 H .669(ou may w).4 F(ant)-.1 E .166
+(space to actually be allocated on output, perhaps to be able to allo)
+69.336 697.6 R 2.666(ws)-.25 G .167
+(pace for some special notation. In that)-2.666 F(case, you pre\214x th\
+e "s" with a "u" to indicate an uncollapseable space.)69.336 709.6 Q
+(If a gi)69.336 727.6 Q -.15(ve)-.25 G 2.5(nv).15 G
+(oice is omitted for a particular measure, Mup def)-2.7 E
+(aults to a measure of space.)-.1 E EP
+%%Page: 17 23
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)274.506 48 S 2.5(7-)-2.5 G 69.336 100
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.3.1 Measur)72.336 100 R 3(ed)-.444 G
+(ur)-3 E(ation)-.18 E 69.336 112 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .346
+(There is a special duration of "m," which means an entire measure.)
+72.183 112 R .346(It can only be used with a rest, space,)5.346 F
+(or "rpt" \(repeat\). F)69.336 124 Q(or e)-.15 E(xample:)-.15 E/F1 10
+/Courier@0 SF 6(11)105.336 142 S 6(:m)-6 G(r;)-6 E 6(12)105.336 154 S 6
+(:m)-6 G(s;)-6 E F0 3.605(Am)69.336 180 S 1.105(easure rest looks lik)
+-3.605 F 3.605(eaw)-.1 G 1.105(hole rest, b)-3.605 F 1.105
+(ut is centered in the measure.)-.2 F 1.105
+(It should be used when a whole)6.105 F .006(measure is a rest, re)
+69.336 192 R -.05(ga)-.15 G .006(rdless of the time signature.).05 F(Ho)
+5.006 E(we)-.25 E -.15(ve)-.25 G .806 -.4(r, i).15 H 2.505(fy).4 G .005
+(ou w)-2.505 F .005(ant to force use of a symbol other than)-.1 F .466
+(the whole rest symbol, you can specify a duration before the mr)69.336
+204 R 2.966(,a)-.4 G .466(nd the rest symbol for that duration will)
+-2.966 F(be dra)69.336 216 Q(wn instead.)-.15 E F1 12(4mr; //)105.336
+234 R(use a quarter rest symbol)6 E 6(1/4mr; //)105.336 246 R
+(use a quadruple whole rest symbol)6 E(2.. mr;)105.336 258 Q
+(// use a double-dotted half rest)12 E F0 .947(Using "m rpt" will cause\
+ the measure repeat symbol to be printed, indicating the measure is jus\
+t lik)69.336 284 R 3.446(et)-.1 G(he)-3.446 E(pre)69.336 296 Q .842(vio\
+us measure. Measures repeats will automatically be numbered, unless the\
+ numbermrpt parameter is)-.25 F .856
+(set to n. If there is more than one v)69.336 308 R .856
+(oice, you only need to specify the mrpt on v)-.2 F .856
+(oice 1. If you do specify)-.2 F(other v)69.336 320 Q
+(oices as well, the)-.2 E 2.5(ym)-.15 G(ust be either a mrpt or ms.)-2.5
+E F1(1: c;d;e;f;)105.336 338 Q(bar)105.336 350 Q
+(// another measure just like the first)105.336 374 Q(1: m rpt;)105.336
+386 Q(bar)105.336 398 Q(// the space between m and rpt is optional)
+105.336 422 Q(1: mrpt;)105.336 434 Q(bar)105.336 446 Q 127.836 455.6
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 320 0 rlineto 0 61 neg rlineto closepath stroke grestore
+EEND 160 702 320 320 -61 61 126.836 516.6 PBEGIN
+%%BeginDocument: mugex10.ps
+%%BoundingBox: 160 702 480 763
+save
+192278223 192278013 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+540.29 1235.00 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+221.38 713.00 1.000000 4n
+0.70 setlinewidth
+215.15 713.00 moveto
+227.62 713.00 lineto stroke
+225.07 713.75 moveto
+225.07 734.00 lineto stroke
+252.32 716.00 1.000000 4n
+256.01 716.75 moveto
+256.01 737.00 lineto stroke
+283.27 719.00 1.000000 4n
+286.95 719.75 moveto
+286.95 740.00 lineto stroke
+315.04 722.00 1.000000 4n
+318.73 722.75 moveto
+318.73 743.00 lineto stroke
+restore
+%  S_BAR
+5 linenum
+0.70 setlinewidth
+345.17 743.00 moveto
+345.17 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+375.79 731.00 1.000000 measrpt
+/Times-Roman findfont
+11 scalefont
+setfont
+373.05 746.00 moveto
+(2) show
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+406.41 743.00 moveto
+406.41 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+437.03 731.00 1.000000 measrpt
+/Times-Roman findfont
+11 scalefont
+setfont
+434.29 746.00 moveto
+(3) show
+restore
+%  S_BAR
+13 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 534.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.3.2 Accidentals)72.336 534.6 R 69.336
+546.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(Each pitch letter in a chord may be follo)
+71.836 546.6 Q(wed by an accidental.)-.25 E -1.11(Va)5 G
+(lid accidentals are:)1.11 E/F1 10/Times-Bold@0 SF 19.3(Input Meaning)
+240.196 564.6 R .4 LW 330.476 569.1 240.196 569.1 DL/F2 10/Courier@0 SF
+(#)249.146 578.6 Q F0(sharp)23.95 E F2(&)249.146 590.6 Q F0(\215at)23.95
+E F2(x)249.146 602.6 Q F0(double sharp)23.95 E F2(&&)246.146 614.6 Q F0
+(double \215at)20.95 E F2(n)249.146 626.6 Q F0(natural)23.95 E
+(The accidental can be placed inside parentheses if you w)69.336 644.6 Q
+(ant it to be printed within parentheses.)-.1 E 69.336 660.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.3.3 Octave)72.336 660.6 R 69.336
+672.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.847(An octa)73.683 672.6 R 2.147 -.15
+(ve i)-.2 H 1.848(ndicator may be speci\214ed after the pitch letter or\
+ optional accidental.).15 F 1.848(The octa)6.848 F 2.148 -.15(ve c)-.2 H
+1.848(an be).15 F .814(speci\214ed in either of tw)69.336 684.6 R 3.314
+(ow)-.1 G .814(ays: absolute or relati)-3.414 F -.15(ve)-.25 G 3.314
+(.An).15 G .813(umber from 0 to 9 is used to specify an absolute)-3.314
+F(octa)69.336 696.6 Q -.15(ve)-.2 G 3.491(.O).15 G(cta)-3.491 E -.15(ve)
+-.2 G 3.491(sr).15 G .992(un from C up to B. Octa)-3.491 F 1.292 -.15
+(ve 4 i)-.2 H 3.492(st).15 G .992(he octa)-3.492 F 1.292 -.15(ve s)-.2 H
+.992(tarting on middle C. Octa).15 F 1.292 -.15(ve 3 i)-.2 H 3.492(st)
+.15 G .992(he octa)-3.492 F -.15(ve)-.2 G(belo)69.336 708.6 Q 2.5(wt)
+-.25 G(hat, etc.)-2.5 E 2.5(Ar)5 G(elati)-2.5 E .3 -.15(ve o)-.25 H(cta)
+.15 E .3 -.15(ve i)-.2 H 2.5(ss).15 G(peci\214ed by one or more plus or\
+ minus signs, and indicates that number)-2.5 E(of octa)69.336 720.6 Q
+-.15(ve)-.2 G 2.5(sa).15 G(bo)-2.5 E .3 -.15(ve o)-.15 H 2.5(rb).15 G
+(elo)-2.5 E 2.5(wt)-.25 G(he def)-2.5 E(ault octa)-.1 E -.15(ve)-.2 G
+2.5(.F).15 G(or e)-2.65 E(xample:)-.15 E EP
+%%Page: 18 24
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)274.506 48 S 2.5(8-)-2.5 G/F1 10
+/Courier@0 SF 19(c/)105.336 96 S 6(/ci)-19 G 6(nt)-6 G
+(he default octave)-6 E 1(e++ //)105.336 108 R 6(et)6 G
+(wo octaves above default octave)-6 E 14(f#--- //)105.336 120 R
+(f# three octaves below default octave)6 E 1(b&6 //)105.336 132 R 6(bf)6
+G(lat in octave 6)-6 E F0 .423(The def)69.336 158 R .423(ault octa)-.1 F
+.723 -.15(ve c)-.2 H .424(an be set using the "defoct" parameter).15 F
+2.924(,w)-.4 G .424(hich is described in the "P)-2.924 F .424
+(arameters" section.)-.15 F .638(If that parameter is not set, the def)
+69.336 170 R .638(ault octa)-.1 F .938 -.15(ve i)-.2 H 3.138(st).15 G
+.638(he octa)-3.138 F .938 -.15(ve c)-.2 H .637
+(ontaining the note associated with the middle).15 F(line of the staf)
+69.336 182 Q(f, based on the current clef.)-.25 E(In other w)5 E
+(ords, the def)-.1 E(ault octa)-.1 E -.15(ve)-.2 G 2.5(sa).15 G(re:)-2.5
+E/F2 10/Times-Bold@0 SF 32.495(Clef Octa)254.131 200 R -.1(ve)-.25 G .4
+LW 336.536 204.5 234.136 204.5 DL F0 33.7(frenchviolin 5)234.136 214 R
+54.81(8treble 5)234.136 226 R 59.81(treble 4)234.136 238 R 50.92
+(soprano 4)234.136 250 R 24.82(mezzosoprano 4)234.136 262 R 67.58
+(alto 4)234.136 274 R 54.81(treble8 3)234.136 286 R 62.03(tenor 3)
+234.136 298 R 49.81(baritone 3)234.136 310 R 65.36(bass 3)234.136 322 R
+69.336 345 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.1.4 Shorthand)72.586 345 R
+(notations)3.25 E 69.336 357 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .037(If a chord is omitted, the v)71.873 357
+R .037(alues for the pre)-.25 F .038(vious chord are reused. This w)-.25
+F .038(orks for pitches, rests, and spaces.)-.1 F -.15(Fo)69.336 369 S
+3.466(rn).15 G .966(ormal, 5-line staf)-3.466 F .965
+(fs, the pitches for the \214rst chord of e)-.25 F -.15(ve)-.25 G .965
+(ry measure must al).15 F -.1(wa)-.1 G .965(ys be speci\214ed, since).1
+F(there is no pre)69.336 381 Q(vious chord.)-.25 E
+(Putting all these things together)69.336 399 Q 2.5(,h)-.4 G
+(ere are some e)-2.5 E(xamples:)-.15 E/F1 10/Courier@0 SF
+(// Two eighth notes, each b#, followed by an eighth)105.336 417 Q
+(// note d, eighth note e, and half note e, with the)105.336 429 Q
+(// last 3 notes being in the next higher octave.)105.336 441 Q 6(11)
+105.336 453 S 6(:8)-6 G(b#; ; d+; e+; 2;)-6 E
+(// Whole note C-E-G chord in default octave)105.336 477 Q
+(// for voice 2 of staff 1)105.336 489 Q 6(12)105.336 501 S 6(:1)-6 G
+(ceg;)-6 E(// Four quarter notes on staff 2, voice 1.)105.336 525 Q
+(// The last is in the octave above the default octave.)105.336 537 Q
+(2: 4g; a; b; c+;)105.336 549 Q 127.836 558.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 121 rlineto 320 0 rlineto 0 121 neg rlineto closepath stroke grestore
+EEND 160 642 320 320 -121 121 126.836 679.6 PBEGIN
+%%BeginDocument: mugex11.ps
+%%BoundingBox: 160 642 480 763
+save
+192278223 192278013 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+2 linenum
+%  S_FEED
+540.29 1229.00 828.00 5 1.000000 1.000000 stf
+540.29 1175.00 828.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+180.29 737.00 moveto
+180.29 659.00 lineto stroke
+%  S_CLEFSIG
+192.08 719.00 1.000000 gclef
+192.08 665.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+230.48 725.00 1.000000 4n
+219.94 725.00 1.000000 sharp
+234.16 725.75 moveto
+234.16 746.00 lineto stroke
+237.19 746.00 1.000000 dnflag
+262.08 725.00 1.000000 4n
+265.76 725.75 moveto
+265.76 746.00 lineto stroke
+268.78 746.00 1.000000 dnflag
+293.67 731.00 1.000000 4n
+297.36 731.75 moveto
+297.36 752.00 lineto stroke
+300.38 752.00 1.000000 dnflag
+325.24 734.00 1.000000 4n
+328.92 734.75 moveto
+328.92 755.00 lineto stroke
+331.94 755.00 1.000000 dnflag
+361.61 734.00 1.000000 2n
+365.51 734.75 moveto
+365.51 755.00 lineto stroke
+230.48 719.00 1.000000 1n
+230.48 713.00 1.000000 1n
+230.48 707.00 1.000000 1n
+223.06 707.00 moveto
+237.90 707.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+230.48 665.00 1.000000 4n
+0.70 setlinewidth
+234.16 665.75 moveto
+234.16 686.00 lineto stroke
+293.67 668.00 1.000000 4n
+297.36 668.75 moveto
+297.36 689.00 lineto stroke
+361.61 671.00 1.000000 4n
+357.93 670.25 moveto
+357.93 650.00 lineto stroke
+417.47 674.00 1.000000 4n
+413.78 673.25 moveto
+413.78 653.00 lineto stroke
+restore
+%  S_BAR
+17 linenum
+0.70 setlinewidth
+467.65 737.00 moveto
+467.65 713.00 lineto stroke
+467.65 683.00 moveto
+467.65 659.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF -.15(Fo)69.336 699.6 S 2.82(r1).15 G .32
+(-line staf)-2.82 F .32(fs, it is ne)-.25 F -.15(ve)-.25 G 2.82(rn).15 G
+.32(ecessary to specify a pitch, since all notes go on the single staf)
+-2.82 F 2.82(fl)-.25 G .32(ine. Y)-2.82 F .32(ou can,)-1.1 F(ho)69.336
+711.6 Q(we)-.25 E -.15(ve)-.25 G 1.837 -.4(r, s).15 H 1.037
+(pecify a pitch if you wish.).4 F 1.036
+(The pitch will be ignored for the purposes of printing, b)6.036 F 1.036
+(ut will be)-.2 F(used for MIDI output.)69.336 723.6 Q(If you don')5 E
+2.5(ts)-.18 G(pecify a pitch, it is arbitrarily set to middle C.)-2.5 E
+EP
+%%Page: 19 25
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)274.506 48 S 2.5(9-)-2.5 G 69.336 101
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.1.5 Note)72.586 101 R(attrib)3.25 E
+(utes)-.26 E 69.336 113 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .226(There are se)72.062 113 R -.15(ve)-.25
+G .226(ral optional attrib).15 F .226
+(utes that can be speci\214ed for each note.)-.2 F(An)5.227 E 2.727(yo)
+-.15 G 2.727(ra)-2.727 G .227(ll of these may appear on)-2.727 F(an)
+69.336 125 Q 2.5(yn)-.15 G(ote in an)-2.5 E 2.5(yo)-.15 G
+(rder after the letter)-2.5 E 2.5(,a)-.4 G(ccidental, and octa)-2.5 E .3
+-.15(ve s)-.2 H 2.5(peci\214cations. The).15 F 2.5(yi)-.15 G(nclude:)
+-2.5 E 5<8a73>79.336 143 S(mall note head)-5 E 5<8a74>79.336 161 S(ie)-5
+E 5<8a73>79.336 179 S(lurs)-5 E 5<8a68>79.336 197 S(eadshape)-5 E 5
+<8a6c>79.336 215 S(ocation tag)-5 E 69.336 231 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.5.1 Small)72.336 231 R(note head)3 E
+69.336 243 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 2.967(An)72.303 243 S .467
+(ote speci\214cation can be follo)-2.967 F .467(wed by a "?")-.25 F .466
+(to indicate the note is to be printed with a small note head,)5.466 F
+.133(rather than the normal size. \(Note: if you ha)69.336 255 R .433
+-.15(ve s)-.2 H -2.15 -.25(ev e).15 H .133(ral notes in a chord and w)
+.25 F .134(ant all of them to be small, the)-.1 F
+("cue" construct, described later)69.336 267 Q 2.5(,m)-.4 G
+(ay be preferable.\))-2.5 E(Examples:)69.336 285 Q/F1 10/Courier@0 SF
+(// print the "e" as a small note)105.336 303 Q(1: 1c e? g;)105.336 315
+Q(bar)105.336 327 Q(// make the second note small)105.336 351 Q
+(1: f; ?; g; ;)105.336 363 Q(bar)105.336 375 Q 127.836 384.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 320 0 rlineto 0 61 neg rlineto closepath stroke grestore
+EEND 160 702 320 320 -61 61 126.836 445.6 PBEGIN
+%%BeginDocument: mugex12.ps
+%%BoundingBox: 160 702 480 763
+save
+192278223 192278013 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+540.29 1235.00 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+233.49 725.00 1.000000 1n
+233.49 719.00 0.583333 1n
+233.49 713.00 1.000000 1n
+0.70 setlinewidth
+226.07 713.00 moveto
+240.91 713.00 lineto stroke
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+323.06 743.00 moveto
+323.06 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+335.71 722.00 1.000000 4n
+339.40 722.75 moveto
+339.40 743.00 lineto stroke
+368.85 722.00 0.583333 4n
+370.86 722.49 moveto
+370.86 737.00 lineto stroke
+401.71 725.00 1.000000 4n
+405.40 725.75 moveto
+405.40 746.00 lineto stroke
+435.69 725.00 1.000000 4n
+439.38 725.75 moveto
+439.38 746.00 lineto stroke
+restore
+%  S_BAR
+10 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 463.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.5.2 Note)72.336 463.6 R(tie)3 E
+69.336 475.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 2.533(A")71.869 475.6 S .032(~" can be used\
+ to indicate the note is to be tied to the note of the same pitch in th\
+e follo)-2.533 F .032(wing chord. That)-.25 F(follo)69.336 487.6 Q .833
+(wing chord need not be in the same measure, b)-.25 F .834
+(ut it must contain a matching note.)-.2 F .834(\(Note: if a chord)5.834
+F .112(with se)69.336 499.6 R -.15(ve)-.25 G .112(ral notes is to ha).15
+F .412 -.15(ve a)-.2 H .112(ll the notes tied to the follo).15 F .111
+(wing chord, the "tie" construct described later may)-.25 F .36
+(be preferable.\))69.336 511.6 R .36(The ~ may be preceded by the w)5.36
+F .36(ord ')-.1 F .361(dotted' or ')-.5 F .361(dashed' if you w)-.5 F
+.361(ant a dotted or dashed tie;)-.1 F .819
+(otherwise a normal, solid tie is dra)69.336 523.6 R 3.319(wn. The)-.15
+F 3.319(~m)3.319 G .819(ay be follo)-3.319 F .819(wed by the w)-.25 F
+.819(ord 'up' or ')-.1 F(do)-.5 E .819(wn' to specify the)-.25 F .55
+(direction for the curv)69.336 535.6 R(e')-.15 E 3.05(sb)-.55 G .551(ul\
+ge. If neither is speci\214ed, Mup will determine an appropriate direct\
+ion, so you)-3.25 F(only need to gi)69.336 547.6 Q .3 -.15(ve a d)-.25 H
+(irection if you wish to o).15 E -.15(ve)-.15 G(rride Mup').15 E 2.5(sc)
+-.55 G(hoice.)-2.5 E(Examples)69.336 565.6 Q/F1 10/Courier@0 SF
+(1: d~; 8; e~; ; f;)105.336 583.6 Q(bar)105.336 595.6 Q
+(// tie the g \(which also happens)105.336 619.6 Q
+(// to be a "small" note\))105.336 631.6 Q(1: 2g+g?~; 4eg?;)105.336
+643.6 Q(bar)105.336 655.6 Q 127.836 665.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 67 rlineto 320 0 rlineto 0 67 neg rlineto closepath stroke grestore
+EEND 160 696 320 320 -67 67 126.836 732.2 PBEGIN
+%%BeginDocument: mugex13.ps
+%%BoundingBox: 160 696 480 763
+save
+192278223 192278013 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+540.29 1235.00 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+203.87 731.00 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+203.87 718.98 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+233.59 716.00 1.000000 4n
+0.70 setlinewidth
+237.27 716.75 moveto
+237.27 737.00 lineto stroke
+267.03 716.00 1.000000 4n
+270.71 716.75 moveto
+270.71 737.00 lineto stroke
+273.73 737.00 1.000000 dnflag
+288.22 719.00 1.000000 4n
+291.90 719.75 moveto
+291.90 740.00 lineto stroke
+294.92 740.00 1.000000 dnflag
+309.41 719.00 1.000000 4n
+313.09 719.75 moveto
+313.09 740.00 lineto stroke
+316.11 740.00 1.000000 dnflag
+331.43 722.00 1.000000 4n
+335.12 722.75 moveto
+335.12 743.00 lineto stroke
+338.14 743.00 1.000000 dnflag
+290.22 713.90 moveto
+290.29 714.13 lineto
+292.92 712.59 295.76 711.82 298.81 711.82 curveto
+301.86 711.82 304.70 712.59 307.33 714.13 curveto
+307.48 713.67 lineto
+304.96 711.61 302.07 710.58 298.81 710.58 curveto
+295.55 710.58 292.67 711.61 290.14 713.67 curveto
+fill
+235.59 710.90 moveto
+235.63 711.10 lineto
+240.40 709.58 245.30 708.81 250.31 708.81 curveto
+255.32 708.81 260.21 709.58 264.99 711.10 curveto
+265.06 710.70 lineto
+260.36 708.62 255.45 707.59 250.31 707.59 curveto
+245.17 707.59 240.25 708.62 235.55 710.70 curveto
+fill
+restore
+%  S_BAR
+5 linenum
+0.70 setlinewidth
+354.27 743.00 moveto
+354.27 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+372.01 746.00 1.000000 2n
+370.24 725.00 0.583333 2n
+368.12 745.25 moveto
+368.12 704.00 lineto stroke
+434.25 725.00 0.583333 4n
+432.57 719.00 1.000000 4n
+436.25 719.75 moveto
+436.25 746.00 lineto stroke
+372.01 721.40 moveto
+372.03 721.55 lineto
+380.95 719.86 389.94 719.32 398.99 719.93 curveto
+408.05 720.54 416.89 722.28 425.50 725.15 curveto
+425.57 724.85 lineto
+417.11 721.19 408.29 719.06 399.09 718.44 curveto
+389.90 717.82 380.87 718.76 372.00 721.25 curveto
+fill
+restore
+%  S_BAR
+10 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND EP
+%%Page: 20 26
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-2)274.506 48 S 2.5(0-)-2.5 G 69.336 102
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.5.3 Slur)72.336 102 R(s)-.12 E 69.336
+114 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 3.113(An)72.449 114 S .613
+(ote can also be follo)-3.113 F .612
+(wed by a list of notes to be slurred to, enclosed in angle brack)-.25 F
+3.112(ets. A)-.1 F .612(slur will be)3.112 F(dra)69.336 126 Q 1.356
+(wn from the note to each of the notes listed in the angle brack)-.15 F
+1.357(ets. The notes inside the brack)-.1 F 1.357(ets are)-.1 F .003
+(speci\214ed by a pitch and optional octa)69.336 138 R -.15(ve)-.2 G
+2.503(.N).15 G 2.503(oa)-2.503 G .003(ccidentals are speci\214ed, e)
+-2.503 F -.15(ve)-.25 G 2.503(ni).15 G 2.503(ft)-2.503 G .003
+(he note to be slurred to has an)-2.503 F(accidental. Examples:)69.336
+150 Q/F1 10/Courier@0 SF
+(// slur from c of first chord to e of second chord)105.336 168 Q
+(1: c<e>; e; f; g;)105.336 180 Q(bar)105.336 192 Q
+(// slur from c+ of first chord to a& of second chord)105.336 216 Q
+(// and from c+ of first chord to d&+ of second chord)105.336 228 Q
+(1: 2cc+<ad+>; a&d&+;)105.336 240 Q(bar)105.336 252 Q 127.836 261.6
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 64 rlineto 320 0 rlineto 0 64 neg rlineto closepath stroke grestore
+EEND 160 699 320 320 -64 64 126.836 325.6 PBEGIN
+%%BeginDocument: mugex14.ps
+%%BoundingBox: 160 699 480 763
+save
+192278223 192278013 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+540.29 1235.00 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+221.44 713.00 1.000000 4n
+0.70 setlinewidth
+215.21 713.00 moveto
+227.67 713.00 lineto stroke
+225.12 713.75 moveto
+225.12 734.00 lineto stroke
+252.71 719.00 1.000000 4n
+256.39 719.75 moveto
+256.39 740.00 lineto stroke
+283.99 722.00 1.000000 4n
+287.67 722.75 moveto
+287.67 743.00 lineto stroke
+316.10 725.00 1.000000 4n
+319.78 725.75 moveto
+319.78 746.00 lineto stroke
+223.44 707.90 moveto
+223.43 708.11 lineto
+228.17 707.59 232.87 707.84 237.52 708.86 curveto
+242.18 709.89 246.55 711.63 250.63 714.09 curveto
+250.80 713.71 lineto
+246.91 710.73 242.57 708.71 237.79 707.66 curveto
+233.00 706.61 228.22 706.62 223.44 707.69 curveto
+fill
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+346.50 743.00 moveto
+346.50 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+359.39 734.00 1.000000 2n
+359.39 713.00 1.000000 2n
+352.94 713.00 moveto
+365.84 713.00 lineto stroke
+363.29 713.75 moveto
+363.29 755.00 lineto stroke
+417.90 737.00 1.000000 2n
+408.91 737.00 1.000000 flat
+417.90 728.00 1.000000 2n
+405.92 728.00 1.000000 flat
+414.00 736.25 moveto
+414.00 707.00 lineto stroke
+365.64 739.10 moveto
+365.60 739.25 lineto
+373.56 742.65 381.86 744.60 390.50 745.12 curveto
+399.14 745.63 407.61 744.68 415.91 742.25 curveto
+415.89 741.95 lineto
+407.52 743.57 399.09 744.13 390.59 743.62 curveto
+382.08 743.11 373.78 741.56 365.67 738.95 curveto
+fill
+365.64 734.00 moveto
+365.64 734.19 lineto
+371.58 735.27 377.52 735.29 383.47 734.26 curveto
+389.42 733.23 395.01 731.20 400.24 728.18 curveto
+400.12 727.82 lineto
+394.73 730.30 389.11 732.04 383.26 733.06 curveto
+377.42 734.07 371.54 734.33 365.63 733.81 curveto
+fill
+restore
+%  S_BAR
+11 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF 1.424
+(If there is only one note in the follo)69.336 345.6 R 1.424
+(wing chord, it isn')-.25 F 3.924(tn)-.18 G 1.424(ecessary to e)-3.924 F
+1.425(xplicitly state it within the angle)-.15 F(brack)69.336 357.6 Q
+(ets; "<>" will suf)-.1 E(\214ce.)-.25 E/F1 10/Courier@0 SF
+(// slur from c to d, and f to g)105.336 375.6 Q(1: c<>; d; f<>; g;)
+105.336 387.6 Q(bar)105.336 399.6 Q 163.836 409.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 64 rlineto 248 0 rlineto 0 64 neg rlineto closepath stroke grestore
+EEND 200 699 248 248 -64 64 162.836 473.2 PBEGIN
+%%BeginDocument: mugex15.ps
+%%BoundingBox: 200 699 448 763
+save
+3977375 3978157 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+576.29 875.00 648.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+228.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+259.49 713.00 1.000000 4n
+0.70 setlinewidth
+253.25 713.00 moveto
+265.72 713.00 lineto stroke
+263.17 713.75 moveto
+263.17 734.00 lineto stroke
+303.05 716.00 1.000000 4n
+306.73 716.75 moveto
+306.73 737.00 lineto stroke
+346.61 722.00 1.000000 4n
+350.29 722.75 moveto
+350.29 743.00 lineto stroke
+391.01 725.00 1.000000 4n
+394.69 725.75 moveto
+394.69 746.00 lineto stroke
+348.61 716.90 moveto
+348.62 717.07 lineto
+355.37 715.87 362.15 715.53 368.99 716.03 curveto
+375.82 716.54 382.48 717.89 388.97 720.07 curveto
+389.05 719.73 lineto
+382.69 716.90 376.03 715.22 369.08 714.71 curveto
+362.14 714.19 355.31 714.86 348.60 716.73 curveto
+fill
+261.49 707.90 moveto
+261.50 708.07 lineto
+268.11 706.91 274.75 706.58 281.44 707.09 curveto
+288.13 707.59 294.65 708.92 301.01 711.07 curveto
+301.09 710.73 lineto
+294.86 707.95 288.34 706.29 281.54 705.78 curveto
+274.74 705.26 268.05 705.91 261.47 707.73 curveto
+fill
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+431.65 743.00 moveto
+431.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .778(The < may be preceded by the w)
+69.336 493.2 R .778(ord ')-.1 F .778(dotted' or ')-.5 F .778
+(dashed' if you w)-.5 F .778(ant a dotted or dashed slur)-.1 F 3.278(,o)
+-.4 G .778(therwise a)-3.278 F .259(normal, solid slur is dra)69.336
+505.2 R 2.759(wn. The)-.15 F 2.759(>m)2.759 G .259(ay be follo)-2.759 F
+.259(wed by the w)-.25 F .259(ord 'up' or ')-.1 F(do)-.5 E .259
+(wn' to specify the direction for)-.25 F .535(the curv)69.336 517.2 R
+(e')-.15 E 3.035(sb)-.55 G .534(ulge. If neither is speci\214ed, Mup wi\
+ll determine an appropriate direction, so you only need to)-3.235 F(gi)
+69.336 529.2 Q .3 -.15(ve a d)-.25 H(irection if you wish to o).15 E
+-.15(ve)-.15 G(rride Mup').15 E 2.5(sc)-.55 G(hoice.)-2.5 E .688(There \
+are four special "slurs" which are really slides to/from an inde\214nit\
+e note. The)69.336 547.2 R 3.188(ya)-.15 G .689(re most commonly)-3.188
+F 1.265(used on tablature staf)69.336 559.2 R 1.265(fs, b)-.25 F 1.265
+(ut are allo)-.2 F 1.265(wed on ordinary staf)-.25 F 1.265(fs too.)-.25
+F(The)6.265 E 3.765(ya)-.15 G 1.265(re: </n> <\\n> <n/> and <n\\> for)
+-3.765 F .761(sliding upw)69.336 571.2 R .761(ard into the note, do)-.1
+F(wnw)-.25 E .762(ard into the note, upw)-.1 F .762
+(ard out from the note, and do)-.1 F(wnw)-.25 E .762(ard out from)-.1 F
+.376(the note respecti)69.336 583.2 R -.15(ve)-.25 G(ly).15 E 2.876(.T)
+-.65 G .376(hese ha)-2.876 F .676 -.15(ve t)-.2 H 2.876(ob).15 G 2.876
+(ei)-2.876 G 2.876(na)-2.876 G .376(ngle brack)-2.876 F .376
+(ets by themselv)-.1 F .375(es, so if you w)-.15 F .375(ant to ha)-.1 F
+.675 -.15(ve b)-.2 H .375(oth one of).15 F(these slides and another slu\
+r on the same note, multiple sets of angle brack)69.336 595.2 Q
+(ets must be used, as in)-.1 E/F1 10/Courier@0 SF(1: 2c</n><d>;d;)
+105.336 613.2 Q 69.336 637.2 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.5.4 Head)72.336 637.2 R(shape)3 E
+69.336 649.2 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.084(Sometimes you may w)72.92 649.2 R
+1.084(ant to mix head shapes on a single stem.)-.1 F -.15(Fo)6.085 G
+3.585(re).15 G 1.085(xample, you might w)-3.735 F 1.085(ant to use a)-.1
+F .161(diamond to designate a harmonic, with other notes in the same ch\
+ord being normal shape.)69.336 661.2 R .161(There will be an)5.161 F
+1.724(entire section on head shapes, so only a simple e)69.336 673.2 R
+1.724(xample is gi)-.15 F -.15(ve)-.25 G 4.224(nh).15 G 4.224(ere. T)
+-4.224 F 4.224(om)-.8 G(ak)-4.224 E -6.723 4.224(ea s)-.1 H 1.725
+(ingle note ha)-4.224 F 2.025 -.15(ve a)-.2 H(dif)69.336 685.2 Q
+(ferent head shape, use hs follo)-.25 E
+(wed by the name of the shape in quotes.)-.25 E/F1 10/Courier@0 SF
+(1: 2e e+ hs "diam";g;)105.336 703.2 Q EP
+%%Page: 21 27
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-2)274.506 48 S 2.5(1-)-2.5 G 69.336 100
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.5.5 Note)72.336 100 R(location ta)3 E
+(g)-.12 E 69.336 112 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(Finally)71.985 112 Q 2.649(,a")-.65 G .149
+(location tag" can be associated with a note. This w)-2.649 F .148
+(ould enable you to dra)-.1 F 2.648(wt)-.15 G .148(hings relati)-2.648 F
+.448 -.15(ve t)-.25 H 2.648(ot).15 G(he)-2.648 E 2.5(note. A)69.336 124
+R(note location tag is set by using an "=" follo)2.5 E
+(wed by a name. The name can be either:)-.25 E 5<8a61>79.336 142 S
+(single lo)-2.5 E(wer case letter)-.25 E 5<8a61>79.336 160 S 2.5(nu)-5 G
+(nderscore follo)-2.5 E
+(wed by one or more letters, numbers, and underscores in an)-.25 E 2.5
+(yc)-.15 G(ombination.)-2.5 E(The name is arbitrary)69.336 184 Q 2.5(,a)
+-.65 G(nd is used as a tag that can be referred to later)-2.5 E 2.5(.E)
+-.55 G(xamples:)-2.5 E/F1 10/Courier@0 SF
+(// associate tag p with note e&)105.336 202 Q(3: 2c; e& =p g;)105.336
+214 Q(// associate tag _end with note f)105.336 238 Q(2: 1f =_end;)
+105.336 250 Q 69.336 275 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.1.6 Chor)72.586 275 R 3.25(da)-.481
+G(ttrib)-3.25 E(utes)-.26 E 69.336 287 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .541(There are optional attrib)72.377 287 R
+.542(utes that are associated with an entire chord rather than an indi)
+-.2 F .542(vidual note. These)-.25 F 1.61(are put inside square brack)
+69.336 299 R 1.609(ets before the list of notes and the time v)-.1 F
+4.109(alue. There)-.25 F 1.609(are se)4.109 F -.15(ve)-.25 G 1.609
+(ral classes of).15 F(information:)69.336 311 Q 5<8a63>79.336 329 S
+(hord style \(grace, cue, diam, or xnote\))-5 E 5<8a68>79.336 347 S
+(ead shape)-5 E 5<8a73>79.336 365 S(ymbols to be printed with a chord)-5
+E 5<8a73>79.336 383 S(lashes)-5 E 5<8a73>79.336 401 S(tem direction)-5 E
+5<8a73>79.336 419 S(tem length)-5 E 5<8a70>79.336 437 S(adding)-5 E 5
+<8a63>79.336 455 S(hord location tag)-5 E 5<8a68>79.336 473 S
+(orizontal of)-5 E(fset)-.25 E 5<8a72>79.336 491 S(est distance)-5 E
+1.381(Each class of information is separated from the other by a semico\
+lon. All classes are optional, and can)69.336 509 R(occur in an)69.336
+521 Q 2.5(yo)-.15 G(rder)-2.5 E(.)-.55 E 69.336 537 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.6.1 Chor)72.336 537 R 3(ds)-.444 G
+(tyle)-3 E 69.336 549 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(Se)72.439 549 Q -.15(ve)-.25 G .603
+(ral chord styles can be speci\214ed.).15 F .603
+(Grace note chords are designated by the w)5.603 F .602
+(ord "grace," or cue note)-.1 F .347(chords by "cue.")69.336 561 R .347
+(Grace notes can be speci\214ed as an)5.347 F 2.847(yu)-.15 G .347
+(ndotted time v)-2.847 F .348(alue of eighth note or shorter)-.25 F
+2.848(,b)-.4 G .348(ut are)-3.048 F .016
+(treated as taking no time. The time v)69.336 573 R .015(alue gi)-.25 F
+-.15(ve)-.25 G 2.515(ni).15 G 2.515(sm)-2.515 G .015
+(erely used to specify ho)-2.515 F 2.515(wm)-.25 G(an)-2.515 E 2.515
+<798d>-.15 G .015(ags or beams to put on)-2.515 F .708(the grace note.)
+69.336 585 R -1.1(Yo)5.709 G 3.209(uc)1.1 G .709(an also specify a quar\
+ter note grace note, which will be printed as a small, stemless)-3.209 F
+1.509(note, as is used to sho)69.336 597 R 4.009(wa")-.25 G 1.509
+(prebend" in guitar music.)-4.009 F(\(Actually)6.509 E 4.009(,y)-.65 G
+1.509(ou can force a stem if you w)-4.009 F 1.509(ant, by)-.1 F .306
+(specifying a len, as is described later)69.336 609 R 2.807(.\) Cue)-.55
+F .307(notes ha)2.807 F .607 -.15(ve t)-.2 H .307(ime lik).15 F 2.807
+(er)-.1 G -.15(eg)-2.807 G .307(ular notes, b).15 F .307(ut the)-.2 F
+2.807(ya)-.15 G .307(re printed smaller)-2.807 F(.)-.55 E 1.372
+(If there are se)69.336 621 R -.15(ve)-.25 G 1.371
+(ral grace notes in a ro).15 F 2.671 -.65(w, t)-.25 H(he).65 E 3.871(yw)
+-.15 G 1.371(ill be beamed automatically)-3.871 F 6.371(.H)-.65 G -.25
+(ow)-6.371 G -2.15 -.25(ev e).25 H 2.171 -.4(r, y).25 H 1.371
+(ou cannot mix).4 F .103
+(quarter \(stemless\) grace notes with shorter ones.)69.336 633 R .103
+(Cue notes follo)5.103 F 2.603(wt)-.25 G .103
+(he same beaming rules as re)-2.603 F .104(gular notes.)-.15 F 1.503
+(It is also possible to specify "diam," or "xnote.")69.336 651 R 1.502
+(In the case of "diam," the chords will be dra)6.503 F 1.502(wn with)
+-.15 F 1.697
+(diamond-shaped notes, while with "xnote," the chords will be dra)69.336
+663 R 1.697(wn with X-shaped notes. A diamond)-.15 F
+(shaped note head will be used for xnotes that are half note or longer)
+69.336 675 Q 5(.H)-.55 G(ere are some e)-5 E(xamples:)-.15 E/F1 10
+/Courier@0 SF([grace])105.336 693 Q([xnote])105.336 705 Q([cue; xnote])
+105.336 717 Q([diam])105.336 729 Q EP
+%%Page: 22 28
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-2)274.506 48 S 2.5(2-)-2.5 G 69.336 100
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.6.2 Head)72.336 100 R(shape)3 E
+69.336 112 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.694(If you w)73.53 112 R 1.694(ant to ha)
+-.1 F 1.993 -.15(ve t)-.2 H 1.693(he note heads in a chord use a shape \
+other than the normal shapes, you use hs).15 F(follo)69.336 124 Q .241
+(wed by the name of the head shape in quotes.)-.25 F .241
+(There will be an entire section on shaped notes, so only)5.241 F .067
+(the basics are co)69.336 136 R -.15(ve)-.15 G .067
+(red here. The xnote and diam described abo).15 F .367 -.15(ve a)-.15 H
+.067(re really just shorthands for tw).15 F 2.567(oc)-.1 G(ommon)-2.567
+E(head shapes.)69.336 148 Q(The method using hs lets you use man)5 E 2.5
+(yo)-.15 G(ther note head styles, such as a slash, or triangle.)-2.5 E
+/F1 10/Courier@0 SF(1: [hs "righttri"]cf; [hs "slash"]fa;)105.336 166 Q
+F0 .78(The section on shaped notes lists all the b)69.336 192 R .78
+(uiltin head shape names, and e)-.2 F .78(xplains ho)-.15 F 3.28(wy)-.25
+G .78(ou can de\214ne your)-3.28 F -.25(ow)69.336 204 S(n.).25 E 69.336
+220 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.6.3 Symbols)72.336 220 R
+(to be printed with a c)3 E(hor)-.18 E(d)-.444 E 69.336 232 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .937
+(It is possible to specify one or more musical symbols or te)72.773 232
+R .936(xt strings to be printed with a chord.)-.15 F .936(This is)5.936
+F .102(typically used for things lik)69.336 244 R 2.603(es)-.1 G .103
+(taccato and accent marks. The w)-2.603 F .103(ord "with" is follo)-.1 F
+.103(wed by one or more things)-.25 F .366
+(to print. If there are more than one, the)69.336 256 R 2.865(ya)-.15 G
+.365(re separated by commas. The)-2.865 F 2.865(yw)-.15 G .365
+(ill be printed outw)-2.865 F .365(ards from the)-.1 F .421
+(notes in the order speci\214ed.)69.336 268 R .421
+(The "with" list is only allo)5.421 F .422
+(wed on note groups, not rests.)-.25 F .422(The list can include)5.422 F
+(symbols from the follo)69.336 280 Q(wing table:)-.25 E/F1 10
+/Times-Bold@0 SF 12.5(Symbol Meaning)242.831 298 R .4 LW 327.841 302.5
+242.831 302.5 DL/F2 10/Courier@0 SF(.)255.946 312 Q F0(staccato)30.9 E
+F2(-)255.946 324 Q F0(le)34.885 E -.05(ga)-.15 G(to).05 E F2(>)255.946
+336 Q F0(accent)34.235 E F2(^)255.946 348 Q F0(accent)34.235 E 3.445(Aq)
+69.336 366 S .944(uoted string can also be speci\214ed \(e.g., "f)-3.445
+F .944(f", "adagio", etc.\).)-.25 F .944
+(This will be printed in the font and size)5.944 F 1.345
+(speci\214ed by the "fontf)69.336 378 R(amily)-.1 E 1.345
+(," "font," and "size" parameters. An)-.65 F 3.845(yo)-.15 G 3.845(ft)
+-3.845 G 1.346(he special music characters can be)-3.845 F 1.332
+(printed by using the usual con)69.336 390 R -.15(ve)-.4 G 1.331
+(ntion, e.g., \\\(ferm\) for a fermata.).15 F 1.331
+(\(This is described in a later section.\))6.331 F(Ho)69.336 402 Q(we)
+-.25 E -.15(ve)-.25 G 1.265 -.4(r, i).15 H 2.965(ti).4 G 2.965(su)-2.965
+G .465(sually preferable to use the printing of te)-2.965 F .466
+(xt strings relati)-.15 F .766 -.15(ve t)-.25 H 2.966(ob).15 G 2.966
+(eats. This)-2.966 F .466(will be described)2.966 F(in a later section.)
+69.336 414 Q(Here are some e)69.336 432 Q(xamples:)-.15 E F2
+([with ., -])105.336 450 Q([with ^, "\\\(ferm\)"])105.336 462 Q
+([with "sfz"; cue])105.336 474 Q F0 1.639
+(If the symbols acc_hat, ferm, or wedge are used by themselv)69.336 500
+R 1.638(es in a "with" list item, the)-.15 F 4.138(ya)-.15 G 1.638
+(re handled)-4.138 F(specially)69.336 512 Q 2.735(.I)-.65 G 2.735(ft)
+-2.735 G .235(he stem direction is such that the upside do)-2.735 F .235
+(wn v)-.25 F .235(ersions of these characters should be used, the)-.15 F
+(upside do)69.336 524 Q(wn v)-.25 E(ersion will be used.)-.15 E 69.336
+540 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.6.4 Slashes)72.336 540 R 69.336 552
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(Diagonal lines to be dra)71.836 552 Q
+(wn through the stem of the group can be speci\214ed using)-.15 E/F1 10
+/Courier@0 SF(slash)105.336 570 Q/F2 10/Times-Italic@0 SF(N)6 E F0
+(where)69.336 590 Q F2(N)2.699 E F0 .199
+(is the number of slashes to dra)2.699 F 1.498 -.65(w. I)-.15 H 2.698
+(nt).65 G .198(he case of grace notes,)-2.698 F F2(N)2.698 E F0 .198
+(can only be 1, which will produce a)2.698 F .53
+(grace note with a slash through it.)69.336 602 R .531
+(In the case of other notes,)5.531 F F2(N)3.031 E F0 .531
+(can be 1 or greater)3.031 F 3.031(,a)-.4 G .531(nd is used to specify)
+-3.031 F(tremolo or repetition of the note group. Examples:)69.336 614 Q
+F1([slash 2])105.336 632 Q([grace; slash 1])105.336 644 Q 69.336 668
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.6.5 Stem)72.336 668 R(dir)3 E(ection)
+-.444 E 69.336 680 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .581
+(The chord stem direction can be speci\214ed as "up" or "do)72.418 680 R
+3.081(wn". Normally)-.25 F .581(Mup chooses the stem direction,)3.081 F
+-.2(bu)69.336 692 S 2.816(to).2 G .316(nce in a while you may w)-2.816 F
+.316(ant to o)-.1 F -.15(ve)-.15 G .316
+(rride its choice. There are some restrictions.).15 F -1.1(Yo)5.317 G
+2.817(uc)1.1 G .317(annot specify a)-2.817 F .058(direction on grace no\
+tes. All chords beamed together and the pair of chords in an alternatio\
+n pair \(described)69.336 704 R(later\) must ha)69.336 716 Q .3 -.15
+(ve t)-.2 H(he same stem direction.).15 E(Examples:)5 E EP
+%%Page: 23 29
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-2)274.506 48 S 2.5(3-)-2.5 G/F1 10
+/Courier@0 SF([up])105.336 96 Q([down])105.336 108 Q F0 -.15(Fo)69.336
+134 S 2.695(rv).15 G .195(oice 3, stem direction w)-2.895 F .195
+(orks a little dif)-.1 F(ferently)-.25 E 2.695(.B)-.65 G 2.695(yd)-2.695
+G(ef)-2.695 E .195(ault, the stem direction for v)-.1 F .195
+(oice 3 is up, b)-.2 F .195(ut for)-.2 F -.2(vo)69.336 146 S 1.388
+(ice 3 on an).2 F 3.888(yg)-.15 G -2.15 -.25(iv e)-3.888 H 3.888(ns).25
+G(taf)-3.888 E 1.388
+(f, when you specify a stem direction, that direction will remain in ef)
+-.25 F 1.387(fect until)-.25 F -.15(ex)69.336 158 S .17
+(plicitly changed.).15 F .171(Thus, for e)5.171 F .171(xample, if you w)
+-.15 F .171(ant all v)-.1 F .171(oice 3 stems on a gi)-.2 F -.15(ve)-.25
+G 2.671(ns).15 G(taf)-2.671 E 2.671(fi)-.25 G 2.671(na)-2.671 G 2.671
+(ne)-2.671 G .171(ntire song to be)-2.671 F(do)69.336 170 Q
+(wn, you only need to specify "[do)-.25 E(wn]" on the \214rst chord.)
+-.25 E 69.336 186 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.6.6 Stem)72.336 186 R(len)3 E 69.336
+198 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(Normally)72.347 198 Q 3.011(,M)-.65 G .511
+(up sets stem lengths as appropriate, b)-3.011 F .511
+(ut sometimes you might w)-.2 F .51(ant to mak)-.1 F 3.01(eas)-.1 G .51
+(tem longer or)-3.01 F 2.588
+(shorter than normal. This is done with the k)69.336 210 R -.15(ey)-.1 G
+-.1(wo).15 G 2.589(rd "len" follo).1 F 2.589
+(wed by a length in stepsizes.)-.25 F(Some)7.589 E -.15(ex)69.336 222 S
+(amples:).15 E/F1 10/Courier@0 SF 6([l)105.336 240 S(en 14 ])-6 E 6([l)
+105.336 252 S(en 7; up ])-6 E F0 -1.1(Yo)69.336 278 S 2.93(uc)1.1 G .429
+(annot specify stem length on chords inside of beams.)-2.93 F .429
+(The len can be set to 0 to produce a note head)5.429 F
+(with no stem at all.)69.336 290 Q .533
+(There is a stemlen parameter that can be used to set the def)69.336 308
+R .533(ault stem length.)-.1 F .533(If you don')5.533 F 3.033(tw)-.18 G
+.533(ant an)-3.133 F 3.033(ys)-.15 G(tems,)-3.033 E
+(setting that parameter to 0 is more con)69.336 320 Q -.15(ve)-.4 G
+(nient than setting len to 0 on each chord indi).15 E(vidually)-.25 E(.)
+-.65 E 1.781(On beamed chords, Mup will sometimes shorten a stem slight\
+ly from its normal minimum length. By)69.336 338 R(def)69.336 350 Q .662
+(ault it will ne)-.1 F -.15(ve)-.25 G 3.162(rs).15 G .663
+(horten by more than one stemsize, b)-3.162 F .663
+(ut there is a stemshorten parameter that lets you)-.2 F .177(adjust ho)
+69.336 362 R 2.677(wm)-.25 G .177(uch it will shorten. If you don')
+-2.677 F 2.677(tw)-.18 G .176(ant Mup to e)-2.777 F -.15(ve)-.25 G 2.676
+(rs).15 G .176(horten stems, you can set this parameter to)-2.676 F
+(zero.)69.336 374 Q 69.336 390 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.6.7 P)72.336 390 R(adding)-.96 E
+69.336 402 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .322
+(Sometimes it may be desirable to space notes some)72.157 402 R .322
+(what dif)-.25 F .322(ferently than Mup w)-.25 F .322
+(ould normally place them.)-.1 F 1.806
+(It is possible to specify "padding" before an)69.336 414 R 4.306(yn)
+-.15 G 1.806(ote group.)-4.306 F 1.806(This is done by specifying the w)
+6.806 F 1.805(ord "pad")-.1 F(follo)69.336 426 Q 1.149(wed by a number \
+of stepsizes of white space padding to add before the chord.)-.25 F
+1.149(The number can be)6.149 F(fractional, as in 0.5 or 2.25.)69.336
+438 Q -.15(Fo)5 G 2.5(re).15 G(xample:)-2.65 E/F1 10/Courier@0 SF 6([p)
+105.336 456 S(ad 2.5 ])-6 E F0 .752(The padding can also be ne)69.336
+482 R -.05(ga)-.15 G(ti).05 E -.15(ve)-.25 G 3.252(.P).15 G .752
+(adding af)-3.402 F .752
+(fects the minimum amount of width allocated to a chord, so)-.25 F 1.094
+(you can use positi)69.336 494 R 1.394 -.15(ve p)-.25 H 1.094(adding v)
+.15 F 1.095(alues to force additional room in front of a chord, or ne)
+-.25 F -.05(ga)-.15 G(ti).05 E 1.395 -.15(ve p)-.25 H 1.095(adding to)
+.15 F(allo)69.336 506 Q 2.5(wt)-.25 G(hings closer together)-2.5 E(.)
+-.55 E 69.336 522 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.6.8 Chor)72.336 522 R 3(dl)-.444 G
+(ocation ta)-3 E(g)-.12 E 69.336 534 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .685(It is possible to set a location tag w\
+hich is associated with an entire chord rather than an indi)72.521 534 R
+.684(vidual note.)-.25 F .745(This tag is speci\214ed lik)69.336 546 R
+3.245(el)-.1 G .745(ocation tags for notes, with an "=" follo)-3.245 F
+.745(wed by a name, b)-.25 F .745(ut is inside the square)-.2 F(brack)
+69.336 558 Q(ets rather than after a note.)-.1 E/F1 10/Courier@0 SF
+(3: 2cf; [=h] egc+;)105.336 576 Q(1: [cue; with >; =_ch] fa;)105.336 588
+Q 69.336 612 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.6.9 Horizontal)72.336 612 R(of)3 E
+(fset)-.216 E 69.336 624 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 3.259(Ah)72.595 624 S .759(orizontal of)
+-3.259 F .759(fset can be applied to a chord by specifying "ho" follo)
+-.25 F .759(wed by a number of stepsizes. The)-.25 F 1.332
+(number can be positi)69.336 636 R 1.632 -.15(ve o)-.25 H 3.832(rn).15 G
+-2.25 -.15(eg a)-3.832 H(ti).15 E -.15(ve)-.25 G 3.832(,a).15 G 1.332
+(nd can include a fractional part. A positi)-3.832 F 1.633 -.15(ve n)
+-.25 H 1.333(umber will cause the).15 F .489(chord to be placed that f)
+69.336 648 R .489
+(ar right of where the horizontal center of the chord w)-.1 F .489
+(ould normally be; a ne)-.1 F -.05(ga)-.15 G(ti).05 E -.15(ve)-.25 G .14
+(number will place it that f)69.336 660 R .141(ar to the left.)-.1 F
+.141
+(It is also possible to simply specify a "+" or "-" which says to place)
+5.141 F(the chord to the right or left, as close as possible without ru\
+nning into something.)69.336 672 Q 3.318(Ah)69.336 690 S .818
+(orizontal of)-3.318 F .818(fset is most commonly used on the third v)
+-.25 F .818(oice of a staf)-.2 F .818
+(f, although it can be used on other)-.25 F -.2(vo)69.336 702 S 1.968
+(ices too.).2 F 1.969(By def)6.968 F 1.969(ault, Mup places third v)-.1
+F 1.969(oice chords as close as it thinks is safe for a)-.2 F -.2(vo)-.2
+G 1.969(iding most).2 F .113(collisions. Sometimes it may actually be o\
+kay visually to place the chord a little closer than that, or perhaps)
+69.336 714 R 1.193
+(there is a better "nook" to tuck it into on the left side.)69.336 726 R
+1.194(By specifying a horizontal of)6.194 F 1.194(fset, you can place)
+-.25 F .14(chords an)69.336 738 R .14(ywhere you w)-.15 F 2.64(ant. Mup)
+-.1 F(mak)2.64 E .14(es no checks to a)-.1 F -.2(vo)-.2 G .14
+(id collisions when you specify a horizontal of).2 F(fset,)-.25 E EP
+%%Page: 24 30
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-2)274.506 48 S 2.5(4-)-2.5 G
+(so this attrib)69.336 96 Q(ute needs to be used with some care.)-.2 E
+(Here is an e)69.336 114 Q(xample of the use of horizontal of)-.15 E
+(fset and stem direction on v)-.25 E(oice 3.)-.2 E/F1 10/Courier@0 SF
+(score)105.336 132 Q(vscheme=3f)117.336 144 Q(music)105.336 168 Q 6(11)
+105.336 180 S 6(:c)-6 G(+;b;a;c+;)-6 E 6(12)105.336 192 S 6(:e)-6 G
+(;d;e;f;)-6 E 6(13)105.336 204 S 6(:[)-6 G
+(ho+1] g; [ho-5.2; down]; [ho-] f; [ho+; up] a;)-6 E(bar)105.336 216 Q
+127.836 225.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 76 rlineto 320 0 rlineto 0 76 neg rlineto closepath stroke grestore
+EEND 160 687 320 320 -76 76 126.836 301.6 PBEGIN
+%%BeginDocument: mugex16.ps
+%%BoundingBox: 160 687 480 763
+save
+3977375 3978157 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+540.29 875.00 684.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+223.39 734.00 1.000000 4n
+0.70 setlinewidth
+227.07 734.75 moveto
+227.07 755.00 lineto stroke
+286.37 731.00 1.000000 4n
+290.05 731.75 moveto
+290.05 752.00 lineto stroke
+349.61 728.00 1.000000 4n
+353.29 728.75 moveto
+353.29 749.00 lineto stroke
+410.33 734.00 1.000000 4n
+414.01 734.75 moveto
+414.01 755.00 lineto stroke
+223.39 719.00 1.000000 4n
+219.70 718.25 moveto
+219.70 698.00 lineto stroke
+286.37 716.00 1.000000 4n
+282.69 715.25 moveto
+282.69 695.00 lineto stroke
+349.61 719.00 1.000000 4n
+345.93 718.25 moveto
+345.93 698.00 lineto stroke
+410.33 722.00 1.000000 4n
+406.65 721.25 moveto
+406.65 701.00 lineto stroke
+226.39 725.00 1.000000 4n
+230.07 725.75 moveto
+230.07 746.00 lineto stroke
+270.77 725.00 1.000000 4n
+267.09 724.25 moveto
+267.09 704.00 lineto stroke
+339.55 722.00 1.000000 4n
+335.86 721.25 moveto
+335.86 701.00 lineto stroke
+420.40 728.00 1.000000 4n
+424.08 728.75 moveto
+424.08 749.00 lineto stroke
+restore
+%  S_BAR
+11 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 319.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.6.10 Rest)72.336 319.6 R(distance)3 E
+69.336 331.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .597(Usually Mup')72.433 331.6 R 3.097(sp)
+-.55 G .597(lacement of rests is satisf)-3.097 F(actory)-.1 E 3.097(,b)
+-.65 G .598(ut once in a while you might w)-3.297 F .598
+(ant to force a rest to be)-.1 F .921(placed a little higher or lo)
+69.336 343.6 R .921(wer than Mup w)-.25 F .921(ould place it. Y)-.1 F
+.92(ou can specify a "dist" which is the number of)-1.1 F .214
+(stepsizes from the center of the staf)69.336 355.6 R 2.714(ft)-.25 G
+2.714(op)-2.714 G .215(lace the rest symbol, with positi)-2.714 F .515
+-.15(ve n)-.25 H .215(umbers being abo).15 F .515 -.15(ve t)-.15 H .215
+(he center).15 F .846(and ne)69.336 367.6 R -.05(ga)-.15 G(ti).05 E
+1.146 -.15(ve n)-.25 H .846(umbers belo).15 F 4.646 -.65(w. I)-.25 H
+3.346(ft).65 G .845(he staf)-3.346 F 3.345(fi)-.25 G 3.345(st)-3.345 G
+.845(ransposed, the placement of the rest symbol will be adjusted)-3.345
+F(accordingly)69.336 379.6 Q(.)-.65 E/F1 10/Courier@0 SF
+(// The first and last rests are in normal position.)105.336 397.6 Q
+(// The second is forced higher, the third is forced lower.)105.336
+409.6 Q(1: r; [dist 6]; [dist -4]; r;)105.336 421.6 Q(bar)105.336 433.6
+Q 127.836 443.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 65 rlineto 320 0 rlineto 0 65 neg rlineto closepath stroke grestore
+EEND 160 698 320 320 -65 65 126.836 508.2 PBEGIN
+%%BeginDocument: mugex17.ps
+%%BoundingBox: 160 698 480 763
+save
+3977375 3978157 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+540.29 871.34 684.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 721.34 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+225.88 727.34 1.000000 4rest
+287.69 745.34 1.000000 4rest
+349.49 715.34 1.000000 4rest
+411.97 727.34 1.000000 4rest
+restore
+%  S_BAR
+10 linenum
+0.70 setlinewidth
+467.65 739.34 moveto
+467.65 715.34 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 526.2 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.6.11 Repeated)72.336 526.2 R(attrib)3
+E(utes)-.24 E 69.336 538.2 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.504(If tw)73.34 538.2 R 4.004(oo)-.1 G
+4.004(rm)-4.004 G 1.504(ore chords in a ro)-4.004 F 4.004(wh)-.25 G
+-2.25 -.2(av e)-4.004 H 1.505(the same brack)4.204 F 1.505(eted attrib)
+-.1 F 1.505(utes, there are tw)-.2 F 4.005(os)-.1 G 1.505
+(horthand notations.)-4.005 F .31(Specifying an empty set of brack)
+69.336 550.2 R .31(ets "[]" means to use the same attrib)-.1 F .31
+(utes as were speci\214ed on the pre)-.2 F(vious)-.25 E 2.5(chord. The)
+69.336 562.2 R(pre)2.5 E(vious chord must be within the same measure.)
+-.25 E(Some e)5 E(xamples:)-.15 E/F1 10/Courier@0 SF
+(1: [cue] 4c;[]d;[grace; slash 1] 8f;2e;)105.336 580.2 Q(bar)105.336
+592.2 Q(1: d; [with .,-]d; []e; []f;)105.336 616.2 Q(bar)105.336 628.2 Q
+127.836 637.8 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 68 rlineto 320 0 rlineto 0 68 neg rlineto closepath stroke grestore
+EEND 160 695 320 320 -68 68 126.836 705.8 PBEGIN
+%%BeginDocument: mugex18.ps
+%%BoundingBox: 160 695 480 763
+save
+3977375 3978157 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+540.29 875.00 684.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+220.19 713.00 0.583333 4n
+0.70 setlinewidth
+215.63 713.00 moveto
+224.74 713.00 lineto stroke
+222.19 713.49 moveto
+222.19 728.00 lineto stroke
+248.67 716.00 0.583333 4n
+250.67 716.49 moveto
+250.67 731.00 lineto stroke
+273.22 722.00 0.583333 4n
+275.22 722.49 moveto
+275.22 737.00 lineto stroke
+276.98 737.00 0.583333 dnflag
+newpath
+271.97 725.75 moveto
+271.97 727.25 lineto
+278.47 734.25 lineto
+278.47 732.75 lineto
+closepath
+fill
+285.14 719.00 1.000000 2n
+289.04 719.75 moveto
+289.04 740.00 lineto stroke
+restore
+%  S_BAR
+5 linenum
+0.70 setlinewidth
+333.73 743.00 moveto
+333.73 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+345.66 716.00 1.000000 4n
+349.34 716.75 moveto
+349.34 737.00 lineto stroke
+376.13 716.00 1.000000 4n
+/Times-Roman findfont
+12 scalefont
+setfont
+373.90 709.46 moveto
+376.13 709.46 1.000000 dot
+378.36 709.46 moveto
+/Times-Roman findfont
+12 scalefont
+setfont
+371.09 702.86 moveto
+376.13 702.86 1.000000 leg
+381.17 702.86 moveto
+379.81 716.75 moveto
+379.81 737.00 lineto stroke
+406.60 719.00 1.000000 4n
+/Times-Roman findfont
+12 scalefont
+setfont
+404.37 712.46 moveto
+406.60 712.46 1.000000 dot
+408.84 712.46 moveto
+/Times-Roman findfont
+12 scalefont
+setfont
+401.56 705.86 moveto
+406.60 705.86 1.000000 leg
+411.64 705.86 moveto
+410.29 719.75 moveto
+410.29 740.00 lineto stroke
+437.92 722.00 1.000000 4n
+/Times-Roman findfont
+12 scalefont
+setfont
+435.68 715.46 moveto
+437.92 715.46 1.000000 dot
+440.15 715.46 moveto
+/Times-Roman findfont
+12 scalefont
+setfont
+432.88 708.86 moveto
+437.92 708.86 1.000000 leg
+442.96 708.86 moveto
+441.60 722.75 moveto
+441.60 743.00 lineto stroke
+restore
+%  S_BAR
+8 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .142
+(The other shorthand is to put 3 dots after a set of brack)69.336 725.8
+R .142(eted items.)-.1 F .142(This means to repeat the same brack)5.142
+F(eted)-.1 E .962
+(items on all chords for the rest of the measure, or until a ne)69.336
+737.8 R 3.462(ws)-.25 G .962(et of brack)-3.462 F .962
+(eted items is speci\214ed.)-.1 F .961(If you)5.961 F EP
+%%Page: 25 31
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-2)274.506 48 S 2.5(5-)-2.5 G .129
+(wish to cancel this before the end of a measure b)69.336 96 R .13
+(ut without specifying a ne)-.2 F 2.63(ws)-.25 G .13
+(et, the special set "[-]" can be)-2.63 F(used.)69.336 108 Q/F1 10
+/Courier@0 SF(// put staccato marks on all notes)105.336 126 Q
+(1: [with .]... c; d; e; g;)105.336 138 Q(bar)105.336 150 Q
+(// put several cue size notes in the middle of a measure)105.336 162 Q
+(1: c; [cue]... 8d; f; e; g; [-] 4c+;)105.336 174 Q(bar)105.336 186 Q
+127.836 195.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 66 rlineto 320 0 rlineto 0 66 neg rlineto closepath stroke grestore
+EEND 160 697 320 320 -66 66 126.836 261.6 PBEGIN
+%%BeginDocument: mugex19.ps
+%%BoundingBox: 160 697 480 763
+save
+3977375 3978157 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+540.29 875.00 684.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+220.93 713.00 1.000000 4n
+0.70 setlinewidth
+214.70 713.00 moveto
+227.16 713.00 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+218.70 706.46 moveto
+220.93 706.46 1.000000 dot
+223.16 706.46 moveto
+224.61 713.75 moveto
+224.61 734.00 lineto stroke
+249.16 716.00 1.000000 4n
+/Times-Roman findfont
+12 scalefont
+setfont
+246.93 709.46 moveto
+249.16 709.46 1.000000 dot
+251.39 709.46 moveto
+252.84 716.75 moveto
+252.84 737.00 lineto stroke
+277.39 719.00 1.000000 4n
+/Times-Roman findfont
+12 scalefont
+setfont
+275.15 712.46 moveto
+277.39 712.46 1.000000 dot
+279.62 712.46 moveto
+281.07 719.75 moveto
+281.07 740.00 lineto stroke
+306.45 725.00 1.000000 4n
+/Times-Roman findfont
+12 scalefont
+setfont
+304.22 717.36 moveto
+306.45 717.36 1.000000 dot
+308.68 717.36 moveto
+310.13 725.75 moveto
+310.13 746.00 lineto stroke
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+334.31 743.00 moveto
+334.31 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+346.15 713.00 1.000000 4n
+339.92 713.00 moveto
+352.38 713.00 lineto stroke
+349.83 713.75 moveto
+349.83 734.00 lineto stroke
+372.24 716.00 0.583333 4n
+374.24 716.49 moveto
+374.24 731.00 lineto stroke
+376.00 731.00 0.583333 dnflag
+388.45 722.00 0.583333 4n
+390.45 722.49 moveto
+390.45 737.00 lineto stroke
+392.21 737.00 0.583333 dnflag
+404.66 719.00 0.583333 4n
+406.66 719.49 moveto
+406.66 734.00 lineto stroke
+408.43 734.00 0.583333 dnflag
+420.59 725.00 0.583333 4n
+422.60 725.49 moveto
+422.60 740.00 lineto stroke
+424.36 740.00 0.583333 dnflag
+439.79 734.00 1.000000 4n
+436.11 733.25 moveto
+436.11 713.00 lineto stroke
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF -1.1(Yo)69.336 281.6 S 4.379(uc)1.1 G
+1.879(an use more than one set of back)-4.379 F 1.879
+(ets on a single chord.)-.1 F -.15(Fo)6.879 G 4.379(re).15 G 1.879
+(xample "[len 5][do)-4.529 F 1.878(wn]" and "[len)-.25 F(5;do)69.336
+293.6 Q 1.383(wn]" are equi)-.25 F -.25(va)-.25 G 3.883(lent. Ho).25 F
+(we)-.25 E -.15(ve)-.25 G 2.183 -.4(r, [).15 H 1.384
+(-] can only be used by itself, and if you w).4 F 1.384
+(ant to use [] along with)-.1 F .212(another back)69.336 305.6 R .211
+(eted set of items \(to duplicate the items on the pre)-.1 F .211
+(vious chord plus add some more\), the empty)-.25 F
+([] needs to be \214rst, before the other set of items.)69.336 317.6 Q
+69.336 334.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.1.7 Mid-measur)72.586 334.6 R 3.25
+(ep)-.481 G(ar)-3.25 E(ameter c)-.195 E(hang)-.195 E(es)-.13 E 69.336
+346.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .221(The group attrib)72.057 346.6 R .222
+(utes can optionally be preceded by mid-measure parameter changes.)-.2 F
+.222(This is not used v)5.222 F(ery)-.15 E 1.452(often, b)69.336 358.6 R
+1.452(ut the most common use is to change the clef in the middle of a m\
+easure. There are tw)-.2 F 3.952(oo)-.1 G(ther)-3.952 E 1.625
+(parameters that can also be changed here: defoct and release.)69.336
+370.6 R 1.626(The change is enclosed in double angle)6.626 F(brack)
+69.336 382.6 Q 4.301(ets. After)-.1 F 1.801(the opening angle brack)
+4.301 F 1.801(et is the conte)-.1 F 1.8
+(xt to which the changes applies \(score, staf)-.15 F 1.8(f, or)-.25 F
+-.2(vo)69.336 394.6 S(ice\), follo).2 E
+(wed by one or more parameter changes.)-.25 E/F1 10/Courier@0 SF
+(1: c; e; <<score clef=bass>> 2g;)105.336 412.6 Q(bar)105.336 424.6 Q
+91.836 434.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 392 0 rlineto 0 61 neg rlineto closepath stroke grestore
+EEND 128 702 392 392 -61 61 90.836 495.2 PBEGIN
+%%BeginDocument: mugex20.ps
+%%BoundingBox: 128 702 520 763
+save
+3977375 3978157 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+504.29 875.00 720.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+156.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+194.40 713.00 1.000000 4n
+0.70 setlinewidth
+188.17 713.00 moveto
+200.64 713.00 lineto stroke
+198.09 713.75 moveto
+198.09 734.00 lineto stroke
+276.59 719.00 1.000000 4n
+280.27 719.75 moveto
+280.27 740.00 lineto stroke
+353.66 737.00 0.750000 fclef
+366.44 740.00 1.000000 2n
+362.54 739.25 moveto
+362.54 719.00 lineto stroke
+restore
+%  S_BAR
+7 linenum
+0.70 setlinewidth
+503.65 743.00 moveto
+503.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF
+(If there is more than one parameter listed, the)69.336 509.2 Q 2.5(ya)
+-.15 G(re separated by semicolons.)-2.5 E/F1 10/Courier@0 SF
+(<< staff clef = tenor ; defoct = 4 >>)105.336 527.2 Q F0
+(If you wish to change parameters in more than one conte)69.336 553.2 Q
+(xt, multiple angle-brack)-.15 E(eted items can be gi)-.1 E -.15(ve)-.25
+G(n:).15 E F1(2-3 2: 2c; <<score release=100>><<staff clef=alto>><<voic\
+e defoct=3>> c;)105.336 571.2 Q F0 .086(If you specify "staf)69.336
+597.2 R .086(f" or "v)-.25 F .086(oice" conte)-.2 F .086
+(xt, the speci\214c staf)-.15 F .086(f\(s\) or v)-.25 F .086
+(oice\(s\) to which the changes apply is based)-.2 F 1.283
+(on which staf)69.336 609.2 R 1.283(f\(s\) or v)-.25 F 1.283
+(oice\(s\) are being described on the input line. So in the e)-.2 F
+1.282(xample abo)-.15 F -.15(ve)-.15 G 3.782(,t).15 G 1.282(he clef is)
+-3.782 F .905(changed to alto on staf)69.336 621.2 R .906
+(fs 2 and 3, and the defoct is changed to 3 for v)-.25 F .906
+(oice 2 on both of those staf)-.2 F .906(fs. The)-.25 F
+(release change applies to the entire score.)69.336 633.2 Q 69.336 650.2
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.1.8 Cr)72.586 650.2 R(oss-staf)-.585
+E 3.25(fs)-.234 G(tems)-3.25 E 69.336 662.2 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .759
+(Sometimes, on music for instruments that use more than one staf)72.595
+662.2 R .758(f, you may w)-.25 F .758(ant some of the notes of a)-.1 F
+.518(chord to be printed on the staf)69.336 674.2 R 3.018(fa)-.25 G(bo)
+-3.018 E .818 -.15(ve o)-.15 H 3.018(rb).15 G(elo)-3.018 E 1.819 -.65
+(w, r)-.25 H .519(ather than using a lot of le).65 F .519(ger lines.)
+-.15 F -1.1(Yo)5.519 G 3.019(uc)1.1 G .519(an specify this)-3.019 F .266
+(by putting the w)69.336 686.2 R .266
+(ord "with" before the notes that are to go on the other staf)-.1 F .266
+(f, and follo)-.25 F .266(wing those notes with)-.25 F("abo)69.336 698.2
+Q -.15(ve)-.15 G 2.5("o).15 G 2.5(r")-2.5 G(belo)-2.5 E
+(w" to specify which is the other staf)-.25 E 2.5(f. F)-.25 F(or e)-.15
+E(xample:)-.15 E EP
+%%Page: 26 32
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-2)274.506 48 S 2.5(6-)-2.5 G/F1 10
+/Courier@0 SF(score)105.336 96 Q(staffs=2)130.336 108 Q(staff 2)105.336
+120 Q(clef=bass)130.336 132 Q(music)105.336 144 Q(1: 1e+g+c++;)105.336
+168 Q(2: cc+; ee+; g with g+ above; with c+c++ above;)105.336 180 Q(bar)
+105.336 192 Q(1: cc+; g with g- below; e with e- below; with cc- below;)
+105.336 216 Q(2: 1c-e-g-;)105.336 228 Q(bar)105.336 240 Q 91.836 249.6
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 125 rlineto 392 0 rlineto 0 125 neg rlineto closepath stroke grestore
+EEND 128 639 392 392 -125 125 90.836 374.6 PBEGIN
+%%BeginDocument: mugex21.ps
+%%BoundingBox: 128 639 520 764
+save
+3977375 3978157 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_SSV
+7 linenum
+%  S_FEED
+504.29 871.72 720.00 5 1.000000 1.000000 stf
+504.29 817.72 720.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+144.29 739.72 moveto
+144.29 661.72 lineto stroke
+%  S_CLEFSIG
+156.08 721.72 1.000000 gclef
+156.33 679.72 1.000000 fclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+188.24 751.72 1.000000 1n
+180.82 751.72 moveto
+195.66 751.72 lineto stroke
+180.82 745.72 moveto
+195.66 745.72 lineto stroke
+188.24 742.72 1.000000 1n
+188.24 736.72 1.000000 1n
+restore
+%  S_STAFF
+% staff 2
+save
+188.24 691.72 1.000000 4n
+0.70 setlinewidth
+182.01 691.72 moveto
+194.47 691.72 lineto stroke
+188.24 670.72 1.000000 4n
+184.56 690.97 moveto
+184.56 649.72 lineto stroke
+226.15 697.72 1.000000 4n
+219.92 697.72 moveto
+232.39 697.72 lineto stroke
+219.92 691.72 moveto
+232.39 691.72 lineto stroke
+226.15 676.72 1.000000 4n
+222.47 696.97 moveto
+222.47 655.72 lineto stroke
+264.07 721.72 1.000000 4n
+264.07 682.72 1.000000 4n
+260.39 720.97 moveto
+260.39 661.72 lineto stroke
+302.83 730.72 1.000000 4n
+302.83 709.72 1.000000 4n
+296.60 709.72 moveto
+309.06 709.72 lineto stroke
+299.15 729.97 moveto
+299.15 688.72 lineto stroke
+restore
+%  S_BAR
+13 linenum
+0.70 setlinewidth
+338.76 739.72 moveto
+338.76 715.72 lineto stroke
+338.76 685.72 moveto
+338.76 661.72 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+353.13 730.72 1.000000 4n
+353.13 709.72 1.000000 4n
+346.89 709.72 moveto
+359.36 709.72 lineto stroke
+356.81 710.47 moveto
+356.81 751.72 lineto stroke
+391.04 721.72 1.000000 4n
+391.04 682.72 1.000000 4n
+394.72 683.47 moveto
+394.72 742.72 lineto stroke
+428.96 715.72 1.000000 4n
+428.96 676.72 1.000000 4n
+432.64 677.47 moveto
+432.64 736.72 lineto stroke
+467.71 691.72 1.000000 4n
+461.48 691.72 moveto
+473.95 691.72 lineto stroke
+467.71 670.72 1.000000 4n
+471.40 671.47 moveto
+471.40 712.72 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+353.13 661.72 1.000000 1n
+353.13 655.72 1.000000 1n
+0.70 setlinewidth
+345.71 655.72 moveto
+360.55 655.72 lineto stroke
+353.13 649.72 1.000000 1n
+345.71 649.72 moveto
+360.55 649.72 lineto stroke
+345.71 655.72 moveto
+360.55 655.72 lineto stroke
+restore
+%  S_BAR
+17 linenum
+0.70 setlinewidth
+503.65 739.72 moveto
+503.65 715.72 lineto stroke
+503.65 685.72 moveto
+503.65 661.72 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .71(The notes for the other staf)69.336
+394.6 R 3.21(fh)-.25 G -2.25 -.2(av e)-3.21 H .71(to follo)3.41 F 3.21
+(wt)-.25 G .71(he notes on the normal staf)-3.21 F 3.21(fi)-.25 G 3.21
+(nt)-3.21 G .71(he input.)-3.21 F .71(As is sho)5.71 F .71(wn in the)
+-.25 F -.15(ex)69.336 406.6 S .674(ample, it is possible to ha).15 F
+-.15(ve)-.2 G/F1 10/Times-Italic@0 SF(all)3.324 E F0 .674
+(the notes on the "other" staf)3.174 F .674(f, if you wish.)-.25 F .674
+(The octa)5.674 F .973 -.15(ve i)-.2 H 3.173(ss).15 G .673
+(peci\214ed as if)-3.173 F 1.22(the note were on the normal staf)69.336
+418.6 R 1.22
+(f; Mup will automatically adjust appropriately for the other staf)-.25
+F .55(f')-.25 G 3.72(sc)-1.1 G(lef.)-3.72 E .426
+(Once in a while, Mup may not be able to \214gure out ho)69.336 430.6 R
+2.925(wt)-.25 G 2.925(oc)-2.925 G .425(ompletely a)-2.925 F -.2(vo)-.2 G
+.425(id colliding with other notes; in).2 F
+(that case you can use the horizontal of)69.336 442.6 Q(fset that w)-.25
+E(as described earlier)-.1 E(.)-.55 E -.15(Fo)69.336 460.6 S 3.678(rM)
+.15 G 1.178(IDI purposes, only the normal staf)-3.678 F .55(f')-.25 G
+3.678(sk)-1.1 G 1.478 -.15(ey s)-3.778 H 1.178
+(ignature and accidentals are considered, so if the other).15 F(staf)
+69.336 472.6 Q 3.525(fh)-.25 G 1.025(as a dif)-3.525 F 1.025(ferent k)
+-.25 F 1.325 -.15(ey s)-.1 H 1.025(ignature or accidentals that should \
+really apply to these notes, you will ha).15 F 1.325 -.15(ve t)-.2 H(o)
+.15 E(supply accidentals e)69.336 484.6 Q(xplicitly)-.15 E(.)-.65 E
+69.336 501.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.1.9 Inter)72.586 501.6 R(-c)-.26 E
+(hor)-.195 E 3.25(da)-.481 G(ttrib)-3.25 E(utes)-.26 E 69.336 513.6
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .209(In addition to the chord attrib)72.045
+513.6 R .209(utes that can appear in the square brack)-.2 F .21
+(ets before time and pitch information,)-.1 F 1.045(there are a fe)
+69.336 525.6 R 3.544(wa)-.25 G(ttrib)-3.544 E 1.044(utes that are speci\
+\214ed after the time and pitch information. These are attrib)-.2 F
+1.044(utes that)-.2 F(start or end on the chord b)69.336 537.6 Q
+(ut also af)-.2 E(fect other chords. There are se)-.25 E -.15(ve)-.25 G
+(ral such attrib).15 E(utes:)-.2 E 5<8a63>79.336 555.6 S(hord ties)-5 E
+5<8a63>79.336 573.6 S(hord slurs)-5 E 5<8a63>79.336 591.6 S
+(ustom beaming)-5 E 5<8a63>79.336 609.6 S(ross-staf)-5 E 2.5(fb)-.25 G
+(eams)-2.5 E 5<8a61>79.336 627.6 S(lternation)-5 E 5<8a73>79.336 645.6 S
+(lope)-5 E(If se)69.336 663.6 Q -.15(ve)-.25 G
+(ral of these are speci\214ed on a single chord, the).15 E 2.5(ym)-.15 G
+(ay be in an)-2.5 E 2.5(yo)-.15 G(rder)-2.5 E 2.5(,s)-.4 G
+(eparated by commas.)-2.5 E 69.336 679.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.9.1 Chor)72.336 679.6 R 3(dt)-.444 G
+(ies)-3 E 69.336 691.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .594
+(If all notes in a chord are to be tied to the follo)72.429 691.6 R .594
+(wing chord, the k)-.25 F -.15(ey)-.1 G -.1(wo).15 G .594
+(rd "tie" can be placed at the end of).1 F(the chord. As w)69.336 703.6
+Q(as mentioned earlier)-.1 E 2.5(,i)-.4 G(ndi)-2.5 E
+(vidual notes can be tied using a "~" symbol.)-.25 E(Thus:)5 E/F1 10
+/Courier@0 SF(ceg tie;)105.336 721.6 Q EP
+%%Page: 27 33
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-2)274.506 48 S 2.5(7-)-2.5 G(is equi)69.336
+96 Q -.25(va)-.25 G(lent to).25 E/F1 10/Courier@0 SF(c~e~g~;)105.336 114
+Q F0 2.06(The w)69.336 134 R 2.06(ord "tie" may be preceded by the w)-.1
+F 2.06(ord "dotted" or "dashed" to produce dotted or dashed ties,)-.1 F
+1.039(otherwise normal, solid ties are dra)69.336 146 R 3.539(wn. The)
+-.15 F -.1(wo)3.539 G 1.039(rd "tie" may be follo).1 F 1.04
+(wed by the w)-.25 F 1.04(ord "up" or "do)-.1 F 1.04(wn" to)-.25 F 1.959
+(specify the direction of each curv)69.336 158 R(e')-.15 E 4.459(sb)-.55
+G 1.958
+(ulge. If neither is speci\214ed, Mup will determine an appropriate)
+-4.659 F(direction, so you only need to gi)69.336 170 Q .3 -.15(ve a d)
+-.25 H(irection if you wish to o).15 E -.15(ve)-.15 G(rride Mup').15 E
+2.5(sc)-.55 G(hoice.)-2.5 E -1.1(Yo)69.336 188 S 3.147(uc)1.1 G .647
+(an also produce the ef)-3.147 F .647
+(fect of tying chords by using additi)-.25 F .947 -.15(ve t)-.25 H .647
+(ime v).15 F .647(alues. F)-.25 F .647(or e)-.15 F .647
+(xample, the follo)-.15 F(wing)-.25 E(lines produce the same output:)
+69.336 200 Q F1(1: 2ceg tie;8;;4;)105.336 218 Q(// explicit tie)12 E
+(1: 2+8ceg;8;4;)105.336 242 Q(// tie implied by added time values)16 E
+69.336 266 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.9.2 Chor)72.336 266 R 3(ds)-.444 G
+(lur)-3 E(s)-.12 E 69.336 278 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.117(The k)72.953 278 R -.15(ey)-.1 G -.1
+(wo).15 G 1.116(rd "slur" can be placed at the end of a chord to indica\
+te that each note in the chord is to be).1 F .141
+(slurred to the corresponding note in the follo)69.336 290 R .142
+(wing chord. In other w)-.25 F .142
+(ords, the top note of the chord is slurred)-.1 F .143
+(to the top note of the follo)69.336 302 R .142(wing chord, the second \
+from the top note in the \214rst chord to the second from the)-.25 F
+(top note in the second chord, etc.)69.336 314 Q(Thus the follo)5 E
+(wing 2 measures gi)-.25 E .3 -.15(ve e)-.25 H(qui).15 E -.25(va)-.25 G
+(lent output:).25 E/F1 10/Courier@0 SF(1: 2f<d> a<b> c+<d+>; dbd+;)
+105.336 332 Q(bar)105.336 344 Q(1: 2fac+ slur; dbd+;)105.336 368 Q(bar)
+105.336 380 Q 187.836 389.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 64 rlineto 200 0 rlineto 0 64 neg rlineto closepath stroke grestore
+EEND 208 699 200 200 -64 64 186.836 453.6 PBEGIN
+%%BeginDocument: mugex22.ps
+%%BoundingBox: 208 699 408 763
+save
+3977375 3978157 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+588.07 872.00 612.00 5 1.000000 1.000000 stf
+/Times-Roman findfont
+12 scalefont
+setfont
+216.00 725.73 moveto
+(   ) show
+%  S_CLEFSIG
+239.86 722.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+267.46 731.00 1.000000 2n
+267.46 725.00 1.000000 2n
+267.46 719.00 1.000000 2n
+0.70 setlinewidth
+271.36 719.75 moveto
+271.36 752.00 lineto stroke
+298.28 734.00 1.000000 2n
+298.28 728.00 1.000000 2n
+298.28 713.00 1.000000 2n
+302.18 713.75 moveto
+302.18 755.00 lineto stroke
+269.46 713.90 moveto
+269.55 714.09 lineto
+273.55 711.63 277.84 709.89 282.42 708.87 curveto
+287.00 707.84 291.62 707.59 296.28 708.11 curveto
+296.27 707.69 lineto
+291.57 706.62 286.86 706.61 282.15 707.66 curveto
+277.44 708.72 273.18 710.73 269.38 713.71 curveto
+fill
+273.71 725.00 moveto
+273.74 725.24 lineto
+276.67 724.19 279.66 723.92 282.73 724.45 curveto
+285.79 724.98 288.52 726.24 290.92 728.22 curveto
+291.14 727.78 lineto
+288.94 725.31 286.20 723.79 282.94 723.23 curveto
+279.67 722.66 276.59 723.17 273.68 724.76 curveto
+fill
+273.71 736.10 moveto
+273.64 736.31 lineto
+277.24 738.83 281.23 740.36 285.59 740.89 curveto
+289.96 741.43 294.20 740.90 298.30 739.32 curveto
+298.26 738.88 lineto
+294.14 739.92 289.96 740.18 285.74 739.67 curveto
+281.52 739.15 277.54 737.89 273.79 735.89 curveto
+fill
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+326.40 740.00 moveto
+326.40 716.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+336.71 731.00 1.000000 2n
+336.71 725.00 1.000000 2n
+336.71 719.00 1.000000 2n
+340.61 719.75 moveto
+340.61 752.00 lineto stroke
+367.53 734.00 1.000000 2n
+367.53 728.00 1.000000 2n
+367.53 713.00 1.000000 2n
+371.42 713.75 moveto
+371.42 755.00 lineto stroke
+338.71 713.90 moveto
+338.80 714.09 lineto
+342.79 711.63 347.08 709.89 351.66 708.87 curveto
+356.24 707.84 360.87 707.59 365.53 708.11 curveto
+365.52 707.69 lineto
+360.81 706.62 356.10 706.61 351.39 707.66 curveto
+346.68 708.72 342.43 710.73 338.63 713.71 curveto
+fill
+342.96 725.00 moveto
+342.99 725.24 lineto
+345.92 724.19 348.91 723.92 351.97 724.45 curveto
+355.04 724.98 357.77 726.24 360.17 728.22 curveto
+360.39 727.78 lineto
+358.18 725.31 355.45 723.79 352.19 723.23 curveto
+348.92 722.66 345.84 723.17 342.93 724.76 curveto
+fill
+342.96 736.10 moveto
+342.89 736.31 lineto
+346.49 738.83 350.47 740.36 354.84 740.89 curveto
+359.21 741.43 363.44 740.90 367.55 739.32 curveto
+367.51 738.88 lineto
+363.38 739.92 359.21 740.18 354.99 739.67 curveto
+350.77 739.15 346.78 737.89 343.03 735.89 curveto
+fill
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+395.65 740.00 moveto
+395.65 716.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .386(The chord with the "slur" k)69.336
+473.6 R -.15(ey)-.1 G -.1(wo).15 G .387(rd and the chord that follo).1 F
+.387(ws it must ha)-.25 F .687 -.15(ve t)-.2 H .387
+(he same number of notes.).15 F(The)5.387 E -.1(wo)69.336 485.6 S .1
+(rd "slur" may be preceded by the w).1 F .099
+(ord "dotted" or "dashed" to produce dotted or dashed slurs, otherwise)
+-.1 F .21(normal, solid slurs are dra)69.336 497.6 R 2.71(wn. The)-.15 F
+-.1(wo)2.71 G .21(rd "slur" may be follo).1 F .21(wed by the w)-.25 F
+.21(ord "up" or "do)-.1 F .21(wn" to specify the)-.25 F .378
+(direction of each curv)69.336 509.6 R(e')-.15 E 2.878(sb)-.55 G .377(u\
+lge. If neither is speci\214ed, Mup will determine an appropriate direc\
+tion, so you)-3.078 F(only need to gi)69.336 521.6 Q .3 -.15(ve a d)-.25
+H(irection if you wish to o).15 E -.15(ve)-.15 G(rride Mup').15 E 2.5
+(sc)-.55 G(hoice.)-2.5 E 69.336 537.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.9.3 Custom)72.336 537.6 R(beaming)3 E
+69.336 549.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(Normally)72.795 549.6 Q 3.459(,n)-.65 G .959
+(otes of eighth or shorter duration are automatically beamed according \
+to the speci\214cation of)-3.459 F 2.597(the "beamstyle" parameter)
+69.336 561.6 R 7.597(.O)-.55 G(ccasionally)-7.597 E 5.097(,y)-.65 G
+2.597(ou may wish to o)-5.097 F -.15(ve)-.15 G 2.596(rride the def).15 F
+2.596(ault beaming style for a)-.1 F 1.46(particular situation.)69.336
+573.6 R 1.46(This is done using the "bm" and "ebm" k)6.46 F -.15(ey)-.1
+G -.1(wo).15 G 1.46(rds. The "bm" \(short for "beam"\) is).1 F .248
+(placed at the end of the chord which is the \214rst to be beamed.)
+69.336 585.6 R 2.748(The "ebm")5.248 F .248
+(\(short for "end beam"\) is placed)2.748 F 1.18
+(at the end of the last chord.)69.336 597.6 R 1.18
+(Both chords must be in the same measure. If there is an)6.18 F 3.68(yc)
+-.15 G 1.18(ustom beaming)-3.68 F 1.245(speci\214ed for a gi)69.336
+609.6 R -.15(ve)-.25 G 3.745(nv).15 G 1.244(oice in a gi)-3.945 F -.15
+(ve)-.25 G 3.744(nm).15 G 1.244(easure, the def)-3.744 F 1.244
+(ault beamstyle is turned of)-.1 F 3.744(ff)-.25 G 1.244(or that v)
+-3.744 F 1.244(oice for the)-.2 F
+(entire measure, meaning that only what you e)69.336 621.6 Q
+(xplicitly specify to be beamed will be beamed.)-.15 E(An e)5 E(xample:)
+-.15 E/F1 10/Courier@0 SF(// The d, e, and f will be beamed together,)
+105.336 639.6 Q(// but other 8th notes will not be.)105.336 651.6 Q
+(1: 4c; 8; d bm; e; f ebm; g; a;)105.336 663.6 Q(bar)105.336 675.6 Q
+(// First two chords beamed together.)105.336 699.6 Q
+(// Second chord is tied to third chord.)105.336 711.6 Q
+(1: 8.fa bm; 16gc+ tie, ebm; 2; 8a; g;)105.336 723.6 Q(bar)105.336 735.6
+Q EP
+%%Page: 28 34
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-2)274.506 48 S 2.5(8-)-2.5 G 127.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 62 rlineto 320 0 rlineto 0 62 neg rlineto closepath stroke grestore
+EEND 160 701 320 320 -62 62 126.836 158 PBEGIN
+%%BeginDocument: mugex23.ps
+%%BoundingBox: 160 701 480 763
+save
+3977375 3978157 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+540.29 873.82 684.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 723.82 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+220.64 711.82 1.000000 4n
+0.70 setlinewidth
+214.41 711.82 moveto
+226.87 711.82 lineto stroke
+224.32 712.57 moveto
+224.32 732.82 lineto stroke
+244.40 711.82 1.000000 4n
+238.17 711.82 moveto
+250.63 711.82 lineto stroke
+248.08 712.57 moveto
+248.08 732.82 lineto stroke
+251.11 732.82 1.000000 dnflag
+260.45 714.82 1.000000 4n
+264.13 715.57 moveto
+264.13 735.12 lineto stroke
+275.66 717.82 1.000000 4n
+279.34 718.57 moveto
+279.34 738.12 lineto stroke
+290.87 720.82 1.000000 4n
+294.55 721.57 moveto
+294.55 741.12 lineto stroke
+305.24 723.82 1.000000 4n
+308.92 724.57 moveto
+308.92 744.82 lineto stroke
+311.94 744.82 1.000000 dnflag
+321.28 726.82 1.000000 4n
+324.97 727.57 moveto
+324.97 747.82 lineto stroke
+327.99 747.82 1.000000 dnflag
+newpath
+263.78 736.62 moveto
+294.90 742.62 lineto
+294.90 739.62 lineto
+263.78 733.62 lineto
+closepath
+fill
+restore
+%  S_BAR
+7 linenum
+0.70 setlinewidth
+339.14 741.82 moveto
+339.14 717.82 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+348.13 726.82 1.000000 4n
+357.39 726.82 1.000000 dot
+348.13 720.82 1.000000 4n
+357.39 720.82 1.000000 dot
+351.81 721.57 moveto
+351.81 747.50 lineto stroke
+368.71 732.82 1.000000 4n
+368.71 723.82 1.000000 4n
+372.39 724.57 moveto
+372.39 753.50 lineto stroke
+393.60 732.82 1.000000 2n
+393.60 723.82 1.000000 2n
+397.50 724.57 moveto
+397.50 753.82 lineto stroke
+433.75 726.82 1.000000 4n
+437.43 727.57 moveto
+437.43 747.82 lineto stroke
+440.45 747.82 1.000000 dnflag
+449.80 723.82 1.000000 4n
+453.48 724.57 moveto
+453.48 744.82 lineto stroke
+456.50 744.82 1.000000 dnflag
+newpath
+351.46 749.00 moveto
+372.74 755.00 lineto
+372.74 752.00 lineto
+351.46 746.00 lineto
+closepath
+fill
+newpath
+372.04 750.00 moveto
+363.97 747.65 lineto
+363.97 744.65 lineto
+372.04 747.00 lineto
+closepath
+fill
+370.71 718.72 moveto
+370.77 718.95 lineto
+374.06 717.41 377.52 716.65 381.15 716.65 curveto
+384.79 716.65 388.25 717.41 391.54 718.95 curveto
+391.66 718.50 lineto
+388.46 716.44 384.96 715.40 381.15 715.40 curveto
+377.35 715.40 373.85 716.44 370.65 718.50 curveto
+fill
+374.74 737.92 moveto
+374.67 738.15 lineto
+377.50 740.22 380.67 741.25 384.17 741.25 curveto
+387.67 741.25 390.83 740.22 393.66 738.15 curveto
+393.53 737.69 lineto
+390.60 739.23 387.48 740.00 384.17 740.00 curveto
+380.86 740.00 377.74 739.23 374.80 737.69 curveto
+fill
+restore
+%  S_BAR
+12 linenum
+0.70 setlinewidth
+467.65 741.82 moveto
+467.65 717.82 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF 1.126(In the absence of custom beaming,\
+ Mup will beam notes together using the beamstyle parameter)69.336 178 R
+3.627(,i)-.4 G 3.627(ft)-3.627 G(hat)-3.627 E .088(parameter is set.)
+69.336 190 R .088(The beamstyle parameter is a list of time v)5.088 F
+.087(alues that add up to a measure. Each time v)-.25 F(alue)-.25 E
+1.349(tells ho)69.336 202 R 3.849(wm)-.25 G(an)-3.849 E 3.849(yc)-.15 G
+1.349(hords to beam together)-3.849 F 6.349(.F)-.55 G 1.349(or e)-6.499
+F 1.35(xample, a 2 means to beam a half note w)-.15 F 1.35
+(orth of chords)-.1 F(together)69.336 214 Q 3.692(,w)-.4 G 1.192
+(hereas 1.. w)-3.692 F 1.191
+(ould indicate that a double dotted whole note w)-.1 F 1.191
+(orth of chords should be beamed)-.1 F(together)69.336 226 Q 5(.H)-.55 G
+(ere are some e)-5 E(xamples of ho)-.15 E 2.5(wt)-.25 G
+(he beamstyle parameter w)-2.5 E(orks.)-.1 E EP
+%%Page: 29 35
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-2)274.506 48 S 2.5(9-)-2.5 G/F1 10
+/Courier@0 SF(// beam each quarter note worth of notes together,)105.336
+96 Q(// breaking the beaming at each quarter note boundary)105.336 108 Q
+(score beamstyle = 4,4,4,4)105.336 120 Q(music)105.336 132 Q
+(1: 8c;d;e;f;g;a;b;c+;)105.336 144 Q(bar)105.336 156 Q
+(1: 8c;d;4e;f;8g;c;)105.336 168 Q(bar)105.336 180 Q
+(// beam each half note worth of notes together,)105.336 204 Q
+(// breaking the beaming at each half note boundary)105.336 216 Q
+(score beamstyle = 2,2)105.336 228 Q(music)105.336 240 Q
+(1: 8c;d;e;f;g;a;b;c+;)105.336 252 Q(bar)105.336 264 Q
+(// the middle two eighth notes will not be beamed together,)105.336 276
+Q(// because they are on opposite sides of the half note boundary)
+105.336 288 Q(1: 8c;4d;8e;f;4g;8c;)105.336 300 Q(bar)105.336 312 Q
+(// beam each whole note worth of notes together)105.336 336 Q
+(score beamstyle = 1)105.336 348 Q(music)105.336 360 Q
+(1: 8c;d;e;f;g;a;b;c+;)105.336 372 Q(bar)105.336 384 Q
+(1: 8c;4d;8e;f;4g;8c;)105.336 396 Q(bar)105.336 408 Q
+(// in 9/8 time, beam each dotted quarter note worth of notes together)
+105.336 432 Q(score time = 9/8 ; beamstyle = 4., 4., 4.)105.336 444 Q
+(music)105.336 456 Q(1: 8c;d;e;d;e;f;e;f;g;)105.336 468 Q(bar)105.336
+480 Q(// the eight notes will not be beamed together,)105.336 492 Q
+(// because they are on opposite side of the dotted quarter boundary)
+105.336 504 Q(1: 4.c;4d;8e;8f;4g;)105.336 516 Q(bar)105.336 528 Q(// in\
+ each measure, beam the first dotted half worth of notes together,)
+105.336 552 Q
+(// then beam the remaining dotted quarter worth of notes together)
+105.336 564 Q(score beamstyle = 2., 4.)105.336 576 Q(music)105.336 588 Q
+(1: 8c;d;e;d;e;f;e;f;g;)105.336 600 Q(bar)105.336 612 Q(// in each meas\
+ure, beam the first dotted quarter worth of notes together)105.336 636 Q
+(// then beam the remaining dotted half worth of notes together)105.336
+648 Q(score beamstyle = 4., 2.;)105.336 660 Q(music)105.336 672 Q
+(1: 8c;d;e;d;e;f;e;f;g;)105.336 684 Q(bar)105.336 696 Q EP
+%%Page: 30 36
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-3)274.506 48 S 2.5(0-)-2.5 G 71.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 260 rlineto 432 0 rlineto 0 260 neg rlineto closepath stroke grestore
+EEND 88 503 432 432 -260 260 70.836 356 PBEGIN
+%%BeginDocument: mugex24.ps
+%%BoundingBox: 88 503 520 763
+save
+3977375 3978157 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+6 linenum
+%  S_FEED
+480.07 874.09 720.00 5 1.000000 1.000000 stf
+/Times-Roman findfont
+12 scalefont
+setfont
+108.00 727.83 moveto
+(   ) show
+%  S_CLEFSIG
+131.86 724.09 1.000000 gclef
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+143.66 730.09 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+143.66 718.08 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+169.41 712.09 1.000000 4n
+0.70 setlinewidth
+163.17 712.09 moveto
+175.64 712.09 lineto stroke
+173.09 712.84 moveto
+173.09 732.52 lineto stroke
+182.49 715.09 1.000000 4n
+186.17 715.84 moveto
+186.17 735.52 lineto stroke
+195.57 718.09 1.000000 4n
+199.25 718.84 moveto
+199.25 738.52 lineto stroke
+208.65 721.09 1.000000 4n
+212.33 721.84 moveto
+212.33 741.52 lineto stroke
+221.73 724.09 1.000000 4n
+225.41 724.84 moveto
+225.41 744.52 lineto stroke
+234.81 727.09 1.000000 4n
+238.50 727.84 moveto
+238.50 747.52 lineto stroke
+247.90 730.09 1.000000 4n
+244.21 729.34 moveto
+244.21 709.72 lineto stroke
+261.82 733.09 1.000000 4n
+258.13 732.34 moveto
+258.13 712.72 lineto stroke
+newpath
+172.74 734.02 moveto
+186.52 737.02 lineto
+186.52 734.02 lineto
+172.74 731.02 lineto
+closepath
+fill
+newpath
+198.90 740.02 moveto
+212.68 743.02 lineto
+212.68 740.02 lineto
+198.90 737.02 lineto
+closepath
+fill
+newpath
+225.06 746.02 moveto
+238.85 749.02 lineto
+238.85 746.02 lineto
+225.06 743.02 lineto
+closepath
+fill
+newpath
+243.86 711.22 moveto
+258.48 714.22 lineto
+258.48 711.22 lineto
+243.86 708.22 lineto
+closepath
+fill
+restore
+%  S_BAR
+10 linenum
+0.70 setlinewidth
+277.06 742.09 moveto
+277.06 718.09 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+286.09 712.09 1.000000 4n
+279.86 712.09 moveto
+292.32 712.09 lineto stroke
+289.77 712.84 moveto
+289.77 732.52 lineto stroke
+299.17 715.09 1.000000 4n
+302.85 715.84 moveto
+302.85 735.52 lineto stroke
+313.87 718.09 1.000000 4n
+317.55 718.84 moveto
+317.55 739.09 lineto stroke
+336.65 721.09 1.000000 4n
+340.33 721.84 moveto
+340.33 742.09 lineto stroke
+357.81 724.09 1.000000 4n
+361.49 724.84 moveto
+361.49 739.13 lineto stroke
+371.73 712.09 1.000000 4n
+365.49 712.09 moveto
+377.96 712.09 lineto stroke
+375.41 712.84 moveto
+375.41 734.06 lineto stroke
+newpath
+289.42 734.02 moveto
+303.20 737.02 lineto
+303.20 734.02 lineto
+289.42 731.02 lineto
+closepath
+fill
+newpath
+361.14 740.63 moveto
+375.76 735.56 lineto
+375.76 732.56 lineto
+361.14 737.63 lineto
+closepath
+fill
+restore
+%  S_BAR
+12 linenum
+0.70 setlinewidth
+386.97 742.09 moveto
+386.97 718.09 lineto stroke
+%  S_SSV
+15 linenum
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+396.00 712.09 1.000000 4n
+389.77 712.09 moveto
+402.23 712.09 lineto stroke
+399.68 712.84 moveto
+399.68 732.52 lineto stroke
+409.08 715.09 1.000000 4n
+412.76 715.84 moveto
+412.76 735.52 lineto stroke
+422.16 718.09 1.000000 4n
+425.85 718.84 moveto
+425.85 738.52 lineto stroke
+435.25 721.09 1.000000 4n
+438.93 721.84 moveto
+438.93 741.52 lineto stroke
+448.33 724.09 1.000000 4n
+452.01 724.84 moveto
+452.01 744.48 lineto stroke
+461.41 727.09 1.000000 4n
+465.09 727.84 moveto
+465.09 747.43 lineto stroke
+474.49 730.09 1.000000 4n
+478.17 730.84 moveto
+478.17 750.37 lineto stroke
+488.41 733.09 1.000000 4n
+492.09 733.84 moveto
+492.09 753.50 lineto stroke
+newpath
+399.33 734.02 moveto
+439.28 743.02 lineto
+439.28 740.02 lineto
+399.33 731.02 lineto
+closepath
+fill
+newpath
+451.66 745.98 moveto
+492.44 755.00 lineto
+492.44 752.00 lineto
+451.66 742.98 lineto
+closepath
+fill
+restore
+%  S_BAR
+19 linenum
+0.70 setlinewidth
+503.65 742.09 moveto
+503.65 718.09 lineto stroke
+%  S_FEED
+468.00 808.09 720.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+119.79 658.09 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+145.62 646.09 1.000000 4n
+139.38 646.09 moveto
+151.85 646.09 lineto stroke
+149.30 646.84 moveto
+149.30 667.09 lineto stroke
+152.32 667.09 1.000000 dnflag
+162.96 649.09 1.000000 4n
+166.64 649.84 moveto
+166.64 670.09 lineto stroke
+184.20 652.09 1.000000 4n
+187.88 652.84 moveto
+187.88 673.09 lineto stroke
+190.91 673.09 1.000000 dnflag
+199.31 655.09 1.000000 4n
+202.99 655.84 moveto
+202.99 676.09 lineto stroke
+206.02 676.09 1.000000 dnflag
+216.66 658.09 1.000000 4n
+220.34 658.84 moveto
+220.34 679.09 lineto stroke
+238.46 646.09 1.000000 4n
+232.23 646.09 moveto
+244.69 646.09 lineto stroke
+242.14 646.84 moveto
+242.14 667.09 lineto stroke
+245.17 667.09 1.000000 dnflag
+restore
+%  S_BAR
+23 linenum
+0.70 setlinewidth
+254.88 676.09 moveto
+254.88 652.09 lineto stroke
+%  S_SSV
+25 linenum
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+263.98 646.09 1.000000 4n
+257.75 646.09 moveto
+270.21 646.09 lineto stroke
+267.66 646.84 moveto
+267.66 666.41 lineto stroke
+277.46 649.09 1.000000 4n
+281.14 649.84 moveto
+281.14 669.39 lineto stroke
+290.94 652.09 1.000000 4n
+294.62 652.84 moveto
+294.62 672.38 lineto stroke
+304.42 655.09 1.000000 4n
+308.10 655.84 moveto
+308.10 675.36 lineto stroke
+317.90 658.09 1.000000 4n
+321.58 658.84 moveto
+321.58 678.35 lineto stroke
+331.38 661.09 1.000000 4n
+335.06 661.84 moveto
+335.06 681.33 lineto stroke
+344.86 664.09 1.000000 4n
+348.54 664.84 moveto
+348.54 684.32 lineto stroke
+359.18 667.09 1.000000 4n
+362.86 667.84 moveto
+362.86 687.49 lineto stroke
+newpath
+267.31 667.91 moveto
+363.21 688.99 lineto
+363.21 685.99 lineto
+267.31 664.91 lineto
+closepath
+fill
+restore
+%  S_BAR
+29 linenum
+0.70 setlinewidth
+374.75 676.09 moveto
+374.75 652.09 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+383.29 646.09 1.000000 4n
+377.05 646.09 moveto
+389.52 646.09 lineto stroke
+386.97 646.84 moveto
+386.97 667.09 lineto stroke
+389.99 667.09 1.000000 dnflag
+400.63 649.09 1.000000 4n
+404.32 649.84 moveto
+404.32 670.09 lineto stroke
+422.44 652.09 1.000000 4n
+426.12 652.84 moveto
+426.12 672.49 lineto stroke
+435.92 655.09 1.000000 4n
+439.60 655.84 moveto
+439.60 675.49 lineto stroke
+451.07 658.09 1.000000 4n
+454.75 658.84 moveto
+454.75 679.09 lineto stroke
+472.87 646.09 1.000000 4n
+466.64 646.09 moveto
+479.10 646.09 lineto stroke
+476.55 646.84 moveto
+476.55 667.09 lineto stroke
+479.58 667.09 1.000000 dnflag
+newpath
+425.77 673.99 moveto
+439.95 676.99 lineto
+439.95 673.99 lineto
+425.77 670.99 lineto
+closepath
+fill
+restore
+%  S_BAR
+31 linenum
+0.70 setlinewidth
+489.28 676.09 moveto
+489.28 652.09 lineto stroke
+%  S_SSV
+33 linenum
+%  S_CLEFSIG
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+492.78 664.09 moveto
+(9) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+492.78 651.88 moveto
+(8) show
+%  S_FEED
+468.00 742.09 720.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+119.79 592.09 1.000000 gclef
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+131.58 598.09 moveto
+(9) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+131.58 585.89 moveto
+(8) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+158.42 580.09 1.000000 4n
+152.19 580.09 moveto
+164.66 580.09 lineto stroke
+162.11 580.84 moveto
+162.11 600.21 lineto stroke
+178.04 583.09 1.000000 4n
+181.72 583.84 moveto
+181.72 603.21 lineto stroke
+197.65 586.09 1.000000 4n
+201.33 586.84 moveto
+201.33 606.21 lineto stroke
+217.27 583.09 1.000000 4n
+220.95 583.84 moveto
+220.95 603.21 lineto stroke
+236.88 586.09 1.000000 4n
+240.56 586.84 moveto
+240.56 606.21 lineto stroke
+256.49 589.09 1.000000 4n
+260.17 589.84 moveto
+260.17 609.21 lineto stroke
+276.11 586.09 1.000000 4n
+279.79 586.84 moveto
+279.79 606.20 lineto stroke
+295.72 589.09 1.000000 4n
+299.40 589.84 moveto
+299.40 609.13 lineto stroke
+316.17 592.09 1.000000 4n
+319.85 592.84 moveto
+319.85 612.20 lineto stroke
+newpath
+161.76 601.71 moveto
+201.68 607.71 lineto
+201.68 604.71 lineto
+161.76 598.71 lineto
+closepath
+fill
+newpath
+220.60 604.71 moveto
+260.52 610.71 lineto
+260.52 607.71 lineto
+220.60 601.71 lineto
+closepath
+fill
+newpath
+279.44 607.70 moveto
+320.20 613.70 lineto
+320.20 610.70 lineto
+279.44 604.70 lineto
+closepath
+fill
+restore
+%  S_BAR
+37 linenum
+0.70 setlinewidth
+336.86 610.09 moveto
+336.86 586.09 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+350.21 580.09 1.000000 4n
+359.48 583.09 1.000000 dot
+343.98 580.09 moveto
+356.44 580.09 lineto stroke
+353.89 580.84 moveto
+353.89 601.09 lineto stroke
+396.64 583.09 1.000000 4n
+400.32 583.84 moveto
+400.32 604.09 lineto stroke
+427.52 586.09 1.000000 4n
+431.20 586.84 moveto
+431.20 607.09 lineto stroke
+434.23 607.09 1.000000 dnflag
+447.14 589.09 1.000000 4n
+450.82 589.84 moveto
+450.82 610.09 lineto stroke
+453.84 610.09 1.000000 dnflag
+470.85 592.09 1.000000 4n
+474.54 592.84 moveto
+474.54 613.09 lineto stroke
+restore
+%  S_BAR
+41 linenum
+0.70 setlinewidth
+503.65 610.09 moveto
+503.65 586.09 lineto stroke
+%  S_SSV
+44 linenum
+%  S_FEED
+468.00 676.09 720.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+119.79 526.09 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+147.11 514.09 1.000000 4n
+140.88 514.09 moveto
+153.34 514.09 lineto stroke
+150.79 514.84 moveto
+150.79 533.99 lineto stroke
+166.14 517.09 1.000000 4n
+169.82 517.84 moveto
+169.82 535.44 lineto stroke
+185.17 520.09 1.000000 4n
+188.85 520.84 moveto
+188.85 536.90 lineto stroke
+204.19 517.09 1.000000 4n
+207.88 517.84 moveto
+207.88 538.36 lineto stroke
+223.22 520.09 1.000000 4n
+226.90 520.84 moveto
+226.90 539.82 lineto stroke
+242.25 523.09 1.000000 4n
+245.93 523.84 moveto
+245.93 541.27 lineto stroke
+261.28 520.09 1.000000 4n
+264.96 520.84 moveto
+264.96 540.22 lineto stroke
+280.31 523.09 1.000000 4n
+283.99 523.84 moveto
+283.99 543.15 lineto stroke
+300.17 526.09 1.000000 4n
+303.85 526.84 moveto
+303.85 546.21 lineto stroke
+newpath
+150.44 535.49 moveto
+246.28 542.77 lineto
+246.28 539.77 lineto
+150.44 532.49 lineto
+closepath
+fill
+newpath
+264.61 541.72 moveto
+304.20 547.71 lineto
+304.20 544.71 lineto
+264.61 538.72 lineto
+closepath
+fill
+restore
+%  S_BAR
+48 linenum
+0.70 setlinewidth
+320.37 544.09 moveto
+320.37 520.09 lineto stroke
+%  S_SSV
+51 linenum
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+330.39 514.09 1.000000 4n
+324.16 514.09 moveto
+336.62 514.09 lineto stroke
+334.07 514.84 moveto
+334.07 534.23 lineto stroke
+349.42 517.09 1.000000 4n
+353.10 517.84 moveto
+353.10 537.23 lineto stroke
+368.45 520.09 1.000000 4n
+372.13 520.84 moveto
+372.13 540.23 lineto stroke
+387.48 517.09 1.000000 4n
+391.16 517.84 moveto
+391.16 537.00 lineto stroke
+406.50 520.09 1.000000 4n
+410.19 520.84 moveto
+410.19 538.45 lineto stroke
+425.53 523.09 1.000000 4n
+429.21 523.84 moveto
+429.21 539.90 lineto stroke
+444.56 520.09 1.000000 4n
+448.24 520.84 moveto
+448.24 541.35 lineto stroke
+463.59 523.09 1.000000 4n
+467.27 523.84 moveto
+467.27 542.80 lineto stroke
+483.45 526.09 1.000000 4n
+487.14 526.84 moveto
+487.14 544.31 lineto stroke
+newpath
+333.72 535.73 moveto
+372.48 541.73 lineto
+372.48 538.73 lineto
+333.72 532.73 lineto
+closepath
+fill
+newpath
+390.81 538.50 moveto
+487.49 545.81 lineto
+487.49 542.81 lineto
+390.81 535.50 lineto
+closepath
+fill
+restore
+%  S_BAR
+55 linenum
+0.70 setlinewidth
+503.65 544.09 moveto
+503.65 520.09 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .147(The v)69.336 376 R .147
+(alue of the beamstyle parameter is remembered for an)-.25 F 2.648(yl)
+-.15 G .148(ater changes back to the same time signature.)-2.648 F -.15
+(Fo)69.336 388 S 2.5(re).15 G(xample, suppose you set)-2.65 E/F1 10
+/Courier@0 SF(time=4/4)105.336 406 Q(beamstyle=4,4,4,4)105.336 418 Q F0
+(then later in the piece switched to)69.336 438 Q F1(time=3/4)105.336
+456 Q(beamstyle=4,4,4)105.336 468 Q F0 1.846(Then an)69.336 488 R 4.346
+(yt)-.15 G 1.846(ime you went back to 4/4 or 3/4, the beamstyle you had\
+ set for that time signature w)-4.346 F(ould)-.1 E .561
+(automatically be set as well.)69.336 500 R -1.1(Yo)5.562 G 3.062(uc)1.1
+G .562(ould, of course, o)-3.062 F -.15(ve)-.15 G .562
+(rride the automatic setting with a ne).15 F 3.062(wb)-.25 G .562
+(eamstyle if)-3.062 F(you wished.)69.336 512 Q .546
+(Normally Mup will break beams whene)69.336 530 R -.15(ve)-.25 G 3.046
+(ri).15 G 3.046(te)-3.046 G .546(ncounters a rest or space, b)-3.046 F
+.546(ut if you or specify an "r" at the)-.2 F 1.67
+(end of the beamstyle parameter)69.336 542 R 4.17(,i)-.4 G 4.17(tw)-4.17
+G 1.67
+(ill beam across rests of eighth note or shorter duration. Similarly)
+-4.17 F(,)-.65 E .058(specifying an "s" at the end of the beamstyle par\
+ameter will cause it to beam across spaces of eighth note or)69.336 554
+R(shorter)69.336 566 Q 3.773(.S)-.55 G 1.274(pecifying both \(in either\
+ order\) will result in beaming across both. Mup will also beam across)
+-3.773 F(eighth note or shorter rests or spaces inside of custom beams.)
+69.336 578 Q 1.671(Sometimes, if there are man)69.336 596 R 4.171(ys)
+-.15 G 1.671(hort notes beamed together)-4.171 F 4.171(,y)-.4 G 1.67
+(ou may wish to subdi)-4.171 F 1.67(vide the beams into)-.25 F .527
+(smaller groupings, where the outer)69.336 608 R 3.027(,o)-.4 G 3.027
+(rp)-3.027 G .527(rimary beam remains unbrok)-3.027 F .527(en, b)-.1 F
+.528(ut the inner)-.2 F 3.028(,o)-.4 G 3.028(rs)-3.028 G .528
+(econdary beams)-3.028 F .624(are brok)69.336 620 R .624
+(en periodically)-.1 F 3.124(.W)-.65 G .623(hen using custom beaming, t\
+his is speci\214ed by "esbm" \("end subbeam" or "end)-3.124 F 3.022
+(secondary beam"\) on the chord after which you w)69.336 632 R 3.022
+(ant the break to occur)-.1 F 8.022(.W)-.55 G 3.022
+(hen using beamstyle,)-8.022 F(parentheses are used to indicate what se\
+ts of secondary beams are to be included in a gi)69.336 644 Q -.15(ve)
+-.25 G 2.5(no).15 G(uter beam.)-2.5 E EP
+%%Page: 31 37
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-3)274.506 48 S 2.5(1-)-2.5 G/F1 10
+/Courier@0 SF(score)105.336 96 Q(beamstyle=\(4,4\),\(4,4\))105.336 108 Q
+(music)105.336 120 Q(// use the beamstyle parameter)105.336 144 Q
+(1: 16c;d;e;f; g;a;b;c+; c+;b;a;g; 32f;e;f;e;d;c;d;c;)105.336 156 Q(bar)
+105.336 168 Q(// use custom beaming)105.336 192 Q
+(1: 16c bm;d;e;f;g;a esbm;b;c+;c+;b;a;g esbm;f;e;d;c ebm;)105.336 204 Q
+(bar)105.336 216 Q 71.836 225.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 130 rlineto 432 0 rlineto 0 130 neg rlineto closepath stroke grestore
+EEND 88 633 432 432 -130 130 70.836 355.6 PBEGIN
+%%BeginDocument: mugex25.ps
+%%BoundingBox: 88 633 520 763
+save
+3977375 3978157 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+504.29 872.37 720.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+156.08 722.37 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+183.42 710.37 1.000000 4n
+0.70 setlinewidth
+177.19 710.37 moveto
+189.65 710.37 lineto stroke
+187.10 711.12 moveto
+187.10 730.50 lineto stroke
+202.60 713.37 1.000000 4n
+206.28 714.12 moveto
+206.28 733.50 lineto stroke
+221.78 716.37 1.000000 4n
+225.46 717.12 moveto
+225.46 736.50 lineto stroke
+240.96 719.37 1.000000 4n
+244.64 720.12 moveto
+244.64 739.50 lineto stroke
+260.13 722.37 1.000000 4n
+263.81 723.12 moveto
+263.81 742.50 lineto stroke
+279.31 725.37 1.000000 4n
+282.99 726.12 moveto
+282.99 745.50 lineto stroke
+298.49 728.37 1.000000 4n
+302.17 729.12 moveto
+302.17 748.50 lineto stroke
+317.67 731.37 1.000000 4n
+321.35 732.12 moveto
+321.35 751.50 lineto stroke
+336.84 731.37 1.000000 4n
+340.52 732.12 moveto
+340.52 753.50 lineto stroke
+356.02 728.37 1.000000 4n
+359.70 729.12 moveto
+359.70 750.87 lineto stroke
+375.20 725.37 1.000000 4n
+378.88 726.12 moveto
+378.88 748.24 lineto stroke
+394.37 722.37 1.000000 4n
+398.06 723.12 moveto
+398.06 745.62 lineto stroke
+412.19 719.37 1.000000 4n
+415.87 720.12 moveto
+415.87 743.18 lineto stroke
+423.21 716.37 1.000000 4n
+426.89 717.12 moveto
+426.89 741.67 lineto stroke
+434.22 719.37 1.000000 4n
+437.90 720.12 moveto
+437.90 740.16 lineto stroke
+445.24 716.37 1.000000 4n
+448.92 717.12 moveto
+448.92 738.65 lineto stroke
+456.25 713.37 1.000000 4n
+459.93 714.12 moveto
+459.93 737.14 lineto stroke
+467.26 710.37 1.000000 4n
+461.03 710.37 moveto
+473.50 710.37 lineto stroke
+470.95 711.12 moveto
+470.95 735.63 lineto stroke
+478.28 713.37 1.000000 4n
+481.96 714.12 moveto
+481.96 734.12 lineto stroke
+490.13 710.37 1.000000 4n
+483.90 710.37 moveto
+496.36 710.37 lineto stroke
+493.81 711.12 moveto
+493.81 732.50 lineto stroke
+newpath
+186.75 732.00 moveto
+321.70 753.00 lineto
+321.70 750.00 lineto
+186.75 729.00 lineto
+closepath
+fill
+newpath
+186.75 727.00 moveto
+244.99 736.00 lineto
+244.99 733.00 lineto
+186.75 724.00 lineto
+closepath
+fill
+newpath
+263.46 739.00 moveto
+321.70 748.00 lineto
+321.70 745.00 lineto
+263.46 736.00 lineto
+closepath
+fill
+newpath
+340.17 755.00 moveto
+494.16 734.00 lineto
+494.16 731.00 lineto
+340.17 752.00 lineto
+closepath
+fill
+newpath
+340.17 750.00 moveto
+398.41 742.12 lineto
+398.41 739.12 lineto
+340.17 747.00 lineto
+closepath
+fill
+newpath
+415.52 739.68 moveto
+494.16 729.00 lineto
+494.16 726.00 lineto
+415.52 736.68 lineto
+closepath
+fill
+newpath
+415.52 734.68 moveto
+494.16 724.00 lineto
+494.16 721.00 lineto
+415.52 731.68 lineto
+closepath
+fill
+restore
+%  S_BAR
+11 linenum
+0.70 setlinewidth
+503.65 740.37 moveto
+503.65 716.37 lineto stroke
+%  S_FEED
+468.00 806.37 720.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+119.79 656.37 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+147.63 644.37 1.000000 4n
+141.40 644.37 moveto
+153.86 644.37 lineto stroke
+151.31 645.12 moveto
+151.31 681.87 lineto stroke
+169.79 647.37 1.000000 4n
+173.47 648.12 moveto
+173.47 681.87 lineto stroke
+191.95 650.37 1.000000 4n
+195.63 651.12 moveto
+195.63 681.87 lineto stroke
+214.11 653.37 1.000000 4n
+217.79 654.12 moveto
+217.79 681.87 lineto stroke
+236.27 656.37 1.000000 4n
+239.95 657.12 moveto
+239.95 681.87 lineto stroke
+258.42 659.37 1.000000 4n
+262.11 660.12 moveto
+262.11 681.87 lineto stroke
+280.58 662.37 1.000000 4n
+284.26 663.12 moveto
+284.26 681.87 lineto stroke
+302.74 665.37 1.000000 4n
+306.42 666.12 moveto
+306.42 681.87 lineto stroke
+324.90 665.37 1.000000 4n
+328.58 666.12 moveto
+328.58 681.87 lineto stroke
+347.06 662.37 1.000000 4n
+350.74 663.12 moveto
+350.74 681.87 lineto stroke
+369.22 659.37 1.000000 4n
+372.90 660.12 moveto
+372.90 681.87 lineto stroke
+391.37 656.37 1.000000 4n
+395.06 657.12 moveto
+395.06 681.87 lineto stroke
+413.53 653.37 1.000000 4n
+417.21 654.12 moveto
+417.21 681.87 lineto stroke
+435.69 650.37 1.000000 4n
+439.37 651.12 moveto
+439.37 681.87 lineto stroke
+457.85 647.37 1.000000 4n
+461.53 648.12 moveto
+461.53 681.87 lineto stroke
+480.85 644.37 1.000000 4n
+474.61 644.37 moveto
+487.08 644.37 lineto stroke
+484.53 645.12 moveto
+484.53 681.87 lineto stroke
+newpath
+150.96 683.37 moveto
+484.88 683.37 lineto
+484.88 680.37 lineto
+150.96 680.37 lineto
+closepath
+fill
+newpath
+150.96 678.37 moveto
+262.46 678.37 lineto
+262.46 675.37 lineto
+150.96 675.37 lineto
+closepath
+fill
+newpath
+283.91 678.37 moveto
+395.41 678.37 lineto
+395.41 675.37 lineto
+283.91 675.37 lineto
+closepath
+fill
+newpath
+416.86 678.37 moveto
+484.88 678.37 lineto
+484.88 675.37 lineto
+416.86 675.37 lineto
+closepath
+fill
+restore
+%  S_BAR
+15 linenum
+0.70 setlinewidth
+503.65 674.37 moveto
+503.65 650.37 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 373.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.9.4 Cr)72.336 373.6 R(oss-staf)-.54 E
+3(fb)-.216 G(eams)-3 E 69.336 385.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.621(In k)73.457 385.6 R -.15(ey)-.1 G
+1.621(board music, sometimes notes on adjacent staf).15 F 1.621
+(fs are beamed together)-.25 F 6.62(.M)-.55 G 1.62
+(up will do this with a)-6.62 F -.25(va)69.336 397.6 S .558
+(riation on custom beaming.).25 F 3.058(Ab)5.558 G 3.058(ma)-3.058 G
+.558(nd ebm must be speci\214ed on both staf)-3.058 F .558
+(fs, and in each case the bm is)-.25 F(follo)69.336 409.6 Q .36
+(wed by a quali\214er: on the \214rst of the tw)-.25 F 2.86(os)-.1 G
+(taf)-2.86 E .36(fs, "bm with staf)-.25 F 2.86(fb)-.25 G(elo)-2.86 E .36
+(w" must be speci\214ed, while on the)-.25 F .4(second staf)69.336 421.6
+R 2.9(fy)-.25 G .4(ou use "bm with staf)-2.9 F 2.9(fa)-.25 G(bo)-2.9 E
+-.15(ve)-.15 G 2.9(". F).15 F .4(or e)-.15 F -.15(ve)-.25 G .401
+(ry point in time for the duration of the beam, one staf).15 F(f)-.25 E
+.26(must ha)69.336 433.6 R .56 -.15(ve a c)-.2 H .26
+(hord with notes in it, and the other staf).15 F 2.759(fm)-.25 G .259
+(ust ha)-2.759 F .559 -.15(ve a s)-.2 H .259(pace chord. \(This is some)
+.15 F .259(what dif)-.25 F(ferent)-.25 E .687(than ordinary)69.336 445.6
+R 3.187(,n)-.65 G(on-cross-staf)-3.187 E 3.187(fb)-.25 G .688
+(eams controlled by the beamstyle parameter)-3.187 F 3.188(,w)-.4 G .688
+(here spaces are not allo)-3.188 F(wed)-.25 E .459
+(unless beaming across spaces is speci\214cally requested.\))69.336
+457.6 R .459(The tw)5.459 F 2.959(o")-.1 G .458
+(bm" marks must occur at the same time)-2.959 F 1.84
+(in the measure. Similarly)69.336 469.6 R 4.34(,t)-.65 G 1.84(he tw)
+-4.34 F 4.34(o")-.1 G 1.84
+(ebm" marks must occur at the same time in each staf)-4.34 F 4.34
+(f. Grouping)-.25 F
+(subbeams using "esbm" is not supported on cross-staf)69.336 481.6 Q 2.5
+(fb)-.25 G(eams.)-2.5 E(Some e)69.336 499.6 Q(xamples:)-.15 E/F1 10
+/Courier@0 SF(1: 8f bm with staff below; a; 4s ebm; 4s bm with staff be\
+low; 8b; d ebm;)105.336 517.6 Q(2: 4s bm with staff above; 8a; b ebm; b\
+ bm with staff above; d; 4s ebm;)105.336 529.6 Q(bar)105.336 541.6 Q
+91.836 551.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 106 rlineto 392 0 rlineto 0 106 neg rlineto closepath stroke grestore
+EEND 128 657 392 392 -106 106 90.836 657.2 PBEGIN
+%%BeginDocument: mugex26.ps
+%%BoundingBox: 128 657 520 763
+save
+3977375 3978157 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+4 linenum
+%  S_FEED
+504.29 875.00 720.00 5 1.000000 1.000000 stf
+504.29 821.00 720.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+144.29 743.00 moveto
+144.29 665.00 lineto stroke
+%  S_CLEFSIG
+156.08 725.00 1.000000 gclef
+156.33 683.00 1.000000 fclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+187.35 722.00 1.000000 4n
+183.67 721.25 moveto
+183.67 701.20 lineto stroke
+227.16 728.00 1.000000 4n
+223.47 727.25 moveto
+223.47 705.11 lineto stroke
+425.66 731.00 1.000000 4n
+421.97 730.25 moveto
+421.97 702.37 lineto stroke
+466.21 716.00 1.000000 4n
+462.53 715.25 moveto
+462.53 698.10 lineto stroke
+newpath
+183.32 702.70 moveto
+310.54 715.20 lineto
+310.54 712.20 lineto
+183.32 699.70 lineto
+closepath
+fill
+newpath
+349.55 711.40 moveto
+462.88 699.60 lineto
+462.88 696.60 lineto
+349.55 708.40 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+266.79 689.00 1.000000 4n
+0.70 setlinewidth
+270.47 689.75 moveto
+270.47 709.80 lineto stroke
+306.50 692.00 1.000000 4n
+310.19 692.75 moveto
+310.19 713.70 lineto stroke
+346.22 692.00 1.000000 4n
+349.90 692.75 moveto
+349.90 709.90 lineto stroke
+386.03 677.00 1.000000 4n
+389.71 677.75 moveto
+389.71 705.70 lineto stroke
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+503.65 743.00 moveto
+503.65 719.00 lineto stroke
+503.65 689.00 moveto
+503.65 665.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .565(Normally the beam will be dra)
+69.336 677.2 R .565(wn between the staf)-.15 F .565(fs, b)-.25 F .565
+(ut you can force the beam to be abo)-.2 F .865 -.15(ve o)-.15 H 3.065
+(rb).15 G(elo)-3.065 E 3.065(wa)-.25 G(ll)-3.065 E .591
+(the notes by specifying a stem direction.)69.336 689.2 R -1.1(Yo)5.591
+G 3.091(uc)1.1 G .591(an also adjust the appearance of the beam by gi)
+-3.091 F .592(ving stems)-.25 F
+(lengths for the \214rst and last chords in the beam.)69.336 701.2 Q EP
+%%Page: 32 38
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-3)274.506 48 S 2.5(2-)-2.5 G/F1 10
+/Courier@0 SF(1: [up]8f bm with staff below;a;4s ebm;4s bm with staff b\
+elow;8b;[len 11]d ebm;)105.336 96 Q(2: 4s bm with staff above;8a;b ebm;\
+[down;len 14]b bm with staff above;d;4s ebm;)105.336 108 Q(bar)105.336
+120 Q 91.836 129.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 123 rlineto 392 0 rlineto 0 123 neg rlineto closepath stroke grestore
+EEND 128 643 392 392 -123 123 90.836 252.6 PBEGIN
+%%BeginDocument: mugex27.ps
+%%BoundingBox: 128 643 520 766
+save
+1960644268 1960643998 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+4 linenum
+%  S_FEED
+576.29 803.00 864.00 5 1.000000 1.000000 stf
+576.29 749.00 864.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+144.29 743.00 moveto
+144.29 665.00 lineto stroke
+%  S_CLEFSIG
+156.08 725.00 1.000000 gclef
+156.33 683.00 1.000000 fclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+187.35 722.00 1.000000 4n
+191.03 722.75 moveto
+191.03 756.12 lineto stroke
+227.16 728.00 1.000000 4n
+230.84 728.75 moveto
+230.84 743.19 lineto stroke
+425.66 731.00 1.000000 4n
+421.97 730.25 moveto
+421.97 673.35 lineto stroke
+466.21 716.00 1.000000 4n
+462.53 715.25 moveto
+462.53 684.50 lineto stroke
+newpath
+190.68 757.62 moveto
+310.54 718.93 lineto
+310.54 715.93 lineto
+190.68 754.62 lineto
+closepath
+fill
+newpath
+342.19 653.00 moveto
+462.88 686.00 lineto
+462.88 683.00 lineto
+342.19 650.00 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+266.79 689.00 1.000000 4n
+0.70 setlinewidth
+270.47 689.75 moveto
+270.47 730.32 lineto stroke
+306.50 692.00 1.000000 4n
+310.19 692.75 moveto
+310.19 717.43 lineto stroke
+346.22 692.00 1.000000 4n
+342.54 691.25 moveto
+342.54 651.50 lineto stroke
+386.03 677.00 1.000000 4n
+382.35 676.25 moveto
+382.35 662.45 lineto stroke
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+503.65 743.00 moveto
+503.65 719.00 lineto stroke
+503.65 689.00 moveto
+503.65 665.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .338(If a cross-staf)69.336 272.6 R
+2.838(fb)-.25 G .337
+(eam includes tuplets, the tuplet numbers will not be printed. Y)-2.838
+F .337(ou w)-1.1 F .337(ould ha)-.1 F .637 -.15(ve t)-.2 H 2.837(op).15
+G .337(rint them)-2.837 F
+(yourself using either a "print" statement or a "boldital" statement.)
+69.336 284.6 Q .406(It is possible for cross-staf)69.336 302.6 R 2.906
+(fb)-.25 G .406
+(eams to collide with other items, such as dynamic marks.)-2.906 F .407
+(In these cases, you)5.406 F .036(may need to mo)69.336 314.6 R .336
+-.15(ve t)-.15 H .035(he other items. Another thing you might try is sp\
+ecifying stem lengths to alter where the).15 F .357
+(beams get placed, or printing a blank string between the staf)69.336
+326.6 R .358(fs to cause them to get placed further apart.)-.25 F(If)
+5.358 E 1.087(you specify a slope, you ha)69.336 338.6 R 1.387 -.15
+(ve t)-.2 H 3.587(os).15 G 1.087(pecify it on the staf)-3.587 F 3.587
+(fh)-.25 G -.2(av)-3.587 G 1.086
+(ing notes in the \214rst chord, not the staf).2 F 3.586(fw)-.25 G(ith)
+-3.586 E 2.5(space. Slashes)69.336 350.6 R(are not allo)2.5 E
+(wed on cross-staf)-.25 E 2.5(fb)-.25 G(eams.)-2.5 E .341(Mup doesn')
+69.336 368.6 R 2.841(td)-.18 G .342(irectly allo)-2.841 F 2.842(wc)-.25
+G(ross-staf)-2.842 E 2.842(fg)-.25 G .342(race note beams.)-2.842 F(Ho)
+5.342 E(we)-.25 E -.15(ve)-.25 G 1.142 -.4(r, y).15 H .342
+(ou may be able simulate the ef).4 F .342(fect by)-.25 F .42
+(using cue note chords along with in)69.336 380.6 R .42
+(visible time signature changes and possibly in)-.4 F .42
+(visible bar lines.)-.4 F .42(See the)5.42 F
+(section on "Special uses of in)69.336 392.6 Q
+(visbar" for more details.)-.4 E -1.1(Yo)69.336 410.6 S 3.187(um)1.1 G
+.687(ay w)-3.187 F .688(ant to also look at the section on cross-staf)
+-.1 F 3.188(fs)-.25 G .688(tems, for an alternate w)-3.188 F .688
+(ay to handles some cases)-.1 F(where you might use cross-staf)69.336
+422.6 Q 2.5(fb)-.25 G(eams.)-2.5 E 69.336 438.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.9.5 Alternation)72.336 438.6 R 69.336
+450.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .158
+(Alternation pairs can be speci\214ed using "alt)71.994 450.6 R/F1 10
+/Times-Italic@0 SF(N)2.658 E F0 2.658("w)C(here)-2.658 E F1(N)2.658 E F0
+.158(is a number)2.658 F 2.658(.A)-.55 G 2.658(na)-2.658 G .158
+(lternation pair is tw)-2.658 F 2.658(oc)-.1 G .158(hords that)-2.658 F
+.812(are to played alternately in quick succession b)69.336 462.6 R .812
+(ut are not written out as such. This is sho)-.2 F .812(wn by dra)-.25 F
+(wing)-.15 E F1(N)3.313 E F0 .606
+(beams between the stems of the chords. The note v)69.336 474.6 R .606
+(alue you specify for each chord must be the same, and)-.25 F .303
+(the time v)69.336 486.6 R .303(alue of each must equal the time tak)
+-.25 F .303(en by the pair)-.1 F 2.804(.F)-.55 G .304(or e)-2.954 F .304
+(xample, if the pair tak)-.15 F .304(es up the time of a)-.1 F
+(half note, each chord w)69.336 498.6 Q(ould be a half note.)-.1 E
+(Here is an e)5 E(xample:)-.15 E/F2 10/Courier@0 SF
+(// Alternate between c and c an octave)105.336 516.6 Q
+(// higher. Total time taken is that of)105.336 528.6 Q
+(// a half note. Two "beam"-like lines)105.336 540.6 Q
+(// will be drawn to show the alternation.)105.336 552.6 Q
+(1: 2c alt 2; 2c+;2g;)105.336 564.6 Q(bar)105.336 576.6 Q 127.836 586.2
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 62 rlineto 320 0 rlineto 0 62 neg rlineto closepath stroke grestore
+EEND 160 701 320 320 -62 62 126.836 648.2 PBEGIN
+%%BeginDocument: mugex28.ps
+%%BoundingBox: 160 701 480 763
+save
+1960644268 1960643998 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+612.29 801.67 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 723.67 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+225.89 711.67 1.000000 2n
+0.70 setlinewidth
+219.44 711.67 moveto
+232.34 711.67 lineto stroke
+229.79 712.42 moveto
+229.79 732.50 lineto stroke
+newpath
+229.79 726.00 moveto
+229.79 729.00 lineto
+296.99 750.00 lineto
+296.99 747.00 lineto
+closepath
+fill
+newpath
+229.79 731.00 moveto
+229.79 734.00 lineto
+296.99 755.00 lineto
+296.99 752.00 lineto
+closepath
+fill
+293.10 732.67 1.000000 2n
+296.99 733.42 moveto
+296.99 753.50 lineto stroke
+364.05 723.67 1.000000 2n
+367.95 724.42 moveto
+367.95 744.67 lineto stroke
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+467.65 741.67 moveto
+467.65 717.67 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF(Alternation is not allo)69.336 668.2 Q
+(wed on cross-staf)-.25 E 2.5(fb)-.25 G(eams.)-2.5 E 69.336 684.2 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 12/Times-Italic@0 SF 3(5.1.9.6 Slope)72.336 684.2 R 69.336 696.2
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .157
+(On the \214rst chord of a set of chords that are beamed together)71.993
+696.2 R 2.657(,y)-.4 G .157(ou can specify a beam angle from -45 to 45)
+-2.657 F(de)69.336 708.2 Q 2.5(grees. This)-.15 F(will o)2.5 E -.15(ve)
+-.15 G(rride whate).15 E -.15(ve)-.25 G 2.5(ra).15 G(ngle Mup w)-2.5 E
+(ould ha)-.1 E .3 -.15(ve u)-.2 H(sed.).15 E EP
+%%Page: 33 39
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-3)274.506 48 S 2.5(3-)-2.5 G/F1 10
+/Courier@0 SF(1: 8g slope 11; b; g slope 0; b;)105.336 96 Q 6(gs)12 G
+(lope -5.75; b;)-6 E(bar)105.336 108 Q 127.836 117.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 320 0 rlineto 0 61 neg rlineto closepath stroke grestore
+EEND 160 702 320 320 -61 61 126.836 178.6 PBEGIN
+%%BeginDocument: mugex29.ps
+%%BoundingBox: 160 702 480 763
+save
+1960644268 1960643998 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+612.29 803.00 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+203.87 731.00 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+203.87 718.98 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+233.97 725.00 1.000000 4n
+0.70 setlinewidth
+237.65 725.75 moveto
+237.65 743.67 lineto stroke
+273.14 731.00 1.000000 4n
+276.82 731.75 moveto
+276.82 751.28 lineto stroke
+312.31 725.00 1.000000 4n
+316.00 725.75 moveto
+316.00 747.50 lineto stroke
+351.49 731.00 1.000000 4n
+355.17 731.75 moveto
+355.17 747.50 lineto stroke
+390.66 725.00 1.000000 4n
+394.34 725.75 moveto
+394.34 751.12 lineto stroke
+430.67 731.00 1.000000 4n
+434.35 731.75 moveto
+434.35 747.09 lineto stroke
+newpath
+237.30 745.17 moveto
+277.17 752.78 lineto
+277.17 749.78 lineto
+237.30 742.17 lineto
+closepath
+fill
+newpath
+315.65 749.00 moveto
+355.52 749.00 lineto
+355.52 746.00 lineto
+315.65 746.00 lineto
+closepath
+fill
+newpath
+393.99 752.62 moveto
+434.70 748.59 lineto
+434.70 745.59 lineto
+393.99 749.62 lineto
+closepath
+fill
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 197.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.1.10 T)72.586 197.6 R(uplets)-.715 E
+69.336 209.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF -.45(Tu)74.007 209.6 S 2.171
+(plets are speci\214ed by gi).45 F 2.172
+(ving a list of chords within curly braces.)-.25 F 2.172
+(The ending brace is optionally)7.172 F(follo)69.336 221.6 Q 2.462
+(wed by a side \("abo)-.25 F -.15(ve)-.15 G 4.961("o).15 G 4.961(r")
+-4.961 G(belo)-4.961 E 4.961(w"\). This)-.25 F 2.461(is follo)4.961 F
+2.461(wed by a number or pair of numbers, and a)-.25 F(semicolon.)69.336
+233.6 Q 1.225
+(The "side" tells Mup whether to print the tuplet number and brack)
+69.336 251.6 R 1.225(et abo)-.1 F 1.525 -.15(ve o)-.15 H 3.725(rb).15 G
+(elo)-3.725 E 3.725(wt)-.25 G 1.225(he chords. It only)-3.725 F 1.026
+(applies on v)69.336 263.6 R 1.025(oice 1 or 2 when the other v)-.2 F
+1.025(oice \(1 or 2\) is none)-.2 F 1.025(xistent or a space.)-.15 F
+1.025(If there are at least tw)6.025 F(o)-.1 E -.2(vo)69.336 275.6 S
+.228(ices, the number and brack).2 F .228(et will al)-.1 F -.1(wa)-.1 G
+.228(ys be put abo).1 F .528 -.15(ve o)-.15 H 2.728(nv).15 G .228
+(oice 1 and belo)-2.928 F 2.728(wo)-.25 G 2.728(nv)-2.728 G .228
+(oice 2.)-2.928 F -1.1(Yo)5.228 G 2.728(uc)1.1 G .228(an al)-2.728 F -.1
+(wa)-.1 G(ys).1 E .213(force the side on v)69.336 287.6 R .213(oice 3.)
+-.2 F .212(If you don')5.213 F 2.712(ts)-.18 G .212
+(pecify a side for a tuplet, Mup will choose the side that seems best.)
+-2.712 F .077(The \214rst number is the number that should be printed w\
+ith the tuplet.)69.336 305.6 R .077(If it is follo)5.077 F .078
+(wed by an "n" the number)-.25 F .395(\(and brack)69.336 317.6 R .395
+(et\) will not actually be printed.)-.1 F .395(If it is follo)5.395 F
+.395(wed by a "y" the number and brack)-.25 F .395(et will al)-.1 F -.1
+(wa)-.1 G .395(ys be).1 F .11(printed, unless there is only a single ch\
+ord in the tuplet, in which case only the number will be printed.)69.336
+329.6 R .111(If it)5.111 F .617(is follo)69.336 341.6 R .617
+(wed by "num" the number will al)-.25 F -.1(wa)-.1 G .617
+(ys be printed, b).1 F .617(ut the brack)-.2 F .617(et will ne)-.1 F
+-.15(ve)-.25 G 3.117(rb).15 G 3.117(ep)-3.117 G 3.116(rinted. If)-3.117
+F .616(none of)3.116 F .05
+(those modi\214ers are are speci\214ed, the number will al)69.336 353.6
+R -.1(wa)-.1 G .05(ys be printed, b).1 F .05(ut the brack)-.2 F .05
+(et will be omitted in cases)-.1 F .917(where all the notes in the tupl\
+et are beamed together and the beam does not include an)69.336 365.6 R
+3.416(yn)-.15 G .916(otes not in the)-3.416 F(tuplet.)69.336 377.6 Q
+.471(The second number)69.336 395.6 R 2.972(,i)-.4 G 2.972(fa)-2.972 G
+-.15(ny)-2.972 G 2.972(,i)-.5 G 2.972(ss)-2.972 G .472(eparated from th\
+e \214rst by a comma, and tells the time unit that the tuplet is)-2.972
+F .163(to tak)69.336 407.6 R 2.663(eu)-.1 G .163
+(p. This number can be dotted if necessary)-2.663 F 5.163(.I)-.65 G
+2.663(tc)-5.163 G .163(an also be a time e)-2.663 F .163(xpression, lik)
+-.15 F 2.663(e2)-.1 G .163(+8, although that)-2.663 F .601(is v)69.336
+419.6 R .601(ery rarely lik)-.15 F .601(ely to be useful.)-.1 F .601
+(If no second number is gi)5.601 F -.15(ve)-.25 G .601(n, the def).15 F
+.602(ault is to \214t in the ne)-.1 F .602(xt shorter un-)-.15 F .751
+(dotted note. F)69.336 431.6 R .751(or e)-.15 F .751
+(xample, three eighth notes w)-.15 F .75
+(ould be \214tted into the time of a quarter note, or \214v)-.1 F 3.25
+(ee)-.15 G(ighth)-3.25 E(notes w)69.336 443.6 Q
+(ould be \214tted into the time of a half note.)-.1 E .239(Occasionally\
+ in music, as a shorthand, a single note or chord is printed with a tup\
+let number to indicate the)69.336 461.6 R .3
+(note or chord is to be repeated se)69.336 473.6 R -.15(ve)-.25 G .3
+(ral times as a tuplet.).15 F .299(Mup will allo)5.299 F 2.799(wt)-.25 G
+.299(his; simply use a tuplet with only)-2.799 F
+(one chord, and add one or more slashes.)69.336 485.6 Q(Here are some e)
+69.336 503.6 Q(xamples of tuplets:)-.15 E EP
+%%Page: 34 40
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-3)274.506 48 S 2.5(4-)-2.5 G/F1 10
+/Courier@0 SF(// This has a triplet, where 3 eighth)105.336 96 Q
+(// notes take as much time as a)105.336 108 Q(// normal quarter note.)
+105.336 120 Q(1: { 8ce; df; eg;}3; 4fa;)105.336 132 Q(bar)105.336 144 Q
+(// This has a dublet, in which 2 quarter notes)105.336 168 Q
+(// take the time of a normal dotted quarter)105.336 180 Q
+(1: { 4f; g; } 2, 4.;8a;)105.336 192 Q(bar)105.336 204 Q
+(// A quarter note and eighth note that)105.336 228 Q
+(// make up a triplet the length of a)105.336 240 Q
+(// normal quarter note,)105.336 252 Q
+(// with the 3 printed above the notes)105.336 264 Q
+(1: { 4c+; 8b; } above 3; 4c+;)105.336 276 Q(bar)105.336 288 Q
+(// A septuplet in the time of a half note)105.336 312 Q
+(// with the "7" printed below the notes)105.336 324 Q
+(1: { 8c; b-; c; e; d; f; a; } below 7;)105.336 336 Q(bar)105.336 348 Q
+(// single chord tuplet)105.336 372 Q 6(1: {)105.336 384 R
+([slash 1] 4.ceg;}3; 4;)6 E(bar)105.336 396 Q 91.836 405.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 72 rlineto 392 0 rlineto 0 72 neg rlineto closepath stroke grestore
+EEND 128 686 392 392 -72 72 90.836 477.6 PBEGIN
+%%BeginDocument: mugex30.ps
+%%BoundingBox: 128 686 520 758
+save
+1960644268 1960643998 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+576.29 797.12 864.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+156.08 719.12 1.000000 gclef
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+167.87 725.12 moveto
+(2) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+167.87 713.10 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+193.12 713.12 1.000000 4n
+193.12 707.12 1.000000 4n
+0.70 setlinewidth
+186.89 707.12 moveto
+199.35 707.12 lineto stroke
+196.80 707.87 moveto
+196.80 733.82 lineto stroke
+203.18 716.12 1.000000 4n
+203.18 710.12 1.000000 4n
+206.87 710.87 moveto
+206.87 736.82 lineto stroke
+213.25 719.12 1.000000 4n
+213.25 713.12 1.000000 4n
+216.93 713.87 moveto
+216.93 739.82 lineto stroke
+226.11 722.12 1.000000 4n
+226.11 716.12 1.000000 4n
+229.79 716.87 moveto
+229.79 743.12 lineto stroke
+/NewCenturySchlbk-BoldItalic findfont
+11 scalefont
+setfont
+203.70 740.86 moveto
+(3) show
+newpath
+196.45 735.32 moveto
+217.28 741.32 lineto
+217.28 738.32 lineto
+196.45 732.32 lineto
+closepath
+fill
+restore
+%  S_BAR
+8 linenum
+0.70 setlinewidth
+248.63 737.12 moveto
+248.63 713.12 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+258.38 716.12 1.000000 4n
+262.06 716.87 moveto
+262.06 737.12 lineto stroke
+275.71 719.12 1.000000 4n
+279.39 719.87 moveto
+279.39 740.12 lineto stroke
+292.24 722.12 1.000000 4n
+295.92 722.87 moveto
+295.92 743.12 lineto stroke
+298.95 743.12 1.000000 dnflag
+/NewCenturySchlbk-BoldItalic findfont
+11 scalefont
+setfont
+263.87 740.90 moveto
+(2) show
+254.34 743.40 moveto
+261.87 744.44 lineto stroke
+272.21 745.36 moveto
+279.74 746.40 lineto stroke
+254.34 743.40 moveto
+254.34 740.40 lineto stroke
+279.74 746.40 moveto
+279.74 743.40 lineto stroke
+restore
+%  S_BAR
+13 linenum
+0.70 setlinewidth
+307.86 737.12 moveto
+307.86 713.12 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+317.35 728.12 1.000000 4n
+313.67 727.37 moveto
+313.67 707.12 lineto stroke
+332.17 725.12 1.000000 4n
+328.49 724.37 moveto
+328.49 704.12 lineto stroke
+331.51 704.12 1.000000 upflag
+345.03 728.12 1.000000 4n
+341.35 727.37 moveto
+341.35 707.12 lineto stroke
+/NewCenturySchlbk-BoldItalic findfont
+11 scalefont
+setfont
+321.59 738.40 moveto
+(3) show
+313.32 742.40 moveto
+319.59 742.40 lineto stroke
+329.93 742.40 moveto
+336.20 742.40 lineto stroke
+313.32 742.40 moveto
+313.32 739.40 lineto stroke
+336.20 742.40 moveto
+336.20 739.40 lineto stroke
+restore
+%  S_BAR
+20 linenum
+0.70 setlinewidth
+367.55 737.12 moveto
+367.55 713.12 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+376.09 707.12 1.000000 4n
+369.85 707.12 moveto
+380.82 707.12 lineto stroke
+379.77 707.87 moveto
+379.77 724.64 lineto stroke
+386.15 704.12 1.000000 4n
+381.42 707.12 moveto
+390.88 707.12 lineto stroke
+389.83 704.87 moveto
+389.83 727.21 lineto stroke
+396.21 707.12 1.000000 4n
+391.48 707.12 moveto
+402.45 707.12 lineto stroke
+399.90 707.87 moveto
+399.90 729.77 lineto stroke
+406.28 713.12 1.000000 4n
+409.96 713.87 moveto
+409.96 732.33 lineto stroke
+416.34 710.12 1.000000 4n
+420.02 710.87 moveto
+420.02 734.89 lineto stroke
+426.41 716.12 1.000000 4n
+430.09 716.87 moveto
+430.09 737.46 lineto stroke
+436.97 722.12 1.000000 4n
+440.65 722.87 moveto
+440.65 740.15 lineto stroke
+/NewCenturySchlbk-BoldItalic findfont
+11 scalefont
+setfont
+403.36 693.34 moveto
+(7) show
+newpath
+379.42 726.14 moveto
+441.00 741.65 lineto
+441.00 738.65 lineto
+379.42 723.14 lineto
+closepath
+fill
+restore
+%  S_BAR
+25 linenum
+0.70 setlinewidth
+447.98 737.12 moveto
+447.98 713.12 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+457.10 719.12 1.000000 4n
+466.36 722.12 1.000000 dot
+457.10 713.12 1.000000 4n
+466.36 716.12 1.000000 dot
+457.10 707.12 1.000000 4n
+466.36 710.12 1.000000 dot
+450.87 707.12 moveto
+463.33 707.12 lineto stroke
+460.78 707.87 moveto
+460.78 740.12 lineto stroke
+newpath
+455.78 731.42 moveto
+455.78 734.42 lineto
+465.78 738.82 lineto
+465.78 735.82 lineto
+closepath
+fill
+481.13 719.12 1.000000 4n
+481.13 713.12 1.000000 4n
+481.13 707.12 1.000000 4n
+474.90 707.12 moveto
+487.36 707.12 lineto stroke
+484.81 707.87 moveto
+484.81 740.12 lineto stroke
+/NewCenturySchlbk-BoldItalic findfont
+11 scalefont
+setfont
+453.93 742.40 moveto
+(3) show
+restore
+%  S_BAR
+29 linenum
+0.70 setlinewidth
+503.65 737.12 moveto
+503.65 713.12 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /NewCenturySchlbk-Bold /NewCenturySchlbk-BoldItalic 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 497.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(5.2 Chord-at-a-time)72.836 497.6 R
+(input style)3.5 E 69.336 515.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .437(There is an alternate input style, in \
+which you enter music a chord at a time, rather than a v)72.273 515.6 R
+.438(oice at a time.)-.2 F 1.019
+(In this style, the speci\214cation before the colon gi)69.336 527.6 R
+-.15(ve)-.25 G 3.519(so).15 G 1.019(ne or more patterns that tells ho)
+-3.519 F 3.519(wt)-.25 G 3.519(om)-3.519 G 1.019(ap notes to)-3.519 F
+(staf)69.336 539.6 Q(fs and v)-.25 E(oices.)-.2 E .559(Suppose you w)
+69.336 557.6 R .559
+(ant to print some music in a style which is common for man)-.1 F 3.06
+(yt)-.15 G .56(raditional h)-3.06 F .56(ymns: it is to be)-.05 F .384
+(printed on tw)69.336 569.6 R 2.884(os)-.1 G(taf)-2.884 E .384
+(fs, each staf)-.25 F 2.884(fw)-.25 G .384(ill al)-2.884 F -.1(wa)-.1 G
+.384(ys ha).1 F .684 -.15(ve ex)-.2 H .384(actly tw).15 F 2.884(on)-.1 G
+.384(otes, and the rh)-2.884 F .383(ythm is e)-.05 F .383
+(xactly the same for)-.15 F .523(all v)69.336 581.6 R 3.023(oices. W)-.2
+F .524(ith chord at a time input, you specify)-.4 F 3.024(,f)-.65 G .524
+(or each note in a chord, which staf)-3.024 F 3.024(fa)-.25 G .524(nd v)
+-3.024 F .524(oice to map)-.2 F .289(that note. Since there are four no\
+tes in each chord, there will be four mappings listed. Y)69.336 593.6 R
+.289(ou w)-1.1 F .289(ant the bottom)-.1 F(tw)69.336 605.6 Q 2.5(on)-.1
+G(otes to get mapped to staf)-2.5 E 2.5(f2)-.25 G 2.5(,a)-2.5 G
+(nd the top tw)-2.5 E 2.5(on)-.1 G(otes to staf)-2.5 E 2.5(f1)-.25 G 5
+(.T)-2.5 G(his is sho)-5 E(wn as)-.25 E/F1 10/Courier@0 SF
+(// Bass to staff 2 voice 1)105.336 623.6 Q(// |)105.336 635.6 Q
+(Tenor to staff 2 voice 1)24 E(// |)105.336 647.6 Q 24(|A)24 G
+(lto to staff 1 voice 1)-24 E(// |)105.336 659.6 Q 24(||S)24 G
+(oprano to staff 1 voice 1)-24 E 12([2)105.336 671.6 S
+(1; 2 1; 1 1; 1 1 ])-6 E F0 .114
+(Each item in the semicolon-separated list tells ho)69.336 691.6 R 2.614
+(wt)-.25 G 2.614(om)-2.614 G .114(ap one note.)-2.614 F .115
+(So the \214rst note in each chord will get)5.115 F .11(mapped to staf)
+69.336 703.6 R 2.61(f2v)-.25 G .11(oice 1.)-2.81 F .11
+(The second note in each chord will also get mapped to staf)5.11 F 2.61
+(f2v)-.25 G .11(oice 1.)-2.81 F .11(The third)5.11 F
+(and fourth notes will get mapped to staf)69.336 715.6 Q 2.5(f1v)-.25 G
+(oice 1.)-2.7 E(Since v)69.336 733.6 Q(oice 1 is, as al)-.2 E -.1(wa)-.1
+G(ys, the def).1 E(ault, this could be written more compactly as just:)
+-.1 E EP
+%%Page: 35 41
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-3)274.506 48 S 2.5(5-)-2.5 G/F1 10
+/Courier@0 SF 6([2)105.336 96 S 6(;2)-6 G 6(;1)-6 G 6(;1])-6 G F0 .363
+(If you w)69.336 116 R .364(anted to input notes from top to bottom ins\
+tead \(in soprano-alto-tenor)-.1 F .364(-bass order)-.2 F 2.864(,r)-.4 G
+.364(ather than bass-)-2.864 F(tenor)69.336 128 Q
+(-alto-soprano order\), you could use:)-.2 E F1(// Soprano)105.336 146 Q
+18(// Alto)105.336 158 R 36(// Tenor)105.336 170 R 54(// Bass)105.336
+182 R 12([1)105.336 194 S 6(;1)-12 G 6(;2)-6 G 6(;2])-6 G F0 1.566
+(If you w)69.336 214 R 1.566(anted to use tw)-.1 F 4.066(os)-.1 G 1.566
+(eparate v)-4.066 F 1.566(oices on each staf)-.2 F 4.066(f\()-.25 G
+1.566(going back to bottom-to-top order\), you could)-4.066 F(specify:)
+69.336 226 Q F1(// Bass to staff 2 voice 2)105.336 244 Q(// |)105.336
+256 Q(Tenor to staff 2 voice 1)24 E(// |)105.336 268 Q 24(|A)24 G
+(lto to staff 1 voice 2)-24 E(// |)105.336 280 Q 24(||S)24 G
+(oprano to staff 1 voice 1)-24 E 12([2)105.336 292 S(2; 2 1; 1 2; 1 1)-6
+E(])12 E F0(No)69.336 318 Q 2.5(wl)-.25 G(et')-2.5 E 2.5(sp)-.55 G
+(ut these mappings with music data.)-2.5 E F1(score)105.336 336 Q
+(staffs=2)129.336 348 Q(vscheme=2f)129.336 360 Q(staff 2)105.336 372 Q
+(clef=bass)123.336 384 Q(music)105.336 408 Q 6([2)105.336 432 S 6(;2)-6
+G 6(;1)-6 G 6(;1]:f)-6 G(acf;dgfb;2cgec+;)-6 E(bar)105.336 444 Q 6([11)
+105.336 468 S 6(;12)-6 G 6(;21)-6 G 6(;22]:f)-6 G(caf;bfgd;2c+egc;)-6 E
+(bar)105.336 480 Q 127.836 489.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 138 rlineto 320 0 rlineto 0 138 neg rlineto closepath stroke grestore
+EEND 160 625 320 320 -138 138 126.836 627.6 PBEGIN
+%%BeginDocument: mugex31.ps
+%%BoundingBox: 160 625 480 763
+save
+1960644268 1960643998 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_SSV
+7 linenum
+%  S_FEED
+612.29 803.00 828.00 5 1.000000 1.000000 stf
+612.29 729.00 828.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+180.29 743.00 moveto
+180.29 645.00 lineto stroke
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+192.33 663.00 1.000000 fclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+221.94 722.00 1.000000 4n
+221.94 713.00 1.000000 4n
+215.70 713.00 moveto
+228.17 713.00 lineto stroke
+225.62 713.75 moveto
+225.62 743.00 lineto stroke
+253.14 731.00 1.000000 4n
+253.14 722.00 1.000000 4n
+256.82 722.75 moveto
+256.82 752.00 lineto stroke
+289.07 734.00 1.000000 2n
+289.07 719.00 1.000000 2n
+292.97 719.75 moveto
+292.97 755.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+221.94 669.00 1.000000 4n
+221.94 663.00 1.000000 4n
+0.70 setlinewidth
+218.25 668.25 moveto
+218.25 642.00 lineto stroke
+253.14 666.00 1.000000 4n
+253.14 657.00 1.000000 4n
+249.45 665.25 moveto
+249.45 636.00 lineto stroke
+289.07 666.00 1.000000 2n
+289.07 654.00 1.000000 2n
+285.17 665.25 moveto
+285.17 633.00 lineto stroke
+restore
+%  S_BAR
+13 linenum
+0.70 setlinewidth
+338.76 743.00 moveto
+338.76 719.00 lineto stroke
+338.76 669.00 moveto
+338.76 645.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+350.82 722.00 1.000000 4n
+354.51 722.75 moveto
+354.51 743.00 lineto stroke
+382.02 731.00 1.000000 4n
+385.71 731.75 moveto
+385.71 752.00 lineto stroke
+417.96 734.00 1.000000 2n
+421.85 734.75 moveto
+421.85 755.00 lineto stroke
+350.82 713.00 1.000000 4n
+344.59 713.00 moveto
+357.06 713.00 lineto stroke
+347.14 712.25 moveto
+347.14 692.00 lineto stroke
+382.02 722.00 1.000000 4n
+378.34 721.25 moveto
+378.34 701.00 lineto stroke
+417.96 719.00 1.000000 2n
+414.06 718.25 moveto
+414.06 698.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+350.82 669.00 1.000000 4n
+0.70 setlinewidth
+354.51 669.75 moveto
+354.51 690.00 lineto stroke
+382.02 666.00 1.000000 4n
+385.71 666.75 moveto
+385.71 687.00 lineto stroke
+417.96 666.00 1.000000 2n
+421.85 666.75 moveto
+421.85 687.00 lineto stroke
+350.82 663.00 1.000000 4n
+347.14 662.25 moveto
+347.14 642.00 lineto stroke
+382.02 657.00 1.000000 4n
+378.34 656.25 moveto
+378.34 636.00 lineto stroke
+417.96 654.00 1.000000 2n
+414.06 653.25 moveto
+414.06 633.00 lineto stroke
+restore
+%  S_BAR
+16 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+467.65 669.00 moveto
+467.65 645.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .68
+(In the \214rst measure, the \214rst tw)69.336 641.6 R 3.18(on)-.1 G .68
+(otes listed in each chord are mapped to staf)-3.18 F 3.18(f2)-.25 G
+3.18(,v)-3.18 G .68(oice 1, while the third)-3.38 F .587
+(and fourth notes listed in each chord are mapped to staf)69.336 653.6 R
+3.087(f1v)-.25 G .587(oice 1. In the second measure, tw)-3.287 F 3.087
+(ov)-.1 G .587(oices are)-3.287 F .565
+(used and notes are entered in descending order)69.336 665.6 R 3.065(.N)
+-.55 G .565(ote that each note tak)-3.065 F .565(es on the correct def)
+-.1 F .565(ault octa)-.1 F .865 -.15(ve f)-.2 H(or).15 E(whiche)69.336
+677.6 Q -.15(ve)-.25 G 2.5(rs).15 G(taf)-2.5 E 2.5(fi)-.25 G 2.5(ti)-2.5
+G 2.5(sm)-2.5 G(apped to.)-2.5 E
+(It is also possible to use rests or spaces for some of the v)69.336
+695.6 Q(oices.)-.2 E EP
+%%Page: 36 42
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-3)274.506 48 S 2.5(6-)-2.5 G/F1 10
+/Courier@0 SF(score)105.336 96 Q(key=3&)117.336 108 Q(vscheme=2f)117.336
+120 Q(music)105.336 144 Q 6([12)105.336 168 S 6(;11])-6 G 6(:r)-6 G
+(b; eg; ca; gr;)-6 E(bar)105.336 180 Q 6([12)105.336 204 S 6(;11])-6 G 6
+(:e)-6 G(r; sr; 8sf; se; 4sg;)-6 E(bar)105.336 216 Q 91.836 225.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 79 rlineto 392 0 rlineto 0 79 neg rlineto closepath stroke grestore
+EEND 128 684 392 392 -79 79 90.836 304.6 PBEGIN
+%%BeginDocument: mugex32.ps
+%%BoundingBox: 128 684 520 763
+save
+1960644268 1960643998 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+576.29 803.00 864.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+156.08 725.00 1.000000 gclef
+169.62 731.00 1.000000 flat
+175.10 740.00 1.000000 flat
+180.59 728.00 1.000000 flat
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+204.58 731.00 1.000000 4n
+0.70 setlinewidth
+208.26 731.75 moveto
+208.26 752.00 lineto stroke
+239.89 725.00 1.000000 4n
+243.57 725.75 moveto
+243.57 746.00 lineto stroke
+275.20 728.00 1.000000 4n
+278.88 728.75 moveto
+278.88 749.00 lineto stroke
+311.35 743.00 1.000000 4rest
+204.58 707.00 1.000000 4rest
+239.89 719.00 1.000000 4n
+236.21 718.25 moveto
+236.21 698.00 lineto stroke
+275.20 713.00 1.000000 4n
+268.97 713.00 moveto
+281.43 713.00 lineto stroke
+271.52 712.25 moveto
+271.52 692.00 lineto stroke
+311.35 725.00 1.000000 4n
+307.67 724.25 moveto
+307.67 704.00 lineto stroke
+restore
+%  S_BAR
+11 linenum
+0.70 setlinewidth
+345.12 743.00 moveto
+345.12 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+358.02 737.00 1.000000 4rest
+393.33 731.00 1.000000 4rest
+425.14 722.00 1.000000 4n
+428.82 722.75 moveto
+428.82 743.00 lineto stroke
+431.84 743.00 1.000000 dnflag
+445.42 719.00 1.000000 4n
+449.10 719.75 moveto
+449.10 740.00 lineto stroke
+452.12 740.00 1.000000 dnflag
+469.88 725.00 1.000000 4n
+473.57 725.75 moveto
+473.57 746.00 lineto stroke
+358.02 719.00 1.000000 4n
+354.34 718.25 moveto
+354.34 698.00 lineto stroke
+restore
+%  S_BAR
+14 linenum
+0.70 setlinewidth
+503.65 743.00 moveto
+503.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF 1.177(Chord attrib)69.336 324.6 R 1.177
+(utes and interchord attrib)-.2 F 1.177(utes \(lik)-.2 F 3.677(et)-.1 G
+1.177(ie, slur)-3.677 F 3.677(,x)-.4 G 1.176
+(note, len, and alt\) can be speci\214ed just lik)-3.677 F 3.676(ef)-.1
+G(or)-3.676 E -.2(vo)69.336 336.6 S 1.008
+(ice-at-a-time input. Note attrib).2 F 1.008(utes \(lik)-.2 F 3.508(e?a)
+-.1 G 1.008(nd ~\) apply to the note where)-3.508 F -.15(ve)-.25 G 3.508
+(ri).15 G 3.509(tg)-3.508 G 1.009(ets mapped, and items)-3.509 F
+(that apply to the chord as a whole will be applied to all the notes.)
+69.336 348.6 Q/F1 10/Courier@0 SF
+([1 2; 1 1] : [cue; xnote; len 6] b-e; [with > ] ce& slur; dg~; c?g;)
+105.336 366.6 Q 127.836 376.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 86 rlineto 320 0 rlineto 0 86 neg rlineto closepath stroke grestore
+EEND 160 677 320 320 -86 86 126.836 462.2 PBEGIN
+%%BeginDocument: mugex33.ps
+%%BoundingBox: 160 677 480 763
+save
+1960644268 1960643998 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+612.29 803.00 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+224.01 719.00 0.583333 xnote
+0.70 setlinewidth
+226.14 720.95 moveto
+226.14 737.00 lineto stroke
+285.51 719.00 1.000000 4n
+276.73 719.00 1.000000 flat
+/Times-Roman findfont
+12 scalefont
+setfont
+278.81 744.32 moveto
+285.51 744.32 1.000000 acc_gt
+292.20 744.32 moveto
+289.19 719.75 moveto
+289.19 740.00 lineto stroke
+347.46 725.00 1.000000 4n
+351.14 725.75 moveto
+351.14 746.00 lineto stroke
+411.69 725.00 1.000000 4n
+415.37 725.75 moveto
+415.37 746.00 lineto stroke
+224.01 710.00 0.583333 xnote
+219.33 713.00 moveto
+228.69 713.00 lineto stroke
+221.88 708.05 moveto
+221.88 692.00 lineto stroke
+285.51 713.00 1.000000 4n
+279.28 713.00 moveto
+291.74 713.00 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+278.81 687.75 moveto
+285.51 687.75 1.000000 acc_gt
+292.20 687.75 moveto
+281.83 712.25 moveto
+281.83 692.00 lineto stroke
+347.46 716.00 1.000000 4n
+343.78 715.25 moveto
+343.78 695.00 lineto stroke
+411.69 713.00 0.583333 4n
+407.13 713.00 moveto
+416.24 713.00 lineto stroke
+409.68 712.51 moveto
+409.68 698.00 lineto stroke
+285.51 707.90 moveto
+285.52 708.05 lineto
+294.65 706.20 303.85 705.52 313.15 706.03 curveto
+322.45 706.54 331.53 708.21 340.40 711.05 curveto
+340.46 710.75 lineto
+331.74 707.12 322.66 705.05 313.23 704.53 curveto
+303.80 704.02 294.56 705.09 285.49 707.75 curveto
+fill
+353.49 730.10 moveto
+353.47 730.25 lineto
+362.89 733.56 372.60 735.21 382.59 735.21 curveto
+392.58 735.21 402.28 733.56 411.71 730.25 curveto
+411.66 729.95 lineto
+402.13 732.46 392.44 733.71 382.59 733.71 curveto
+372.73 733.71 363.04 732.46 353.51 729.95 curveto
+fill
+291.54 724.10 moveto
+291.50 724.25 lineto
+300.21 728.41 309.37 731.01 318.97 732.04 curveto
+328.57 733.07 338.07 732.47 347.46 730.25 curveto
+347.45 729.95 lineto
+338.04 731.36 328.60 731.56 319.13 730.55 curveto
+309.66 729.53 300.48 727.33 291.58 723.95 curveto
+fill
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .987(It is possible to map a note to mo\
+re than one place by using ranges, and/or by gi)69.336 482.2 R .986
+(ving a list of staf)-.25 F .986(fs and)-.25 F -.2(vo)69.336 494.2 S
+.783(ices, separated by ampersands. This may be useful, for e).2 F .784
+(xample, if se)-.15 F -.15(ve)-.25 G .784(ral v).15 F .784
+(oices are in unison.)-.2 F .784(In the)5.784 F(ne)69.336 506.2 Q 1.088
+(xt e)-.15 F 1.087
+(xample, the \214rst note in each chord will be mapped to v)-.15 F 1.087
+(oice 1 of staf)-.2 F 1.087(fs 1 through 3, as well as to)-.25 F -.2(vo)
+69.336 518.2 S(ice 2 of staf).2 E 2.5(f1)-.25 G 2.5(,w)-2.5 G
+(hile the second note in each chord will be mapped to v)-2.5 E
+(oice 2 of staf)-.2 E(fs 2 and 3.)-.25 E/F1 10/Courier@0 SF 6([1)105.336
+536.2 S(-3 1)-6 E 12(&1)12 G 6(2; 2-3)-6 F 6(2]:e)6 G(c;fd;ge;af;)-6 E
+127.836 545.8 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 195 rlineto 320 0 rlineto 0 195 neg rlineto closepath stroke grestore
+EEND 160 568 320 320 -195 195 126.836 740.8 PBEGIN
+%%BeginDocument: mugex34.ps
+%%BoundingBox: 160 568 480 763
+save
+1960644268 1960643998 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+612.29 803.00 828.00 5 1.000000 1.000000 stf
+612.29 748.00 828.00 5 1.000000 1.000000 stf
+612.29 687.00 828.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+180.29 743.00 moveto
+180.29 603.00 lineto stroke
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+192.08 670.00 1.000000 gclef
+192.08 609.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+226.49 719.00 1.000000 4n
+230.17 719.75 moveto
+230.17 740.00 lineto stroke
+288.05 722.00 1.000000 4n
+291.73 722.75 moveto
+291.73 743.00 lineto stroke
+349.61 725.00 1.000000 4n
+353.29 725.75 moveto
+353.29 746.00 lineto stroke
+412.01 728.00 1.000000 4n
+415.69 728.75 moveto
+415.69 749.00 lineto stroke
+226.49 719.00 1.000000 4n
+222.80 718.25 moveto
+222.80 698.00 lineto stroke
+288.05 722.00 1.000000 4n
+284.37 721.25 moveto
+284.37 701.00 lineto stroke
+349.61 725.00 1.000000 4n
+345.93 724.25 moveto
+345.93 704.00 lineto stroke
+412.01 728.00 1.000000 4n
+408.33 727.25 moveto
+408.33 707.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+226.49 664.00 1.000000 4n
+0.70 setlinewidth
+230.17 664.75 moveto
+230.17 685.00 lineto stroke
+288.05 667.00 1.000000 4n
+291.73 667.75 moveto
+291.73 688.00 lineto stroke
+349.61 670.00 1.000000 4n
+353.29 670.75 moveto
+353.29 691.00 lineto stroke
+412.01 673.00 1.000000 4n
+415.69 673.75 moveto
+415.69 694.00 lineto stroke
+226.49 658.00 1.000000 4n
+220.25 658.00 moveto
+232.72 658.00 lineto stroke
+222.80 657.25 moveto
+222.80 637.00 lineto stroke
+288.05 661.00 1.000000 4n
+284.37 660.25 moveto
+284.37 640.00 lineto stroke
+349.61 664.00 1.000000 4n
+345.93 663.25 moveto
+345.93 643.00 lineto stroke
+412.01 667.00 1.000000 4n
+408.33 666.25 moveto
+408.33 646.00 lineto stroke
+restore
+%  S_STAFF
+% staff 3
+save
+226.49 603.00 1.000000 4n
+0.70 setlinewidth
+230.17 603.75 moveto
+230.17 624.00 lineto stroke
+288.05 606.00 1.000000 4n
+291.73 606.75 moveto
+291.73 627.00 lineto stroke
+349.61 609.00 1.000000 4n
+353.29 609.75 moveto
+353.29 630.00 lineto stroke
+412.01 612.00 1.000000 4n
+415.69 612.75 moveto
+415.69 633.00 lineto stroke
+226.49 597.00 1.000000 4n
+220.25 597.00 moveto
+232.72 597.00 lineto stroke
+222.80 596.25 moveto
+222.80 576.00 lineto stroke
+288.05 600.00 1.000000 4n
+284.37 599.25 moveto
+284.37 579.00 lineto stroke
+349.61 603.00 1.000000 4n
+345.93 602.25 moveto
+345.93 582.00 lineto stroke
+412.01 606.00 1.000000 4n
+408.33 605.25 moveto
+408.33 585.00 lineto stroke
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+467.65 688.00 moveto
+467.65 664.00 lineto stroke
+467.65 627.00 moveto
+467.65 603.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND EP
+%%Page: 37 43
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-3)274.506 48 S 2.5(7-)-2.5 G 2.104
+(It is also possible to specify more than one brack)69.336 104 R 2.104
+(eted mapping.)-.1 F 2.104(Each must include a mapping for a)7.104 F
+(dif)69.336 116 Q .862(ferent number of notes.)-.25 F .862(So, for e)
+5.862 F .862(xample, if some chords in a measure ha)-.15 F 1.161 -.15
+(ve t)-.2 H 1.061 -.1(wo n).15 H .861(otes and others ha).1 F -.15(ve)
+-.2 G 1.236(three, you can de\214ne tw)69.336 128 R 3.736(om)-.1 G 1.236
+(aps: one for tw)-3.736 F 3.736(on)-.1 G 1.237
+(otes, and one for three. The e)-3.736 F 1.237(xample belo)-.15 F 3.737
+(wd)-.25 G(emonstrates)-3.737 E(placing alto and soprano as tw)69.336
+140 Q 2.5(ov)-.1 G(oices on one staf)-2.7 E(f, b)-.25 E
+(ut sometimes the alto part splits.)-.2 E/F1 10/Courier@0 SF
+(// For chords with two notes,)105.336 158 Q
+(// map the first to staff 1 voice 2 \(alto\),)105.336 170 Q
+(// and the second to staff 1 voice 1 \(soprano\).)105.336 182 Q
+(// For chords with three notes,)105.336 194 Q
+(// map the first two notes to staff 1 voice 2)105.336 206 Q
+(// \(first and second alto part\),)105.336 218 Q
+(// and the third to staff 1 voice 1 \(soprano\).)105.336 230 Q 6([12)
+105.336 242 S 6(;11][12)-6 G 6(;12)-6 G 6(;11])-6 G 6(:c)-6 G
+(ec+;df;eg;a-fc+;)-6 E 127.836 251.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 85 rlineto 320 0 rlineto 0 85 neg rlineto closepath stroke grestore
+EEND 160 678 320 320 -85 85 126.836 336.6 PBEGIN
+%%BeginDocument: mugex35.ps
+%%BoundingBox: 160 678 480 763
+save
+1960644268 1960643998 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+612.29 803.00 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+226.49 734.00 1.000000 4n
+0.70 setlinewidth
+230.17 734.75 moveto
+230.17 755.00 lineto stroke
+288.05 722.00 1.000000 4n
+291.73 722.75 moveto
+291.73 743.00 lineto stroke
+349.61 725.00 1.000000 4n
+353.29 725.75 moveto
+353.29 746.00 lineto stroke
+412.01 734.00 1.000000 4n
+415.69 734.75 moveto
+415.69 755.00 lineto stroke
+226.49 719.00 1.000000 4n
+226.49 713.00 1.000000 4n
+220.25 713.00 moveto
+232.72 713.00 lineto stroke
+222.80 718.25 moveto
+222.80 692.00 lineto stroke
+288.05 716.00 1.000000 4n
+284.37 715.25 moveto
+284.37 695.00 lineto stroke
+349.61 719.00 1.000000 4n
+345.93 718.25 moveto
+345.93 698.00 lineto stroke
+412.01 722.00 1.000000 4n
+412.01 707.00 1.000000 4n
+405.78 707.00 moveto
+418.24 707.00 lineto stroke
+405.78 713.00 moveto
+418.24 713.00 lineto stroke
+408.33 721.25 moveto
+408.33 686.00 lineto stroke
+restore
+%  S_BAR
+15 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .077(If mappings of dif)69.336 350.6 R
+.077(ferent chords need to v)-.25 F .077
+(ary by something other than the number of notes in the chord, then)-.25
+F(you will ha)69.336 362.6 Q .3 -.15(ve t)-.2 H 2.5(ou).15 G(se the v)
+-2.5 E(oice-at-a-time input style.)-.2 E .425
+(Since the mapping speci\214cations can get rather comple)69.336 380.6 R
+.425(x, and the)-.15 F 2.925(ym)-.15 G .425(ay be used man)-2.925 F
+2.926(yt)-.15 G .426(imes during a song,)-2.926 F .181
+(it is usually best to de\214ne macros for them, and possibly e)69.336
+392.6 R -.15(ve)-.25 G 2.68(np).15 G .18
+(ut the macro de\214nitions in an "include" \214le.)-2.68 F
+(Macros and include \214les are described in a later section.)69.336
+404.6 Q -1.1(Yo)69.336 422.6 S 2.949(uc)1.1 G .449(an use the dif)-2.949
+F .449(ferent input styles in dif)-.25 F .45
+(ferent measures of a single song, and use dif)-.25 F .45
+(ferent mappings in)-.25 F(dif)69.336 434.6 Q 1.078(ferent measures.)
+-.25 F -1.1(Yo)6.077 G 3.577(uc)1.1 G 1.077(an e)-3.577 F -.15(ve)-.25 G
+3.577(nm).15 G 1.077(ix the tw)-3.577 F 3.577(oi)-.1 G 1.077
+(nput styles within a measure, b)-3.577 F 1.077(ut a gi)-.2 F -.15(ve)
+-.25 G 3.577(ns).15 G(taf)-3.577 E(f/v)-.25 E 1.077(oice can)-.2 F .125
+(only appear on one line of input per measure. So, for e)69.336 446.6 R
+.125(xample, you could choose to input staf)-.15 F .125(fs 1 and 2 of a)
+-.25 F(song in chord-at-a-time input style, and staf)69.336 458.6 Q 2.5
+(f3i)-.25 G 2.5(nv)-2.5 G(oice-at-a-time style.)-2.7 E 69.336 476.6
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(5.3 Bar)72.836 476.6 R(lines)3.5 E 69.336
+494.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF
+(Each measure must be ended with a "bar" of some kind. There are se)
+71.836 494.6 Q -.15(ve)-.25 G(ral kinds:).15 E/F1 10/Times-Bold@0 SF
+-.25(Ke)152.281 512.6 S(yw).25 E 101.18(ord Meaning)-.1 F .4 LW 419.951
+517.1 150.721 517.1 DL F0 41.94(bar ordinary)150.721 526.6 R(bar line)
+2.5 E 29.16(dblbar double)150.721 538.6 R(bar)2.5 E 13.06
+(repeatstart be)150.721 550.6 R(ginning of repeated section)-.15 E 12.5
+(repeatboth end)150.721 562.6 R(of one repeated section and be)2.5 E
+(ginning of another)-.15 E 15.84(repeatend end)150.721 574.6 R
+(of repeated section)2.5 E 27.5(endbar hea)150.721 586.6 R
+(vy double bar line used at end of song)-.2 E(in)150.721 598.6 Q 22.89
+(visbar no)-.4 F(bar line printed)2.5 E 29.72(restart end)150.721 610.6
+R(staf)2.5 E(fs and be)-.25 E(gin ane)-.15 E(w)-.25 E .558
+(In addition, the bar and dblbar types can be preceded by the w)69.336
+628.6 R .557(ord "dashed" or "dotted" to produce dashed)-.1 F
+(or dotted bar lines.)69.336 640.6 Q EP
+%%Page: 38 44
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-3)274.506 48 S 2.5(8-)-2.5 G/F1 10
+/Courier@0 SF(1: mr;)105.336 96 Q(bar)105.336 108 Q(1: mr;)105.336 120 Q
+(dblbar)105.336 132 Q(1: mr;)105.336 144 Q(dashed bar)105.336 156 Q
+(1: mr;)105.336 168 Q(dotted dblbar)105.336 180 Q(1: mr;)105.336 192 Q
+(repeatstart)105.336 204 Q(1: mr;)105.336 216 Q(repeatboth)105.336 228 Q
+(1: mr;)105.336 240 Q(repeatend)105.336 252 Q(1: mr;)105.336 264 Q
+(endbar)105.336 276 Q 115.836 285.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 344 0 rlineto 0 61 neg rlineto closepath stroke grestore
+EEND 136 702 344 344 -61 61 114.836 346.6 PBEGIN
+%%BeginDocument: mugex36.ps
+%%BoundingBox: 136 702 480 763
+save
+1960644268 1960643998 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+588.07 803.00 828.00 5 1.000000 1.000000 stf
+/Times-Roman findfont
+12 scalefont
+setfont
+144.00 728.73 moveto
+(   ) show
+%  S_CLEFSIG
+167.86 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+200.33 731.00 1.000000 ll1rest
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+215.51 743.00 moveto
+215.51 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+230.69 731.00 1.000000 ll1rest
+restore
+%  S_BAR
+7 linenum
+0.70 setlinewidth
+244.87 743.00 moveto
+244.87 719.00 lineto stroke
+247.87 743.00 moveto
+247.87 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+263.04 731.00 1.000000 ll1rest
+restore
+%  S_BAR
+10 linenum
+1.00 setlinewidth
+[3 3] 0 setdash
+278.22 741.88 moveto
+278.22 719.30 lineto stroke
+0.70 setlinewidth
+[] 0 setdash
+0 setlinecap
+0 setlinejoin
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+293.40 731.00 1.000000 ll1rest
+restore
+%  S_BAR
+11 linenum
+1.00 setlinewidth
+[0.1 5] 0 setdash
+1 setlinecap
+1 setlinejoin
+307.58 741.88 moveto
+307.58 719.30 lineto stroke
+310.58 741.88 moveto
+310.58 719.30 lineto stroke
+0.70 setlinewidth
+[] 0 setdash
+0 setlinecap
+0 setlinejoin
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+325.76 731.00 1.000000 ll1rest
+restore
+%  S_BAR
+13 linenum
+349.43 734.00 1.000000 dot
+349.43 728.00 1.000000 dot
+0.70 setlinewidth
+346.43 743.00 moveto
+346.43 719.00 lineto stroke
+3.00 setlinewidth
+342.43 743.00 moveto
+342.43 719.00 lineto stroke
+0.70 setlinewidth
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+365.11 731.00 1.000000 ll1rest
+restore
+%  S_BAR
+15 linenum
+393.29 734.00 1.000000 dot
+393.29 728.00 1.000000 dot
+379.29 734.00 1.000000 dot
+379.29 728.00 1.000000 dot
+0.70 setlinewidth
+3.00 setlinewidth
+383.79 743.00 moveto
+383.79 719.00 lineto stroke
+388.79 743.00 moveto
+388.79 719.00 lineto stroke
+0.70 setlinewidth
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+407.47 731.00 1.000000 ll1rest
+restore
+%  S_BAR
+17 linenum
+423.14 734.00 1.000000 dot
+423.14 728.00 1.000000 dot
+0.70 setlinewidth
+427.14 743.00 moveto
+427.14 719.00 lineto stroke
+3.00 setlinewidth
+431.14 743.00 moveto
+431.14 719.00 lineto stroke
+0.70 setlinewidth
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+446.82 731.00 1.000000 ll1rest
+restore
+%  S_BAR
+19 linenum
+0.70 setlinewidth
+462.50 743.00 moveto
+462.50 719.00 lineto stroke
+3.00 setlinewidth
+466.50 743.00 moveto
+466.50 719.00 lineto stroke
+0.70 setlinewidth
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .478(When a repeatstart w)69.336 366.6 R
+.478(ould end up at the end of a score, it will automatically get mo)-.1
+F -.15(ve)-.15 G 2.978(dt).15 G 2.978(ot)-2.978 G .478(he be)-2.978 F
+.478(ginning of)-.15 F .109(the follo)69.336 378.6 R .109(wing score.)
+-.25 F .109(In that case, it isn')5.109 F 2.608(tc)-.18 G .108
+(lear what kind of bar line you w)-2.608 F .108(ould lik)-.1 F 2.608(et)
+-.1 G 2.608(oh)-2.608 G -2.25 -.2(av e)-2.608 H .108(put at the end of)
+2.808 F 1.606(the original score. By def)69.336 390.6 R 1.606
+(ault, Mup will use an ordinary bar)-.1 F 4.107(,b)-.4 G 1.607
+(ut in some cases\212lik)-4.307 F 4.107(ei)-.1 G 4.107(ft)-4.107 G 1.607
+(he repeatstart)-4.107 F(be)69.336 402.6 Q .112(gins a ne)-.15 F 2.612
+(ws)-.25 G .112(ection, or there is also a k)-2.612 F .411 -.15(ey c)-.1
+H .111(hange\212you might w).15 F .111(ant to ha)-.1 F .411 -.15(ve a d)
+-.2 H .111(blbar instead. Y).15 F .111(ou can get a)-1.1 F(dblbar there\
+ by specifying dblbar in parentheses before the repeatstart:)69.336
+414.6 Q/F1 10/Courier@0 SF(\(dblbar\) repeatstart)105.336 432.6 Q F0
+(Actually)69.336 452.6 Q 3.715(,y)-.65 G 1.215(ou are allo)-3.715 F
+1.216(wed to specify an)-.25 F 3.716(yb)-.15 G 1.216
+(ar type in the parentheses, b)-3.716 F 1.216(ut dblbar or possibly in)
+-.2 F 1.216(visbar are)-.4 F 1.135(probably the only ones lik)69.336
+464.6 R 1.135(ely to be useful.)-.1 F 1.134
+(If the repeatstart ends up in the middle of a score, so that it)6.134 F
+(doesn')69.336 476.6 Q 2.698(tn)-.18 G .198(eed to get mo)-2.698 F -.15
+(ve)-.15 G 2.698(dt).15 G 2.698(ot)-2.698 G .198(he be)-2.698 F .198
+(ginning of the ne)-.15 F .198
+(xt score, the parenthesized bar type is not needed, so it)-.15 F
+(is just ignored.)69.336 488.6 Q 1.574
+(Sometimes music is printed without bar lines. The "in)69.336 506.6 R
+1.573(visbar" can be used in this case, to ful\214ll Mup')-.4 F(s)-.55 E
+(requirement to specify some sort of bar after e)69.336 518.6 Q -.15(ve)
+-.25 G(ry measure without actually printing bar lines.).15 E 1.003
+(The restart is a special kind of bar)69.336 536.6 R 3.503(.I)-.55 G
+3.504(tf)-3.503 G(ollo)-3.504 E 1.004
+(ws immediately after another bar line without an)-.25 F 3.504(yi)-.15 G
+(nterv)-3.504 E(ening)-.15 E .186(music data. \(That is, you can')69.336
+548.6 R 2.685(th)-.18 G -2.25 -.2(av e)-2.685 H(an)2.885 E 2.685(yn)-.15
+G .185(otes. Y)-2.685 F .185(ou can use score or staf)-1.1 F 2.685(fc)
+-.25 G(onte)-2.685 E .185(xt things, lik)-.15 F 2.685(ec)-.1 G .185
+(hanging time)-2.685 F(or k)69.336 560.6 Q .3 -.15(ey s)-.1 H
+(ignature.\) It w).15 E(ould be most commonly used for something lik)-.1
+E 2.5(eas)-.1 G(hort coda.)-2.5 E EP
+%%Page: 39 45
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-3)274.506 48 S 2.5(9-)-2.5 G/F1 10
+/Courier@0 SF(score)105.336 96 Q(staffs=2)130.336 108 Q(brace=1-2)
+130.336 120 Q(staff 2)105.336 132 Q(clef=bass)130.336 144 Q(music)
+105.336 156 Q(1-2: c;d;e;f;)105.336 180 Q
+(rom above 1: 3 "D.C. al Coda";)105.336 192 Q(dblbar)105.336 204 Q
+(// The restart follows a bar)105.336 228 Q
+(// without any music data in between.)105.336 240 Q(restart)105.336 252
+Q(rom above 1: 1 "Coda";)105.336 276 Q(1-2: f;e;d;c;)105.336 288 Q
+(endbar)105.336 300 Q 91.836 309.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 120 rlineto 392 0 rlineto 0 120 neg rlineto closepath stroke grestore
+EEND 128 643 392 392 -120 120 90.836 429.6 PBEGIN
+%%BeginDocument: mugex37.ps
+%%BoundingBox: 128 643 520 763
+save
+1960644268 1960643998 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_SSV
+7 linenum
+%  S_FEED
+586.29 797.54 864.00 5 1.000000 1.000000 stf
+586.29 743.54 864.00 5 1.000000 1.000000 stf
+153.79 737.54 659.54 brace
+0.70 setlinewidth
+154.29 737.54 moveto
+154.29 659.54 lineto stroke
+320.39 738.54 344.39 658.54 whitebox
+342.89 737.54 659.54 brace
+344.04 737.54 moveto
+344.04 659.54 lineto stroke
+%  S_CLEFSIG
+166.08 719.54 1.000000 gclef
+166.33 677.54 1.000000 fclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+195.69 707.54 1.000000 4n
+189.46 707.54 moveto
+201.92 707.54 lineto stroke
+199.37 708.29 moveto
+199.37 728.54 lineto stroke
+225.43 710.54 1.000000 4n
+229.12 711.29 moveto
+229.12 731.54 lineto stroke
+255.18 713.54 1.000000 4n
+258.86 714.29 moveto
+258.86 734.54 lineto stroke
+285.77 716.54 1.000000 4n
+289.45 717.29 moveto
+289.45 737.54 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+250.86 746.78 moveto
+(D.C. al Coda ) show
+restore
+%  S_STAFF
+% staff 2
+save
+195.69 668.54 1.000000 4n
+0.70 setlinewidth
+199.37 669.29 moveto
+199.37 689.54 lineto stroke
+225.43 671.54 1.000000 4n
+221.75 670.79 moveto
+221.75 650.54 lineto stroke
+255.18 674.54 1.000000 4n
+251.50 673.79 moveto
+251.50 653.54 lineto stroke
+285.77 677.54 1.000000 4n
+282.08 676.79 moveto
+282.08 656.54 lineto stroke
+restore
+%  S_BAR
+12 linenum
+0.70 setlinewidth
+317.04 737.54 moveto
+317.04 713.54 lineto stroke
+320.04 737.54 moveto
+320.04 713.54 lineto stroke
+317.04 683.54 moveto
+317.04 659.54 lineto stroke
+320.04 683.54 moveto
+320.04 659.54 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+restore
+%  S_STAFF
+% staff 2
+save
+restore
+%  S_BAR
+16 linenum
+0.70 setlinewidth
+%  S_CLEFSIG
+356.19 719.54 1.000000 gclef
+356.44 677.54 1.000000 fclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+378.79 716.54 1.000000 4n
+382.48 717.29 moveto
+382.48 737.54 lineto stroke
+408.54 713.54 1.000000 4n
+412.22 714.29 moveto
+412.22 734.54 lineto stroke
+438.29 710.54 1.000000 4n
+441.97 711.29 moveto
+441.97 731.54 lineto stroke
+468.87 707.54 1.000000 4n
+462.64 707.54 moveto
+475.10 707.54 lineto stroke
+472.55 708.29 moveto
+472.55 728.54 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+374.80 746.78 moveto
+(Coda ) show
+restore
+%  S_STAFF
+% staff 2
+save
+378.79 677.54 1.000000 4n
+0.70 setlinewidth
+375.11 676.79 moveto
+375.11 656.54 lineto stroke
+408.54 674.54 1.000000 4n
+404.86 673.79 moveto
+404.86 653.54 lineto stroke
+438.29 671.54 1.000000 4n
+434.61 670.79 moveto
+434.61 650.54 lineto stroke
+468.87 668.54 1.000000 4n
+472.55 669.29 moveto
+472.55 689.54 lineto stroke
+restore
+%  S_BAR
+20 linenum
+0.70 setlinewidth
+498.50 737.54 moveto
+498.50 713.54 lineto stroke
+3.00 setlinewidth
+502.50 737.54 moveto
+502.50 713.54 lineto stroke
+0.70 setlinewidth
+498.50 683.54 moveto
+498.50 659.54 lineto stroke
+3.00 setlinewidth
+502.50 683.54 moveto
+502.50 659.54 lineto stroke
+0.70 setlinewidth
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF 1.122(There are se)69.336 449.6 R -.15
+(ve)-.25 G 1.122(ral optional directi).15 F -.15(ve)-.25 G 3.622(st).15
+G 1.122(hat can follo)-3.622 F 3.622(wt)-.25 G 1.122(he bar line k)
+-3.622 F -.15(ey)-.1 G -.1(wo).15 G 3.623(rd. The).1 F 3.623(yc)-.15 G
+1.123(an be speci\214ed in an)-3.623 F(y)-.15 E
+(order and are described belo)69.336 461.6 Q -.65(w.)-.25 G 69.336 478.6
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.3.1 Bar)72.586 478.6 R(line padding)
+3.25 E 69.336 490.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .322(One optional directi)72.158 490.6 R
+.622 -.15(ve i)-.25 H 2.822(sp).15 G 2.822(adding. It)-2.822 F .322
+(can be used to force Mup to place e)2.822 F .321
+(xtra white space to the left of the)-.15 F 1.224
+(bar line. It is speci\214ed by the k)69.336 502.6 R -.15(ey)-.1 G -.1
+(wo).15 G 1.224(rd "pad" follo).1 F 1.224
+(wed by a number of stepsizes of padding to add. F)-.25 F(or)-.15 E -.15
+(ex)69.336 514.6 S(ample:).15 E/F1 10/Courier@0 SF(dblbar pad 3)105.336
+532.6 Q F0 -.1(wo)69.336 552.6 S(uld add 3 stepsizes of padding.).1 E
+69.336 569.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.3.2 Bar)72.586 569.6 R
+(line location ta)3.25 E(g)-.13 E 69.336 581.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF
+(It is also possible to associate a location tag with a bar line.)71.836
+581.6 Q -.15(Fo)5 G 2.5(re).15 G(xample:)-2.65 E/F1 10/Courier@0 SF
+(// Associate tag "_bar6" with bar line)105.336 599.6 Q(bar =_bar6)
+105.336 611.6 Q(// Do double bar with an extra stepsize of)105.336 635.6
+Q(// padding, and associate tag "q")105.336 647.6 Q
+(// with the bar line)105.336 659.6 Q(dblbar pad 1 =q)105.336 671.6 Q F0
+.098(The y coordinate of a bar line is not v)69.336 697.6 R .097(ery us\
+eful. Special rules apply if a bar line happens to be placed at the)-.15
+F .486(end of a score. An)69.336 709.6 R 2.986(yl)-.15 G .486
+(ocations tak)-2.986 F .486(en relati)-.1 F .786 -.15(ve t)-.25 H 2.986
+(ot).15 G .486(he bar that w)-2.986 F .486
+(ould be to the right of the bar are treated as if)-.1 F .429
+(the bar line were at the be)69.336 721.6 R .429(ginning of the follo)
+-.15 F .429(wing score, just be)-.25 F .429
+(yond the clef and time and k)-.15 F .728 -.15(ey s)-.1 H(ignatures,).15
+E(if an)69.336 733.6 Q -.65(y.)-.15 G EP
+%%Page: 40 46
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-4)274.506 48 S 2.5(0-)-2.5 G 69.336 101
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.3.3 Endings)72.586 101 R 69.336 113
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.239
+(First and second endings, etc. can be designated at bar lines.)73.074
+113 R 1.239(This is done with the k)6.239 F -.15(ey)-.1 G -.1(wo).15 G
+1.239(rd "ending,").1 F(follo)69.336 125 Q .699(wed by a quoted string \
+to use as the label for the ending that should be)-.25 F .698
+(gin at the bar line. An ending)-.15 F .136(will span bars until either\
+ another ending is speci\214ed, the piece ends, or the special k)69.336
+137 R -.15(ey)-.1 G -.1(wo).15 G .136(rd "endending" is).1 F
+(used. Examples:)69.336 149 Q/F1 10/Courier@0 SF(bar ending "1.")105.336
+167 Q(repeatend ending "2-3")105.336 179 Q(endbar endending)105.336 191
+Q F0 .1(The ending label will al)69.336 217 R -.1(wa)-.1 G .099(ys be f\
+orced into 12 point times roman font. If you change font or size or inc\
+lude).1 F(special characters in the ending label, the output is not lik)
+69.336 229 Q(ely to be aligned properly)-.1 E(.)-.65 E 1.073(The "endin\
+gstyle" parameter \(described in the section on parameters\) controls w\
+here endings are placed.)69.336 247 R
+(Endings cannot start at or cross o)69.336 259 Q -.15(ve)-.15 G 2.5(rar)
+.15 G(estart bar)-2.5 E(.)-.55 E 69.336 276 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.3.4 Rehear)72.586 276 R(sal marks)
+-.13 E 69.336 288 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF
+(Rehearsal letters or numbers can be speci\214ed on an)71.836 288 Q 2.5
+(yb)-.15 G(ar line. There are four formats:)-2.5 E/F1 10/Times-Bold@0 SF
+-.18(re)105.336 300 S(hearsal let).18 E -.18(re)105.336 312 S
+(hearsal num).18 E -.18(re)105.336 324 S(hearsal mnum).18 E -.18(re)
+105.336 336 S(hearsal ").18 E/F2 10/Times-Italic@0 SF(label)A F1(")A F0
+.981(In the \214rst e)69.336 354 R .981
+(xample, a rehearsal letter will be placed on the bar)-.15 F 3.48(.T)
+-.55 G .98(he \214rst occurrence of this will become)-3.48 F .116
+(rehearsal "A", the ne)69.336 366 R .116
+(xt "B", and so forth. The second format w)-.15 F .116
+(orks in a similar f)-.1 F .116(ashion e)-.1 F .117(xcept that numbers)
+-.15 F .13(are used rather than letters. W)69.336 378 R .129
+(ith the third format, the current measure number is used. W)-.4 F .129
+(ith the last format,)-.4 F(an)69.336 390 Q 3.047(ya)-.15 G .547
+(rbitrary string within the quotes will be used. The k)-3.047 F -.15(ey)
+-.1 G -.1(wo).15 G .547(rd "rehearsal" can be abbre).1 F .547
+(viated to "reh" if)-.25 F .798
+(you wish. Only one rehearsal mark is allo)69.336 402 R .798(wed on an)
+-.25 F 3.298(yo)-.15 G .798(ne bar)-3.298 F 3.298(,b)-.4 G .798
+(ut the types can be mix)-3.498 F .797(ed throughout the)-.15 F 5.054
+(composition. \(Note)69.336 414 R 2.554
+(that mixing "num" with "mnum" is lik)5.054 F 2.554(ely to be v)-.1 F
+2.555(ery confusing, ho)-.15 F(we)-.25 E -.15(ve)-.25 G -.55(r.).15 G
+7.555(\)T).55 G(he)-7.555 E(rehearsal marks can be intermix)69.336 426 Q
+(ed with other bar options:)-.15 E/F3 10/Courier@0 SF(1: 1c;)105.336 444
+Q(dblbar reh num ending "1")105.336 456 Q(1: 1e;)105.336 468 Q
+(repeatend pad 1 =_xyz reh let ending "2.")105.336 480 Q(1: 1g;)105.336
+492 Q(bar rehearsal "Duet")105.336 504 Q(1: 1ce;)105.336 516 Q
+(endbar endending)105.336 528 Q 127.836 537.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 77 rlineto 320 0 rlineto 0 77 neg rlineto closepath stroke grestore
+EEND 160 685 320 320 -77 77 126.836 614.6 PBEGIN
+%%BeginDocument: mugex38.ps
+%%BoundingBox: 160 685 480 762
+save
+1960644268 1960643998 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+612.29 785.78 828.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+272.03 727.78 moveto
+272.03 738.78 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+275.03 728.78 moveto
+(1) show
+272.03 738.78 moveto
+336.19 738.78 lineto stroke
+336.19 738.78 moveto
+336.19 727.78 lineto stroke
+340.19 727.78 moveto
+340.19 738.78 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+343.19 728.78 moveto
+(2.) show
+340.19 738.78 moveto
+462.50 738.78 lineto stroke
+462.50 738.78 moveto
+462.50 727.78 lineto stroke
+%  S_CLEFSIG
+192.08 707.78 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+225.79 695.78 1.000000 1n
+218.37 695.78 moveto
+233.21 695.78 lineto stroke
+restore
+%  S_BAR
+4 linenum
+0.70 setlinewidth
+268.03 725.78 moveto
+268.03 701.78 lineto stroke
+271.03 725.78 moveto
+271.03 701.78 lineto stroke
+/Times-Bold findfont
+12 scalefont
+setfont
+newpath
+265.04 742.78 moveto
+265.04 754.00 lineto
+275.52 754.00 lineto
+275.52 742.78 lineto
+closepath
+stroke
+267.04 744.28 moveto
+(1) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+287.45 701.78 1.000000 1n
+restore
+%  S_BAR
+6 linenum
+334.19 716.78 1.000000 dot
+334.19 710.78 1.000000 dot
+0.70 setlinewidth
+338.19 725.78 moveto
+338.19 701.78 lineto stroke
+3.00 setlinewidth
+342.19 725.78 moveto
+342.19 701.78 lineto stroke
+0.70 setlinewidth
+/Times-Bold findfont
+12 scalefont
+setfont
+newpath
+331.87 742.78 moveto
+331.87 754.00 lineto
+345.01 754.00 lineto
+345.01 742.78 lineto
+closepath
+stroke
+333.87 744.28 moveto
+(A) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+359.11 707.78 1.000000 1n
+restore
+%  S_BAR
+8 linenum
+0.70 setlinewidth
+402.34 725.78 moveto
+402.34 701.78 lineto stroke
+/Times-Bold findfont
+12 scalefont
+setfont
+newpath
+396.02 742.78 moveto
+396.02 753.93 lineto
+425.15 753.93 lineto
+425.15 742.78 lineto
+closepath
+stroke
+398.02 744.43 moveto
+(Duet) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+418.77 701.78 1.000000 1n
+418.77 695.78 1.000000 1n
+411.35 695.78 moveto
+426.19 695.78 lineto stroke
+restore
+%  S_BAR
+10 linenum
+0.70 setlinewidth
+462.50 725.78 moveto
+462.50 701.78 lineto stroke
+3.00 setlinewidth
+466.50 725.78 moveto
+466.50 701.78 lineto stroke
+0.70 setlinewidth
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /Times-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .234
+(The rehearsal marks are normally put directly abo)69.336 634.6 R .534
+-.15(ve t)-.15 H .234(he bar line. Ho).15 F(we)-.25 E -.15(ve)-.25 G
+1.033 -.4(r, i).15 H 2.733(ft).4 G .233(he bar line f)-2.733 F .233
+(alls at the end of)-.1 F 4.427(as)69.336 646.6 S 1.928
+(core, the rehearsal mark will be placed at the be)-4.427 F 1.928
+(ginning of the follo)-.15 F 1.928(wing score, after the clef, k)-.25 F
+-.15(ey)-.1 G .142(signature, and time signature.)69.336 658.6 R .141(T\
+he "endingstyle" parameter \(described in the section on parameters\) i\
+s used)5.142 F .498(to determine which staf)69.336 670.6 R .498
+(fs get rehearsal marks.)-.25 F .499
+(The "rehstyle" parameter speci\214es whether to put rehearsal)5.499 F
+(marks inside a box or a circle or lea)69.336 682.6 Q .3 -.15(ve t)-.2 H
+(hem plain.).15 E 2.692(The rehearsal k)69.336 700.6 R -.15(ey)-.1 G -.1
+(wo).15 G 2.692(rd may be follo).1 F 2.691(wed by a speci\214cation for)
+-.25 F/F1 10/Times-Italic@0 SF(fontfamily)5.191 E F0(,)A F1(font)5.191 E
+F0 5.191(,a)C(nd/or)-5.191 E/F2 10/Times-Bold@0 SF(\()5.191 E F1(size)A
+F2(\))A F0 7.691(.O)C(nce)-7.691 E(speci\214ed, these remain in ef)
+69.336 712.6 Q(fect for an)-.25 E 2.5(yf)-.15 G
+(uture rehearsal marks, until e)-2.5 E(xplictly changed. Some e)-.15 E
+(xamples:)-.15 E EP
+%%Page: 41 47
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-4)274.506 48 S 2.5(1-)-2.5 G/F1 10
+/Courier@0 SF(bar rehearsal helvetica bold \(14\) let)105.336 96 Q
+(repeatend reh newcentury num)105.336 108 Q
+(invisbar reh rom \(10\) mnum)105.336 120 Q F0 .234
+(After all the options listed abo)69.336 146 R -.15(ve)-.15 G 2.734(,y)
+.15 G .234(ou may specify "dist)-2.734 F/F2 10/Times-Italic@0 SF(N)2.734
+E F0 2.734("w)C(here)-2.734 E F2(N)2.734 E F0 .235
+(is some number of stepsizes. This will)2.734 F -.15(ove)69.336 158 S
+.008(rride the dist parameter for determining ho).15 F 2.507(wc)-.25 G
+.007(lose to the staf)-2.507 F 2.507(ft)-.25 G 2.507(op)-2.507 G .007
+(lace the rehearsal mark.)-2.507 F .007(If the number)5.007 F .408
+(is follo)69.336 170 R .408(wed by a "!" Mup will place the mark e)-.25
+F .408(xactly that f)-.15 F .408(ar from the top of the staf)-.1 F .409
+(f, e)-.25 F -.15(ve)-.25 G 2.909(ni).15 G 2.909(fi)-2.909 G 2.909(to)
+-2.909 G -.15(ve)-3.059 G(rwrites).15 E(other things; otherwise the v)
+69.336 182 Q(alue speci\214es a minimum distance.)-.25 E F1
+(rehearsal num dist 5)105.336 200 Q(// at least 5 stepsizes away)30 E
+(reh bold "A1" dist 2 !)105.336 212 Q(// exactly 2 stepsizes away)18 E
+69.336 237 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.3.5 Setting)72.586 237 R(the measur)
+3.25 E 3.25(en)-.481 G(umber)-3.25 E 69.336 249 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .854(Mup k)72.69 249 R .854
+(eeps track of measure numbers automatically)-.1 F 3.354(,b)-.65 G .853
+(ut sometimes you may w)-3.554 F .853(ant to o)-.1 F -.15(ve)-.15 G .853
+(rride this to set).15 F .686
+(the current measure number to some speci\214c v)69.336 261 R 3.186
+(alue. This)-.25 F .687(is done by adding mnum=)3.186 F/F1 10
+/Times-Italic@0 SF(number)A F0 .687(on a bar line,)3.187 F
+(which will set the current measure number to the gi)69.336 273 Q -.15
+(ve)-.25 G(n).15 E F1(number)2.5 E F0(.)A/F2 10/Courier@0 SF
+(// Set the current measure number to 50)105.336 291 Q(dblbar mnum=50)
+105.336 303 Q 69.336 328 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.3.6 Setting)72.586 328 R -.481(re)
+3.25 G(hear).481 E(sal letter or number)-.13 E 69.336 340 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.413(If you are using the "rehearsal let" \
+or "rehearsal num" styles, you can set those to speci\214c v)73.249 340
+R 1.412(alues too,)-.25 F .75(similarly to ho)69.336 352 R 3.25(wm)-.25
+G .75(num can be set.)-3.25 F .75(This might be useful, for e)5.75 F .75
+(xample, if you ha)-.15 F 1.05 -.15(ve a s)-.2 H .75
+(ingle input \214le that).15 F .694(contains multiple songs or mo)69.336
+364 R -.15(ve)-.15 G .694(ments, and you w).15 F .693
+(ant the rehearsal marks to start o)-.1 F -.15(ve)-.15 G 3.193(ra).15 G
+3.193(tt)-3.193 G .693(he be)-3.193 F .693(ginning of)-.15 F
+(each song or mo)69.336 376 Q -.15(ve)-.15 G(ment.).15 E
+(The rehearsal number can be set on an)69.336 394 Q 2.5(yb)-.15 G
+(ar line using num=)-2.5 E/F1 10/Times-Italic@0 SF(N)A F0 2.5(,w)C(here)
+-2.5 E F1(N)2.5 E F0(is a number)2.5 E 2.5(,t)-.4 G(ypically 1.)-2.5 E
+/F2 10/Courier@0 SF(bar num=1)105.336 412 Q F0 .225
+(The rehearsal letter can be set in a similar w)69.336 432 R(ay)-.1 E
+2.725(,u)-.65 G .225(sing let=")-2.725 F F1(X)A F0 2.725("w)C(here)
+-2.725 E F1(X)2.725 E F0 .226(is either a single upper case letter)2.725
+F 2.726(,A)-.4 G(to Z, or tw)69.336 444 Q 2.5(ou)-.1 G
+(pper case letters, AA to ZZ.)-2.5 E F2(dblbar let="A" reh let)105.336
+462 Q 69.336 487 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(5.3.7 Hiding)72.586 487 R(time/k)3.25
+E .78 -.39(ey s)-.13 H(ignatur).39 E 3.25(ea)-.481 G(nd clef c)-3.25 E
+(hang)-.195 E(es)-.13 E 69.336 499 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.049
+(Generally in printed music, when a time signature or k)72.885 499 R
+1.348 -.15(ey s)-.1 H 1.048(ignature change occurs at the be).15 F 1.048
+(ginning of a)-.15 F .138
+(score, these changes are also printed at the v)69.336 511 R .138
+(ery end of the pre)-.15 F .138(vious score, to mak)-.25 F 2.638(ei)-.1
+G 2.638(tc)-2.638 G .138(lear there is a change)-2.638 F 1.242
+(coming up.)69.336 523 R 1.242(Mup normally does this, b)6.242 F 1.241
+(ut occasionally you may not w)-.2 F 1.241(ant that beha)-.1 F(vior)-.2
+E 6.241(.S)-.55 G 1.241(ometimes you)-6.241 F 1.638(may w)69.336 535 R
+1.638(ant to mak)-.1 F 4.138(ean)-.1 G 2.138 -.25(ew s)-4.138 H 1.638
+(core appear lik).25 F 4.138(et)-.1 G 1.638(he be)-4.138 F 1.638
+(ginning of a ne)-.15 F 4.138(wp)-.25 G 1.638
+(iece. If you wish to suppress the)-4.138 F .036
+(printing of time signature, k)69.336 547 R .336 -.15(ey s)-.1 H .036(i\
+gnature, and clef changes at the end of the preceding score, you can us\
+e the).15 F 1.656("hidechanges" k)69.336 559 R -.15(ey)-.1 G -.1(wo).15
+G 1.657(rd on the bar line at which the changes occur).1 F 6.657(.H)-.55
+G 1.657(idechanges cannot be used on a)-6.657 F(restart bar)69.336 571 Q
+(.)-.55 E EP
+%%Page: 42 48
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-4)274.506 48 S 2.5(2-)-2.5 G/F1 10
+/Courier@0 SF(1: c;d;e;f;)105.336 96 Q(bar)105.336 108 Q
+(// change time/key with normal treatment)105.336 120 Q(newscore)105.336
+144 Q(score time=5/4 ; key = 1&)105.336 156 Q(music)105.336 168 Q
+(1: d;e;f;2g;)105.336 180 Q
+(// don't show changes at end of previous score)105.336 192 Q
+(bar hidechanges)105.336 204 Q(newscore)105.336 228 Q
+(score time=6/4 ; key = 2#)105.336 252 Q(music)105.336 264 Q
+(1: d;e;f;2.g;)105.336 276 Q(bar)105.336 288 Q 111.836 297.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 193 rlineto 352 0 rlineto 0 193 neg rlineto closepath stroke grestore
+EEND 128 570 352 352 -193 193 110.836 490.6 PBEGIN
+%%BeginDocument: mugex39.ps
+%%BoundingBox: 128 570 480 763
+save
+1960644268 1960643998 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+588.07 803.00 828.00 5 1.000000 1.000000 stf
+/Times-Roman findfont
+12 scalefont
+setfont
+144.00 728.73 moveto
+(   ) show
+%  S_CLEFSIG
+167.86 725.00 1.000000 gclef
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+179.66 731.00 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+179.66 718.98 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+213.12 713.00 1.000000 4n
+0.70 setlinewidth
+206.89 713.00 moveto
+219.35 713.00 lineto stroke
+216.80 713.75 moveto
+216.80 734.00 lineto stroke
+272.47 716.00 1.000000 4n
+276.15 716.75 moveto
+276.15 737.00 lineto stroke
+331.81 719.00 1.000000 4n
+335.50 719.75 moveto
+335.50 740.00 lineto stroke
+392.00 722.00 1.000000 4n
+395.68 722.75 moveto
+395.68 743.00 lineto stroke
+restore
+%  S_BAR
+7 linenum
+0.70 setlinewidth
+445.80 743.00 moveto
+445.80 719.00 lineto stroke
+%  S_SSV
+10 linenum
+%  S_CLEFSIG
+451.04 731.00 1.000000 flat
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+456.78 731.00 moveto
+(5) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+456.78 718.98 moveto
+(4) show
+%  S_FEED
+9 linenum
+576.00 737.00 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+155.79 659.00 1.000000 gclef
+169.33 665.00 1.000000 flat
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+175.07 665.00 moveto
+(5) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+175.07 652.98 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+207.92 650.00 1.000000 4n
+211.60 650.75 moveto
+211.60 671.00 lineto stroke
+263.56 653.00 1.000000 4n
+267.25 653.75 moveto
+267.25 674.00 lineto stroke
+319.18 656.00 1.000000 4n
+322.86 656.75 moveto
+322.86 677.00 lineto stroke
+381.66 659.00 1.000000 2n
+385.56 659.75 moveto
+385.56 680.00 lineto stroke
+restore
+%  S_BAR
+14 linenum
+0.70 setlinewidth
+467.65 677.00 moveto
+467.65 653.00 lineto stroke
+%  S_SSV
+18 linenum
+%  S_CLEFSIG
+%  S_FEED
+16 linenum
+576.00 671.00 828.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+155.79 593.00 1.000000 gclef
+169.90 611.00 1.000000 sharp
+176.54 602.00 1.000000 sharp
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+182.86 599.00 moveto
+(6) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+182.86 586.98 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+214.33 584.00 1.000000 4n
+218.01 584.75 moveto
+218.01 605.00 lineto stroke
+261.67 587.00 1.000000 4n
+265.35 587.75 moveto
+265.35 608.00 lineto stroke
+308.97 590.00 1.000000 4n
+312.66 590.75 moveto
+312.66 611.00 lineto stroke
+364.54 593.00 1.000000 2n
+374.02 596.00 1.000000 dot
+368.44 593.75 moveto
+368.44 614.00 lineto stroke
+restore
+%  S_BAR
+22 linenum
+0.70 setlinewidth
+467.65 611.00 moveto
+467.65 587.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 510.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(5.4 Multir)72.836 510.6 R(est)-.252 E
+69.336 528.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .783(Multiple measure rests can be indicate\
+d using the "multirest" statement.)72.619 528.6 R .782(It is follo)5.782
+F .782(wed by the number of)-.25 F .162(measures of rest.)69.336 540.6 R
+.162(The number must be greater than 1, and no lar)5.162 F .163
+(ger than 1000.)-.18 F .163(There must not be an)5.163 F 2.663(yn)-.15 G
+(ote)-2.663 E(or lyric information speci\214ed for a multirest measure.)
+69.336 552.6 Q(Examples:)5 E/F1 10/Courier@0 SF(multirest 15)105.336
+570.6 Q(bar)105.336 582.6 Q(1: 2c;4;;)105.336 594.6 Q(bar)105.336 606.6
+Q(1: 2.c;4r;)105.336 618.6 Q(bar)105.336 630.6 Q(multirest 5)105.336
+642.6 Q(bar)105.336 654.6 Q 91.836 664.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 64 rlineto 392 0 rlineto 0 64 neg rlineto closepath stroke grestore
+EEND 128 698 392 392 -64 64 90.836 728.2 PBEGIN
+%%BeginDocument: mugex40.ps
+%%BoundingBox: 128 698 520 762
+save
+703918026 703917304 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+144.29 1230.79 792.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+156.08 720.79 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+1.50 setlinewidth
+187.90 720.79 moveto
+187.90 732.79 lineto stroke
+246.42 720.79 moveto
+246.42 732.79 lineto stroke
+3.00 setlinewidth
+187.90 726.79 moveto
+246.42 726.79 lineto stroke
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+207.95 741.79 moveto
+(15) show
+restore
+%  S_BAR
+5 linenum
+0.70 setlinewidth
+260.96 738.79 moveto
+260.96 714.79 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+273.29 708.79 1.000000 2n
+266.84 708.79 moveto
+279.74 708.79 lineto stroke
+277.19 709.54 moveto
+277.19 729.79 lineto stroke
+302.88 708.79 1.000000 4n
+296.65 708.79 moveto
+309.11 708.79 lineto stroke
+306.56 709.54 moveto
+306.56 729.79 lineto stroke
+321.99 708.79 1.000000 4n
+315.76 708.79 moveto
+328.22 708.79 lineto stroke
+325.67 709.54 moveto
+325.67 729.79 lineto stroke
+restore
+%  S_BAR
+7 linenum
+0.70 setlinewidth
+341.55 738.79 moveto
+341.55 714.79 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+354.71 708.79 1.000000 2n
+364.19 711.79 1.000000 dot
+348.26 708.79 moveto
+361.16 708.79 lineto stroke
+358.61 709.54 moveto
+358.61 729.79 lineto stroke
+396.66 726.79 1.000000 4rest
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+416.07 738.79 moveto
+416.07 714.79 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+1.50 setlinewidth
+430.60 720.79 moveto
+430.60 732.79 lineto stroke
+489.12 720.79 moveto
+489.12 732.79 lineto stroke
+3.00 setlinewidth
+430.60 726.79 moveto
+489.12 726.79 lineto stroke
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+455.25 741.79 moveto
+(5) show
+restore
+%  S_BAR
+11 linenum
+0.70 setlinewidth
+503.65 738.79 moveto
+503.65 714.79 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND EP
+%%Page: 43 49
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-4)274.506 48 S 2.5(3-)-2.5 G
+(See also the -c command line option, and the restcombine parameter)
+69.336 96 Q(.)-.55 E(Normally)69.336 114 Q 5.668(,t)-.65 G 3.167
+(he number of measures of rest is printed, b)-5.668 F 3.167
+(ut it is possible to turn this of)-.2 F 5.667(fu)-.25 G 3.167(sing the)
+-5.667 F(printmultnum parameter)69.336 126 Q 5(.A)-.55 G 2.5(na)-5 G
+(lternate notation can be speci\214ed using the restsymmult parameter)
+-2.5 E(.)-.55 E 69.336 144 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(5.5 L)72.836 144 R(yrics)-.77 E 69.336
+162 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF -.55(Ly)72.318 162 S .482
+(rics are speci\214ed in a some).55 F .483
+(what similar manner to note groups.)-.25 F -.55(Ly)5.483 G .483
+(rics for each staf).55 F 2.983(fa)-.25 G .483(re speci\214ed with)
+-2.983 F .747(the w)69.336 174 R .747(ord "lyrics" optionally follo)-.1
+F .747(wed by a)-.25 F/F1 10/Times-Italic@0 SF(place)3.247 E F0 3.247
+(,f)C(ollo)-3.247 E .746(wed by the)-.25 F F1(staf)3.246 E 3.246(fn)-.18
+G(umber)-3.246 E F0 3.246(,f)C(ollo)-3.246 E .746(wed by a colon, then)
+-.25 F(the timing and syllable information.)69.336 186 Q(The)69.336 204
+Q F1(place)2.883 E F0 2.883(,i)C 2.883(fs)-2.883 G .383
+(peci\214ed, can be "abo)-2.883 F -.15(ve)-.15 G 2.883("o).15 G 2.883
+(r")-2.883 G(belo)-2.883 E -.65(w,)-.25 G 2.883("t).65 G 2.883(oi)-2.883
+G .383(ndicate whether the lyrics are to be printed abo)-2.883 F .684
+-.15(ve o)-.15 H(r).15 E(belo)69.336 216 Q 2.5(wt)-.25 G(he gi)-2.5 E
+-.15(ve)-.25 G 2.5(ns).15 G(taf)-2.5 E(f. The def)-.25 E(ault is belo)
+-.1 E -.65(w.)-.25 G(The)69.336 234 Q F1(staf)2.921 E 2.921(fn)-.18 G
+(umber)-2.921 E F0 .421
+(can be a single number or list of ranges of numbers.)2.921 F .421
+(It can also be gi)5.421 F -.15(ve)-.25 G 2.921(na).15 G 2.921(st)-2.921
+G .42(he k)-2.921 F -.15(ey)-.1 G -.1(wo).15 G(rd).1 E
+("all," which will place the lyrics abo)69.336 246 Q .3 -.15(ve t)-.15 H
+(he top visible staf).15 E 2.5(fo)-.25 G 2.5(rb)-2.5 G(elo)-2.5 E 2.5
+(wt)-.25 G(he bottom visible staf)-2.5 E(f.)-.25 E .222
+(The place can also be speci\214ed as "between)69.336 264 R F1(M)2.722 E
+/F2 10/Times-Bold@0 SF(&)A F1(N)A F0 2.722("w)C(here)-2.722 E F1(M)2.722
+E F0(and)2.722 E F1(N)2.722 E F0 .222(are numbers.)2.722 F .222
+(This will cause the lyrics)5.222 F(to printed approximately halfw)
+69.336 276 Q(ay between staf)-.1 E(f)-.25 E F1(M)2.5 E F0(and staf)2.5 E
+(f)-.25 E F1(N)2.5 E F0(.)A F1(N)2.5 E F0(must be e)2.5 E
+(xactly one greater than)-.15 E F1(M)2.5 E F0(.)A/F3 10/Courier@0 SF
+(lyrics 1:)105.336 294 Q(lyrics above 2,3:)105.336 306 Q
+(lyrics between 1&2, 3&4:)105.336 318 Q F0 .686(If you w)69.336 344 R
+.686(ant the same lyrics abo)-.1 F .986 -.15(ve s)-.15 H .686(ome staf)
+.15 F .686(fs b)-.25 F .686(ut belo)-.2 F 3.186(wo)-.25 G .686
+(thers, you can specify se)-3.186 F -.15(ve)-.25 G .685
+(ral places and list of).15 F(staf)69.336 356 Q
+(fs, separated by semicolons.)-.25 E -.15(Fo)5 G 2.5(re).15 G(xample:)
+-2.65 E F3(lyrics above 1,3 ; below 2,4 ; between 5&6 :)105.336 374 Q F0
+.626(After the colon comes a list of time v)69.336 400 R 3.126(alues. T)
+-.25 F .626(ime v)-.35 F .626
+(alues are separated by semicolons and are speci\214ed as)-.25 F(the)
+69.336 412 Q 2.5(ya)-.15 G
+(re for notes: "2" for half notes, "8." for dotted eight, etc.)-2.5 E
+.507(If the time v)69.336 430 R .507
+(alues for lyrics are the same as the time v)-.25 F .506
+(alues for the notes on the staf)-.25 F .506(f, the time v)-.25 F .506
+(alues need)-.25 F .16(not be speci\214ed. If you don')69.336 442 R 2.66
+(ts)-.18 G .16(pecify them, Mup will deri)-2.66 F .461 -.15(ve t)-.25 H
+.161(he appropriate v).15 F .161(alues from the music input.)-.25 F(If)
+5.161 E .761(you list more than one staf)69.336 454 R .761
+(f, the time v)-.25 F .761(alues will be deri)-.25 F -.15(ve)-.25 G
+3.261(df).15 G .761(rom the \214rst staf)-3.261 F 3.261(fy)-.25 G .761
+(ou list. Usually)-3.261 F 3.261(,t)-.65 G .761(he time)-3.261 F -.25
+(va)69.336 466 S .107(lues will be deri).25 F -.15(ve)-.25 G 2.607(df)
+.15 G .107(rom v)-2.607 F .107(oice 1, b)-.2 F .108(ut if v)-.2 F .108
+(oice 1 music data doesn')-.2 F 2.608(te)-.18 G .108(xist or is in)
+-2.758 F .108(visible, or if the lyrics are)-.4 F -.15(ex)69.336 478 S
+.641(plicitly speci\214ed as "belo).15 F .641
+(w" and there is a visible v)-.25 F .64(oice 2, then v)-.2 F .64
+(oice 2 will be used.)-.2 F -1.29(Vo)5.64 G .64(ice 3, if an)1.29 F 1.94
+-.65(y, i)-.15 H(s).65 E(ne)69.336 490 Q -.15(ve)-.25 G 2.5(ru).15 G
+(sed for automatically deri)-2.5 E(ving time v)-.25 E(alues for lyrics.)
+-.25 E(Some e)5 E(xamples:)-.15 E EP
+%%Page: 44 50
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-4)274.506 48 S 2.5(4-)-2.5 G/F1 10
+/Courier@0 SF(1: c;d;e;f;)105.336 96 Q(lyrics 1: "The sun will shine";)
+105.336 108 Q(// The time values will be all quarter notes,)105.336 120
+Q(// as derived from the music on staff 1)105.336 132 Q(bar)105.336 144
+Q(1: 8g;4.f;4g;a;)105.336 168 Q(lyrics 1: "up-on the earth.";)105.336
+180 Q(// The derived time values will be 8;4.;4;;)105.336 192 Q(bar)
+105.336 204 Q(// In these examples, time values will be taken)105.336
+228 Q(// from staff 4, since it is the first one listed.)105.336 240 Q
+(// In the last case, because "below" is specified explicitly,)105.336
+252 Q(// the times will be taken from voice 2)105.336 264 Q
+(// if there is a visible voice 2; in all the other cases)105.336 276 Q
+(// it will be taken from voice 1 if voice 1 music)105.336 288 Q
+(// has been entered and is visible.)105.336 300 Q
+(lyrics 4,7,9: "for-ev-er";)105.336 312 Q
+(lyrics above 4-6: "nev-er-more";)105.336 324 Q
+(lyrics between 4&5,6&7: "this is it";)105.336 336 Q
+(lyrics below 4,2: "and so forth";)105.336 348 Q F0 .011
+(The line describing the music from which to deri)69.336 368 R .311 -.15
+(ve t)-.25 H .011
+(he times must appear in the input prior to the lyrics line).15 F .233
+(that is deri)69.336 380 R .233(ving the times.)-.25 F .233
+(If chords in the music are tied or slurred together)5.233 F 2.732(,M)
+-.4 G .232(up will treat those chords as)-2.732 F 1.229
+(being for a single syllable.)69.336 392 R(Ho)6.229 E(we)-.25 E -.15(ve)
+-.25 G 2.029 -.4(r, t).15 H 1.23
+(here may be some circumstances in which the rules Mup uses to).4 F
+(deri)69.336 404 Q .503 -.15(ve t)-.25 H .203(ime v).15 F .203
+(alues may not yield what you w)-.25 F .203
+(ant, in which case you will ha)-.1 F .502 -.15(ve t)-.2 H 2.702(oe).15
+G .202(xplicitly specify the times)-2.852 F(for that measure.)69.336 416
+Q -.15(Fo)69.336 434 S(llo).15 E .607(wing the time v)-.25 F .608
+(alues is a list of one or more v)-.25 F .608
+(erse numbers and lyric strings containing the w)-.15 F .608(ords of)-.1
+F .474(the lyrics.)69.336 446 R .474(The v)5.474 F .474
+(erse number\(s\) are gi)-.15 F -.15(ve)-.25 G 2.974(nw).15 G .474
+(ithin square brack)-2.974 F .474(ets. If no v)-.1 F .473
+(erse is speci\214ed on the \214rst set of)-.15 F .977
+(lyrics for a staf)69.336 458 R 3.477(fa)-.25 G .977(nd place, v)-3.477
+F .977(erse 1 is assumed.)-.15 F .978
+(On subsequent lyrics strings for that staf)5.977 F 3.478(fa)-.25 G .978
+(nd place, the)-3.478 F -.15(ve)69.336 470 S .307
+(rse number is assumed to be one more than the pre).15 F .307(vious v)
+-.25 F .307(erse number)-.15 F 5.307(.T)-.55 G .307
+(hus you only need to e)-5.307 F(xplicitly)-.15 E(specify a v)69.336 482
+Q(erse number if you w)-.15 E(ant to skip o)-.1 E -.15(ve)-.15 G 2.5
+(rav).15 G(erse or supply them out of order)-2.65 E(.)-.55 E -1.11(Ve)
+69.336 500 S .075(rse numbers need not be consecuti)1.11 F -.15(ve)-.25
+G 5.075(.T).15 G .075(he staf)-5.075 F 2.575(fn)-.25 G .076(umber and v)
+-2.575 F .076(erse number can be gi)-.15 F -.15(ve)-.25 G 2.576(na).15 G
+2.576(sl)-2.576 G .076(ists or ranges.)-2.576 F(Another e)69.336 512 Q
+(xample:)-.15 E F1(1-2: 4.c+;8c;{4e;f;g;}3;)105.336 530 Q
+(lyrics below 1-2: 4.;8;{4;;;}3; \\)105.336 542 Q
+("This is some-thing else."; \\)153.336 554 Q
+([4,5] "How do you like this?"; \\)153.336 566 Q
+([2-3,6] "Now try this out too.";)153.336 578 Q(bar)105.336 590 Q EP
+%%Page: 45 51
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-4)274.506 48 S 2.5(5-)-2.5 G 127.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 269 rlineto 320 0 rlineto 0 269 neg rlineto closepath stroke grestore
+EEND 160 493 320 320 -269 269 126.836 365 PBEGIN
+%%BeginDocument: mugex41.ps
+%%BoundingBox: 160 493 480 762
+save
+703918026 703917304 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+180.29 1233.86 756.00 5 1.000000 1.000000 stf
+180.29 1105.59 756.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+180.29 741.86 moveto
+180.29 589.59 lineto stroke
+%  S_CLEFSIG
+192.08 723.86 1.000000 gclef
+192.08 595.59 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+222.82 697.86 moveto
+(This) show
+/Times-Roman findfont
+12 scalefont
+setfont
+301.28 697.86 moveto
+(is) show
+/Times-Roman findfont
+12 scalefont
+setfont
+363.64 697.86 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+330.29 697.86 moveto
+(some) show
+/Times-Roman findfont
+12 scalefont
+setfont
+374.65 697.86 moveto
+(thing) show
+/Times-Roman findfont
+12 scalefont
+setfont
+420.07 697.86 moveto
+(else.) show
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+222.34 684.61 moveto
+(Now) show
+/Times-Roman findfont
+12 scalefont
+setfont
+299.97 684.61 moveto
+(try) show
+/Times-Roman findfont
+12 scalefont
+setfont
+333.29 684.61 moveto
+(this) show
+/Times-Roman findfont
+12 scalefont
+setfont
+376.97 684.61 moveto
+(out) show
+/Times-Roman findfont
+12 scalefont
+setfont
+420.91 684.61 moveto
+(too.) show
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+222.34 671.29 moveto
+(Now) show
+/Times-Roman findfont
+12 scalefont
+setfont
+299.97 671.29 moveto
+(try) show
+/Times-Roman findfont
+12 scalefont
+setfont
+333.29 671.29 moveto
+(this) show
+/Times-Roman findfont
+12 scalefont
+setfont
+376.97 671.29 moveto
+(out) show
+/Times-Roman findfont
+12 scalefont
+setfont
+420.91 671.29 moveto
+(too.) show
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+222.34 657.97 moveto
+(How) show
+/Times-Roman findfont
+12 scalefont
+setfont
+300.29 657.97 moveto
+(do) show
+/Times-Roman findfont
+12 scalefont
+setfont
+333.13 657.97 moveto
+(you) show
+/Times-Roman findfont
+12 scalefont
+setfont
+376.31 657.97 moveto
+(like) show
+/Times-Roman findfont
+12 scalefont
+setfont
+419.83 657.97 moveto
+(this?) show
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+222.34 644.65 moveto
+(How) show
+/Times-Roman findfont
+12 scalefont
+setfont
+300.29 644.65 moveto
+(do) show
+/Times-Roman findfont
+12 scalefont
+setfont
+333.13 644.65 moveto
+(you) show
+/Times-Roman findfont
+12 scalefont
+setfont
+376.31 644.65 moveto
+(like) show
+/Times-Roman findfont
+12 scalefont
+setfont
+419.83 644.65 moveto
+(this?) show
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+222.34 631.33 moveto
+(Now) show
+/Times-Roman findfont
+12 scalefont
+setfont
+299.97 631.33 moveto
+(try) show
+/Times-Roman findfont
+12 scalefont
+setfont
+333.29 631.33 moveto
+(this) show
+/Times-Roman findfont
+12 scalefont
+setfont
+376.97 631.33 moveto
+(out) show
+/Times-Roman findfont
+12 scalefont
+setfont
+420.91 631.33 moveto
+(too.) show
+228.15 732.86 1.000000 4n
+237.41 732.86 1.000000 dot
+224.47 732.11 moveto
+224.47 711.86 lineto stroke
+303.28 711.86 1.000000 4n
+297.05 711.86 moveto
+309.51 711.86 lineto stroke
+306.96 712.61 moveto
+306.96 732.86 lineto stroke
+309.98 732.86 1.000000 dnflag
+337.61 717.85 1.000000 4n
+341.29 718.61 moveto
+341.29 738.86 lineto stroke
+380.79 720.86 1.000000 4n
+384.47 721.61 moveto
+384.47 741.86 lineto stroke
+425.48 723.86 1.000000 4n
+429.17 724.61 moveto
+429.17 744.86 lineto stroke
+/NewCenturySchlbk-BoldItalic findfont
+11 scalefont
+setfont
+378.38 745.31 moveto
+(3) show
+333.58 747.32 moveto
+376.38 749.11 lineto stroke
+386.72 749.50 moveto
+429.52 751.29 lineto stroke
+333.58 747.32 moveto
+333.58 744.32 lineto stroke
+429.52 751.29 moveto
+429.52 748.29 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+222.82 569.59 moveto
+(This) show
+/Times-Roman findfont
+12 scalefont
+setfont
+301.28 569.59 moveto
+(is) show
+/Times-Roman findfont
+12 scalefont
+setfont
+363.64 569.59 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+330.29 569.59 moveto
+(some) show
+/Times-Roman findfont
+12 scalefont
+setfont
+374.65 569.59 moveto
+(thing) show
+/Times-Roman findfont
+12 scalefont
+setfont
+420.07 569.59 moveto
+(else.) show
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+222.34 556.34 moveto
+(Now) show
+/Times-Roman findfont
+12 scalefont
+setfont
+299.97 556.34 moveto
+(try) show
+/Times-Roman findfont
+12 scalefont
+setfont
+333.29 556.34 moveto
+(this) show
+/Times-Roman findfont
+12 scalefont
+setfont
+376.97 556.34 moveto
+(out) show
+/Times-Roman findfont
+12 scalefont
+setfont
+420.91 556.34 moveto
+(too.) show
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+222.34 543.02 moveto
+(Now) show
+/Times-Roman findfont
+12 scalefont
+setfont
+299.97 543.02 moveto
+(try) show
+/Times-Roman findfont
+12 scalefont
+setfont
+333.29 543.02 moveto
+(this) show
+/Times-Roman findfont
+12 scalefont
+setfont
+376.97 543.02 moveto
+(out) show
+/Times-Roman findfont
+12 scalefont
+setfont
+420.91 543.02 moveto
+(too.) show
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+222.34 529.70 moveto
+(How) show
+/Times-Roman findfont
+12 scalefont
+setfont
+300.29 529.70 moveto
+(do) show
+/Times-Roman findfont
+12 scalefont
+setfont
+333.13 529.70 moveto
+(you) show
+/Times-Roman findfont
+12 scalefont
+setfont
+376.31 529.70 moveto
+(like) show
+/Times-Roman findfont
+12 scalefont
+setfont
+419.83 529.70 moveto
+(this?) show
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+222.34 516.38 moveto
+(How) show
+/Times-Roman findfont
+12 scalefont
+setfont
+300.29 516.38 moveto
+(do) show
+/Times-Roman findfont
+12 scalefont
+setfont
+333.13 516.38 moveto
+(you) show
+/Times-Roman findfont
+12 scalefont
+setfont
+376.31 516.38 moveto
+(like) show
+/Times-Roman findfont
+12 scalefont
+setfont
+419.83 516.38 moveto
+(this?) show
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+222.34 503.06 moveto
+(Now) show
+/Times-Roman findfont
+12 scalefont
+setfont
+299.97 503.06 moveto
+(try) show
+/Times-Roman findfont
+12 scalefont
+setfont
+333.29 503.06 moveto
+(this) show
+/Times-Roman findfont
+12 scalefont
+setfont
+376.97 503.06 moveto
+(out) show
+/Times-Roman findfont
+12 scalefont
+setfont
+420.91 503.06 moveto
+(too.) show
+228.15 604.59 1.000000 4n
+237.41 604.59 1.000000 dot
+0.70 setlinewidth
+224.47 603.84 moveto
+224.47 583.59 lineto stroke
+303.28 583.59 1.000000 4n
+297.05 583.59 moveto
+309.51 583.59 lineto stroke
+306.96 584.34 moveto
+306.96 604.59 lineto stroke
+309.98 604.59 1.000000 dnflag
+337.61 589.59 1.000000 4n
+341.29 590.34 moveto
+341.29 610.59 lineto stroke
+380.79 592.59 1.000000 4n
+384.47 593.34 moveto
+384.47 613.59 lineto stroke
+425.48 595.59 1.000000 4n
+429.17 596.34 moveto
+429.17 616.59 lineto stroke
+/NewCenturySchlbk-BoldItalic findfont
+11 scalefont
+setfont
+378.38 617.04 moveto
+(3) show
+333.58 619.06 moveto
+376.38 620.84 lineto stroke
+386.72 621.23 moveto
+429.52 623.02 lineto stroke
+333.58 619.06 moveto
+333.58 616.06 lineto stroke
+429.52 623.02 moveto
+429.52 620.02 lineto stroke
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+467.65 741.86 moveto
+467.65 717.85 lineto stroke
+467.65 613.59 moveto
+467.65 589.59 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /NewCenturySchlbk-BoldItalic 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .187(In this e)69.336 385 R .187
+(xample, the lyrics will go belo)-.15 F 2.687(ws)-.25 G(taf)-2.687 E
+.186
+(fs 1 and 2. There are 5 syllables. The \214rst is a dotted quarter in)
+-.25 F .322(length, the second is an eighth, and the last three mak)
+69.336 397 R 2.822(eu)-.1 G 2.822(paq)-2.822 G .322
+(uarter note triplet. The \214rst string is for v)-2.822 F(erse)-.15 E
+.012(1, since no v)69.336 409 R .012(erse number w)-.15 F .012
+(as speci\214ed. The second string will be used for v)-.1 F .012
+(erses 4 and 5, and the last string)-.15 F(for v)69.336 421 Q
+(erses 2, 3, and 6.)-.15 E -1.1(Yo)69.336 439 S 2.543(uc)1.1 G .043
+(an also specify a v)-2.543 F .043(erse number of "c" which means the v)
+-.15 F .043(erse is to be centered v)-.15 F(ertically)-.15 E 2.543(.T)
+-.65 G .043(his is useful)-2.543 F .041(if you ha)69.336 451 R .341 -.15
+(ve a r)-.2 H .041(efrain that is identical for se).15 F -.15(ve)-.25 G
+.041(ral v).15 F .041(erses, and you don')-.15 F 2.541(tw)-.18 G .041
+(ant to ha)-2.641 F .341 -.15(ve i)-.2 H 2.541(tp).15 G .041
+(rinted multiple times.)-2.541 F/F1 10/Courier@0 SF(1: c;;e;;)105.336
+469 Q(lyrics 1: ;;2s; [1] "verse one"; [2] "verse two";)105.336 481 Q
+(lyrics 1: 2s;4;; [c] "The refrain";)105.336 493 Q(// centered lyrics)15
+E(bar)105.336 505 Q 163.836 514.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 84 rlineto 248 0 rlineto 0 84 neg rlineto closepath stroke grestore
+EEND 200 679 248 248 -84 84 162.836 598.6 PBEGIN
+%%BeginDocument: mugex42.ps
+%%BoundingBox: 200 679 448 763
+save
+703918026 703917304 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+216.29 1235.00 720.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+228.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+7 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+340.05 692.60 moveto
+(The) show
+/Times-Roman findfont
+12 scalefont
+setfont
+380.18 692.60 moveto
+(refrain) show
+6 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+251.58 699.00 moveto
+(verse) show
+/Times-Roman findfont
+12 scalefont
+setfont
+299.64 699.00 moveto
+(one) show
+6 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+251.58 686.19 moveto
+(verse) show
+/Times-Roman findfont
+12 scalefont
+setfont
+299.48 686.19 moveto
+(two) show
+257.90 713.00 1.000000 4n
+0.70 setlinewidth
+251.66 713.00 moveto
+264.13 713.00 lineto stroke
+261.58 713.75 moveto
+261.58 734.00 lineto stroke
+303.96 713.00 1.000000 4n
+297.73 713.00 moveto
+310.19 713.00 lineto stroke
+307.64 713.75 moveto
+307.64 734.00 lineto stroke
+344.72 719.00 1.000000 4n
+348.40 719.75 moveto
+348.40 740.00 lineto stroke
+388.14 719.00 1.000000 4n
+391.82 719.75 moveto
+391.82 740.00 lineto stroke
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+431.65 743.00 moveto
+431.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .744(The lyrics string is follo)69.336
+618.6 R .744(wed by a semicolon.)-.25 F .745
+(There must normally be one syllable in the lyrics string for)5.744 F
+.937(each time v)69.336 630.6 R 3.437(alue. \(There)-.25 F .936
+(is one e)3.437 F .936(xception, discussed later)-.15 F 3.436
+(.\) Syllables)-.55 F .936(are separated in the lyrics string by)3.436 F
+(white space, a dash, or an underscore.)69.336 642.6 Q 1.043
+(Sometimes a syllable is to be held out for se)69.336 660.6 R -.15(ve)
+-.25 G 1.044(ral counts or o).15 F -.15(ve)-.15 G 3.544(rs).15 G -2.15
+-.25(ev e)-3.544 H 1.044(ral notes. This can be indicated by).25 F .228
+(dashes or underscores.)69.336 672.6 R .228(If the syllable in the lyri\
+c string ends with a dash, on output the dash will be placed)5.228 F
+(halfw)69.336 684.6 Q .296(ay between the gi)-.1 F -.15(ve)-.25 G 2.796
+(ns).15 G .296(yllable and the ne)-2.796 F .296(xt syllable.)-.15 F .297
+(If the distance between the tw)5.296 F 2.797(os)-.1 G .297
+(yllables is long,)-2.797 F(se)69.336 696.6 Q -.15(ve)-.25 G .889(ral e)
+.15 F -.15(ve)-.25 G .889(nly-spaced dashes will be printed.).15 F .889
+(If a syllable in the lyric string ends with an underscore, an)5.889 F
+.767(underscore line will be printed from the end of the current syllab\
+le to the edge of the last note associated)69.336 708.6 R
+(with the syllable.)69.336 720.6 Q(Here are some e)69.336 738.6 Q
+(xamples:)-.15 E EP
+%%Page: 46 52
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-4)274.506 48 S 2.5(6-)-2.5 G/F1 10
+/Courier@0 SF(// Verse 1. The first two words have the)105.336 96 Q
+(// duration of a quarter note each.)105.336 108 Q
+(// The last word lasts a half note.)105.336 120 Q(1: e;d;2c;)105.336
+132 Q(lyrics 1: 4;;2; [1] "Three blind mice";)105.336 144 Q(bar)105.336
+156 Q 127.836 165.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 71 rlineto 320 0 rlineto 0 71 neg rlineto closepath stroke grestore
+EEND 160 692 320 320 -71 71 126.836 236.6 PBEGIN
+%%BeginDocument: mugex43.ps
+%%BoundingBox: 160 692 480 763
+save
+703918026 703917304 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+180.29 1235.00 756.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+7 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+218.74 698.90 moveto
+(Three) show
+/Times-Roman findfont
+12 scalefont
+setfont
+285.36 698.90 moveto
+(blind) show
+/Times-Roman findfont
+12 scalefont
+setfont
+359.02 698.90 moveto
+(mice) show
+225.72 719.00 1.000000 4n
+0.70 setlinewidth
+229.40 719.75 moveto
+229.40 740.00 lineto stroke
+291.49 716.00 1.000000 4n
+295.18 716.75 moveto
+295.18 737.00 lineto stroke
+364.86 713.00 1.000000 2n
+358.41 713.00 moveto
+371.30 713.00 lineto stroke
+368.75 713.75 moveto
+368.75 734.00 lineto stroke
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Courier@0 SF
+(// examples of above lyrics with dash and underscore)105.336 256.6 Q
+(1: 4d<>;e;8g;b;4a;)105.336 268.6 Q(lyrics above 1: "now_ or nev-er";)
+105.336 280.6 Q(bar)105.336 292.6 Q 127.836 302.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 67 rlineto 320 0 rlineto 0 67 neg rlineto closepath stroke grestore
+EEND 160 693 320 320 -67 67 126.836 369.2 PBEGIN
+%%BeginDocument: mugex44.ps
+%%BoundingBox: 160 693 480 760
+save
+703918026 703917304 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+180.29 1228.18 756.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 718.18 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+4 linenum
+0.70 setlinewidth
+246.28 746.28 moveto
+290.66 746.28 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+219.71 746.28 moveto
+(now) show
+/Times-Roman findfont
+12 scalefont
+setfont
+337.98 746.28 moveto
+(or) show
+/Times-Roman findfont
+12 scalefont
+setfont
+396.98 746.28 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+368.16 746.28 moveto
+(nev) show
+/Times-Roman findfont
+12 scalefont
+setfont
+411.53 746.28 moveto
+(er) show
+226.36 709.18 1.000000 4n
+230.04 709.93 moveto
+230.04 730.18 lineto stroke
+286.63 712.18 1.000000 4n
+290.31 712.93 moveto
+290.31 733.18 lineto stroke
+340.46 718.18 1.000000 4n
+344.14 718.93 moveto
+344.14 739.18 lineto stroke
+347.17 739.18 1.000000 dnflag
+373.47 724.18 1.000000 4n
+369.78 723.43 moveto
+369.78 703.18 lineto stroke
+372.81 703.18 1.000000 upflag
+413.85 721.18 1.000000 4n
+417.53 721.93 moveto
+417.53 742.18 lineto stroke
+228.36 704.08 moveto
+228.37 704.23 lineto
+237.72 702.31 247.15 701.60 256.68 702.11 curveto
+266.21 702.62 275.51 704.33 284.60 707.23 curveto
+284.66 706.94 lineto
+275.72 703.24 266.42 701.13 256.76 700.61 curveto
+247.10 700.10 237.62 701.21 228.34 703.93 curveto
+fill
+restore
+%  S_BAR
+7 linenum
+0.70 setlinewidth
+467.65 736.18 moveto
+467.65 712.18 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF 1.308(Mup does its best to \214gure out\
+ where to end dashes or underscores. Ho)69.336 389.2 R(we)-.25 E -.15
+(ve)-.25 G 2.108 -.4(r, i).15 H 3.808(ft).4 G 1.308(here isn')-3.808 F
+3.808(taf)-.18 G(ollo)-3.808 E(wing)-.25 E .08
+(syllable after a dash or underscore, Mup w)69.336 401.2 R .08(ould e)
+-.1 F .08(xtend the dash or underscore to the end of the piece, which)
+-.15 F 1.358(may not be what you w)69.336 413.2 R 1.358
+(ant. There are a fe)-.1 F 3.858(wo)-.25 G 1.358
+(ther cases where Mup may be unable to properly deduce)-3.858 F .455
+(where you had intended an underscore to end.)69.336 425.2 R -1.1(Yo)
+5.455 G 2.955(uc)1.1 G .455
+(an manually halt the dash or underscore by adding in)-2.955 F 1.718
+(an "empty syllable," consisting of "<>". Normally)69.336 437.2 R 4.217
+(,t)-.65 G 1.717(he angle brack)-4.217 F 1.717
+(ets are used inside lyrics to enclose)-.1 F 1.426
+(special non-lyrics items, as will be described a bit later)69.336 449.2
+R 6.427(.H)-.55 G -.25(ow)-6.427 G -2.15 -.25(ev e).25 H 2.227 -.4(r, i)
+.25 H 3.927(ft).4 G(he)-3.927 E 3.927(ya)-.15 G 1.427
+(re used by themselv)-3.927 F 1.427(es with)-.15 F
+(nothing between them, the)69.336 461.2 Q 2.5(ye)-.15 G
+(ssentially mean a syllable with no te)-2.5 E(xt.)-.15 E/F1 10/Courier@0
+SF(1: 2c;4d<>;e;)105.336 479.2 Q(lyrics 1: "last word._";)105.336 491.2
+Q(bar)105.336 503.2 Q(1: 4d;e;f;g;)105.336 527.2 Q
+(// add empty syllable to end the underscore)105.336 539.2 Q
+(lyrics 1: 1; "<>";)105.336 551.2 Q(bar)105.336 563.2 Q 91.836 572.8
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 73 rlineto 392 0 rlineto 0 73 neg rlineto closepath stroke grestore
+EEND 128 690 392 392 -73 73 90.836 645.8 PBEGIN
+%%BeginDocument: mugex45.ps
+%%BoundingBox: 128 690 520 763
+save
+703918026 703917304 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+144.29 1235.00 792.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+156.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+3 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+185.45 697.03 moveto
+(last) show
+0.70 setlinewidth
+278.84 697.03 moveto
+300.25 697.03 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+245.28 697.03 moveto
+(word.) show
+189.61 713.00 1.000000 2n
+183.16 713.00 moveto
+196.06 713.00 lineto stroke
+193.51 713.75 moveto
+193.51 734.00 lineto stroke
+253.67 716.00 1.000000 4n
+257.35 716.75 moveto
+257.35 737.00 lineto stroke
+296.22 719.00 1.000000 4n
+299.90 719.75 moveto
+299.90 740.00 lineto stroke
+255.67 710.90 moveto
+255.69 711.08 lineto
+262.13 709.95 268.60 709.64 275.12 710.15 curveto
+281.64 710.66 287.99 711.97 294.18 714.07 curveto
+294.26 713.73 lineto
+288.20 711.00 281.85 709.38 275.22 708.87 curveto
+268.59 708.35 262.07 708.97 255.66 710.72 curveto
+fill
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+333.50 743.00 moveto
+333.50 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+9 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+346.94 697.03 moveto
+346.94 716.00 1.000000 4n
+350.63 716.75 moveto
+350.63 737.00 lineto stroke
+386.47 719.00 1.000000 4n
+390.16 719.75 moveto
+390.16 740.00 lineto stroke
+426.00 722.00 1.000000 4n
+429.68 722.75 moveto
+429.68 743.00 lineto stroke
+466.37 725.00 1.000000 4n
+470.05 725.75 moveto
+470.05 746.00 lineto stroke
+restore
+%  S_BAR
+11 linenum
+0.70 setlinewidth
+503.65 743.00 moveto
+503.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF(Occasionally)69.336 665.8 Q 2.576(,as)
+-.65 G .075(ingle chord is used for more than one syllable.)-2.576 F
+.075(If the syllables are within the same w)5.075 F .075(ord, it)-.1 F
+.031(is suf)69.336 677.8 R .031(\214cient to omit the dashes between sy\
+llables, so that Mup will treat them as a single syllable.)-.25 F(Ho)
+5.032 E(we)-.25 E -.15(ve)-.25 G -.4(r,).15 G 1.494
+(if the syllables are in separate w)69.336 689.8 R 1.494
+(ords, a "~" can be used in place of a space between the syllables.)-.1
+F(On)6.494 E .607
+(output, Mup will replace the "~" with a space and a small, curv)69.336
+701.8 R .607(ed line belo)-.15 F 3.107(wt)-.25 G .607
+(he space, indicating that the)-3.107 F
+(syllables on either side are to be joined. F)69.336 713.8 Q(or e)-.15 E
+(xample:)-.15 E EP
+%%Page: 47 53
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-4)274.506 48 S 2.5(7-)-2.5 G/F1 10
+/Courier@0 SF(1: b;a;2g;)105.336 96 Q(lyrics 1: ;;2; "man-y~a day";)
+105.336 108 Q(bar)105.336 120 Q 127.836 129.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 74 rlineto 320 0 rlineto 0 74 neg rlineto closepath stroke grestore
+EEND 160 689 320 320 -74 74 126.836 203.6 PBEGIN
+%%BeginDocument: mugex46.ps
+%%BoundingBox: 160 689 480 763
+save
+703918026 703917304 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+180.29 1235.00 756.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+263.13 699.28 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+219.88 699.28 moveto
+(man) show
+/Times-Roman findfont
+12 scalefont
+setfont
+288.72 699.28 moveto
+(y a) show
+0.70 setlinewidth
+293.69 699.28 moveto
+294.60 698.83 295.81 698.83 296.72 699.28 curveto
+/Times-Roman findfont
+12 scalefont
+setfont
+360.15 699.28 moveto
+(day) show
+226.03 731.00 1.000000 4n
+222.35 730.25 moveto
+222.35 710.00 lineto stroke
+292.30 728.00 1.000000 4n
+295.98 728.75 moveto
+295.98 749.00 lineto stroke
+364.47 725.00 1.000000 2n
+368.37 725.75 moveto
+368.37 746.00 lineto stroke
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF 1.309(If you don')69.336 217.6 R 3.809
+(tw)-.18 G 1.309(ant the curv)-3.909 F 1.308(ed line, you can use the s\
+pecial character name "\\\(space\)" instead of a literal)-.15 F 3.05
+(space. That)69.336 229.6 R .55(special space character is printed lik)
+3.05 F 3.05(ean)-.1 G .55(ormal space on output, b)-3.05 F .55
+(ut is not considered a space)-.2 F 3.268
+(for the purposes of determining syllable boundaries. Alternately)69.336
+241.6 R 5.767(,at)-.65 G 3.267(echnique using angle brack)-5.767 F(ets,)
+-.1 E(described later)69.336 253.6 Q 2.5(,c)-.4 G(an be used.)-2.5 E
+(If se)69.336 271.6 Q -.15(ve)-.25 G(ral v).15 E
+(erses use the same time v)-.15 E
+(alues, you can specify them all on one input line.)-.25 E -.15(Fo)5 G
+2.5(re).15 G(xample:)-2.65 E/F1 10/Courier@0 SF(1: d;f;a;g;)105.336
+289.6 Q(lyrics 1: [1] "this is verse one"; \\)105.336 301.6 Q
+([2] "this is verse two";)147.336 313.6 Q(bar)105.336 325.6 Q 127.836
+335.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 81 rlineto 320 0 rlineto 0 81 neg rlineto closepath stroke grestore
+EEND 160 682 320 320 -81 81 126.836 416.2 PBEGIN
+%%BeginDocument: mugex47.ps
+%%BoundingBox: 160 682 480 763
+save
+703918026 703917304 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+180.29 1235.00 756.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+3 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+220.34 702.00 moveto
+(this) show
+/Times-Roman findfont
+12 scalefont
+setfont
+285.17 702.00 moveto
+(is) show
+/Times-Roman findfont
+12 scalefont
+setfont
+340.47 702.00 moveto
+(verse) show
+/Times-Roman findfont
+12 scalefont
+setfont
+406.29 702.00 moveto
+(one) show
+3 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+220.34 689.19 moveto
+(this) show
+/Times-Roman findfont
+12 scalefont
+setfont
+285.17 689.19 moveto
+(is) show
+/Times-Roman findfont
+12 scalefont
+setfont
+340.47 689.19 moveto
+(verse) show
+/Times-Roman findfont
+12 scalefont
+setfont
+406.13 689.19 moveto
+(two) show
+224.66 716.00 1.000000 4n
+0.70 setlinewidth
+228.34 716.75 moveto
+228.34 737.00 lineto stroke
+287.17 722.00 1.000000 4n
+290.85 722.75 moveto
+290.85 743.00 lineto stroke
+346.79 728.00 1.000000 4n
+350.47 728.75 moveto
+350.47 749.00 lineto stroke
+410.61 725.00 1.000000 4n
+414.29 725.75 moveto
+414.29 746.00 lineto stroke
+restore
+%  S_BAR
+7 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .845(In this e)69.336 436.2 R .845
+(xample, because of the \\ at the end of the \214rst line, both v)-.15 F
+.845(erses are ef)-.15 F(fecti)-.25 E -.15(ve)-.25 G .846
+(ly on the same input).15 F(line.)69.336 448.2 Q(Occasionally)69.336
+466.2 Q 4.009(,l)-.65 G 1.508
+(yrics may occur during only part of a measure.)-4.009 F 1.508
+(This case can be handled by specifying)6.508 F
+("space" by using an "s" after time v)69.336 478.2 Q(alues that ha)-.25
+E .3 -.15(ve n)-.2 H 2.5(ol).15 G(yric syllable associated with them. F)
+-2.5 E(or e)-.15 E(xample:)-.15 E/F1 10/Courier@0 SF(1: 2r;g;)105.336
+496.2 Q(lyrics 1: 2s;; [1] "Now";)105.336 508.2 Q(bar)105.336 520.2 Q
+127.836 529.8 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 67 rlineto 320 0 rlineto 0 67 neg rlineto closepath stroke grestore
+EEND 160 696 320 320 -67 67 126.836 596.8 PBEGIN
+%%BeginDocument: mugex48.ps
+%%BoundingBox: 160 696 480 763
+save
+703918026 703917304 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+180.29 1235.00 756.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+349.62 703.28 moveto
+(Now) show
+232.31 731.00 1.000000 ll2rest
+355.43 725.00 1.000000 2n
+0.70 setlinewidth
+359.33 725.75 moveto
+359.33 746.00 lineto stroke
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .19(In this e)69.336 616.8 R .19(xample\
+, the \214rst half note of the measure is a space, so there will be no \
+lyric there. The second half)-.15 F .603(note of the measure will ha)
+69.336 628.8 R .903 -.15(ve t)-.2 H .603(he w).15 F .603(ord "No)-.1 F
+.602(w" as its lyric. Note that the "s" does not w)-.25 F .602
+(ork quite the same)-.1 F -.1(wa)69.336 640.8 S 3.881(yw).1 G 1.381
+(ith lyrics as it does with notes. W)-3.881 F 1.381(ith notes, "2s;;" w)
+-.4 F 1.381(ould mean tw)-.1 F 3.881(oh)-.1 G 1.382
+(alf-note spaces, because the)-3.881 F .788(space w)69.336 652.8 R .787
+(ould be used as def)-.1 F .787(ault for the follo)-.1 F .787
+(wing chord where no notes were speci\214ed. W)-.25 F .787
+(ith lyrics, "2s;;")-.4 F(means a half note space, follo)69.336 664.8 Q
+(wed by a half note lyric; the space is not carried forw)-.25 E
+(ard as a def)-.1 E(ault.)-.1 E 1.435(If you don')69.336 682.8 R 3.935
+(ts)-.18 G 1.435(pecify an)-3.935 F 3.935(yt)-.15 G 1.435(ime v)-3.935 F
+1.435(alues, relying on Mup to deri)-.25 F 1.735 -.15(ve t)-.25 H 1.436
+(he time v).15 F 1.436(alues from the corresponding)-.25 F 1.46
+(music time v)69.336 694.8 R 1.46(alues, an)-.25 F 3.96(yr)-.15 G 1.459
+(ests and spaces in the music will be translated to lyric spaces. If th\
+e \214rst note)-3.96 F .197
+(entered in a chord is tied to or slurred to the follo)69.336 706.8 R
+.197(wing chord, that follo)-.25 F .197
+(wing chord will also be translated to)-.25 F 2.5(al)69.336 718.8 S
+(yric space, since you most lik)-2.5 E(ely w)-.1 E
+(ant a single syllable to span both chords in that case.)-.1 E
+(Occasionally)69.336 736.8 Q 2.806(,y)-.65 G .306(ou may w)-2.806 F .305
+(ant to print something within a lyric string which isn')-.1 F 2.805(tr)
+-.18 G .305(eally a lyric syllable.)-2.805 F(The)5.305 E EP
+%%Page: 48 54
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-4)274.506 48 S 2.5(8-)-2.5 G .311
+(most common e)69.336 96 R .311(xample of this w)-.15 F .312
+(ould be that you may w)-.1 F .312(ant to print v)-.1 F .312
+(erse numbers. Other possibilities may)-.15 F .165
+(include associating a dynamic mark \(e.g., "mf"\) with a particular v)
+69.336 108 R .165(erse, or marking a section for a subset of)-.15 F .836
+(the singers \(e.g., "Men:" or "Solo:"\).)69.336 120 R .836(These e)
+5.836 F .836(xtra things are speci\214ed within angle brack)-.15 F .837
+(ets. The)-.1 F 3.337(yc)-.15 G .837(an be)-3.337 F .867
+(placed immediately before or after an)69.336 132 R 3.367(ys)-.15 G
+3.367(yllable. Mup)-3.367 F .867
+(will not consider them when lining up the syllable)3.367 F 1.074
+(with notes.)69.336 144 R(Normally)6.074 E 3.574(,i)-.65 G 3.574(tw)
+-3.574 G 1.075(ill assume there is enough space to print them rather th\
+an reserving space for)-3.574 F(them. If you w)69.336 156 Q(ant Mup to \
+ensure there is enough space to print them, put a "^" immediately after\
+ the "<".)-.1 E(Some e)69.336 174 Q(xamples:)-.15 E/F1 10/Courier@0 SF
+(1: f;e;d;c;)105.336 192 Q(lyrics 1: "<1. >This is verse one.";)105.336
+204 Q(bar)105.336 216 Q(1: 2g;4;;)105.336 228 Q
+(lyrics 1: 2s;4;; "<^\\f\(TX\)ff\\f\(PV\) >Loud-er";)105.336 240 Q(bar)
+105.336 252 Q 127.836 261.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 74 rlineto 320 0 rlineto 0 74 neg rlineto closepath stroke grestore
+EEND 160 689 320 320 -74 74 126.836 335.6 PBEGIN
+%%BeginDocument: mugex49.ps
+%%BoundingBox: 160 689 480 763
+save
+703918026 703917304 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+180.29 1235.00 756.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+3 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+201.87 699.00 moveto
+(1. This) show
+/Times-Roman findfont
+12 scalefont
+setfont
+248.87 699.00 moveto
+(is) show
+/Times-Roman findfont
+12 scalefont
+setfont
+272.78 699.00 moveto
+(verse) show
+/Times-Roman findfont
+12 scalefont
+setfont
+306.19 699.00 moveto
+(one.) show
+219.22 722.00 1.000000 4n
+0.70 setlinewidth
+222.91 722.75 moveto
+222.91 743.00 lineto stroke
+250.87 719.00 1.000000 4n
+254.55 719.75 moveto
+254.55 740.00 lineto stroke
+279.10 716.00 1.000000 4n
+282.78 716.75 moveto
+282.78 737.00 lineto stroke
+311.26 713.00 1.000000 4n
+305.03 713.00 moveto
+317.49 713.00 lineto stroke
+314.94 713.75 moveto
+314.94 734.00 lineto stroke
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+342.46 743.00 moveto
+342.46 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+7 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+427.39 699.00 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+386.06 699.00 moveto
+/Times-BoldItalic findfont
+12 scalefont
+setfont
+(ff) show
+/Times-Roman findfont
+12 scalefont
+setfont
+( Loud) show
+/Times-Roman findfont
+12 scalefont
+setfont
+435.51 699.00 moveto
+(er) show
+357.80 725.00 1.000000 2n
+361.70 725.75 moveto
+361.70 746.00 lineto stroke
+404.31 725.00 1.000000 4n
+407.99 725.75 moveto
+407.99 746.00 lineto stroke
+437.83 725.00 1.000000 4n
+441.51 725.75 moveto
+441.51 746.00 lineto stroke
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /Times-BoldItalic 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .785(The < > construct can also be used\
+ to \214ne-tune the placement of syllables.)69.336 355.6 R .784
+(The placement of syllables is)5.784 F(go)69.336 367.6 Q -.15(ve)-.15 G
+2.552(rned in general by the lyricsalign parameter).15 F 7.552(.S)-.55 G
+2.552(ometimes, ho)-7.552 F(we)-.25 E -.15(ve)-.25 G 3.352 -.4(r, y).15
+H 2.552(ou may w).4 F 2.553(ant to adjust the)-.1 F .332
+(placement of speci\214c syllables.)69.336 379.6 R .331(Suppose you ha)
+5.331 F .631 -.15(ve a l)-.2 H .331(ong syllable, lik).15 F 2.831(e")-.1
+G .331(strength" and w)-2.831 F .331(ould lik)-.1 F 2.831(et)-.1 G 2.831
+(os)-2.831 G .331(hift it)-2.831 F(leftw)69.336 391.6 Q 1.067(ard some)
+-.1 F 1.067(what. Entering it as "<str>ength" w)-.25 F 1.067
+(ould cause Mup to mo)-.1 F 1.368 -.15(ve t)-.15 H 1.068(he syllable f)
+.15 F 1.068(arther to the left)-.1 F(than it normally w)69.336 403.6 Q
+(ould.)-.1 E/F1 10/Courier@0 SF(1: c;d;e;f;)105.336 421.6 Q
+(lyrics 1: "This strength not moved."; \\)105.336 433.6 Q
+("This <str>ength was moved.";)153.336 445.6 Q(bar)105.336 457.6 Q
+127.836 467.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 87 rlineto 320 0 rlineto 0 87 neg rlineto closepath stroke grestore
+EEND 160 676 320 320 -87 87 126.836 554.2 PBEGIN
+%%BeginDocument: mugex50.ps
+%%BoundingBox: 160 676 480 763
+save
+703918026 703917304 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+180.29 1235.00 756.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+3 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+218.35 699.00 moveto
+(This) show
+/Times-Roman findfont
+12 scalefont
+setfont
+274.15 699.00 moveto
+(strength) show
+/Times-Roman findfont
+12 scalefont
+setfont
+343.29 699.00 moveto
+(not) show
+/Times-Roman findfont
+12 scalefont
+setfont
+399.55 699.00 moveto
+(moved.) show
+3 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+218.35 685.76 moveto
+(This) show
+/Times-Roman findfont
+12 scalefont
+setfont
+265.18 685.76 moveto
+(strength) show
+/Times-Roman findfont
+12 scalefont
+setfont
+342.44 685.76 moveto
+(was) show
+/Times-Roman findfont
+12 scalefont
+setfont
+399.55 685.76 moveto
+(moved.) show
+223.67 713.00 1.000000 4n
+0.70 setlinewidth
+217.44 713.00 moveto
+229.91 713.00 lineto stroke
+227.36 713.75 moveto
+227.36 734.00 lineto stroke
+283.78 716.00 1.000000 4n
+287.46 716.75 moveto
+287.46 737.00 lineto stroke
+347.10 719.00 1.000000 4n
+350.78 719.75 moveto
+350.78 740.00 lineto stroke
+408.46 722.00 1.000000 4n
+412.14 722.75 moveto
+412.14 743.00 lineto stroke
+restore
+%  S_BAR
+7 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .337(Angle brack)69.336 574.2 R .337
+(ets may also be useful for entering chant, where man)-.1 F 2.837(yw)
+-.15 G .336(ords are to be associated with a single)-2.937 F(note. F)
+69.336 586.2 Q(or e)-.15 E(xample:)-.15 E/F1 10/Courier@0 SF
+(lyrics 1: "All<^ these words will be treated like one syllable.>";)
+105.336 604.2 Q F0 1.876(The font and size to use for lyrics is initial\
+ly determined from the "lyricsfontf)69.336 630.2 R(amily)-.1 E 1.876
+(," "lyricsfont" and)-.65 F .575
+("lyricssize" parameters for the appropriate staf)69.336 642.2 R 3.075
+(f. If)-.25 F .575("all" is used for the staf)3.075 F 3.075(fn)-.25 G
+(umber)-3.075 E 3.075(,t)-.4 G .575(he score parameters)-3.075 F .237
+(are used.)69.336 654.2 R .238
+(In the case of "between," the parameters for the staf)5.237 F 2.738(fa)
+-.25 G(bo)-2.738 E .538 -.15(ve a)-.15 H .238
+(re used for determining the font and).15 F 2.71(size. The)69.336 666.2
+R .21(usual \\f and \\s forms can be used to change these v)2.71 F .209
+(alues for a gi)-.25 F -.15(ve)-.25 G 2.709(nv).15 G .209(erse. L)-2.859
+F .209(yrics fontf)-.55 F(amily)-.1 E 2.709(,f)-.65 G(ont)-2.709 E .793
+(and size v)69.336 678.2 R .793
+(alues are maintained separately for each combination of staf)-.25 F
+3.294(fn)-.25 G(umber)-3.294 E 3.294(,v)-.4 G .794(erse number)-3.444 F
+3.294(,a)-.4 G .794(nd place,)-3.294 F 1.491(and are carried forw)69.336
+690.2 R 1.491(ard from one measure to the ne)-.1 F 1.49(xt. Thus, for e)
+-.15 F 1.49(xample, if you w)-.15 F 1.49(ant one v)-.1 F 1.49
+(erse to be)-.15 F .747(printed in roman and another in italics \(perha\
+ps one is in English and the other in another language\), you)69.336
+702.2 R .253(need only put a "\\f\(TI\)" at the be)69.336 714.2 R .252
+(ginning of the syllable string for the \214rst measure of the second v)
+-.15 F .252(erse, and)-.15 F 2.039(all subsequent syllables for that v)
+69.336 726.2 R 2.039(erse will be in italics.)-.15 F 2.04
+(Setting the "lyricsfontf)7.039 F(amily)-.1 E 2.04(," "lyricsfont" or)
+-.65 F .731("lyricssize" parameters will reset the v)69.336 738.2 R .731
+(alues for all v)-.25 F .731(erses of the staf)-.15 F 3.23(f\()-.25 G
+.73(if set in staf)-3.23 F 3.23(fc)-.25 G(onte)-3.23 E .73
+(xt\), or the entire)-.15 F EP
+%%Page: 49 55
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-4)274.506 48 S 2.5(9-)-2.5 G
+(score \(if set in score conte)69.336 96 Q(xt\).)-.15 E .239(Another w)
+69.336 114 R .239(ay to align a syllable in a particular w)-.1 F .24
+(ay is to precede the syllable with a |. If the | is preceded by)-.1 F
+4.754(an)69.336 126 S 2.254(umber \(optionally signed\), the left edge \
+of the syllable will be placed that man)-4.754 F 4.753(yp)-.15 G 2.253
+(oints from the)-4.753 F 2.673(horizontal "middle" of the chord.)69.336
+138 R 2.673(If there isn')7.673 F -7.672 5.173(ta n)-.18 H 2.674
+(umber before it, the v)-5.173 F 2.674(alue is obtained from the)-.25 F
+.622(sylposition parameter)69.336 150 R 5.622(.N)-.55 G -2.25 -.15(eg a)
+-5.622 H(ti).15 E .922 -.15(ve v)-.25 H .621
+(alues are to the left, and will usually be what you w)-.1 F 3.121
+(ant. This)-.1 F(alignment)3.121 E .24
+(method is particularly useful for lining up multiple v)69.336 162 R .24
+(erses, either to get v)-.15 F .24(erse numbers to line up or to align)
+-.15 F -.1(wo)69.336 174 S(rds at the be).1 E
+(ginning of a poetic line. The | goes after an)-.15 E
+(ything in angle brack)-.15 E(ets.)-.1 E/F1 10/Courier@0 SF
+(1: 8c;d;4e;8e;g;4c+;)105.336 192 Q
+(lyrics 1: "<1. >|\\"How are you?\\" -7|He asked her."; \\)105.336 204 Q
+("<2. >|\\"I am fine,\\" -7|She re-plied.";)165.336 216 Q(bar)105.336
+228 Q 127.836 237.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 87 rlineto 320 0 rlineto 0 87 neg rlineto closepath stroke grestore
+EEND 160 676 320 320 -87 87 126.836 324.6 PBEGIN
+%%BeginDocument: mugex51.ps
+%%BoundingBox: 160 676 480 763
+save
+703918026 703917304 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+180.29 1235.00 756.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+5 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+201.16 699.00 moveto
+(1. "How) show
+/Times-Roman findfont
+12 scalefont
+setfont
+249.13 699.00 moveto
+(are) show
+/Times-Roman findfont
+12 scalefont
+setfont
+281.05 699.00 moveto
+(you?") show
+/Times-Roman findfont
+12 scalefont
+setfont
+336.04 699.00 moveto
+(He) show
+/Times-Roman findfont
+12 scalefont
+setfont
+367.56 699.00 moveto
+(asked) show
+/Times-Roman findfont
+12 scalefont
+setfont
+408.46 699.00 moveto
+(her.) show
+5 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+201.16 685.68 moveto
+(2. "I) show
+/Times-Roman findfont
+12 scalefont
+setfont
+249.12 685.68 moveto
+(am) show
+/Times-Roman findfont
+12 scalefont
+setfont
+281.46 685.68 moveto
+(fine,") show
+/Times-Roman findfont
+12 scalefont
+setfont
+336.04 685.68 moveto
+(She) show
+/Times-Roman findfont
+12 scalefont
+setfont
+391.83 685.68 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+371.07 685.68 moveto
+(re) show
+/Times-Roman findfont
+12 scalefont
+setfont
+406.30 685.68 moveto
+(plied.) show
+218.19 713.00 1.000000 4n
+0.70 setlinewidth
+211.96 713.00 moveto
+224.42 713.00 lineto stroke
+221.87 713.75 moveto
+221.87 734.00 lineto stroke
+224.89 734.00 1.000000 dnflag
+252.79 716.00 1.000000 4n
+256.47 716.75 moveto
+256.47 737.00 lineto stroke
+259.49 737.00 1.000000 dnflag
+288.09 719.00 1.000000 4n
+291.77 719.75 moveto
+291.77 740.00 lineto stroke
+343.04 719.00 1.000000 4n
+346.72 719.75 moveto
+346.72 740.00 lineto stroke
+349.74 740.00 1.000000 dnflag
+374.39 725.00 1.000000 4n
+378.07 725.75 moveto
+378.07 746.00 lineto stroke
+381.09 746.00 1.000000 dnflag
+413.03 734.00 1.000000 4n
+409.35 733.25 moveto
+409.35 713.00 lineto stroke
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF 2.5(Af)69.336 344.6 S .5 -.25(ew m)-2.5
+H(ore e).25 E(xamples of lyrics:)-.15 E/F1 10/Courier@0 SF
+(1,3-4: c;8e;;4d;r;)105.336 362.6 Q(2: c+;8g;;4b;;)105.336 374.6 Q
+(lyrics between 1&2,3&4: 4;8;;4;s; "This is a test.";)105.336 386.6 Q
+(lyrics above 2: 2s;4;; "The end.";)105.336 398.6 Q(bar)105.336 410.6 Q
+127.836 420.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 237 rlineto 320 0 rlineto 0 237 neg rlineto closepath stroke grestore
+EEND 160 526 320 320 -237 237 126.836 657.2 PBEGIN
+%%BeginDocument: mugex52.ps
+%%BoundingBox: 160 526 480 763
+save
+1589393640 1589394394 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+324.29 1091.00 684.00 5 1.000000 1.000000 stf
+324.29 1025.09 684.00 5 1.000000 1.000000 stf
+324.29 971.09 684.00 5 1.000000 1.000000 stf
+324.29 915.00 684.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+180.29 743.00 moveto
+180.29 543.00 lineto stroke
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+192.08 659.09 1.000000 gclef
+192.08 605.09 1.000000 gclef
+192.08 549.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+5 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+218.75 699.00 moveto
+(This) show
+/Times-Roman findfont
+12 scalefont
+setfont
+278.64 699.00 moveto
+(is) show
+/Times-Roman findfont
+12 scalefont
+setfont
+313.36 699.00 moveto
+(a) show
+/Times-Roman findfont
+12 scalefont
+setfont
+346.87 699.00 moveto
+(test.) show
+224.07 713.00 1.000000 4n
+217.84 713.00 moveto
+230.31 713.00 lineto stroke
+227.76 713.75 moveto
+227.76 734.00 lineto stroke
+280.64 719.00 1.000000 4n
+284.32 719.75 moveto
+284.32 740.00 lineto stroke
+287.35 740.00 1.000000 dnflag
+314.69 719.00 1.000000 4n
+318.37 719.75 moveto
+318.37 740.00 lineto stroke
+321.40 740.00 1.000000 dnflag
+351.78 716.00 1.000000 4n
+355.46 716.75 moveto
+355.46 737.00 lineto stroke
+412.21 731.00 1.000000 4rest
+restore
+%  S_STAFF
+% staff 2
+save
+6 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+347.12 686.19 moveto
+(The) show
+/Times-Roman findfont
+12 scalefont
+setfont
+407.13 686.19 moveto
+(end.) show
+224.07 668.09 1.000000 4n
+0.70 setlinewidth
+220.39 667.34 moveto
+220.39 647.09 lineto stroke
+280.64 659.09 1.000000 4n
+284.32 659.84 moveto
+284.32 680.09 lineto stroke
+287.35 680.09 1.000000 dnflag
+314.69 659.09 1.000000 4n
+318.37 659.84 moveto
+318.37 680.09 lineto stroke
+321.40 680.09 1.000000 dnflag
+351.78 665.09 1.000000 4n
+348.10 664.34 moveto
+348.10 644.09 lineto stroke
+412.21 665.09 1.000000 4n
+408.53 664.34 moveto
+408.53 644.09 lineto stroke
+restore
+%  S_STAFF
+% staff 3
+save
+5 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+218.75 579.10 moveto
+(This) show
+/Times-Roman findfont
+12 scalefont
+setfont
+278.64 579.10 moveto
+(is) show
+/Times-Roman findfont
+12 scalefont
+setfont
+313.36 579.10 moveto
+(a) show
+/Times-Roman findfont
+12 scalefont
+setfont
+346.87 579.10 moveto
+(test.) show
+224.07 593.09 1.000000 4n
+0.70 setlinewidth
+217.84 593.09 moveto
+230.31 593.09 lineto stroke
+227.76 593.84 moveto
+227.76 614.09 lineto stroke
+280.64 599.09 1.000000 4n
+284.32 599.84 moveto
+284.32 620.09 lineto stroke
+287.35 620.09 1.000000 dnflag
+314.69 599.09 1.000000 4n
+318.37 599.84 moveto
+318.37 620.09 lineto stroke
+321.40 620.09 1.000000 dnflag
+351.78 596.09 1.000000 4n
+355.46 596.84 moveto
+355.46 617.09 lineto stroke
+412.21 611.09 1.000000 4rest
+restore
+%  S_STAFF
+% staff 4
+save
+224.07 537.00 1.000000 4n
+0.70 setlinewidth
+217.84 537.00 moveto
+230.31 537.00 lineto stroke
+227.76 537.75 moveto
+227.76 558.00 lineto stroke
+280.64 543.00 1.000000 4n
+284.32 543.75 moveto
+284.32 564.00 lineto stroke
+287.35 564.00 1.000000 dnflag
+314.69 543.00 1.000000 4n
+318.37 543.75 moveto
+318.37 564.00 lineto stroke
+321.40 564.00 1.000000 dnflag
+351.78 540.00 1.000000 4n
+355.46 540.75 moveto
+355.46 561.00 lineto stroke
+412.21 555.00 1.000000 4rest
+restore
+%  S_BAR
+8 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+467.65 677.09 moveto
+467.65 653.09 lineto stroke
+467.65 623.09 moveto
+467.65 599.09 lineto stroke
+467.65 567.00 moveto
+467.65 543.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND EP
+%%Page: 50 56
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-5)274.506 48 S 2.5(0-)-2.5 G 69.336 103
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(6. T)73.086 103 R(ABLA)-1.35 E(TURE NO)
+-1.425 E -1.35(TA)-.6 G(TION)-.075 E 69.336 121 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 3.198(Mup can print tablature staf)75.034
+121 R 3.197(fs. T)-.25 F 3.197
+(ablature notation is commonly used for guitar and se)-.8 F -.15(ve)-.25
+G 3.197(ral other).15 F
+(instruments. Mup supports tablature for 1 to 9 strings.)69.336 133 Q
+.575(Mup will automatically create a normal 5-line staf)69.336 151 R
+3.075(fa)-.25 G(bo)-3.075 E .875 -.15(ve e)-.15 H .575
+(ach tablature staf).15 F .576(f, gi)-.25 F .576(ving the equi)-.25 F
+-.25(va)-.25 G .576(lant music).25 F .154(on that staf)69.336 163 R
+2.654(f. This)-.25 F(staf)2.654 E 2.654(fw)-.25 G .154
+(ill be referred to as the "tabnote staf)-2.654 F .153(f." Normally)-.25
+F 2.653(,y)-.65 G .153(ou will input music just for the)-2.653 F 1.104
+(tablature staf)69.336 175 R 1.104(f, and the tabnote staf)-.25 F 3.604
+(fw)-.25 G 1.104(ill be deri)-3.604 F -.15(ve)-.25 G 3.604(df).15 G
+1.104(rom that. Ho)-3.604 F(we)-.25 E -.15(ve)-.25 G 1.904 -.4(r, f).15
+H 1.104(or an).4 F 3.604(yg)-.15 G -2.15 -.25(iv e)-3.604 H 3.604(nm).25
+G 1.105(easure, you can)-3.604 F -.15(ex)69.336 187 S .666
+(plicitly input music for a tabnote staf).15 F .666
+(f, which will turn of)-.25 F 3.166(ft)-.25 G .666
+(he automatic translation for that measure. If)-3.166 F .451(you only w)
+69.336 199 R .452(ant either the tab or tabnote staf)-.1 F 2.952(ft)-.25
+G 2.952(ob)-2.952 G 2.952(ep)-2.952 G .452
+(rinted, you can mark the other one as in)-2.952 F .452
+(visible \(see the)-.4 F .12("visible" parameter\).)69.336 211 R -1.1
+(Yo)5.12 G 2.62(us)1.1 G .12(hould specify the appropriate clef and k)
+-2.62 F .42 -.15(ey s)-.1 H .12(ignature for the tabnote staf).15 F .12
+(f, so that)-.25 F(Mup can mak)69.336 223 Q 2.5(et)-.1 G(he best deri)
+-2.5 E -.25(va)-.25 G(tion.).25 E 69.336 241 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(6.1 Specifying)72.836 241 R 3.5(at)3.5 G
+(ablatur)-3.5 E 3.5(es)-.252 G(taff)-3.5 E 69.336 259 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 2.14 -.8(To s)72.376 259 T .54
+(et up a tablature staf).8 F .54(f, you use the staf)-.25 F .541
+(\215ines parameter)-.25 F 5.541(.T)-.55 G 3.041(og)-6.341 G .541
+(et a standard 6-line guitar tablature staf)-3.041 F(f,)-.25 E
+(you can just say)69.336 271 Q/F1 10/Courier@0 SF(score)105.336 289 Q
+(staffs=2)130.336 301 Q(staff 2)105.336 313 Q(stafflines = tab)130.336
+325 Q F0 1.082(There are 2 staf)69.336 345 R 1.082
+(fs, because there is both the tablature staf)-.25 F 3.582(fa)-.25 G
+1.082(nd the automatically generated tabnote staf)-3.582 F(f.)-.25 E
+1.938(The tablature staf)69.336 357 R 4.438(fi)-.25 G 4.438(sa)-4.438 G
+-.1(lwa)-4.438 G 1.938(ys immediately belo).1 F 4.438(wt)-.25 G 1.939
+(he corresponding tabnote staf)-4.438 F 4.439(f. Setting)-.25 F 1.939
+(the staf)4.439 F(\215ines)-.25 E(parameter to "tab" marks staf)69.336
+369 Q 2.5(f2a)-.25 G 2.5(sat)-2.5 G(ablature staf)-2.5 E(f.)-.25 E 1.01
+(If you w)69.336 387 R 1.009(ant tablature for an instrument other than\
+ a 6-string guitar with standard tuning, you specify the)-.1 F(pitches \
+of the strings from top to bottom within parentheses after the "tab)
+69.336 399 Q(." F)-.4 E(or e)-.15 E(xample:)-.15 E F1
+(stafflines = tab \(e a d& g\))105.336 417 Q F0 -.1(wo)69.336 437 S .272
+(uld de\214ne some instrument that had 4 strings, with the string on th\
+e top line of tablature staf).1 F 2.772(fb)-.25 G .272(eing an e)-2.772
+F .349(string, the ne)69.336 449 R .349(xt a, the ne)-.15 F .349
+(xt d \215at, and the bottom g.)-.15 F .349(As sho)5.349 F .349
+(wn in the e)-.25 F .348(xample, pitches can include a # or &)-.15 F
+.774(if necessary)69.336 461 R 5.774(.S)-.65 G .774
+(trings are assumed to be in octa)-5.774 F 1.074 -.15(ve 4 u)-.2 H .774
+(nless otherwise mark).15 F 3.274(ed. Y)-.1 F .774(ou can specify a dif)
+-1.1 F(ferent)-.25 E(octa)69.336 473 Q 1.156 -.15(ve b)-.2 H 3.356(ys)
+.15 G .856(pecifying an octa)-3.356 F 1.156 -.15(ve n)-.2 H .856
+(umber after the string').15 F 3.356(sp)-.55 G .855
+(itch \(using either an absolute octa)-3.356 F 1.155 -.15(ve n)-.2 H
+.855(umber or).15 F 1.292(pluses or minuses\).)69.336 485 R 1.292
+(If the instrument has more than one string with the same pitch \(e)
+6.292 F -.15(ve)-.25 G 3.792(ni).15 G 3.792(ft)-3.792 G(he)-3.792 E
+3.793(ya)-.15 G 1.293(re in)-3.793 F(dif)69.336 497 Q .51(ferent octa)
+-.25 F -.15(ve)-.2 G .51(s\), the).15 F 3.01(ym)-.15 G .509(ust be dist\
+inguished by adding one or more ' marks after the pitch. The tablature)
+-3.01 F(de\214nition for standard guitar is)69.336 509 Q F1
+(stafflines = tab \(e5 b g d a3 e'3\))105.336 527 Q F0 .123
+(This speci\214es that the top string on the staf)69.336 547 R 2.623(fi)
+-.25 G 2.623(sei)-2.623 G 2.623(no)-2.623 G(cta)-2.623 E .423 -.15(ve 5)
+-.2 H 5.123(.T).15 G .123(he ne)-5.123 F .123
+(xt three strings are in the def)-.15 F .124(ault octa)-.1 F -.15(ve)-.2
+G .333(of 4, and the last tw)69.336 559 R 2.833(os)-.1 G .333
+(trings are in octa)-2.833 F .633 -.15(ve 3)-.2 H 5.333(.S).15 G .333
+(ince there are tw)-5.333 F 2.833(od)-.1 G(if)-2.833 E .332
+(ferent strings with pitch letter of e, the)-.25 F(lo)69.336 571 Q .46
+(wer e is mark)-.25 F .46(ed as e'. Note that the octa)-.1 F -.15(ve)-.2
+G 2.96(sg).15 G -2.15 -.25(iv e)-2.96 H 2.96(na).25 G .461(re ho)-2.96 F
+2.961(wt)-.25 G(he)-2.961 E 2.961(ys)-.15 G .461
+(hould be printed on the tabnote staf)-2.961 F .461(f. A)-.25 F 1.732
+(standard guitar actually sounds an octa)69.336 583 R 2.032 -.15(ve l)
+-.2 H -.25(ow).15 G 1.732(er than written. If you just use "staf).25 F
+1.731(\215ines = tab" without)-.25 F 1.794(specifying an)69.336 595 R
+4.294(ys)-.15 G 1.794(trings, Mup not only assumes the standard guitar \
+layout, and prints in the appropriate)-4.294 F(octa)69.336 607 Q -.15
+(ve)-.2 G 3.49(,b).15 G .989(ut it also automatically transposes the MI\
+DI output to the actual pitches an octa)-3.69 F 1.289 -.15(ve l)-.2 H
+-.25(ow).15 G(er).25 E 3.489(.I)-.55 G 3.489(fy)-3.489 G(ou)-3.489 E
+.967(specify strings e)69.336 619 R(xplicitly)-.15 E 3.467(,y)-.65 G
+.967(ou will ha)-3.467 F 1.267 -.15(ve t)-.2 H 3.467(os).15 G .967
+(pecify the octa)-3.467 F -.15(ve)-.2 G 3.467(sa).15 G .968(nd an)-3.467
+F 3.468(yd)-.15 G .968(esired MIDI transposition v)-3.468 F(alues)-.25 E
+(yourself. Stated another w)69.336 631 Q(ay)-.1 E(,)-.65 E F1(score)
+105.336 649 Q(staffs = 2)130.336 661 Q(staff 2)105.336 673 Q
+(stafflines = tab)130.336 685 Q F0(is equi)69.336 705 Q -.25(va)-.25 G
+(lent to).25 E EP
+%%Page: 51 57
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-5)274.506 48 S 2.5(1-)-2.5 G/F1 10
+/Courier@0 SF(score)105.336 96 Q(staffs=2)130.336 108 Q(staff 2)105.336
+120 Q(stafflines = tab \(e5 b g d a3 e'3\))130.336 132 Q(staff 1)105.336
+144 Q(ifdef MIDI transpose = down perfect 8 endif)130.336 156 Q F0 1.515
+(Note from this last e)69.336 176 R 1.515(xample that MIDI is tak)-.15 F
+1.514(en from the tabnote staf)-.1 F 1.514(f, not the tablature staf)
+-.25 F 1.514(f, so MIDI)-.25 F(directi)69.336 188 Q -.15(ve)-.25 G 2.5
+(ss).15 G(hould be placed with the tabnote staf)-2.5 E(f.)-.25 E .052
+(Mup should be able to handle almost an)69.336 206 R 2.552(yi)-.15 G
+.052(nstrument with up to 9 strings.)-2.552 F(Se)5.052 E -.15(ve)-.25 G
+.052(ral strings can ha).15 F .353 -.15(ve t)-.2 H .053(he same).15 F
+1.307(pitch; you just need to distinguish them with ' marks.)69.336 218
+R 1.307(The strings must be listed in whate)6.307 F -.15(ve)-.25 G 3.807
+(ro).15 G 1.307(rder the)-3.807 F
+(strings are to appear on the tablature staf)69.336 230 Q 2.5(f. As)-.25
+F(another e)2.5 E(xample,)-.15 E F1(stafflines = tab \(g3 d3 a2 e2\))
+105.336 248 Q F0 -.1(wo)69.336 268 S .569
+(uld de\214ne a standard bass guitar).1 F 3.069(.N)-.55 G .569
+(ote that a bass guitar also sounds an octa)-3.069 F .869 -.15(ve l)-.2
+H -.25(ow).15 G .569(er than written, so it).25 F
+(should be transposed for MIDI purposes.)69.336 280 Q 69.336 298 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(6.2 Music)72.836 298 R(input on tablatur)
+3.5 E 3.5(es)-.252 G(taffs)-3.5 E 69.336 316 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .168
+(Input of tablature is similar to that on re)72.004 316 R .168
+(gular staf)-.15 F .168
+(fs. Each note in a chord is speci\214ed by a string and a fret.)-.25 F
+.896(So fret 3 on the g string is designated by g3 or fret 0 on the e' \
+string is designated by e'0.)69.336 328 R .896(If your open)5.896 F .625
+(string pitch includes an accidental, that w)69.336 340 R .625
+(ould be included as well, so if you had an instrument with an f#)-.1 F
+.329(string and w)69.336 352 R .329
+(anted to play the 6th fret on that string, it w)-.1 F .33(ould be f#6.)
+-.1 F .33(Fret numbers can range from 0 to 99.)5.33 F .879(If you w)
+69.336 364 R .879(ant fret numbers to be placed inside parentheses, put\
+ parentheses around them in the input.)-.1 F -1.1(Yo)5.878 G(u)1.1 E
+.854(can also put both the string and fret within a set of parentheses,\
+ in which case, the note generated on the)69.336 376 R(tabnote staf)
+69.336 388 Q 2.5(fw)-.25 G(ill ha)-2.5 E .3 -.15(ve p)-.2 H
+(arentheses around it.).15 E(Here are some e)5 E(xamples of chords:)-.15
+E/F1 10/Courier@0 SF(2: d4; d5a3; b0 d\(5\); e2\(b3\)g2;)105.336 406 Q
+(bar)105.336 418 Q 163.836 427.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 134 rlineto 248 0 rlineto 0 134 neg rlineto closepath stroke grestore
+EEND 200 629 248 248 -134 134 162.836 561.6 PBEGIN
+%%BeginDocument: mugex53.ps
+%%BoundingBox: 200 629 448 763
+save
+1589393640 1589394394 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+3 linenum
+%  S_FEED
+360.29 1091.00 648.00 5 1.000000 1.000000 stf
+360.29 1022.97 648.00 6 1.735000 1.000000 stf
+0.70 setlinewidth
+216.29 743.00 moveto
+216.29 636.95 lineto stroke
+%  S_CLEFSIG
+228.08 725.00 1.000000 gclef
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+219.29 672.91 moveto
+(T) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+219.29 655.03 moveto
+(A) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+219.29 637.15 moveto
+(B) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+267.77 722.00 1.000000 4n
+258.41 722.00 1.000000 sharp
+271.45 722.75 moveto
+271.45 743.00 lineto stroke
+308.54 725.00 1.000000 4n
+308.54 713.00 1.000000 4n
+302.31 713.00 moveto
+314.77 713.00 lineto stroke
+312.22 713.75 moveto
+312.22 746.00 lineto stroke
+347.84 731.00 1.000000 4n
+347.84 725.00 1.000000 4n
+351.52 725.75 moveto
+351.52 752.00 lineto stroke
+392.15 743.00 1.000000 4n
+382.80 743.00 1.000000 sharp
+392.15 737.00 1.000000 4n
+/Times-Roman findfont
+12 scalefont
+setfont
+374.52 733.98 moveto
+(\() show
+/Times-Roman findfont
+12 scalefont
+setfont
+397.18 733.98 moveto
+(\)) show
+392.15 728.00 1.000000 4n
+388.47 742.25 moveto
+388.47 707.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+264.42 653.52 moveto
+(4) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+305.19 653.52 moveto
+(5) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+305.19 643.11 moveto
+(3) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+344.49 674.27 moveto
+(0) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+340.53 654.60 moveto
+(\(5\)) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+388.80 684.57 moveto
+(2) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+388.80 674.34 moveto
+(3) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+388.80 663.75 moveto
+(2) show
+restore
+%  S_BAR
+7 linenum
+0.70 setlinewidth
+431.65 743.00 moveto
+431.65 719.00 lineto stroke
+431.65 689.00 moveto
+431.65 636.95 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /Helvetica-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF -.35(Ti)69.336 581.6 S 1.072(me v).35 F
+1.072(alues are speci\214ed just lik)-.25 F 3.572(eo)-.1 G 3.572(nn)
+-3.572 G 1.072(on-tablature staf)-3.572 F 1.072
+(fs: a number optionally follo)-.25 F 1.072(wed by one or more)-.25 F
+1.957(dots \(lik)69.336 593.6 R 4.457(e4o)-.1 G 4.457(r8)-4.457 G 1.958
+(..\), or a list of such numbers added together \(lik)-4.457 F 4.458(e2)
+-.1 G 1.958(+8\), preceding the chord pitches.)-4.458 F -.8(Ta)69.336
+605.6 S .432(blature staf).8 F .432(fs follo)-.25 F 2.932(wt)-.25 G .432
+(he same rules as non-tablature staf)-2.932 F .432(fs for using time v)
+-.25 F .432(alues from the pre)-.25 F .431(vious chord)-.25 F .523
+(if no time v)69.336 617.6 R .523
+(alue is speci\214ed on the current chord. Similarly)-.25 F 3.024(,i)
+-.65 G 3.024(fn)-3.024 G 3.024(on)-3.024 G .524
+(otes are speci\214ed for a chord, the same)-3.024 F
+(notes used in the pre)69.336 629.6 Q(vious chord are reused. As an e)
+-.25 E(xample:)-.15 E/F1 10/Courier@0 SF(2: 4.e5; ;8;b2;)105.336 647.6 Q
+(bar)105.336 659.6 Q EP
+%%Page: 52 58
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-5)274.506 48 S 2.5(2-)-2.5 G 163.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 134 rlineto 248 0 rlineto 0 134 neg rlineto closepath stroke grestore
+EEND 200 629 248 248 -134 134 162.836 230 PBEGIN
+%%BeginDocument: mugex54.ps
+%%BoundingBox: 200 629 448 763
+save
+1589393640 1589394394 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+3 linenum
+%  S_FEED
+360.29 1091.00 648.00 5 1.000000 1.000000 stf
+360.29 1022.97 648.00 6 1.735000 1.000000 stf
+0.70 setlinewidth
+216.29 743.00 moveto
+216.29 636.95 lineto stroke
+%  S_CLEFSIG
+228.08 725.00 1.000000 gclef
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+219.29 672.91 moveto
+(T) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+219.29 655.03 moveto
+(A) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+219.29 637.15 moveto
+(B) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+261.11 749.00 1.000000 4n
+270.38 752.00 1.000000 dot
+254.88 749.00 moveto
+267.35 749.00 lineto stroke
+257.43 748.25 moveto
+257.43 728.00 lineto stroke
+322.68 749.00 1.000000 4n
+331.94 752.00 1.000000 dot
+316.44 749.00 moveto
+328.91 749.00 lineto stroke
+318.99 748.25 moveto
+318.99 728.00 lineto stroke
+378.17 749.00 1.000000 4n
+371.94 749.00 moveto
+384.40 749.00 lineto stroke
+374.49 748.25 moveto
+374.49 728.00 lineto stroke
+377.51 728.00 1.000000 upflag
+406.01 734.00 1.000000 4n
+396.66 734.00 1.000000 sharp
+402.33 733.25 moveto
+402.33 713.00 lineto stroke
+405.35 713.00 1.000000 upflag
+restore
+%  S_STAFF
+% staff 2
+save
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+257.77 684.75 moveto
+(5) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+319.33 684.75 moveto
+(5) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+374.82 684.75 moveto
+(5) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+402.66 674.16 moveto
+(2) show
+restore
+%  S_BAR
+7 linenum
+0.70 setlinewidth
+431.65 743.00 moveto
+431.65 719.00 lineto stroke
+431.65 689.00 moveto
+431.65 636.95 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Helvetica-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .762
+(Since nothing is speci\214ed for the second chord, both time v)69.336
+244 R .761(alue \(dotted quarter\) and note \(e string fret 5\))-.25 F
+.044(are copied from the \214rst chord.)69.336 256 R .045
+(The third chord in the measure has only a time v)5.045 F .045
+(alue \(an eighth note\) so the)-.25 F
+(note \(string/fret\) is repeated.)69.336 268 Q
+(The \214nal chord has only a note, so the pre)5 E(vious time v)-.25 E
+(alue is used.)-.25 E .091
+(Rests and spaces can be speci\214ed with r and s, just lik)69.336 286 R
+2.59(eo)-.1 G 2.59(nn)-2.59 G .09(on-tablature staf)-2.59 F .09(fs. The)
+-.25 F 2.59(yr)-.15 G .09(esult in nothing being)-2.59 F
+(printed on the tablature staf)69.336 298 Q
+(f, and rest or space being printed on the tabnote staf)-.25 E(f.)-.25 E
+69.336 316 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(6.3 Chord)72.836 316 R(attrib)3.5 E(utes)
+-.28 E 69.336 334 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(An)72.29 334 Q 2.954(yc)-.15 G .454
+(hord on a tablature staf)-2.954 F 2.955(fc)-.25 G .455
+(an be preceded by a list of chord attrib)-2.955 F .455(utes in brack)
+-.2 F .455(ets, just lik)-.1 F 2.955(ew)-.1 G .455(ith non-)-2.955 F
+.029(tablature staf)69.336 346 R .029(fs. If you w)-.25 F .029
+(ant a chord to be printed with X \(for a muf)-.1 F .028
+(\215ed string\) rather than a fret number)-.25 F 2.528(,u)-.4 G(se)
+-2.528 E 2.57([xnote]. In)69.336 358 R .071(this case, the fret number \
+will be used only to determine where to put the X on the tabnote staf)
+2.571 F(f,)-.25 E 1.481(and what note to use for MIDI.)69.336 370 R
+1.481(Using [diam] will ha)6.481 F 1.78 -.15(ve n)-.2 H 3.98(oa).15 G
+-.25(ff)-3.98 G 1.48(ect on the tablature staf).25 F 1.48(f, b)-.25 F
+1.48(ut will cause)-.2 F .167
+(diamond notes to be used on the tabnote staf)69.336 382 R 2.667
+(f. Using)-.25 F .167
+([grace] or [cue] will cause the fret numbers to printed)2.667 F 1.131
+(in a smaller size, and the corresponding notes on the tabnote staf)
+69.336 394 R 3.63(ft)-.25 G 3.63(ob)-3.63 G 3.63(ep)-3.63 G 1.13
+(rinted in a smaller size. Using)-3.63 F([slash)69.336 406 Q/F1 10
+/Times-Italic@0 SF(N)2.833 E F0 2.833(]w)C .333(ill cause)-2.833 F F1(N)
+2.833 E F0 .334(slashes to be printed belo)2.834 F 2.834(wt)-.25 G .334
+(he chord on the tablature staf)-2.834 F .334
+(f, as well as slashes on the)-.25 F .519
+(corresponding chord on the tabnote staf)69.336 418 R 3.019(f. Y)-.25 F
+.519(ou can use the other chord attrib)-1.1 F .518
+(utes \(with, pad, and =tag\) just)-.2 F(lik)69.336 430 Q 2.5(eo)-.1 G
+2.5(nan)-2.5 G(on-tablature staf)-2.5 E(f.)-.25 E 69.336 448 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(6.4 T)72.836 448 R(ies)-.252 E 69.336 466
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .314(From an input point of vie)72.15 466 R
+1.614 -.65(w, t)-.25 H .314(ies w).65 F .314
+(ork much the same on tablature staf)-.1 F .315(fs as on other staf)-.25
+F 2.815(fs. On)-.25 F .315(output, tie)2.815 F .339
+(marks on tablature staf)69.336 478 R .339(fs are normally not printed,\
+ and the frets are not printed on the tied-to chord. If a tie)-.25 F
+.668(goes across to a ne)69.336 490 R 3.168(ws)-.25 G .668
+(core, the frets are printed, b)-3.168 F .669
+(ut in parentheses, to indicate the chord is really just the)-.2 F
+(continuation of a tie.)69.336 502 Q 69.336 520 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(6.5 Slides)72.836 520 R 69.336 538 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.96(In Mup input, slides are sho)73.796 538
+R 1.96(wn with <>, rather lik)-.25 F 4.459(es)-.1 G 1.959
+(lurs on non-tablature staf)-4.459 F 4.459(fs. There)-.25 F 1.959
+(is a special)4.459 F -.25(va)69.336 550 S 1.066
+(riation used for slides that come from no).25 F 1.066
+(where in particular or go to no)-.25 F 1.066(where in particular)-.25 F
+6.066(.T)-.55 G 1.066(hese are)-6.066 F(sho)69.336 562 Q .858
+(wn with <\\n>, </n>, <n\\>, or <n/>.)-.25 F 3.357(As)5.858 G .857
+(lide is indicated on output on tablature staf)-3.357 F .857
+(fs as a slanted line)-.25 F .118(between 2 fret numbers on a string.)
+69.336 574 R .118(On tabnote staf)5.118 F .118(fs, the)-.25 F 2.618(ya)
+-.15 G 2.618(sd)-2.618 G(ra)-2.618 E .118
+(wn as a slanted line between 2 notes.)-.15 F(See)5.118 E(the e)69.336
+586 Q(xamples belo)-.15 E(w:)-.25 E/F1 10/Courier@0 SF
+(2: a5<>; a6; d3<>; d2;)105.336 604 Q(bar)105.336 616 Q
+(2: b4</n>; e3<\\n>; a2<n/>; e'5<n\\>;)105.336 640 Q(bar)105.336 652 Q
+EP
+%%Page: 53 59
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-5)274.506 48 S 2.5(3-)-2.5 G 91.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 137 rlineto 392 0 rlineto 0 137 neg rlineto closepath stroke grestore
+EEND 128 626 392 392 -137 137 90.836 233 PBEGIN
+%%BeginDocument: mugex55.ps
+%%BoundingBox: 128 626 520 763
+save
+1589393640 1589394394 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+3 linenum
+%  S_FEED
+288.29 1091.00 720.00 5 1.000000 1.000000 stf
+288.29 1022.97 720.00 6 1.735000 1.000000 stf
+0.70 setlinewidth
+144.29 743.00 moveto
+144.29 636.95 lineto stroke
+%  S_CLEFSIG
+156.08 725.00 1.000000 gclef
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+147.29 672.91 moveto
+(T) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+147.29 655.03 moveto
+(A) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+147.29 637.15 moveto
+(B) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+184.99 716.00 1.000000 4n
+188.68 716.75 moveto
+188.68 737.00 lineto stroke
+222.33 719.00 1.000000 4n
+213.56 719.00 1.000000 flat
+226.01 719.75 moveto
+226.01 740.00 lineto stroke
+257.28 722.00 1.000000 4n
+260.97 722.75 moveto
+260.97 743.00 lineto stroke
+295.35 719.00 1.000000 4n
+286.90 719.00 1.000000 nat
+299.03 719.75 moveto
+299.03 740.00 lineto stroke
+262.32 722.00 moveto
+282.48 719.00 lineto stroke
+190.03 716.00 moveto
+208.81 719.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+181.65 643.11 moveto
+(5) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+218.98 643.04 moveto
+(6) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+253.94 653.52 moveto
+(3) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+292.00 653.34 moveto
+(2) show
+0.70 setlinewidth
+261.63 660.77 moveto
+290.00 654.77 lineto stroke
+189.34 644.36 moveto
+216.98 650.36 lineto stroke
+restore
+%  S_BAR
+7 linenum
+0.70 setlinewidth
+329.77 743.00 moveto
+329.77 719.00 lineto stroke
+329.77 689.00 moveto
+329.77 636.95 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+358.46 740.00 1.000000 4n
+349.68 740.00 1.000000 flat
+354.78 739.25 moveto
+354.78 719.00 lineto stroke
+396.22 746.00 1.000000 4n
+392.53 745.25 moveto
+392.53 725.00 lineto stroke
+430.64 710.00 1.000000 4n
+424.41 713.00 moveto
+436.87 713.00 lineto stroke
+434.32 710.75 moveto
+434.32 731.00 lineto stroke
+467.57 707.00 1.000000 4n
+461.34 707.00 moveto
+473.80 707.00 lineto stroke
+461.34 713.00 moveto
+473.80 713.00 lineto stroke
+471.25 707.75 moveto
+471.25 731.00 lineto stroke
+473.60 707.00 moveto
+482.60 704.00 lineto stroke
+436.67 710.00 moveto
+445.67 713.00 lineto stroke
+381.18 749.00 moveto
+390.18 746.00 lineto stroke
+335.94 737.00 moveto
+344.94 740.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+355.11 674.34 moveto
+(4) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+392.87 684.75 moveto
+(3) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+427.29 642.93 moveto
+(2) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+464.22 632.70 moveto
+(5) show
+0.70 setlinewidth
+472.92 636.95 moveto
+481.92 633.95 lineto stroke
+435.99 647.36 moveto
+444.99 650.36 lineto stroke
+381.87 692.00 moveto
+390.87 689.00 lineto stroke
+344.11 675.59 moveto
+353.11 678.59 lineto stroke
+restore
+%  S_BAR
+10 linenum
+0.70 setlinewidth
+503.65 743.00 moveto
+503.65 719.00 lineto stroke
+503.65 689.00 moveto
+503.65 636.95 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Helvetica-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 253 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(6.6 Bends)72.836 253 R 69.336 271 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 2.537(Ab)71.873 271 S .037
+(end \(stretching a string to mak)-2.537 F 2.537(ei)-.1 G 2.537(ts)
+-2.537 G .036
+(ound higher than normal\) is speci\214ed on tablature staf)-2.537 F
+.036(fs by putting a)-.25 F(te)69.336 283 Q 1.921
+(xt string after the string. The te)-.15 F 1.921(xt string can be the w)
+-.15 F 1.921(ord "full" or a number and/or fraction.)-.1 F(Some)6.922 E
+-.15(ex)69.336 295 S(amples:).15 E/F1 10/Courier@0 SF
+(2: e4 "full"; e "1/2"; 2e "1 1/2";)105.336 313 Q(bar)105.336 325 Q
+127.836 334.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 182 rlineto 320 0 rlineto 0 182 neg rlineto closepath stroke grestore
+EEND 160 580 320 320 -182 182 126.836 516.6 PBEGIN
+%%BeginDocument: mugex56.ps
+%%BoundingBox: 160 580 480 762
+save
+1589393640 1589394394 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+3 linenum
+%  S_FEED
+324.29 1081.31 684.00 5 1.000000 1.000000 stf
+324.29 973.48 684.00 6 1.735000 1.000000 stf
+0.70 setlinewidth
+180.29 733.31 moveto
+180.29 587.45 lineto stroke
+%  S_CLEFSIG
+192.08 715.31 1.000000 gclef
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+183.29 623.42 moveto
+(T) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+183.29 605.54 moveto
+(A) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+183.29 587.66 moveto
+(B) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+230.98 736.31 0.583333 4n
+225.11 736.31 0.583333 sharp
+/Times-Roman findfont
+7 scalefont
+setfont
+220.28 734.55 moveto
+(\() show
+/Times-Roman findfont
+7 scalefont
+setfont
+234.33 734.55 moveto
+(\)) show
+257.80 742.31 1.000000 4n
+249.03 742.31 1.000000 flat
+251.57 739.31 moveto
+264.03 739.31 lineto stroke
+254.12 741.56 moveto
+254.12 721.31 lineto stroke
+312.05 739.31 1.000000 4n
+305.81 739.31 moveto
+318.28 739.31 lineto stroke
+308.36 738.56 moveto
+308.36 718.31 lineto stroke
+379.02 742.31 1.000000 2n
+370.36 742.31 1.000000 nat
+372.58 739.31 moveto
+385.47 739.31 lineto stroke
+375.13 741.56 moveto
+375.13 721.31 lineto stroke
+314.05 744.41 moveto
+345.15 754.00 lineto stroke
+345.15 754.00 moveto
+377.02 747.41 lineto stroke
+259.80 747.41 moveto
+285.41 753.99 lineto stroke
+285.41 753.99 moveto
+310.05 744.41 lineto stroke
+231.98 743.51 moveto
+243.04 750.66 lineto stroke
+243.04 750.66 moveto
+255.80 747.41 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+254.45 635.26 moveto
+(4) show
+/Helvetica findfont
+12 scalefont
+setfont
+250.13 672.89 moveto
+(full) show
+0.70 setlinewidth
+257.80 645.76 moveto
+257.80 669.73 lineto stroke
+257.80 666.31 1.000000 uwedge
+/Helvetica findfont
+12 scalefont
+setfont
+312.05 657.27 moveto
+(1/2) show
+257.80 669.73 moveto
+260.51 669.88 263.23 669.88 265.94 669.73 curveto
+275.94 669.18 285.93 668.45 295.77 666.41 curveto
+297.63 666.03 299.50 665.67 301.20 664.75 curveto
+305.43 662.44 309.85 660.34 312.05 655.61 curveto
+312.43 654.78 312.43 653.95 312.05 653.12 curveto
+stroke
+312.05 650.70 1.000000 wedge
+/Helvetica findfont
+12 scalefont
+setfont
+365.67 690.59 moveto
+(1 1/2) show
+312.05 654.12 moveto
+315.39 653.85 318.74 653.85 322.09 654.12 curveto
+334.54 655.13 346.92 656.54 358.93 660.17 curveto
+361.30 660.88 363.64 661.65 365.63 663.19 curveto
+371.42 667.66 376.51 672.70 379.02 679.81 curveto
+379.56 681.33 379.56 682.84 379.02 684.35 curveto
+stroke
+379.02 681.93 1.000000 uwedge
+restore
+%  S_BAR
+7 linenum
+0.70 setlinewidth
+467.65 733.31 moveto
+467.65 709.31 lineto stroke
+467.65 639.50 moveto
+467.65 587.45 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /Helvetica /Helvetica-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .529(If you w)69.336 536.6 R .529
+(ant to bend back do)-.1 F .529(wn to ha)-.25 F .529
+(ving no bend \(a release\), the te)-.2 F .528
+(xt string specifying the bend is just an)-.15 F .843
+(empty string of "".)69.336 548.6 R .843(Note that if both a fret and b\
+end other than "" are speci\214ed, this indicates a prebend,)5.843 F
+(whereas if only a bend is speci\214ed, this indicates a normal bend.)
+69.336 560.6 Q .599(Bends need not be an inte)69.336 578.6 R .599
+(ger number of half steps, b)-.15 F .598
+(ut if you specify a bend that f)-.2 F .598(alls between half steps,)-.1
+F .352(when it is used on the tabnote staf)69.336 590.6 R .352
+(f, the bend is rounded to the nearest half step, or rounded do)-.25 F
+(wnw)-.25 E .352(ard if it)-.1 F .673(is e)69.336 602.6 R .673
+(xactly in the middle of a half step.)-.15 F .672
+(When possible, bends of 1/4 step or less are sho)5.672 F .672
+(wn on the tabnote)-.25 F(staf)69.336 614.6 Q 2.5(fb)-.25 G 2.5(yas)-2.5
+G(mall curv)-2.5 E 2.5(er)-.15 G(ather than by a separate note.)-2.5 E
+-1.1(Yo)69.336 632.6 S 2.778(uc)1.1 G .278
+(an specify bends on more than one string at once, b)-2.778 F .279
+(ut a continuation bend \(bending to a ne)-.2 F 2.779(wd)-.25 G(istance)
+-2.779 E(without replucking the string\) is only allo)69.336 644.6 Q
+(wed on a single string at a time. Here are some e)-.25 E(xamples:)-.15
+E/F1 10/Courier@0 SF(2: g0b2e'0; e' "1/2" g "full" b "3/4"; e' ""; a2;)
+105.336 662.6 Q(bar)105.336 674.6 Q
+(2: a "1/2"; a "full"; a "1/2"; a "";)105.336 698.6 Q(bar)105.336 710.6
+Q EP
+%%Page: 54 60
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-5)274.506 48 S 2.5(4-)-2.5 G 103.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 196 rlineto 368 0 rlineto 0 196 neg rlineto closepath stroke grestore
+EEND 136 567 368 368 -196 196 102.836 292 PBEGIN
+%%BeginDocument: mugex57.ps
+%%BoundingBox: 136 567 504 763
+save
+1589393640 1589394394 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+3 linenum
+%  S_FEED
+302.69 1088.00 705.60 5 1.000000 1.000000 stf
+302.69 964.01 705.60 6 1.735000 1.000000 stf
+0.70 setlinewidth
+158.69 740.00 moveto
+158.69 577.99 lineto stroke
+%  S_CLEFSIG
+170.48 722.00 1.000000 gclef
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+161.69 613.95 moveto
+(T) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+161.69 596.07 moveto
+(A) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+161.69 578.19 moveto
+(B) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+206.80 731.00 1.000000 4n
+197.45 731.00 1.000000 sharp
+206.80 722.00 1.000000 4n
+206.80 695.00 1.000000 4n
+200.57 698.00 moveto
+213.04 698.00 lineto stroke
+200.57 704.00 moveto
+213.04 704.00 lineto stroke
+200.57 710.00 moveto
+213.04 710.00 lineto stroke
+210.49 695.75 moveto
+210.49 752.00 lineto stroke
+241.43 734.00 1.000000 4n
+241.43 725.00 1.000000 4n
+241.43 698.00 1.000000 4n
+235.19 698.00 moveto
+247.66 698.00 lineto stroke
+235.19 704.00 moveto
+247.66 704.00 lineto stroke
+235.19 710.00 moveto
+247.66 710.00 lineto stroke
+245.11 698.75 moveto
+245.11 755.00 lineto stroke
+275.16 695.00 1.000000 4n
+268.93 698.00 moveto
+281.39 698.00 lineto stroke
+268.93 704.00 moveto
+281.39 704.00 lineto stroke
+268.93 710.00 moveto
+281.39 710.00 lineto stroke
+278.84 695.75 moveto
+278.84 728.00 lineto stroke
+309.18 707.00 1.000000 4n
+302.95 710.00 moveto
+315.41 710.00 lineto stroke
+312.86 707.75 moveto
+312.86 728.00 lineto stroke
+311.18 701.90 moveto
+332.61 695.32 lineto stroke
+332.61 695.32 moveto
+352.88 704.90 lineto stroke
+243.43 692.90 moveto
+257.48 683.34 lineto stroke
+257.48 683.34 moveto
+273.16 689.90 lineto stroke
+208.80 689.90 moveto
+224.90 683.34 lineto stroke
+224.90 683.34 moveto
+239.43 692.90 lineto stroke
+212.84 722.00 moveto
+224.34 718.29 lineto stroke
+224.34 718.29 moveto
+234.39 725.00 lineto stroke
+212.84 736.10 moveto
+226.29 745.66 lineto stroke
+226.29 745.66 moveto
+241.43 739.10 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+203.46 615.20 moveto
+(2) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+203.46 604.90 moveto
+(0) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+203.46 573.67 moveto
+(0) show
+/Helvetica findfont
+12 scalefont
+setfont
+233.07 671.62 moveto
+(3/4) show
+/Helvetica findfont
+12 scalefont
+setfont
+233.76 660.67 moveto
+(full) show
+/Helvetica findfont
+12 scalefont
+setfont
+233.07 649.80 moveto
+(1/2) show
+0.70 setlinewidth
+212.65 620.63 moveto
+214.09 620.40 215.53 620.40 216.97 620.63 curveto
+222.50 621.48 227.86 622.87 232.79 625.63 curveto
+233.93 626.27 234.91 627.07 235.67 628.13 curveto
+238.66 632.27 240.43 636.92 241.43 641.90 curveto
+241.68 643.15 241.68 644.40 241.43 645.65 curveto
+stroke
+212.65 610.22 moveto
+214.09 609.91 215.53 609.91 216.97 610.22 curveto
+222.75 611.45 228.08 613.68 232.79 617.30 curveto
+234.03 618.26 234.95 619.47 235.67 620.85 curveto
+238.89 626.96 240.45 633.56 241.43 640.34 curveto
+241.68 642.11 241.68 643.88 241.43 645.65 curveto
+stroke
+212.65 578.99 moveto
+214.09 578.46 215.53 578.46 216.97 578.99 curveto
+223.87 581.50 228.57 586.63 232.79 592.32 curveto
+234.28 594.31 234.99 596.64 235.67 598.99 curveto
+239.14 610.96 240.46 623.28 241.43 635.65 curveto
+241.69 638.98 241.69 642.32 241.43 645.65 curveto
+stroke
+241.43 643.23 1.000000 uwedge
+241.43 646.65 moveto
+243.11 647.18 244.80 647.18 246.49 646.65 curveto
+254.05 644.26 259.92 639.47 265.04 633.60 curveto
+266.70 631.70 267.61 629.42 268.41 627.08 curveto
+272.42 615.45 274.03 603.36 275.16 591.19 curveto
+275.46 587.93 275.46 584.67 275.16 581.41 curveto
+stroke
+275.16 578.99 1.000000 wedge
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+305.83 583.97 moveto
+(2) show
+restore
+%  S_BAR
+8 linenum
+0.70 setlinewidth
+341.17 740.00 moveto
+341.17 716.00 lineto stroke
+341.17 630.04 moveto
+341.17 577.99 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+354.88 710.00 1.000000 4n
+348.65 710.00 moveto
+361.11 710.00 lineto stroke
+358.56 710.75 moveto
+358.56 731.00 lineto stroke
+388.48 710.00 1.000000 4n
+379.13 710.00 1.000000 sharp
+382.25 710.00 moveto
+394.71 710.00 lineto stroke
+392.16 710.75 moveto
+392.16 731.00 lineto stroke
+421.29 710.00 1.000000 4n
+412.84 710.00 1.000000 nat
+415.06 710.00 moveto
+427.53 710.00 lineto stroke
+424.98 710.75 moveto
+424.98 731.00 lineto stroke
+457.26 707.00 1.000000 4n
+451.03 710.00 moveto
+463.49 710.00 lineto stroke
+460.94 707.75 moveto
+460.94 728.00 lineto stroke
+423.29 704.90 moveto
+438.52 695.34 lineto stroke
+438.52 695.34 moveto
+455.26 701.90 lineto stroke
+390.48 704.90 moveto
+404.89 696.80 lineto stroke
+404.89 696.80 moveto
+419.29 704.90 lineto stroke
+356.88 704.90 moveto
+371.68 696.80 lineto stroke
+371.68 696.80 moveto
+386.48 704.90 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+/Helvetica findfont
+12 scalefont
+setfont
+346.53 647.80 moveto
+(1/2) show
+0.70 setlinewidth
+315.03 589.40 moveto
+317.02 588.93 319.01 588.93 321.01 589.40 curveto
+329.16 591.30 336.50 594.85 342.93 600.25 curveto
+344.70 601.73 345.92 603.61 346.91 605.67 curveto
+351.44 615.12 353.53 625.22 354.88 635.51 curveto
+355.24 638.22 355.24 640.94 354.88 643.65 curveto
+stroke
+354.88 641.23 1.000000 uwedge
+/Helvetica findfont
+12 scalefont
+setfont
+380.81 663.42 moveto
+(full) show
+354.88 644.65 moveto
+356.56 644.52 358.24 644.52 359.92 644.65 curveto
+366.16 645.14 372.36 645.81 378.40 647.57 curveto
+379.58 647.92 380.75 648.28 381.76 649.04 curveto
+384.63 651.19 387.21 653.58 388.48 657.07 curveto
+388.74 657.80 388.74 658.53 388.48 659.27 curveto
+stroke
+388.48 656.85 1.000000 uwedge
+/Helvetica findfont
+12 scalefont
+setfont
+421.29 647.80 moveto
+(1/2) show
+388.48 660.27 moveto
+390.12 660.42 391.76 660.42 393.40 660.27 curveto
+399.52 659.71 405.59 658.92 411.45 656.94 curveto
+412.62 656.55 413.77 656.10 414.73 655.28 curveto
+417.66 652.77 420.09 649.89 421.29 646.14 curveto
+421.56 645.31 421.56 644.48 421.29 643.65 curveto
+stroke
+421.29 641.23 1.000000 wedge
+421.29 644.65 moveto
+423.09 645.10 424.89 645.10 426.69 644.65 curveto
+434.16 642.78 440.74 639.23 446.47 634.08 curveto
+448.10 632.62 449.18 630.78 450.07 628.80 curveto
+454.20 619.54 456.04 609.72 457.26 599.74 curveto
+457.58 597.10 457.58 594.46 457.26 591.82 curveto
+stroke
+457.26 589.40 1.000000 wedge
+restore
+%  S_BAR
+11 linenum
+0.70 setlinewidth
+489.25 740.00 moveto
+489.25 716.00 lineto stroke
+489.25 630.04 moveto
+489.25 577.99 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Helvetica /Helvetica-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .946(If you ha)69.336 312 R 1.246 -.15
+(ve m)-.2 H .946(ore than one v).15 F .946(oice on a tablature staf)-.2
+F .945(f, bends on other than the top v)-.25 F .945
+(oice may collide with)-.2 F 1.483(other v)69.336 324 R 1.483
+(oices in some cases, and if there are bends from more than one v)-.2 F
+1.484(oice simultaneously)-.2 F 3.984(,t)-.65 G(he)-3.984 E 3.984(ym)
+-.15 G(ay)-3.984 E(collide.)69.336 336 Q .852(On non-tablature staf)
+69.336 354 R .851(fs, bends are speci\214ed with a ^ symbol follo)-.25 F
+.851(wed by the note to bend to. The note to)-.25 F 1.019
+(bend to is speci\214ed by letter and optional octa)69.336 366 R 1.319
+-.15(ve \()-.2 H 1.02(accidentals are not speci\214ed\). If you w).15 F
+1.02(ant just a small)-.1 F
+(bend \(1/4 step\), this is speci\214ed by ^/. F)69.336 378 Q(or e)-.15
+E(xample:)-.15 E/F1 10/Courier@0 SF(1: e ^f; f; b ^c5; c#5;)105.336 396
+Q(bar)105.336 408 Q(1: d+^e+ g^a; e+a; g ^/; c ^/ c+^/;)105.336 432 Q
+(bar)105.336 444 Q 127.836 453.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 67 rlineto 320 0 rlineto 0 67 neg rlineto closepath stroke grestore
+EEND 160 696 320 320 -67 67 126.836 520.6 PBEGIN
+%%BeginDocument: mugex58.ps
+%%BoundingBox: 160 696 480 763
+save
+1589393640 1589394394 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+324.29 1091.00 684.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+221.11 719.00 1.000000 4n
+0.70 setlinewidth
+224.79 719.75 moveto
+224.79 740.00 lineto stroke
+250.38 722.00 1.000000 4n
+254.06 722.75 moveto
+254.06 743.00 lineto stroke
+278.22 731.00 1.000000 4n
+274.54 730.25 moveto
+274.54 710.00 lineto stroke
+309.78 734.00 1.000000 4n
+300.42 734.00 1.000000 sharp
+306.09 733.25 moveto
+306.09 713.00 lineto stroke
+280.22 736.10 moveto
+293.43 742.83 lineto stroke
+293.43 742.83 moveto
+307.78 739.10 lineto stroke
+223.11 713.90 moveto
+236.37 710.17 lineto stroke
+236.37 710.17 moveto
+248.38 716.90 lineto stroke
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+338.51 743.00 moveto
+338.51 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+348.81 737.00 1.000000 4n
+348.81 725.00 1.000000 4n
+345.12 736.25 moveto
+345.12 704.00 lineto stroke
+379.52 740.00 1.000000 4n
+379.52 728.00 1.000000 4n
+375.84 739.25 moveto
+375.84 707.00 lineto stroke
+408.80 725.00 1.000000 4n
+415.83 726.50 moveto
+416.39 726.55 416.89 726.75 417.33 727.10 curveto
+418.33 727.89 418.95 728.95 419.43 730.10 curveto
+419.65 730.63 419.75 731.18 419.73 731.75 curveto
+stroke
+412.48 725.75 moveto
+412.48 746.00 lineto stroke
+438.91 734.00 1.000000 4n
+445.95 735.50 moveto
+446.51 735.55 447.01 735.75 447.45 736.10 curveto
+448.44 736.89 449.06 737.95 449.55 739.10 curveto
+449.77 739.63 449.87 740.18 449.85 740.75 curveto
+stroke
+438.91 713.00 1.000000 4n
+445.95 714.50 moveto
+446.51 714.55 447.01 714.75 447.45 715.10 curveto
+448.44 715.89 449.06 716.95 449.55 718.10 curveto
+449.77 718.63 449.87 719.18 449.85 719.75 curveto
+stroke
+432.68 713.00 moveto
+445.15 713.00 lineto stroke
+442.60 713.75 moveto
+442.60 755.00 lineto stroke
+348.81 719.90 moveto
+361.31 716.18 lineto stroke
+361.31 716.18 moveto
+372.49 722.90 lineto stroke
+350.81 742.10 moveto
+363.58 748.83 lineto stroke
+363.58 748.83 moveto
+377.52 745.10 lineto stroke
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 540.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(6.7 Miscellaneous)72.836 540.6 R 69.336
+558.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .269(Note attrib)72.105 558.6 R .269
+(utes of ~ for tie, ? for a small note, and = for a tag w)-.2 F .269
+(ork the same on tablatures staf)-.1 F .268(fs as on non-)-.25 F
+(tablature staf)69.336 570.6 Q(fs.)-.25 E 1.525
+(If bm, ebm, or esbm are gi)69.336 588.6 R -.15(ve)-.25 G 4.026(no).15 G
+4.026(nt)-4.026 G 1.526(ablature staf)-4.026 F 1.526(fs the)-.25 F 4.026
+(ya)-.15 G 1.526(re transferred to the tabnote staf)-4.026 F 4.026(fa)
+-.25 G 1.526(nd used for)-4.026 F .073(custom beaming there.)69.336
+600.6 R .072
+(Items in "with" lists inside [ ] are also copied to the tabnote staf)
+5.072 F 2.572(f. In)-.25 F .072(general, unless)2.572 F .65
+(otherwise speci\214ed here, if you w)69.336 612.6 R .651
+(ant items such as tempo and dynamic marks to appear on both tablature)
+-.1 F(and tabnote staf)69.336 624.6 Q(f, you ha)-.25 E .3 -.15(ve t)-.2
+H 2.5(os).15 G(pecify them for both staf)-2.5 E(fs.)-.25 E
+(The "alt" inter)69.336 642.6 Q(-chord attrib)-.2 E(ute is not allo)-.2
+E(wed on tablature staf)-.25 E(fs.)-.25 E 1.739
+(When there is a tablature staf)69.336 660.6 R 1.739
+(f, the MIDI is actually generated from the tabnote staf)-.25 F 1.738
+(f. There are some)-.25 F 3.309(limitations. Currently)69.336 672.6 R
+3.309(,n)-.65 G 3.309(oM)-3.309 G .809(IDI pitch bends are generated; s\
+lides and bends are instantaneous rather than)-3.309 F(gradual.)69.336
+684.6 Q .153(If a capo is being used, it probably better to declare a t\
+ransposition of the tabnote staf)69.336 702.6 R 2.652(fr)-.25 G .152
+(ather than declaring)-2.652 F .179(the strings to be dif)69.336 714.6 R
+.179(ferent notes. This is because most people w)-.25 F .18
+(ould rather think of the original string letters)-.1 F .358
+(when entering the tab staf)69.336 726.6 R 2.858(fi)-.25 G .357
+(nformation; and if you decide to put the capo on a dif)-2.858 F .357
+(ferent fret later)-.25 F 2.857(,y)-.4 G .357(ou only)-2.857 F(ha)69.336
+738.6 Q .959 -.15(ve t)-.2 H 3.159(oc).15 G .659
+(hange the "transpose" line.)-3.159 F .659(The automatic MIDI octa)5.659
+F .959 -.15(ve t)-.2 H .66(ranposition for standard guitar will also).15
+F EP
+%%Page: 55 61
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-5)274.506 48 S 2.5(5-)-2.5 G
+(then still apply)69.336 96 Q 2.5(,o)-.65 G 2.5(nt)-2.5 G
+(op of your transposition.)-2.5 E 1.069(If you specify an octa)69.336
+114 R 1.369 -.15(ve m)-.2 H 1.069
+(ark \(discussed in a later section\) on a tabnote staf).15 F 1.069
+(f, the deri)-.25 F -.15(ve)-.25 G 3.569(dm).15 G 1.069(usic will be)
+-3.569 F 1.755(printed with the notes raised or lo)69.336 126 R 1.755
+(wered the appropriate number of octa)-.25 F -.15(ve)-.2 G 4.255(st).15
+G 4.255(oc)-4.255 G 1.755(orrespond to the gi)-4.255 F -.15(ve)-.25 G(n)
+.15 E(octa)69.336 138 Q .3 -.15(ve m)-.2 H(ark interv).15 E(al.)-.25 E
+.799(Since ties are not printed on tablature staf)69.336 156 R .799
+(f, and input notation for tablature slides is lik)-.25 F 3.299(ew)-.1 G
+.799(hat is used for)-3.299 F .452(slurs on ordinary staf)69.336 168 R
+.452(fs, if you w)-.25 F .452(ant a curv)-.1 F .452(ed line lik)-.15 F
+2.952(eat)-.1 G .452(ie or slur on a tablature or tabnote staf)-2.952 F
+.453(f, you ha)-.25 F -.15(ve)-.2 G(to use a phrase mark. See the secti\
+on on phrase marks for more details.)69.336 180 Q .971
+(The chord-at-a-time input style can also be used for tablature.)69.336
+198 R .97(The staf)5.971 F .97(fs being mapped to from a single)-.25 F
+(input line must either be all tablature or all non-tablature, ho)69.336
+210 Q(we)-.25 E -.15(ve)-.25 G -.55(r.).15 G/F1 10/Courier@0 SF(score)
+105.336 228 Q(staffs=4)130.336 240 Q(brace=1-2, 3-4)130.336 252 Q
+(tabwhitebox=y)130.336 264 Q(staff 2)105.336 276 Q(stafflines=tab)
+130.336 288 Q(staff 4)105.336 300 Q(stafflines=tab)130.336 312 Q(music)
+105.336 324 Q(// The first two notes in each chord go to staff 2,)
+105.336 348 Q(// and the last two go to staff 4.)105.336 360 Q 6([2)
+105.336 372 S 6(;2)-6 G 6(;4)-6 G 6(;4)-6 G 6(]:a)-6 G
+(2d0 g0b3; e'0a2 g0e0; 2 e'0d2 b0e3;)-6 E(bar)105.336 384 Q 139.836
+393.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 248 rlineto 296 0 rlineto 0 248 neg rlineto closepath stroke grestore
+EEND 168 515 296 296 -248 248 138.836 641.6 PBEGIN
+%%BeginDocument: mugex59.ps
+%%BoundingBox: 168 515 464 763
+save
+1589393640 1589394394 sv
+0.900000 0.900000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_SSV
+9 linenum
+%  S_SSV
+11 linenum
+%  S_FEED
+366.29 1175.00 720.00 5 1.000000 1.000000 stf
+366.29 1102.59 720.00 6 1.735000 1.000000 stf
+366.29 1034.57 720.00 5 1.000000 1.000000 stf
+366.29 966.54 720.00 6 1.735000 1.000000 stf
+221.79 827.00 716.57 brace
+221.79 686.57 580.52 brace
+0.70 setlinewidth
+222.29 827.00 moveto
+222.29 580.52 lineto stroke
+%  S_CLEFSIG
+234.08 809.00 1.000000 gclef
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+225.29 752.53 moveto
+(T) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+225.29 734.65 moveto
+(A) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+225.29 716.77 moveto
+(B) show
+234.08 668.57 1.000000 gclef
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+225.29 616.48 moveto
+(T) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+225.29 598.60 moveto
+(A) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+225.29 580.72 moveto
+(B) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+268.93 800.00 1.000000 4n
+268.93 794.00 1.000000 4n
+262.70 797.00 moveto
+275.16 797.00 lineto stroke
+272.61 794.75 moveto
+272.61 821.00 lineto stroke
+333.11 794.00 1.000000 4n
+326.88 797.00 moveto
+339.34 797.00 lineto stroke
+333.11 782.00 1.000000 4n
+326.88 785.00 moveto
+339.34 785.00 lineto stroke
+326.88 791.00 moveto
+339.34 791.00 lineto stroke
+326.88 797.00 moveto
+339.34 797.00 lineto stroke
+336.79 782.75 moveto
+336.79 815.00 lineto stroke
+402.74 803.00 1.000000 2n
+402.74 782.00 1.000000 2n
+396.29 785.00 moveto
+409.19 785.00 lineto stroke
+396.29 791.00 moveto
+409.19 791.00 lineto stroke
+396.29 797.00 moveto
+409.19 797.00 lineto stroke
+406.64 782.75 moveto
+406.64 824.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+265.58 731.91 272.28 742.86 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+265.58 733.07 moveto
+(0) show
+265.58 721.61 272.28 732.34 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+265.58 722.55 moveto
+(2) show
+329.76 721.61 336.46 732.34 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+329.76 722.55 moveto
+(2) show
+329.76 711.09 336.46 722.04 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+329.76 712.25 moveto
+(0) show
+399.39 732.02 406.09 742.75 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+399.39 732.96 moveto
+(2) show
+399.39 711.09 406.09 722.04 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+399.39 712.25 moveto
+(0) show
+restore
+%  S_STAFF
+% staff 3
+save
+268.93 680.57 1.000000 4n
+268.93 668.57 1.000000 4n
+0.70 setlinewidth
+265.25 679.82 moveto
+265.25 647.57 lineto stroke
+333.11 683.57 1.000000 4n
+333.11 668.57 1.000000 4n
+329.43 682.82 moveto
+329.43 647.57 lineto stroke
+402.74 689.57 1.000000 2n
+402.74 674.57 1.000000 2n
+398.84 688.82 moveto
+398.84 653.57 lineto stroke
+restore
+%  S_STAFF
+% staff 4
+save
+265.58 616.68 272.28 627.63 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+265.58 617.91 moveto
+(3) show
+265.58 606.27 272.28 617.22 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+265.58 607.43 moveto
+(0) show
+329.76 627.09 336.46 638.04 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+329.76 628.25 moveto
+(0) show
+329.76 606.27 336.46 617.22 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+329.76 607.43 moveto
+(0) show
+399.39 627.09 406.09 638.04 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+399.39 628.32 moveto
+(3) show
+399.39 616.68 406.09 627.63 whitebox
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+399.39 617.84 moveto
+(0) show
+restore
+%  S_BAR
+18 linenum
+0.70 setlinewidth
+503.65 827.00 moveto
+503.65 803.00 lineto stroke
+503.65 768.62 moveto
+503.65 716.57 lineto stroke
+503.65 686.57 moveto
+503.65 662.57 lineto stroke
+503.65 632.57 moveto
+503.65 580.52 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Helvetica-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND EP
+%%Page: 56 62
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-5)274.506 48 S 2.5(6-)-2.5 G 69.336 103
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(7. SHAPED)73.086 103 R(NO)3.75 E(TES)-.6
+E 69.336 121 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .144(If you intend to only use the usual sy\
+stem of note heads, you can skip o)71.98 121 R -.15(ve)-.15 G 2.645(rt)
+.15 G .145(his section on shaped notes.)-2.645 F(If)5.145 E .049
+(you wish to use less common note head shapes, lik)69.336 133 R 2.549
+(eX)-.1 G .049(-shaped notes, rather than normal note heads, or w)-2.549
+F(ant)-.1 E 2.265("shaped note" music that is often used for "Sacred Ha\
+rp" style music, sometimes also called "f)69.336 145 R(asola)-.1 E
+(notation," then this section will e)69.336 157 Q(xplain ho)-.15 E 2.5
+(wy)-.25 G(ou can do that.)-2.5 E 69.336 175 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(7.1 Headshapes)72.836 175 R(context)3.5 E
+69.336 193 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .761(The headshapes conte)72.597 193 R .761
+(xt is used in conjuction with the noteheads parameter to determine wha\
+t characters)-.15 F .077(will be used when printing note heads.)69.336
+205 R .077(It is rarely necessary to include a headshapes conte)5.077 F
+.078(xt in your music,)-.15 F .926
+(since Mup already has the most common v)69.336 217 R .926(alues b)-.25
+F .925(uilt in, so generally you just need to use the noteheads)-.2 F
+1.496(parameter to access them. Ho)69.336 229 R(we)-.25 E -.15(ve)-.25 G
+2.296 -.4(r, i).15 H 3.996(ti).4 G 3.996(ss)-3.996 G 1.496
+(till important to understand what the headshapes conte)-3.996 F 1.496
+(xt can)-.15 F(contain, to understand ho)69.336 241 Q 2.5(wt)-.25 G
+(he b)-2.5 E(uiltin v)-.2 E(alues w)-.25 E(ork.)-.1 E .305
+(The headshapes conte)69.336 259 R .304(xt de\214nes, for a gi)-.15 F
+-.15(ve)-.25 G 2.804(nh).15 G .304
+(ead shape name, what speci\214c note head characters to use for)-2.804
+F .607(the notes of v)69.336 271 R .607(arious durations.)-.25 F .607
+(It contains one or more pairs of strings.)5.607 F .607
+(The \214rst string in the pair gi)5.607 F -.15(ve)-.25 G 3.107(sa).15 G
+.05(name for a set of note head shapes.)69.336 283 R .049(The second st\
+ring contains a space-separated list of the names of 4 note)5.05 F .993
+(head characters to use for that head shape name.)69.336 295 R .994
+(The \214rst shape in the list is used for quarter notes and)5.993 F
+(shorter)69.336 307 Q 2.5(,t)-.4 G(he second for half notes, the third \
+for whole notes, and the fourth for double whole notes.)-2.5 E .463
+(If an upside do)69.336 325 R .463(wn v)-.25 F .463
+(ersion of the character is to be used for stem do)-.15 F .463
+(wn notes, the name is pre\214x)-.25 F .462(ed by "u?")-.15 F .616
+(\(The "u" stands for "upside-do)69.336 337 R .616
+(wn" and the question mark is intended to be mnemonic for the f)-.25 F
+.617(act that the)-.1 F(upside do)69.336 349 Q(wn v)-.25 E
+(ersion will only be used part of the time, namely for stem-do)-.15 E
+(wn notes.\))-.25 E .903(As w)69.336 367 R .903(as mentioned abo)-.1 F
+-.15(ve)-.15 G 3.403(,t).15 G .903
+(he most common mappings are already b)-3.403 F .903(uilt into Mup.)-.2
+F .902(Here is the list of the)5.903 F .864(pre-de\214ned v)69.336 379 R
+3.364(alues. P)-.25 F .864(ay particular attention to the \214rst strin\
+g on each line, since those are the names you)-.15 F
+(will use in the notehead parameter and for o)69.336 391 Q -.15(ve)-.15
+G(rriding chord and note shapes.).15 E 25.27("norm" "4n)69.336 415 R
+(2n 1n dbl)2.5 E(whole")-.1 E 41.38("x" "xnote)69.336 427 R
+(diamond diamond dwhdiamond")2.5 E 31.38("allx" "xnote)69.336 439 R
+(xnote xnote xnote")2.5 E 26.38("diam" "\214lldiamond)69.336 451 R
+(diamond diamond dwhdiamond")2.5 E 24.16("blank" "blankhead)69.336 463 R
+(blankhead blankhead blankhead")2.5 E 18.6
+("righttri" "u?\214llrighttriangle)69.336 475 R
+(u?righttriangle u?righttriangle u?dwhrighttriangle")2.5 E 21.93
+("isostri" "\214llisostriangle)69.336 487 R
+(isostriangle isostriangle dwhisostriangle")2.5 E 31.39
+("rect" "\214llrectangle)69.336 499 R(rectangle rectangle dwhrectangle")
+2.5 E 34.16("pie" "\214llpie)69.336 511 R(wedge pie)-.25 E(wedge pie)
+-.25 E(wedge dwhpie)-.25 E(wedge")-.25 E 12.5
+("semicirc" "\214llsemicircle)69.336 523 R
+(semicircle semicircle dwhsemicircle")2.5 E 26.38
+("slash" "\214llslashhead)69.336 535 R
+(slashhead slashhead dwhslashhead")2.5 E 16.38
+("allslash" "\214llslashhead)69.336 547 R
+(\214llslashhead \214llslashhead \214llslashhead")2.5 E -1.1(Yo)69.336
+565 S 3.21(uc)1.1 G .71(an rede\214ne these or de\214ne ne)-3.21 F 3.21
+(wo)-.25 G .71(nes if you wish.)-3.21 F .71
+(The name \(the \214rst of the tw)5.71 F 3.21(os)-.1 G .71
+(trings in the pair\))-3.21 F .354(can be almost an)69.336 577 R .354
+(ything you w)-.15 F 2.854(ant. The)-.1 F .355
+(four names in the second string must be tak)2.854 F .355
+(en from the list of v)-.1 F(alid)-.25 E(note head characters gi)69.336
+589 Q -.15(ve)-.25 G 2.5(nb).15 G(elo)-2.5 E(w:)-.25 E EP
+%%Page: 57 63
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-5)274.506 48 S 2.5(7-)-2.5 G 68.06(4n 2n)
+174.506 96 R 36.94(1n dbl)10 F(whole)-.1 E 31.94
+(\214lldiamond diamond dwhdiamond)174.506 108 R 20.83
+(\214llisostriangle isostriangle dwhisostriangle)174.506 120 R
+(\214llpie)174.506 132 Q 28.87(wedge pie)-.25 F 28.87(wedge dwhpie)-.25
+F(wedge)-.25 E 30.29(\214llrectangle rectangle dwhrectangle)174.506 144
+R 17.5(\214llrighttriangle righttriangle dwhrighttriangle)174.506 156 R
+12.5(u\214llrighttriangle urighttriangle udwhrighttriangle)174.506 168 R
+25.84(\214llsemicircle semicircle dwhsemicircle)174.506 180 R 28.06
+(\214llslashhead slashhead dwhslashhead)174.506 192 R(xnote)174.506 204
+Q(blankhead)174.506 216 Q .696
+(The righttriangle shape names can be pre\214x)69.336 228 R .696
+(ed by u? when used in the headshapes conte)-.15 F .695
+(xt, to indicate the)-.15 F .767(upside do)69.336 240 R .767(wn v)-.25 F
+.767(ersion of them should be used when the stem is do)-.15 F .768
+(wn. Note that u? cannot be used on an)-.25 F(y)-.15 E
+(other note head characters, since none of the others ha)69.336 252 Q .3
+-.15(ve a c)-.2 H(orresponding upside do).15 E(wn v)-.25 E(ersion.)-.15
+E 1.18(As an e)69.336 270 R 1.18(xample of ho)-.15 F 3.68(wy)-.25 G 1.18
+(ou could use the headshapes conte)-3.68 F 1.179
+(xt, suppose you wished to use xnote for half)-.15 F .91
+(notes and shorter)69.336 282 R 3.41(,a)-.4 G .91
+(nd diamond for longer notes.)-3.41 F .911(That is dif)5.91 F .911
+(ferent than either of the b)-.25 F .911(uiltin v)-.2 F .911
+(alues "x" or)-.25 F("allx" b)69.336 294 Q(ut you could o)-.2 E -.15(ve)
+-.15 G(rride one of them:).15 E/F1 10/Courier@0 SF(headshapes)105.336
+312 Q("x" "xnote xnote diamond diamond")130.336 324 Q F0 .674
+(The blankhead does not print an)69.336 350 R 3.173(yh)-.15 G .673
+(ead at all, it just lea)-3.173 F -.15(ve)-.2 G 3.173(ss).15 G .673
+(pace as if there were a note head. It might be)-3.173 F
+(used if for some reason you just w)69.336 362 Q(ant stems.)-.1 E 69.336
+380 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(7.2 Noteheads)72.836 380 R(parameter)3.5
+E 69.336 398 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.339(The noteheads parameter describes whi\
+ch note head shape to use for each pitch in the scale. It can be)73.175
+398 R .319(speci\214ed in score, staf)69.336 410 R .318(f, or v)-.25 F
+.318(oice conte)-.2 F 2.818(xts. If)-.15 F .318(you w)2.818 F .318
+(ant to use the same shape for all pitches, \(as is the case)-.1 F
+(with standard notation\), only one shape name is speci\214ed.)69.336
+422 Q(Thus the def)5 E(ault v)-.1 E(alue for this parameter is)-.25 E/F1
+10/Courier@0 SF(noteheads = "norm")105.336 440 Q F0 .24(If you w)69.336
+466 R .24(ant to use dif)-.1 F .24(ferent shapes for dif)-.25 F .241
+(ferent pitches, the noteheads v)-.25 F .241
+(alue needs to be a string containing)-.25 F 2.948(al)69.336 478 S .448
+(ist of 7 shape names.)-2.948 F(The)5.448 E 2.947(ya)-.15 G .447
+(re listed from the "tonic" of the major k)-2.947 F .747 -.15(ey u)-.1 H
+2.947(pt).15 G .447(he scale, with the k)-2.947 F .747 -.15(ey b)-.1 H
+(ased).15 E .199(on the number of sharps or \215ats in the k)69.336 490
+R .499 -.15(ey s)-.1 H 2.699(ignature. The).15 F .199
+(shape names must be from the list of pre-de\214ned)2.699 F .845(head s\
+hapes \(norm, xnote, diam, blank, righttri, isostri, rect, pie, semicir\
+c, slash\), or names that you ha)69.336 502 R -.15(ve)-.2 G(gi)69.336
+514 Q -.15(ve)-.25 G 2.5(na).15 G 2.5(st)-2.5 G
+(he \214rst in a pair of strings in the headshapes conte)-2.5 E(xt.)-.15
+E -1.1(Yo)69.336 532 S 2.5(uc)1.1 G
+(an get the most common shaped note system using 4 shapes using:)-2.5 E
+F1(noteheads = "righttri norm rect righttri norm rect diam")105.336 550
+Q F0(There are se)69.336 570 Q -.15(ve)-.25 G
+(ral shaped notes systems using 7 dif).15 E(ferent shapes.)-.25 E
+(One such system is speci\214ed by:)5 E F1
+(noteheads = "isostri semicirc diam righttri norm rect pie")105.336 588
+Q F0 .422
+(Once the noteheads parameter is set, you specify your music just lik)
+69.336 614 R 2.923(ey)-.1 G .423(ou w)-2.923 F .423
+(ould for standard notation, b)-.1 F(ut)-.2 E(Mup will use the appropri\
+ate note heads based on your speci\214cations.)69.336 626 Q EP
+%%Page: 58 64
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-5)274.506 48 S 2.5(8-)-2.5 G/F1 10
+/Courier@0 SF(score)105.336 96 Q(// Use a 7-shaped system.)123.336 108 Q
+(noteheads = "isostri semicirc diam righttri norm rect pie")123.336 120
+Q(// Noteheads are given in order for the major key,)123.336 144 Q
+(// so we'll start out with an example in major.)123.336 156 Q
+(key = d major)123.336 168 Q(music)105.336 192 Q
+(// Do a descending scale in D major)105.336 216 Q(1: d+;c+;b;a;)105.336
+228 Q(bar)105.336 240 Q(1: g;f;e;d;)105.336 264 Q(dblbar)105.336 276 Q
+(score)105.336 300 Q(// Now we switch to D minor, where the "tonic")
+123.336 312 Q(// will start at the rect and then wrap around.)123.336
+324 Q(key = d minor)123.336 336 Q(music)105.336 360 Q
+(// Do a descending scale in D minor)105.336 384 Q(1: d+;c+;b;a;)105.336
+396 Q(bar)105.336 408 Q(1: g;f;e;d;)105.336 432 Q(bar)105.336 444 Q
+111.836 453.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 145 rlineto 352 0 rlineto 0 145 neg rlineto closepath stroke grestore
+EEND 128 618 352 352 -145 145 110.836 598.6 PBEGIN
+%%BeginDocument: mugex60.ps
+%%BoundingBox: 128 618 480 763
+save
+1589393640 1589394394 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+324.29 1091.00 684.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+206.19 743.00 1.000000 sharp
+212.83 734.00 1.000000 sharp
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+235.94 737.00 1.000000 fillisostriangle
+0.70 setlinewidth
+232.04 734.60 moveto
+232.04 716.00 lineto stroke
+261.67 734.00 1.000000 fillpiewedge
+257.77 734.60 moveto
+257.77 713.00 lineto stroke
+287.44 731.00 1.000000 fillrectangle
+283.54 731.00 moveto
+283.54 710.00 lineto stroke
+314.05 728.00 1.000000 4n
+317.73 728.75 moveto
+317.73 749.00 lineto stroke
+restore
+%  S_BAR
+16 linenum
+0.70 setlinewidth
+339.83 743.00 moveto
+339.83 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+351.12 725.00 1.000000 fillrighttriangle
+355.02 725.00 moveto
+355.02 746.00 lineto stroke
+376.85 722.00 1.000000 filldiamond
+380.75 722.00 moveto
+380.75 743.00 lineto stroke
+402.59 719.00 1.000000 fillsemicircle
+406.48 721.40 moveto
+406.48 740.00 lineto stroke
+429.19 716.00 1.000000 fillisostriangle
+433.09 713.60 moveto
+433.09 737.00 lineto stroke
+restore
+%  S_BAR
+18 linenum
+0.70 setlinewidth
+454.01 743.00 moveto
+454.01 719.00 lineto stroke
+457.01 743.00 moveto
+457.01 719.00 lineto stroke
+%  S_SSV
+21 linenum
+%  S_CLEFSIG
+462.26 731.00 1.000000 flat
+%  S_FEED
+288.00 1007.00 684.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+155.79 641.00 1.000000 gclef
+169.33 647.00 1.000000 flat
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+193.08 653.00 1.000000 fillrectangle
+189.18 653.00 moveto
+189.18 632.00 lineto stroke
+225.90 650.00 1.000000 4n
+222.22 649.25 moveto
+222.22 629.00 lineto stroke
+258.69 647.00 1.000000 ufillrighttriangle
+254.79 647.00 moveto
+254.79 626.00 lineto stroke
+292.38 644.00 1.000000 filldiamond
+296.28 644.00 moveto
+296.28 665.00 lineto stroke
+restore
+%  S_BAR
+30 linenum
+0.70 setlinewidth
+324.11 659.00 moveto
+324.11 635.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+336.58 641.00 1.000000 fillsemicircle
+340.48 643.40 moveto
+340.48 662.00 lineto stroke
+369.40 638.00 1.000000 fillisostriangle
+373.30 635.60 moveto
+373.30 659.00 lineto stroke
+402.23 635.00 1.000000 fillpiewedge
+406.12 635.30 moveto
+406.12 656.00 lineto stroke
+435.92 632.00 1.000000 fillrectangle
+439.82 632.00 moveto
+439.82 653.00 lineto stroke
+restore
+%  S_BAR
+33 linenum
+0.70 setlinewidth
+467.65 659.00 moveto
+467.65 635.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 618.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(7.3 Ov)72.836 618.6 R
+(erriding chord note heads)-.14 E 69.336 636.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .151(It is possible to o)71.987 636.6 R -.15
+(ve)-.15 G .151(rride what note shape to use for a chord, by gi).15 F
+.151(ving "hs" follo)-.25 F .151(wed by a head shape name)-.25 F
+(from the headshapes conte)69.336 648.6 Q(xt, inside square brack)-.15 E
+2.5(ets. Thus)-.1 F/F1 10/Courier@0 SF([hs "righttri"])130.336 666.6 Q
+F0 -.1(wo)69.336 686.6 S .095
+(uld use the "righttri" headshape. The speci\214c character to use w).1
+F .096(ould be based on the group')-.1 F 2.596(sd)-.55 G .096
+(uration. In)-2.596 F .078(other w)69.336 698.6 R .078
+(ords, if the chord w)-.1 F .078(as a quarter note or shorter)-.1 F
+2.578(,t)-.4 G .078(he "\214llrighttriangle" note head w)-2.578 F .078
+(ould be used, b)-.1 F .077(ut if)-.2 F 1.151(the chord w)69.336 710.6 R
+1.151(as a half or whole note, a "righttriangle" note head w)-.1 F 1.152
+(ould be used, and a "dwhrighttriangle")-.1 F -.1(wo)69.336 722.6 S
+(uld be used for a double whole note.).1 E(The hs speci\214cation can b\
+e used along with other things that can go in the square brack)69.336
+740.6 Q(ets. F)-.1 E(or e)-.15 E(xample,)-.15 E EP
+%%Page: 59 65
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-5)274.506 48 S 2.5(9-)-2.5 G/F1 10
+/Courier@0 SF([hs "blank"; len 0])130.336 96 Q F0 -.1(wo)69.336 116 S(u\
+ld use blankheads and no stem, resulting in no chord being printed at a\
+ll!).1 E 69.336 134 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(7.4 Ov)72.836 134 R(erriding indi)-.14 E
+(vidual note heads)-.14 E 69.336 152 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .095(If you w)71.931 152 R .095(ant to o)-.1
+F -.15(ve)-.15 G .095(rride the note head shape to be used for one spec\
+i\214c note in a chord, you use hs follo).15 F(wed)-.25 E
+(by the head shape name as a string after the note.)69.336 164 Q/F1 10
+/Courier@0 SF(1: cg e+ hs "diam"; f a hs "x" c+; 2ge+;)105.336 182 Q
+(bar)105.336 194 Q 127.836 203.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 73 rlineto 320 0 rlineto 0 73 neg rlineto closepath stroke grestore
+EEND 160 690 320 320 -73 73 126.836 276.6 PBEGIN
+%%BeginDocument: mugex61.ps
+%%BoundingBox: 160 690 480 763
+save
+1589393640 1589394394 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+324.29 1085.00 684.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 719.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+227.33 734.00 1.000000 filldiamond
+227.55 719.00 1.000000 4n
+227.55 707.00 1.000000 4n
+0.70 setlinewidth
+221.32 707.00 moveto
+233.78 707.00 lineto stroke
+231.23 707.75 moveto
+231.23 755.00 lineto stroke
+293.31 728.00 1.000000 4n
+293.10 722.00 1.000000 xnote
+293.31 716.00 1.000000 4n
+296.99 716.75 moveto
+296.99 749.00 lineto stroke
+364.05 734.00 1.000000 2n
+364.05 719.00 1.000000 2n
+360.15 733.25 moveto
+360.15 698.00 lineto stroke
+restore
+%  S_BAR
+7 linenum
+0.70 setlinewidth
+467.65 737.00 moveto
+467.65 713.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 296.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(7.5 Putting)72.836 296.6 R
+(it all together to use shaped notes)3.5 E 69.336 314.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.867(In summary)73.703 314.6 R 4.367(,n)
+-.65 G 1.868(ote head shapes can be speci\214ed in \214v)-4.367 F 4.368
+(ed)-.15 G(if)-4.368 E 1.868(ferent places: per note, per chord, in v)
+-.25 F(oice)-.2 E(conte)69.336 326.6 Q .14(xt, in staf)-.15 F 2.64(fc)
+-.25 G(onte)-2.64 E .14(xt, and in score conte)-.15 F 2.64(xt. When)-.15
+F .139(deciding what note head shape to use, Mup checks for)2.639 F
+(speci\214cations in that order)69.336 338.6 Q 2.5(,u)-.4 G
+(sing the \214rst it \214nds.)-2.5 E 1.195
+(Since fret numbers are used rather than note heads on tablature staf)
+69.336 356.6 R 1.195(fs, the only head shape name that is)-.25 F(allo)
+69.336 368.6 Q(wed is "allx.")-.25 E(which is used for "muf)5 E
+(\215ed" notes.)-.25 E(Here is a simple e)69.336 386.6 Q
+(xample of shaped notes, using the common 4-shape system.)-.15 E/F1 10
+/Courier@0 SF(score)105.336 404.6 Q
+(noteheads = "righttri norm rect righttri norm rect diam")130.336 416.6
+Q(staffs=4)130.336 428.6 Q(key=2#)130.336 440.6 Q(bracket=1-4)130.336
+452.6 Q(staff 3)105.336 476.6 Q(clef=treble8)130.336 488.6 Q(staff 4)
+105.336 500.6 Q(clef=bass)130.336 512.6 Q(music)105.336 524.6 Q
+(1: 2c+;4d+;e+;)105.336 548.6 Q(2: 2e;4a;f;)105.336 560.6 Q(3: 2e;4f;c;)
+105.336 572.6 Q(4: 2a-;4f-;a-;)105.336 584.6 Q(bar)105.336 596.6 Q
+(1: 1d+;)105.336 620.6 Q(2: 1f;)105.336 632.6 Q(3: 1d;)105.336 644.6 Q
+(4: 1d;)105.336 656.6 Q(endbar)105.336 668.6 Q EP
+%%Page: 60 66
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-6)274.506 48 S 2.5(0-)-2.5 G 163.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 222 rlineto 248 0 rlineto 0 222 neg rlineto closepath stroke grestore
+EEND 200 541 248 248 -222 222 162.836 318 PBEGIN
+%%BeginDocument: mugex62.ps
+%%BoundingBox: 200 541 448 763
+save
+1589393640 1589394394 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_SSV
+10 linenum
+%  S_SSV
+12 linenum
+%  S_FEED
+370.29 1091.00 648.00 5 1.000000 1.000000 stf
+370.29 1037.00 648.00 5 1.000000 1.000000 stf
+370.29 983.00 648.00 5 1.000000 1.000000 stf
+370.29 929.00 648.00 5 1.000000 1.000000 stf
+224.29 746.00 554.00 bracket
+0.70 setlinewidth
+226.29 743.00 moveto
+226.29 557.00 lineto stroke
+%  S_CLEFSIG
+238.08 725.00 1.000000 gclef
+238.08 671.00 1.000000 gclef
+238.08 595.26 moveto
+/Times-Italic findfont
+9 scalefont
+setfont
+(8) show
+238.08 617.00 1.000000 gclef
+238.33 575.00 1.000000 fclef
+252.70 743.00 1.000000 sharp
+259.34 734.00 1.000000 sharp
+252.70 689.00 1.000000 sharp
+259.34 680.00 1.000000 sharp
+252.70 635.00 1.000000 sharp
+259.34 626.00 1.000000 sharp
+252.70 575.00 1.000000 sharp
+259.34 566.00 1.000000 sharp
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+283.74 734.00 1.000000 diamond
+279.84 734.00 moveto
+279.84 713.00 lineto stroke
+314.87 737.00 1.000000 ufillrighttriangle
+310.97 737.00 moveto
+310.97 716.00 lineto stroke
+334.99 740.00 1.000000 4n
+331.31 739.25 moveto
+331.31 719.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+283.74 665.00 1.000000 2n
+0.70 setlinewidth
+287.64 665.75 moveto
+287.64 686.00 lineto stroke
+314.87 674.00 1.000000 4n
+318.55 674.75 moveto
+318.55 695.00 lineto stroke
+334.99 668.00 1.000000 fillrectangle
+338.89 668.00 moveto
+338.89 689.00 lineto stroke
+restore
+%  S_STAFF
+% staff 3
+save
+283.74 611.00 1.000000 2n
+0.70 setlinewidth
+287.64 611.75 moveto
+287.64 632.00 lineto stroke
+314.87 614.00 1.000000 fillrectangle
+318.77 614.00 moveto
+318.77 635.00 lineto stroke
+334.99 605.00 1.000000 filldiamond
+328.55 605.00 moveto
+341.44 605.00 lineto stroke
+338.89 605.00 moveto
+338.89 626.00 lineto stroke
+restore
+%  S_STAFF
+% staff 4
+save
+283.74 560.00 1.000000 2n
+0.70 setlinewidth
+287.64 560.75 moveto
+287.64 581.00 lineto stroke
+314.87 554.00 1.000000 fillrectangle
+318.77 554.00 moveto
+318.77 575.00 lineto stroke
+334.99 560.00 1.000000 4n
+338.68 560.75 moveto
+338.68 581.00 lineto stroke
+restore
+%  S_BAR
+20 linenum
+0.70 setlinewidth
+355.41 743.00 moveto
+355.41 719.00 lineto stroke
+355.41 689.00 moveto
+355.41 665.00 lineto stroke
+355.41 635.00 moveto
+355.41 611.00 lineto stroke
+355.41 581.00 moveto
+355.41 557.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+373.00 737.00 1.000000 urighttriangle
+restore
+%  S_STAFF
+% staff 2
+save
+373.00 668.00 1.000000 rectangle
+restore
+%  S_STAFF
+% staff 3
+save
+373.00 608.00 1.000000 righttriangle
+restore
+%  S_STAFF
+% staff 4
+save
+373.00 569.00 1.000000 urighttriangle
+restore
+%  S_BAR
+25 linenum
+0.70 setlinewidth
+426.50 743.00 moveto
+426.50 719.00 lineto stroke
+3.00 setlinewidth
+430.50 743.00 moveto
+430.50 719.00 lineto stroke
+0.70 setlinewidth
+426.50 689.00 moveto
+426.50 665.00 lineto stroke
+3.00 setlinewidth
+430.50 689.00 moveto
+430.50 665.00 lineto stroke
+0.70 setlinewidth
+426.50 635.00 moveto
+426.50 611.00 lineto stroke
+3.00 setlinewidth
+430.50 635.00 moveto
+430.50 611.00 lineto stroke
+0.70 setlinewidth
+426.50 581.00 moveto
+426.50 557.00 lineto stroke
+3.00 setlinewidth
+430.50 581.00 moveto
+430.50 557.00 lineto stroke
+0.70 setlinewidth
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Italic 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .316(Here is an e)69.336 338 R .316(xam\
+ple of using the same note head shape for all pitches, illustrating ho)
+-.15 F 2.815(wt)-.25 G .315(he proper v)-2.815 F(ersion\212)-.15 E
+(\214lled or open\212of the note head is used, based on the note')69.336
+350 Q 2.5(sd)-.55 G(uration.)-2.5 E EP
+%%Page: 61 67
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-6)274.506 48 S 2.5(1-)-2.5 G/F1 10
+/Courier@0 SF(score)105.336 96 Q(time=8/4)130.336 108 Q
+(beamstyle=2,2,2,2)130.336 120 Q(music)105.336 144 Q(1: 8cf;;4;2;1;)
+105.336 156 Q(bar)105.336 168 Q(score noteheads="isostri")105.336 192 Q
+(music)105.336 204 Q(1: 4ec+;8;;2;1;)105.336 216 Q(bar)105.336 228 Q
+(score noteheads="rect")105.336 252 Q(music)105.336 264 Q
+(1: 1gc+;4;2;8;;)105.336 276 Q(bar)105.336 288 Q(score noteheads="pie")
+105.336 312 Q(music)105.336 324 Q(1: 8cf;;4;2;1;)105.336 336 Q(bar)
+105.336 348 Q(score noteheads="x")105.336 372 Q(music)105.336 384 Q
+(1: 4ec+;8;;2;1;)105.336 396 Q(bar)105.336 408 Q
+(score noteheads="slash")105.336 432 Q(music)105.336 444 Q
+(1: 1gc+;4;2;8;;)105.336 456 Q(bar)105.336 468 Q 111.836 477.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 145 rlineto 352 0 rlineto 0 145 neg rlineto closepath stroke grestore
+EEND 128 618 352 352 -145 145 110.836 622.6 PBEGIN
+%%BeginDocument: mugex63.ps
+%%BoundingBox: 128 618 480 763
+save
+1589393640 1589394394 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+291.00 1091.00 684.00 5 1.000000 1.000000 stf
+/Times-Roman findfont
+12 scalefont
+setfont
+144.00 731.00 moveto
+%  S_CLEFSIG
+158.79 725.00 1.000000 gclef
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+170.58 731.00 moveto
+(8) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+170.58 718.98 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+195.83 722.00 1.000000 4n
+195.83 713.00 1.000000 4n
+0.70 setlinewidth
+189.60 713.00 moveto
+200.56 713.00 lineto stroke
+199.51 713.75 moveto
+199.51 741.50 lineto stroke
+205.90 722.00 1.000000 4n
+205.90 713.00 1.000000 4n
+201.16 713.00 moveto
+210.63 713.00 lineto stroke
+209.58 713.75 moveto
+209.58 741.50 lineto stroke
+216.04 722.00 1.000000 4n
+216.04 713.00 1.000000 4n
+211.31 713.00 moveto
+220.86 713.00 lineto stroke
+219.72 713.75 moveto
+219.72 743.00 lineto stroke
+227.91 722.00 1.000000 2n
+227.91 713.00 1.000000 2n
+222.86 713.00 moveto
+234.36 713.00 lineto stroke
+231.81 713.75 moveto
+231.81 743.00 lineto stroke
+249.80 722.00 1.000000 1n
+249.80 713.00 1.000000 1n
+242.38 713.00 moveto
+257.22 713.00 lineto stroke
+newpath
+199.16 743.00 moveto
+209.93 743.00 lineto
+209.93 740.00 lineto
+199.16 740.00 lineto
+closepath
+fill
+restore
+%  S_BAR
+11 linenum
+0.70 setlinewidth
+281.47 743.00 moveto
+281.47 719.00 lineto stroke
+%  S_SSV
+12 linenum
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+290.26 734.00 1.000000 fillisostriangle
+290.26 719.00 1.000000 fillisostriangle
+294.16 716.60 moveto
+294.16 755.00 lineto stroke
+300.96 734.00 1.000000 fillisostriangle
+300.96 719.00 1.000000 fillisostriangle
+304.86 716.60 moveto
+304.86 753.50 lineto stroke
+311.46 734.00 1.000000 fillisostriangle
+311.46 719.00 1.000000 fillisostriangle
+315.36 716.60 moveto
+315.36 753.50 lineto stroke
+323.32 734.00 1.000000 isostriangle
+323.32 719.00 1.000000 isostriangle
+327.22 716.60 moveto
+327.22 755.00 lineto stroke
+345.21 734.00 1.000000 isostriangle
+345.21 719.00 1.000000 isostriangle
+newpath
+304.51 755.00 moveto
+315.71 755.00 lineto
+315.71 752.00 lineto
+304.51 752.00 lineto
+closepath
+fill
+restore
+%  S_BAR
+16 linenum
+0.70 setlinewidth
+376.72 743.00 moveto
+376.72 719.00 lineto stroke
+%  S_SSV
+17 linenum
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+389.15 734.00 1.000000 rectangle
+389.15 725.00 1.000000 rectangle
+418.08 734.00 1.000000 fillrectangle
+418.08 725.00 1.000000 fillrectangle
+421.98 725.00 moveto
+421.98 755.00 lineto stroke
+430.15 734.00 1.000000 rectangle
+430.15 725.00 1.000000 rectangle
+434.05 725.00 moveto
+434.05 755.00 lineto stroke
+447.48 734.00 1.000000 fillrectangle
+447.48 725.00 1.000000 fillrectangle
+451.38 725.00 moveto
+451.38 753.50 lineto stroke
+458.13 734.00 1.000000 fillrectangle
+458.13 725.00 1.000000 fillrectangle
+462.03 725.00 moveto
+462.03 753.50 lineto stroke
+newpath
+451.03 755.00 moveto
+462.38 755.00 lineto
+462.38 752.00 lineto
+451.03 752.00 lineto
+closepath
+fill
+restore
+%  S_BAR
+21 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  S_SSV
+22 linenum
+%  S_FEED
+288.00 1007.00 684.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+155.79 641.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+181.83 638.00 1.000000 fillpiewedge
+181.83 629.00 1.000000 fillpiewedge
+175.38 629.00 moveto
+186.78 629.00 lineto stroke
+185.73 629.30 moveto
+185.73 657.50 lineto stroke
+192.33 638.00 1.000000 fillpiewedge
+192.33 629.00 1.000000 fillpiewedge
+187.38 629.00 moveto
+197.28 629.00 lineto stroke
+196.23 629.30 moveto
+196.23 657.50 lineto stroke
+202.88 638.00 1.000000 fillpiewedge
+202.88 629.00 1.000000 fillpiewedge
+197.93 629.00 moveto
+207.94 629.00 lineto stroke
+206.77 629.30 moveto
+206.77 659.00 lineto stroke
+215.01 638.00 1.000000 piewedge
+215.01 629.00 1.000000 piewedge
+209.94 629.00 moveto
+221.46 629.00 lineto stroke
+218.91 629.30 moveto
+218.91 659.00 lineto stroke
+237.02 638.00 1.000000 piewedge
+237.02 629.00 1.000000 piewedge
+230.57 629.00 moveto
+243.47 629.00 lineto stroke
+newpath
+185.38 659.00 moveto
+196.58 659.00 lineto
+196.58 656.00 lineto
+185.38 656.00 lineto
+closepath
+fill
+restore
+%  S_BAR
+26 linenum
+0.70 setlinewidth
+268.68 659.00 moveto
+268.68 635.00 lineto stroke
+%  S_SSV
+27 linenum
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+277.48 650.00 1.000000 xnote
+277.48 635.00 1.000000 xnote
+281.38 638.00 moveto
+281.38 671.00 lineto stroke
+288.24 650.00 1.000000 xnote
+288.24 635.00 1.000000 xnote
+292.13 638.00 moveto
+292.13 669.50 lineto stroke
+298.73 650.00 1.000000 xnote
+298.73 635.00 1.000000 xnote
+302.63 638.00 moveto
+302.63 669.50 lineto stroke
+310.61 650.00 1.000000 diamond
+310.61 635.00 1.000000 diamond
+314.51 635.00 moveto
+314.51 671.00 lineto stroke
+332.62 650.00 1.000000 diamond
+332.62 635.00 1.000000 diamond
+newpath
+291.78 671.00 moveto
+302.98 671.00 lineto
+302.98 668.00 lineto
+291.78 668.00 lineto
+closepath
+fill
+restore
+%  S_BAR
+31 linenum
+0.70 setlinewidth
+364.28 659.00 moveto
+364.28 635.00 lineto stroke
+%  S_SSV
+32 linenum
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+378.46 650.00 1.000000 slashhead
+378.46 641.00 1.000000 slashhead
+408.26 650.00 1.000000 fillslashhead
+408.26 641.00 1.000000 fillslashhead
+414.25 646.40 moveto
+414.25 671.00 lineto stroke
+423.96 650.00 1.000000 slashhead
+423.96 641.00 1.000000 slashhead
+430.34 646.40 moveto
+430.34 671.00 lineto stroke
+442.14 650.00 1.000000 fillslashhead
+442.14 641.00 1.000000 fillslashhead
+448.13 646.40 moveto
+448.13 669.50 lineto stroke
+456.81 650.00 1.000000 fillslashhead
+456.81 641.00 1.000000 fillslashhead
+462.80 646.40 moveto
+462.80 669.50 lineto stroke
+newpath
+447.78 671.00 moveto
+463.15 671.00 lineto
+463.15 668.00 lineto
+447.78 668.00 lineto
+closepath
+fill
+restore
+%  S_BAR
+36 linenum
+0.70 setlinewidth
+467.65 659.00 moveto
+467.65 635.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .473(And \214nally)69.336 642.6 R 2.973
+(,h)-.65 G .473(ere is a some)-2.973 F .473(what silly e)-.25 F .474
+(xample that demonstrates ho)-.15 F 2.974(wy)-.25 G .474
+(ou can use the v)-2.974 F .474(arious shaped notes)-.25 F
+(features to get an)69.336 654.6 Q 2.5(yk)-.15 G
+(ind of note head that Mup supports an)-2.5 E(ywhere you w)-.15 E(ant.)
+-.1 E EP
+%%Page: 62 68
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-6)274.506 48 S 2.5(2-)-2.5 G/F1 10
+/Courier@0 SF(headshapes)105.336 96 Q
+(// Make some user-defined head shapes.)130.336 108 Q
+(// These combinations don't really make sense;)130.336 120 Q
+(// they are just to demonstrate what you can do.)130.336 132 Q
+("reg" "4n 2n 2n 2n")130.336 144 Q
+("other" "fillrectangle diamond isostriangle dblwhole")130.336 156 Q
+(score)105.336 180 Q
+(// Set notesheads, using an arbitrary mixture of builtin)130.336 192 Q
+(// and user-defined head shapes.)130.336 204 Q
+(noteheads="norm reg other reg reg other righttri")130.336 216 Q(music)
+105.336 240 Q(1: c;d;2e;)105.336 264 Q(bar)105.336 276 Q(1: 2g;f;)
+105.336 300 Q(bar)105.336 312 Q(1: {b;a;g;}3;2c+;)105.336 336 Q(bar)
+105.336 348 Q(1: 1d;)105.336 372 Q(bar)105.336 384 Q
+(// do some shape overrides, both on group and note)105.336 408 Q
+(1: [ hs "pie" ]2ce; [hs "isostri"] c e g hs "righttri";)105.336 420 Q
+(endbar)105.336 432 Q 103.836 441.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 68 rlineto 368 0 rlineto 0 68 neg rlineto closepath stroke grestore
+EEND 136 692 368 368 -68 68 102.836 509.6 PBEGIN
+%%BeginDocument: mugex64.ps
+%%BoundingBox: 136 692 504 760
+save
+1589393640 1589394394 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_SSV
+12 linenum
+%  S_FEED
+302.69 1080.74 705.60 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+170.48 714.74 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+196.82 702.74 1.000000 4n
+0.70 setlinewidth
+190.59 702.74 moveto
+203.05 702.74 lineto stroke
+200.50 703.49 moveto
+200.50 723.74 lineto stroke
+209.95 705.74 1.000000 4n
+213.63 706.49 moveto
+213.63 726.74 lineto stroke
+225.58 708.74 1.000000 diamond
+229.47 708.74 moveto
+229.47 729.74 lineto stroke
+restore
+%  S_BAR
+20 linenum
+0.70 setlinewidth
+249.05 732.74 moveto
+249.05 708.74 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+259.87 714.74 1.000000 2n
+263.77 715.49 moveto
+263.77 735.74 lineto stroke
+283.66 711.74 1.000000 2n
+287.56 712.49 moveto
+287.56 732.74 lineto stroke
+restore
+%  S_BAR
+23 linenum
+0.70 setlinewidth
+307.14 732.74 moveto
+307.14 708.74 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+315.89 720.74 1.000000 ufillrighttriangle
+311.99 720.74 moveto
+311.99 699.74 lineto stroke
+326.38 717.74 1.000000 fillrectangle
+330.28 717.74 moveto
+330.28 738.74 lineto stroke
+336.66 714.74 1.000000 4n
+340.34 715.49 moveto
+340.34 735.74 lineto stroke
+349.89 723.74 1.000000 2n
+345.99 722.99 moveto
+345.99 702.74 lineto stroke
+/NewCenturySchlbk-BoldItalic findfont
+11 scalefont
+setfont
+323.11 741.73 moveto
+(3) show
+311.64 740.18 moveto
+321.11 744.21 lineto stroke
+331.44 747.26 moveto
+340.69 751.29 lineto stroke
+311.64 740.18 moveto
+311.64 737.18 lineto stroke
+340.69 751.29 moveto
+340.69 748.29 lineto stroke
+restore
+%  S_BAR
+26 linenum
+0.70 setlinewidth
+373.36 732.74 moveto
+373.36 708.74 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+387.88 705.74 1.000000 2n
+restore
+%  S_BAR
+29 linenum
+0.70 setlinewidth
+425.51 732.74 moveto
+425.51 708.74 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+436.33 708.74 1.000000 piewedge
+436.33 702.74 1.000000 piewedge
+429.88 702.74 moveto
+442.78 702.74 lineto stroke
+440.23 703.04 moveto
+440.23 729.74 lineto stroke
+460.13 714.74 1.000000 righttriangle
+460.13 708.74 1.000000 isostriangle
+460.13 702.74 1.000000 isostriangle
+453.68 702.74 moveto
+466.57 702.74 lineto stroke
+464.02 700.34 moveto
+464.02 735.74 lineto stroke
+restore
+%  S_BAR
+32 linenum
+0.70 setlinewidth
+484.10 732.74 moveto
+484.10 708.74 lineto stroke
+3.00 setlinewidth
+488.10 732.74 moveto
+488.10 708.74 lineto stroke
+0.70 setlinewidth
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /NewCenturySchlbk-BoldItalic 
+%%Pages: 2
+%%EndDocument
+end PEND EP
+%%Page: 63 69
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-6)274.506 48 S 2.5(3-)-2.5 G 69.336 103
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(8. TEXT)73.086 103 R(STRINGS)3.75 E
+69.336 121 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF -1.25 -.7(Te x)72.492 121 T 3.156(ts).7 G
+.656(trings are used in man)-3.156 F 3.155(yd)-.15 G(if)-3.155 E .655
+(ferent w)-.25 F 3.155(ays. A)-.1 F(te)3.155 E .655
+(xt string is enclosed in double quotes, and can contain)-.15 F(an)
+69.336 133 Q 2.621(yc)-.15 G .121
+(ombination of letters, numbers, spaces, and punctuation.)-2.621 F .122
+(It can contain a \\n to indicate a ne)5.122 F .122(wline or \\b)-.25 F
+.322(to indicate a backspace, b)69.336 145 R .321
+(ut otherwise cannot contain tabs or other control characters. If you w)
+-.2 F .321(ant a double)-.1 F(quote mark inside a string, it has to be \
+preceded by a backslash, to indicate it is not ending the string:)69.336
+157 Q/F1 10/Courier@0 SF("A \\"word\\" in quotes")105.336 175 Q F0
+(If you w)69.336 201 Q
+(ant an actual backslash in a string, it must be entered as tw)-.1 E 2.5
+(ob)-.1 G(ackslashes.)-2.5 E -1.1(Yo)69.336 219 S 2.5(uc)1.1 G
+(an concatenate strings with a + sign. Thus the follo)-2.5 E
+(wing are equi)-.25 E -.25(va)-.25 G(lent:).25 E F1("this is a string")
+105.336 237 Q("this is " + "a string")105.336 249 Q 69.336 275 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(8.1 Special)72.836 275 R(characters)3.5 E
+69.336 293 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 3.08(As)72.416 293 S .58
+(tring can also contain special music characters.)-3.08 F .58
+(These are speci\214ed by \\\()5.58 F/F1 10/Times-Italic@0 SF(xxx)A F0
+.58(\), where the)B F1(xxx)3.08 E F0 .58(is a code)3.08 F
+(from the follo)69.336 305 Q(wing table:)-.25 E 36.94(type code)94.236
+329 R(music symbol)67.78 E .4 LW 476.436 333.5 94.236 333.5 DL 39.17
+(clef gclef)94.236 343 R 2.5(Gc)66.67 G(lef \(treble clef\))-2.5 E 65.84
+(fclef F)150.896 355 R(clef \(bass clef\))2.5 E 64.73(cclef C)150.896
+367 R(clef \(used for alto clef, tenor clef, etc.\))2.5 E(time sig)
+94.236 391 Q 66.94(com common)24.71 F(time)2.5 E 71.94(cut cut)150.896
+403 R(time)2.5 E 13.62(accidental \215at)94.236 427 R(\215at)73.88 E
+58.6(dbl\215at double)150.896 439 R(\215at)2.5 E 62.5(sharp sharp)
+150.896 451 R 49.72(dblsharp double)150.896 463 R(sharp)2.5 E 71.94
+(nat natural)150.896 475 R 36.94(note 4n)94.236 499 R
+(quarter \(and shorter\) note head)76.66 E 74.16(2n half)150.896 511 R
+(note head)2.5 E 74.16(1n whole)150.896 523 R(note)2.5 E(dbl)150.896 535
+Q 47.04(whole double)-.1 F(whole note)2.5 E 64.16(dn2n half)150.896 547
+R(note with stem do)2.5 E(wn)-.25 E 64.16(dn4n quarter)150.896 559 R
+(note with stem do)2.5 E(wn)-.25 E 64.16(dn8n eighth)150.896 571 R
+(note with stem do)2.5 E(wn)-.25 E 59.16(dn16n 16th)150.896 583 R
+(note with stem do)2.5 E(wn)-.25 E 59.16(dn32n 32nd)150.896 595 R
+(note with stem do)2.5 E(wn)-.25 E 59.16(dn64n 64th)150.896 607 R
+(note with stem do)2.5 E(wn)-.25 E 54.16(dn128n 128th)150.896 619 R
+(note with stem do)2.5 E(wn)-.25 E 54.16(dn256n 256th)150.896 631 R
+(note with stem do)2.5 E(wn)-.25 E 64.16(up2n half)150.896 643 R
+(note with stem up)2.5 E 64.16(up4n quarter)150.896 655 R
+(note with stem up)2.5 E 64.16(up8n eighth)150.896 667 R
+(note with stem up)2.5 E 59.16(up16n 16th)150.896 679 R
+(note with stem up)2.5 E 59.16(up32n 32nd)150.896 691 R
+(note with stem up)2.5 E 59.16(up64n 64th)150.896 703 R
+(note with stem up)2.5 E 54.16(up128n 128th)150.896 715 R
+(note with stem up)2.5 E 54.16(up256n 256th)150.896 727 R
+(note with stem up)2.5 E EP
+%%Page: 64 70
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-6)274.506 48 S 2.5(4-)-2.5 G 59.16
+(up\215ag upw)150.896 96 R(ard \215ag)-.1 E 59.16(dn\215ag do)150.896
+108 R(wnw)-.25 E(ard \215ag)-.1 E(notehead)94.236 132 Q 61.94
+(xnote X-shaped)150.896 144 R(note head)2.5 E 49.16(diamond open)150.896
+156 R(diamond-shaped note head)2.5 E 38.04(\214lldiamond \214lled)
+150.896 168 R(diamond-shaped note head)2.5 E 31.94(dwhdiamond double)
+150.896 180 R(whole diamond-shaped note)2.5 E 38.05(isostriangle open)
+150.896 192 R(isosceles triangle notehead)2.5 E 26.93
+(\214llisostriangle \214lled)150.896 204 R(isosceles triangle notehead)
+2.5 E 20.83(dwhisostriangle double)150.896 216 R
+(whole isosceles triangle notehead)2.5 E(pie)150.896 228 Q 46.09
+(wedge open)-.25 F(pie)2.5 E(wedge notehead)-.25 E(\214llpie)150.896 240
+Q 34.97(wedge \214lled)-.25 F(pie)2.5 E(wedge notehead)-.25 E(dwhpie)
+150.896 252 Q 28.87(wedge double)-.25 F(whole pie)2.5 E(wedge notehead)
+-.25 E 47.51(rectangle open)150.896 264 R(rectangle notehead)2.5 E 36.39
+(\214llrectangle \214lled)150.896 276 R(rectangle notehead)2.5 E 30.29
+(dwhrectangle double)150.896 288 R(whole rectangle notehead)2.5 E 34.72
+(righttriangle open)150.896 300 R(right triangle notehead)2.5 E 23.6
+(\214llrighttriangle \214lled)150.896 312 R(right triangle notehead)2.5
+E 17.5(dwhrighttriangle double)150.896 324 R
+(whole right triangle notehead)2.5 E 29.72(urighttriangle upside-do)
+150.896 336 R(wn open right triangle notehead)-.25 E 18.6
+(u\214llrighttriangle upside-do)150.896 348 R
+(wn \214lled right triangle notehead)-.25 E 12.5
+(udwhrighttriangle upside-do)150.896 360 R
+(wn double whole right triangle notehead)-.25 E 43.06(semicircle open)
+150.896 372 R(semicircle notehead)2.5 E 31.94(\214llsemicircle \214lled)
+150.896 384 R(semicircle notehead)2.5 E 25.84(dwhsemicircle double)
+150.896 396 R(whole semicircle notehead)2.5 E 45.28(slashhead open)
+150.896 408 R(slash notehead)2.5 E 34.16(\214llslashhead \214lled)
+150.896 420 R(slash notehead)2.5 E 28.06(dwhslashhead double)150.896 432
+R(whole slash notehead)2.5 E 43.06(blankhead blank)150.896 444 R
+(notehead)2.5 E 39.72(rest qwhrest)94.236 468 R(quadruple whole rest)55
+E 52.5(dwhrest double)150.896 480 R(whole rest)2.5 E 64.72(1rest whole)
+150.896 492 R(rest)2.5 E 64.72(2rest half)150.896 504 R(rest)2.5 E 64.72
+(4rest quarter)150.896 516 R(rest)2.5 E 64.72(8rest eighth)150.896 528 R
+(rest)2.5 E 59.72(16rest sixteenth)150.896 540 R(rest)2.5 E 59.72
+(32rest thirty-second)150.896 552 R(rest)2.5 E 59.72
+(64rest sixty-fourth)150.896 564 R(rest)2.5 E 54.72(128rest 128th)
+150.896 576 R(rest)2.5 E 54.72(256rest 256th)150.896 588 R(rest)2.5 E
+32.5(pedal be)94.236 612 R 55.43(gped be)-.15 F(gin pedal mark)-.15 E
+55.28(endped end)150.896 624 R(pedal mark)2.5 E 62.5(pedal pedal)150.896
+636 R(up/do)2.5 E(wn mark)-.25 E 12.5(ornaments tr)94.236 660 R(trill)
+80.55 E 68.05(mor mordent)150.896 672 R(in)150.896 684 Q 55.67(vmor in)
+-.4 F -.15(ve)-.4 G(rted mordent).15 E 68.05(turn turn)150.896 696 R(in)
+150.896 708 Q 55.67(vturn in)-.4 F -.15(ve)-.4 G(rted turn).15 E EP
+%%Page: 65 71
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-6)274.506 48 S 2.5(5-)-2.5 G 35.27
+(misc ferm)94.236 96 R(fermata)67.78 E 60.28(uferm upside-do)150.896 108
+R(wn fermata)-.25 E 58.06(acc_gt accent)150.896 120 R(lik)2.5 E 2.5(eag)
+-.1 G(reater)-2.5 E(-than sign)-.2 E 53.62(acc_hat accent)150.896 132 R
+(lik)2.5 E 2.5(ea")-.1 G(hat" \(circum\215e)-2.5 E 2.5(xo)-.15 G 2.5(r")
+-2.5 G(up-arro)-2.5 E(w"\))-.25 E 48.62(acc_uhat accent)150.896 144 R
+(lik)2.5 E 2.5(ea)-.1 G 2.5(nu)-2.5 G(pside do)-2.5 E(wn hat)-.25 E(le)
+150.896 156 Q 74.59(gl)-.15 G -2.25 -.15(eg a)-74.59 H(to mark).15 E
+71.38(dot dot)150.896 168 R 58.06(wedge wedge)150.896 180 R 53.06
+(uwedge upside-do)150.896 192 R(wn wedge)-.25 E 67.49(sign sign)150.896
+204 R(for D. S.)2.5 E 65.28(coda coda)150.896 216 R(mark)2.5 E(upbo)
+150.896 228 Q 59.69(wu)-.25 G 2.5(pb)-59.69 G -.25(ow)-2.5 G(dnbo)
+150.896 240 Q 59.69(wd)-.25 G -.25(ow)-59.69 G 2.5(nb).25 G -.25(ow)-2.5
+G 77.5(rr "railroad)150.896 252 R
+(tracks" or caesura \(2 slanted lines sometimes put)2.5 E
+(at the top of a staf)237.556 264 Q 2.5(ft)-.25 G 2.5(oi)-2.5 G
+(ndicate the end of a musical thought\))-2.5 E 52.5(measrpt measure)
+150.896 276 R(repeat)2.5 E(cop)150.896 288 Q 45.93(yright C-in-circle)
+-.1 F(cop)2.5 E(yright symbol)-.1 E 68.6(dim diminished)150.896 300 R
+53.05(halfdim half)150.896 312 R(diminished)2.5 E 53.61
+(triangle triangle)150.896 324 R EP
+%%Page: 66 72
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-6)274.506 48 S 2.5(6-)-2.5 G 70 157 443 443
+-589 589 62.836 712.6 PBEGIN
+%%BeginDocument: muschar.ps
+%%BoundingBox: 70 157 513 746
+/boxheight 62 def
+/boxwidth 40 def
+/nameheight 10 def
+/tmpstring 50 string def
+/flagsep 1.6 300 mul def
+
+/Times-Roman findfont nameheight 2 sub scalefont setfont
+/prm {
+       /yoff exch def
+       /xoff exch def
+       /sym exch def
+       /name sym tmpstring cvs def
+       /realboxheight boxheight extra add def
+
+       save
+       xoff yoff translate
+
+       % draw box
+       newpath
+       0 0 moveto
+       boxwidth 0 lineto
+       boxwidth realboxheight lineto
+       0 realboxheight lineto
+       closepath
+       stroke
+
+       % print name of music character
+       gsave
+       nameheight 4 sub
+       realboxheight name stringwidth pop sub 2 div 4 add moveto
+       55 rotate
+       0 0.25 0.75 setrgbcolor
+       name show
+       grestore
+       % display the music character
+       boxwidth 2 div nameheight add
+       realboxheight nameheight sub 2 div
+       1.0 sym cvx exec
+       restore
+} def
+
+/offset 72 def
+/col 0 def
+/row 11 def
+/extra 0 def
+/extraoffset 0 def
+
+% go to next display slot on the page and show one music character
+/showone {
+       col boxwidth mul offset add row boxheight mul
+               extra sub extraoffset sub prm
+       /col col 1 add def
+       % go to next column when current one is full
+       col 11 ge { /col 0 def /row row 1 sub def } if
+       % one row has to be extra tall
+       row 5 eq { /extra 28 def } if
+       row 4 eq { /extraoffset 28 def /extra 0 def } if
+} def
+
+/gclef  showone
+/fclef  showone
+/cclef  showone
+/dblwhole  showone
+/1n  showone
+/2n  showone
+/4n  showone
+/upflag  showone
+/dnflag  showone
+/qwhrest  showone
+/dwhrest  showone
+/1rest  showone
+/2rest  showone
+/4rest  showone
+/8rest  showone
+/16rest  showone
+/32rest  showone
+/64rest  showone
+/128rest  showone
+/256rest  showone
+/ll1rest  showone
+/ll2rest  showone
+/dot  showone
+/nat  showone
+/sharp  showone
+/flat  showone
+/dblsharp  showone
+/dblflat  showone
+/xnote  showone
+/dwhdiamond  showone
+/diamond  showone
+/filldiamond  showone
+/up2n  showone
+/dn2n  showone
+/up4n  showone
+/dn4n  showone
+/com  showone
+/cut  showone
+/begped  showone
+/pedal  showone
+/endped  showone
+/dnbow  showone
+/upbow  showone
+/wedge  showone
+/uwedge  showone
+/ferm  showone
+/uferm  showone
+/sign  showone
+/coda  showone
+/mor  showone
+/invmor  showone
+/turn  showone
+/invturn  showone
+/acc_gt  showone
+/acc_hat  showone
+/acc_uhat  showone
+/tr  showone
+/leg  showone
+/rr  showone
+/dim  showone
+/halfdim  showone
+/triangle  showone
+/measrpt  showone
+/copyright  showone
+/up8n  showone
+/dn8n  showone
+/up16n  showone
+/dn16n  showone
+/up32n  showone
+/dn32n  showone
+/up64n  showone
+/dn64n  showone
+/up128n  showone
+/dn128n  showone
+/up256n  showone
+/dn256n  showone
+/dwhrighttriangle  showone
+/righttriangle  showone
+/fillrighttriangle  showone
+/udwhrighttriangle  showone
+/urighttriangle  showone
+/ufillrighttriangle  showone
+/dwhrectangle  showone
+/rectangle  showone
+/fillrectangle  showone
+/dwhisostriangle  showone
+/isostriangle  showone
+/fillisostriangle  showone
+/dwhpiewedge  showone
+/piewedge  showone
+/fillpiewedge  showone
+/dwhsemicircle  showone
+/semicircle  showone
+/fillsemicircle  showone
+/dwhslashhead  showone
+/slashhead  showone
+/fillslashhead  showone
+/blankhead  showone
+showpage
+%%EndDocument
+end PEND EP
+%%Page: 67 73
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-6)274.506 48 S 2.5(7-)-2.5 G(An)69.336 96 Q
+2.914(yo)-.15 G 2.914(ft)-2.914 G .414
+(hese music character names can be pre\214x)-2.914 F .414
+(ed by "sm" to indicate a smaller v)-.15 F .413(ersion of the character)
+-.15 F(.)-.55 E -.15(Fo)69.336 108 S 2.99(re).15 G .49(xample, "smup4n"\
+ is a small quarter note, as might be used for a "cue" note.)-3.14 F .49
+(Small music characters)5.49 F(are 0.65 times as big as re)69.336 120 Q
+(gular characters.)-.15 E -1.11(Va)69.336 138 S 1.226
+(rious non-ASCII characters can be included in te)1.11 F 1.226
+(xt strings. If you ha)-.15 F 1.526 -.15(ve a n)-.2 H 1.226
+(on-United States k).15 F -.15(ey)-.1 G(board).15 E 1.042
+(which can produce characters listed in the table belo)69.336 150 R
+3.542(wf)-.25 G 1.042(rom the "Latin-1" alphabet, you can simply type)
+-3.542 F .386(them into strings as you normally w)69.336 162 R .386
+(ould. If you w)-.1 F .386(ant a character that your k)-.1 F -.15(ey)-.1
+G .386(board does not support, you).15 F .182(can put them in strings b\
+y using their names in a manner similar to the music characters.)69.336
+174 R -.15(Fo)5.182 G 2.683(re).15 G .183(xample, you)-2.833 F .085(can\
+ include an 'a' with an acute accent on it in a string by using \\\(aac\
+ute\), or an upside do)69.336 186 R .084(wn question mark)-.25 F .042
+(using \\\(questiondo)69.336 198 R .042(wn\). Man)-.25 F 2.542(yc)-.15 G
+.042(haracters ha)-2.542 F .342 -.15(ve s)-.2 H .043
+(horthand names too.).15 F -.15(Fo)5.043 G 2.543(re).15 G .043
+(xample, \\\(a'\) is a shorter name for)-2.693 F 1.027
+('a' with an acute accent.)69.336 210 R 1.027(The full names of the spe\
+cial characters and their shorthand names, if an)6.027 F 2.326 -.65
+(y, a)-.15 H(re).65 E(gi)69.336 222 Q -.15(ve)-.25 G 2.5(ni).15 G 2.5
+(nt)-2.5 G(he follo)-2.5 E(wing table:)-.25 E 109.336 225.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 500 rlineto 357 0 rlineto 0 500 neg rlineto closepath stroke grestore
+EEND 53 36 357 357 -500 500 108.336 725.6 PBEGIN
+%%BeginDocument: extchar.ps
+%%BoundingBox: 53 36 410 536
+makeExtEncoding
+/Ext-Times-Roman /Times-Roman makeExtendedFont
+save
+0.5 setgray
+230 36 moveto 0 500 rlineto stroke
+235 36 moveto 0 500 rlineto stroke
+0 setgray
+0.75 0.75 scale
+%start of code for extchar table
+/Ext-Times-Roman findfont
+12 scalefont
+setfont
+85 700 moveto
+( ) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 700 moveto
+(exclamdown) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 700 moveto
+(.) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 700 moveto
+(questiondown) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 686 moveto
+(") show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 686 moveto
+(sterling) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 686 moveto
+(#) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 686 moveto
+(yen) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 672 moveto
+($) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 672 moveto
+(quotedblleft) show
+250 672 moveto
+(\301\301) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 672 moveto
+(-) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 672 moveto
+(quotedblright) show
+520 672 moveto
+(\302\302) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 658 moveto
+(%) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 658 moveto
+(guillemotleft) show
+250 658 moveto
+(<<) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 658 moveto
+(&) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 658 moveto
+(guillemotright) show
+520 658 moveto
+(>>) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 644 moveto
+(') show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 644 moveto
+(guilsinglleft) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 644 moveto
+(\() show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 644 moveto
+(guilsinglright) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 630 moveto
+(\)) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 630 moveto
+(dagger) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 630 moveto
+(*) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 630 moveto
+(daggerdbl) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 616 moveto
+(/) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 616 moveto
+(grave) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 616 moveto
+(0) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 616 moveto
+(acute) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 602 moveto
+(1) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 602 moveto
+(macron) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 602 moveto
+(2) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 602 moveto
+(breve) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 588 moveto
+(3) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 588 moveto
+(dotaccent) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 588 moveto
+(4) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 588 moveto
+(dieresis) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 574 moveto
+(5) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 574 moveto
+(ring) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 574 moveto
+(6) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 574 moveto
+(cedilla) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 560 moveto
+(7) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 560 moveto
+(hungarumlaut) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 560 moveto
+(8) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 560 moveto
+(ogonek) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 546 moveto
+(9) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 546 moveto
+(caron) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 546 moveto
+(:) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 546 moveto
+(emdash) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 532 moveto
+(;) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 532 moveto
+(AE) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 532 moveto
+(<) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 532 moveto
+(ae) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 518 moveto
+(=) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 518 moveto
+(ordfeminine) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 518 moveto
+(>) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 518 moveto
+(ordmasculine) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 504 moveto
+(?) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 504 moveto
+(Lslash) show
+250 504 moveto
+(L/) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 504 moveto
+(@) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 504 moveto
+(lslash) show
+520 504 moveto
+(l/) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 490 moveto
+(A) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 490 moveto
+(Oslash) show
+250 490 moveto
+(O/) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 490 moveto
+(B) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 490 moveto
+(oslash) show
+520 490 moveto
+(o/) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 476 moveto
+(C) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 476 moveto
+(OE) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 476 moveto
+(D) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 476 moveto
+(oe) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 462 moveto
+(E) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 462 moveto
+(dotlessi) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 462 moveto
+(F) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 462 moveto
+(germandbls) show
+520 462 moveto
+(ss) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 448 moveto
+(G) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 448 moveto
+(Aacute) show
+250 448 moveto
+(A') show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 448 moveto
+(H) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 448 moveto
+(aacute) show
+520 448 moveto
+(a') show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 434 moveto
+(I) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 434 moveto
+(Acircumflex) show
+250 434 moveto
+(A^) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 434 moveto
+(J) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 434 moveto
+(acircumflex) show
+520 434 moveto
+(a^) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 420 moveto
+(K) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 420 moveto
+(Adieresis) show
+250 420 moveto
+(A:) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 420 moveto
+(L) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 420 moveto
+(adieresis) show
+520 420 moveto
+(a:) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 406 moveto
+(M) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 406 moveto
+(Agrave) show
+250 406 moveto
+(A`) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 406 moveto
+(N) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 406 moveto
+(agrave) show
+520 406 moveto
+(a`) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 392 moveto
+(O) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 392 moveto
+(Aring) show
+250 392 moveto
+(Ao) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 392 moveto
+(P) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 392 moveto
+(aring) show
+520 392 moveto
+(ao) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 378 moveto
+(Q) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 378 moveto
+(Atilde) show
+250 378 moveto
+(A~) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 378 moveto
+(R) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 378 moveto
+(atilde) show
+520 378 moveto
+(a~) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 364 moveto
+(S) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 364 moveto
+(Ccedilla) show
+250 364 moveto
+(C,) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 364 moveto
+(T) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 364 moveto
+(ccedilla) show
+520 364 moveto
+(c,) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 350 moveto
+(U) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 350 moveto
+(Eacute) show
+250 350 moveto
+(E') show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 350 moveto
+(V) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 350 moveto
+(eacute) show
+520 350 moveto
+(e') show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 336 moveto
+(W) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 336 moveto
+(Ecircumflex) show
+250 336 moveto
+(E^) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 336 moveto
+(X) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 336 moveto
+(ecircumflex) show
+520 336 moveto
+(e^) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 322 moveto
+(Y) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 322 moveto
+(Edieresis) show
+250 322 moveto
+(E:) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 322 moveto
+(Z) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 322 moveto
+(edieresis) show
+520 322 moveto
+(e:) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 308 moveto
+([) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 308 moveto
+(Egrave) show
+250 308 moveto
+(E`) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 308 moveto
+(\\) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 308 moveto
+(egrave) show
+520 308 moveto
+(e`) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 294 moveto
+(]) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 294 moveto
+(Iacute) show
+250 294 moveto
+(I') show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 294 moveto
+(^) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 294 moveto
+(iacute) show
+520 294 moveto
+(i') show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 280 moveto
+(_) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 280 moveto
+(Icircumflex) show
+250 280 moveto
+(I^) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 280 moveto
+(`) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 280 moveto
+(icircumflex) show
+520 280 moveto
+(i^) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 266 moveto
+(a) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 266 moveto
+(Idieresis) show
+250 266 moveto
+(I:) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 266 moveto
+(b) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 266 moveto
+(idieresis) show
+520 266 moveto
+(i:) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 252 moveto
+(c) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 252 moveto
+(Igrave) show
+250 252 moveto
+(I`) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 252 moveto
+(d) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 252 moveto
+(igrave) show
+520 252 moveto
+(i`) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 238 moveto
+(e) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 238 moveto
+(Ntilde) show
+250 238 moveto
+(N~) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 238 moveto
+(f) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 238 moveto
+(ntilde) show
+520 238 moveto
+(n~) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 224 moveto
+(g) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 224 moveto
+(Oacute) show
+250 224 moveto
+(O') show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 224 moveto
+(h) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 224 moveto
+(oacute) show
+520 224 moveto
+(o') show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 210 moveto
+(i) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 210 moveto
+(Ocircumflex) show
+250 210 moveto
+(O^) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 210 moveto
+(j) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 210 moveto
+(ocircumflex) show
+520 210 moveto
+(o^) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 196 moveto
+(k) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 196 moveto
+(Odieresis) show
+250 196 moveto
+(O:) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 196 moveto
+(l) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 196 moveto
+(odieresis) show
+520 196 moveto
+(o:) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 182 moveto
+(m) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 182 moveto
+(Ograve) show
+250 182 moveto
+(O`) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 182 moveto
+(n) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 182 moveto
+(ograve) show
+520 182 moveto
+(o`) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 168 moveto
+(o) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 168 moveto
+(Otilde) show
+250 168 moveto
+(O~) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 168 moveto
+(p) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 168 moveto
+(otilde) show
+520 168 moveto
+(o~) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 154 moveto
+(q) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 154 moveto
+(Scaron) show
+250 154 moveto
+(Sv) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 154 moveto
+(r) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 154 moveto
+(scaron) show
+520 154 moveto
+(sv) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 140 moveto
+(s) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 140 moveto
+(Uacute) show
+250 140 moveto
+(U') show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 140 moveto
+(t) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 140 moveto
+(uacute) show
+520 140 moveto
+(u') show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 126 moveto
+(u) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 126 moveto
+(Ucircumflex) show
+250 126 moveto
+(U^) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 126 moveto
+(v) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 126 moveto
+(ucircumflex) show
+520 126 moveto
+(u^) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 112 moveto
+(w) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 112 moveto
+(Udieresis) show
+250 112 moveto
+(U:) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 112 moveto
+(x) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 112 moveto
+(udieresis) show
+520 112 moveto
+(u:) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 98 moveto
+(y) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 98 moveto
+(Ugrave) show
+250 98 moveto
+(U`) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 98 moveto
+(z) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 98 moveto
+(ugrave) show
+520 98 moveto
+(u`) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 84 moveto
+({) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 84 moveto
+(Ydieresis) show
+250 84 moveto
+(Y:) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 84 moveto
+(|) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 84 moveto
+(ydieresis) show
+520 84 moveto
+(y:) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 70 moveto
+(}) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 70 moveto
+(Zcaron) show
+250 70 moveto
+(Zv) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+355 70 moveto
+(~) show
+/Times-Roman findfont
+15 scalefont
+setfont
+415 70 moveto
+(zcaron) show
+520 70 moveto
+(zv) show
+/Ext-Times-Roman findfont
+15 scalefont
+setfont
+85 56 moveto
+(+) show
+/Times-Roman findfont
+15 scalefont
+setfont
+145 56 moveto
+(bullet) show
+%end of code for extchar table
+showpage
+restore
+%%Pages: 2
+%%EndDocument
+end PEND EP
+%%Page: 68 74
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-6)274.506 48 S 2.5(8-)-2.5 G .586(There is\
+ one additional special characters, speci\214ed by \\\(space\).)69.336
+96 R .587(This character appears as a normal space)5.587 F .655
+(on output, b)69.336 108 R .655(ut is not treated lik)-.2 F 3.155(eas)
+-.1 G .655(pace when Mup is looking for w)-3.155 F .654
+(ord or syllable boundaries.)-.1 F .654(The most)5.654 F 1.864
+(common use for this is probably in lyrics when you w)69.336 120 R 1.864
+(ant se)-.1 F -.15(ve)-.25 G 1.864(ral w).15 F 1.865
+(ords to be sung on a single note.)-.1 F .227(Another use w)69.336 132 R
+.227(ould be in cases where Mup w)-.1 F .226
+(ould normally split up a long string between w)-.1 F .226
+(ords in order to)-.1 F -.2(avo)69.336 144 S(id running of).2 E 2.5(ft)
+-.25 G(he edge of a page, b)-2.5 E(ut you w)-.2 E(ant to pre)-.1 E -.15
+(ve)-.25 G(nt that split.).15 E 69.336 162 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(8.2 F)72.836 162 R(ont and size changes)
+-.35 E 69.336 180 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .097(Strings can also contain special codes\
+ to indicate changes in font or size.)71.933 180 R .097
+(The font codes be)5.097 F .097(gin with \\f, and)-.15 F 1.403
+(can either be spelled out, as in the \214rst column of the table belo)
+69.336 192 R 2.702 -.65(w, o)-.25 H 3.902(ra).65 G 3.902(st)-3.902 G
+1.402(he abbre)-3.902 F 1.402(viations gi)-.25 F -.15(ve)-.25 G 3.902
+(ni).15 G 3.902(nt)-3.902 G(he)-3.902 E(second column.)69.336 204 Q
+51.39(Code Abbr)153.626 222 R(Meaning)93.105 E .4 LW 452.606 226.5
+118.066 226.5 DL(\\f\(a)118.066 236 Q -.25(va)-.2 G(ntg).25 E
+(arde rom\))-.05 E 13.05(\\f\(AR\) change)32.48 F(to)2.5 E/F1 10
+/AvantGarde-Book@0 SF -1.67 -.7(Av a)2.5 H(nt Gar).7 E(de r)-.06 E(om)
+-.2 E(an f)-.2 E(ont)-.4 E F0(\\f\(a)118.066 248 Q -.25(va)-.2 G(ntg).25
+E(arde bold\))-.05 E 13.05(\\f\(AB\) change)30.81 F(to)2.5 E/F2 10
+/AvantGarde-Demi@0 SF -1.7 -.7(Av a)2.5 H(nt Gar).7 E(de bold f)-.06 E
+(ont)-.2 E F0(\\f\(a)118.066 260 Q -.25(va)-.2 G(ntg).25 E(arde ital\))
+-.05 E 16.39(\\f\(AI\) change)35.81 F(to)2.5 E/F3 10
+/AvantGarde-BookOblique@0 SF -1.67 -.7(Av a)2.5 H(nt Gar).7 E
+(de italic f)-.06 E(ont)-.4 E F0(\\f\(a)118.066 272 Q -.25(va)-.2 G(ntg)
+.25 E(arde boldital\))-.05 E 12.5(\\f\(AX\) change)18.03 F(to)2.5 E/F4
+10/AvantGarde-DemiOblique@0 SF -1.7 -.7(Av a)2.5 H(nt Gar).7 E
+(de bold-italic f)-.06 E(ont)-.2 E 452.606 276.5 118.066 276.5 DL F0
+(\\f\(bookman rom\))118.066 286 Q 13.6(\\f\(BR\) change)38.63 F(to)2.5 E
+/F5 10/Bookman-Light@0 SF(Bookman r)2.5 E(oman font).08 E F0
+(\\f\(bookman bold\))118.066 298 Q 13.6(\\f\(BB\) change)36.96 F(to)2.5
+E/F6 10/Bookman-Demi@0 SF(Bookman bold font)2.5 E F0
+(\\f\(bookman ital\))118.066 310 Q 16.94(\\f\(BI\) change)41.96 F(to)2.5
+E/F7 10/Bookman-LightItalic@0 SF(Bookman italic font)2.5 E F0
+(\\f\(bookman boldital\))118.066 322 Q 13.05(\\f\(BX\) change)24.18 F
+(to)2.5 E/F8 10/Bookman-DemiItalic@0 SF(Bookman bold-italic font)2.5 E
+452.606 326.5 118.066 326.5 DL F0(\\f\(courier rom\))118.066 336 Q 13.6
+(\\f\(CR\) change)47.53 F(to)2.5 E/F9 10/Courier@0 SF
+(Courier roman font)2.5 E F0(\\f\(courier bold\))118.066 348 Q 13.6
+(\\f\(CB\) change)45.86 F(to)2.5 E/F10 10/Courier-Bold@0 SF
+(Courier bold font)2.5 E F0(\\f\(courier ital\))118.066 360 Q 16.94
+(\\f\(CI\) change)50.86 F(to)2.5 E/F11 10/Courier-Oblique@0 SF
+(Courier italic font)2.5 E F0(\\f\(courier boldital\))118.066 372 Q
+13.05(\\f\(CX\) change)33.08 F(to)2.5 E/F12 10/Courier-BoldOblique@0 SF
+(Courier bold-italic font)2.5 E 452.606 376.5 118.066 376.5 DL F0
+(\\f\(helv)118.066 386 Q(etica rom\))-.15 E 13.05(\\f\(HR\) change)39.9
+F(to)2.5 E/F13 10/Helvetica@0 SF(Helv)2.5 E(etica* roman f)-.25 E(ont)
+-.3 E F0(\\f\(helv)118.066 398 Q(etica bold\))-.15 E 13.05
+(\\f\(HB\) change)38.23 F(to)2.5 E/F14 10/Helvetica-Bold@0 SF
+(Helvetica bold f)2.5 E(ont)-.2 E F0(\\f\(helv)118.066 410 Q
+(etica ital\))-.15 E 16.39(\\f\(HI\) change)43.23 F(to)2.5 E/F15 10
+/Helvetica-Oblique@0 SF(Helv)2.5 E(etica italic f)-.25 E(ont)-.3 E F0
+(\\f\(helv)118.066 422 Q(etica boldital\))-.15 E 12.5(\\f\(HX\) change)
+25.45 F(to)2.5 E/F16 10/Helvetica-BoldOblique@0 SF
+(Helvetica bold-italic f)2.5 E(ont)-.2 E 452.606 426.5 118.066 426.5 DL
+F0(\\f\(ne)118.066 436 Q(wcentury rom\))-.25 E 13.05(\\f\(NR\) change)
+29.45 F(to)2.5 E/F17 10/NewCenturySchlbk-Roman@0 SF
+(New Century roman font)2.5 E F0(\\f\(ne)118.066 448 Q(wcentury bold\))
+-.25 E 13.05(\\f\(NB\) change)27.78 F(to)2.5 E/F18 10
+/NewCenturySchlbk-Bold@0 SF(New Century bold font)2.5 E F0(\\f\(ne)
+118.066 460 Q(wcentury ital\))-.25 E 16.39(\\f\(NI\) change)32.78 F(to)
+2.5 E/F19 10/NewCenturySchlbk-Italic@0 SF(New Century italic f)2.5 E
+(ont)-.1 E F0(\\f\(ne)118.066 472 Q(wcentury boldital\))-.25 E 12.5
+(\\f\(NX\) change)15 F(to)2.5 E/F20 10/NewCenturySchlbk-BoldItalic@0 SF
+(Ne)2.5 E 2.87(wC)-.15 G(entur)-2.87 E 2.87(yb)-.2 G(old-italic)-2.87 E
+452.606 476.5 118.066 476.5 DL F0(\\f\(palatino rom\))118.066 486 Q
+14.71(\\f\(PR\) change)43.63 F(to)2.5 E/F21 10/Palatino-Roman@0 SF
+(Palatino r)2.5 E(oman font)-.18 E F0(\\f\(palatino bold\))118.066 498 Q
+14.71(\\f\(PB\) change)41.96 F(to)2.5 E/F22 10/Palatino-Bold@0 SF
+(Palatino bold font)2.5 E F0(\\f\(palatino ital\))118.066 510 Q 18.05
+(\\f\(PI\) change)46.96 F(to)2.5 E/F23 10/Palatino-Italic@0 SF
+(Palatino italic font)2.5 E F0(\\f\(palatino boldital\))118.066 522 Q
+14.16(\\f\(PX\) change)29.18 F(to)2.5 E/F24 10/Palatino-BoldItalic@0 SF
+(Palatino bold-italic font)2.5 E 452.606 526.5 118.066 526.5 DL F0
+(\\f\(times rom\))118.066 536 Q 14.16(\\f\(TR\) change)54.18 F(to T)2.5
+E(imes* roman font)-.35 E(\\f\(times bold\))118.066 548 Q 14.16
+(\\f\(TB\) change)52.51 F(to)2.5 E/F25 10/Times-Bold@0 SF -.18(Ti)2.5 G
+(mes bold f).18 E(ont)-.25 E F0(\\f\(times ital\))118.066 560 Q 17.5
+(\\f\(TI\) change)57.51 F(to)2.5 E/F26 10/Times-Italic@0 SF -.55(Ti)2.5
+G(mes italic font).55 E F0(\\f\(times boldital\))118.066 572 Q 13.61
+(\\f\(TX\) change)39.73 F(to)2.5 E/F27 10/Times-BoldItalic@0 SF -.37(Ti)
+2.5 G(mes bold-italic f).37 E(ont)-.1 E 452.606 576.5 118.066 576.5 DL
+F0(\\f\(pre)118.066 586 Q 57.77(vious\) \\f\(PV\))-.25 F
+(change back to pre)16.66 E(vious font)-.25 E .565
+(Some of the special characters look better in some fonts than others.)
+69.336 604 R 2.165 -.8(We h)5.565 H -2.25 -.2(av e).8 H .565
+(found that some PostScript)3.265 F(interpreters unfortunately don')
+69.336 616 Q 2.5(ta)-.18 G -.1(lwa)-2.5 G
+(ys implement all the special characters in all fonts.).1 E .226
+(If you need a font other than those Mup supports directly)69.336 634 R
+2.725(,i)-.65 G 2.725(ti)-2.725 G 2.725(sp)-2.725 G .225(ossible to o)
+-2.725 F -.15(ve)-.15 G .225(rride Mup').15 F 2.725(sb)-.55 G .225
+(uiltin fonts with)-2.925 F(other fonts.)69.336 646 Q
+(This is described later in the section on "Installing other fonts.")5 E
+(The point size can also be changed. \(A "point" is about 1/72 of an in\
+ch.\))69.336 664 Q .32 LW 73.336 727 69.336 727 DL 77.336 727 73.336 727
+DL 81.336 727 77.336 727 DL 85.336 727 81.336 727 DL 89.336 727 85.336
+727 DL 93.336 727 89.336 727 DL 97.336 727 93.336 727 DL 101.336 727
+97.336 727 DL 105.336 727 101.336 727 DL 109.336 727 105.336 727 DL
+113.336 727 109.336 727 DL 117.336 727 113.336 727 DL 121.336 727
+117.336 727 DL 125.336 727 121.336 727 DL 129.336 727 125.336 727 DL
+133.336 727 129.336 727 DL 137.336 727 133.336 727 DL 141.336 727
+137.336 727 DL 145.336 727 141.336 727 DL 149.336 727 145.336 727 DL/F28
+8/Times-Roman@0 SF(*)69.336 744 Q -.28(Ti)90.595 744 S
+(mes is a trademark and Helv).28 E(etica is a re)-.12 E
+(gistered trademark of Allied Corporation.)-.12 E EP
+%%Page: 69 75
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-6)274.506 48 S 2.5(9-)-2.5 G 89.725
+(Code Meaning)205.206 96 R .4 LW 398.391 100.5 172.281 100.5 DL(\\s\()
+172.281 110 Q/F1 10/Times-Italic@0 SF(N\))A F0(change to point size)
+81.96 E F1(N)2.5 E F0(\\s\(+)172.281 122 Q F1(N\))A F0
+(increase point size by)76.32 E F1(N)2.5 E F0(points)2.5 E(\\s\(-)
+172.281 134 Q F1(N\))A F0(decrease point size by)78.63 E F1(N)2.5 E F0
+(points)2.5 E(\\s\(PV\) or \\s\(pre)172.281 146 Q 12.5(vious\) re)-.25 F
+-.15(ve)-.25 G(rt to pre).15 E(vious size)-.25 E .283(The point size ca\
+n range from 1 to 100. A font or size change will last until changed or\
+ until the end of the)69.336 164 R 1.345(string. An)69.336 176 R 3.845
+(ys)-.15 G 1.344(ubsequent strings will be)-3.845 F 1.344(gin with def)
+-.15 F 1.344(ault font and size v)-.1 F 1.344(alues, e)-.25 F 1.344
+(xcept in the case of lyrics,)-.15 F .251
+(where font and size information is maintained separately for each staf)
+69.336 188 R 2.751(fa)-.25 G .251(nd v)-2.751 F .252
+(erse, and carried forw)-.15 F .252(ard from)-.1 F .042(measure to meas\
+ure, and rehearsal marks, where the information is also carried forw)
+69.336 200 R 2.542(ard. The)-.1 F(def)2.542 E .042(ault v)-.1 F(alues)
+-.25 E .658(can be set as described in the "P)69.336 212 R .658
+(arameters" section. The music symbols are af)-.15 F .659
+(fected by size changes.)-.25 F .659(If a)5.659 F(music symbol follo)
+69.336 224 Q(ws italics or bolditalics characters, it will be made ital\
+ics to match.)-.25 E(Here are some e)69.336 242 Q(xamples of strings:)
+-.15 E/F2 10/Courier@0 SF("hello")105.336 260 Q
+("\( \\\(up2n\) = 100 \)")105.336 272 Q
+("\\f\(TB\)this will be bold. \\f\(TI\)this will be italics")105.336 284
+Q("A \\f\(TX\)\\s\(+12\)BIG\\f\(PV\)\\s\(-12\) word")105.336 296 Q
+("\\f\(newcentury boldital\)Allegro")105.336 308 Q 69.336 334 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(8.3 Horizontal)72.836 334 R(and v)3.5 E
+(ertical motion)-.14 E 69.336 352 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .371
+(It is also possible to specify a string that tak)72.207 352 R .37
+(es up more than one line, by putting a "\\n" where you w)-.1 F .37
+(ant to)-.1 F(mo)69.336 364 Q .54 -.15(ve t)-.15 H 2.74(oan).15 G .74
+-.25(ew l)-2.74 H .24(ine. The place where this is most lik).25 F .24
+(ely to be useful is for staf)-.1 F 2.74(fl)-.25 G .24
+(abels, which you may w)-2.74 F(ant)-.1 E(to mak)69.336 376 Q 2.5(em)-.1
+G(ulti-line, to k)-2.5 E(eep them from becoming e)-.1 E(xcessi)-.15 E
+-.15(ve)-.25 G(ly wide.).15 E -.15(Fo)5 G 2.5(re).15 G(xample:)-2.65 E
+/F1 10/Courier@0 SF("Violins\\nI&II")105.336 394 Q F0 2.939(A")69.336
+420 S .439(\\b" can be used to specify a backspace. This might be usefu\
+l for adding underlines to te)-2.939 F 2.939(xt. If)-.15 F .439
+(you wish)2.939 F .519
+(to use letters with diacritical marks, you will probably w)69.336 432 R
+.519(ant to use the special characters, described earlier)-.1 F(in this\
+ section, rather than trying to construct them using the plain letter)
+69.336 444 Q 2.5(,ab)-.4 G(ackspace, and the mark.)-2.5 E -1.1(Yo)69.336
+462 S 3.692(ua)1.1 G 1.192(re not allo)-3.692 F 1.192
+(wed to back up to before the be)-.25 F 1.192(ginning of a line.)-.15 F
+1.192(Note that in all fonts e)6.192 F 1.192(xcept Courier)-.15 F(,)-.4
+E(dif)69.336 474 Q .196(ferent characters ha)-.25 F .496 -.15(ve d)-.2 H
+(if).15 E .196(ferent widths, so using backspaces can be a bit trick)
+-.25 F 1.496 -.65(y. F)-.15 H .196(or e).5 F .196(xample, underlining)
+-.15 F 4.033(a5)69.336 486 S 1.533(-letter w)-4.033 F 1.533
+(ord might require more than 5 underscores, if the characters in the w)
+-.1 F 1.532(ord are wider than an)-.1 F 3.554(underscore character)
+69.336 498 R 6.054(.I)-.55 G 6.054(ng)-6.054 G 3.554(eneral, it w)-6.054
+F 3.555(orks better to enter an entire string, then backspace to add)-.1
+F 1.515(underscoring or accents, rather than doing them along the w)
+69.336 510 R(ay)-.1 E 4.015(.F)-.65 G 1.514(or e)-4.165 F 1.514
+(xample, "My\\b\\b___" will line up)-.15 F
+(much better than "M\\b_y\\b_".)69.336 522 Q -1.11(Ve)69.336 540 S .965
+(rtical motion within a string can be speci\214ed using "\\v\()1.11 F/F2
+10/Times-Italic@0 SF(N)A F0 .965(\)" where)B F2(N)3.465 E F0 .966
+(is some percentage of the current)3.465 F 1.049(font height.)69.336 552
+R 1.049(The distance may be ne)6.049 F -.05(ga)-.15 G(ti).05 E 1.349
+-.15(ve f)-.25 H 1.049(or do).15 F(wnw)-.25 E 1.049
+(ard motion or positi)-.1 F 1.348 -.15(ve f)-.25 H 1.048(or upw).15 F
+1.048(ard motion, ranging)-.1 F 1.022(from -100 to 100.)69.336 564 R
+1.023(This might be used for creating superscripts and subscripts, alth\
+ough the ne)6.022 F 1.023(xt section)-.15 F .2(describes an alternate w)
+69.336 576 R .2(ay of doing that which is usually better)-.1 F 2.7(.I)
+-.55 G 2.7(tm)-2.7 G .2(ight also be used just to line something)-2.7 F
+.081(up dif)69.336 588 R .081(ferently than Mup normally w)-.25 F 2.582
+(ould. Y)-.1 F .082(ou cannot put ne)-1.1 F .082
+(wlines \(with \\n\) in the same string with v)-.25 F(ertical)-.15 E
+(motion.)69.336 600 Q 69.336 618 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(8.4 Piled)72.836 618 R(text, f)3.5 E
+(or superscripts, subscripts, etc.)-.35 E 69.336 636 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .157
+(It is also possible to "pile up" lines of te)71.993 636 R .157
+(xt in a string.)-.15 F .157
+(Some common uses of this could be for superscripts)5.157 F 1.175
+(and subscripts or for \214gured bass notation.)69.336 648 R 1.175
+(Some f)6.175 F 1.175
+(acilities to speci\214cally deal with \214gured bass will be)-.1 F .182
+(described in a later section, b)69.336 660 R .182
+(ut here we describe the general-purpose constructs for piling te)-.2 F
+2.681(xt. A)-.15 F .181(\\: is used)2.681 F .855(to indicate the be)
+69.336 672 R .856(ginning of piling. An)-.15 F 3.356(ys)-.15 G .856
+(ubsequent instances of \\: in the same string will alternately turn)
+-3.356 F .158(piling of)69.336 684 R 2.658(fa)-.25 G .158(nd on.)-2.658
+F .158(When a pile is be)5.158 F .158(gun, the te)-.15 F .157
+(xt size is automatically made smaller)-.15 F 2.657(,a)-.4 G .157
+(nd the te)-2.657 F .157(xt baseline is)-.15 F(mo)69.336 696 Q -.15(ve)
+-.15 G 3.172(du).15 G .672(p, so that the \214rst line of piled te)
+-3.172 F .673(xt is lik)-.15 F 3.173(eas)-.1 G .673
+(uperscript, and the ne)-3.173 F .673(xt lik)-.15 F 3.173(eas)-.1 G .673
+(ubscript. If there are)-3.173 F .326(additional lines, the)69.336 708 R
+2.826(ya)-.15 G .326(re placed belo)-2.826 F 2.825(wt)-.25 G .325
+(he subscript.)-2.825 F .325(By def)5.325 F .325
+(ault, the lines in a pile are placed such that the)-.1 F .373(last dig\
+it in each line all line up, or if there is no digit, the last characte\
+r)69.336 720 R 5.373(.H)-.55 G -.25(ow)-5.373 G -2.15 -.25(ev e).25 H
+1.173 -.4(r, y).25 H .373(ou can force dif).4 F(ferent)-.25 E 2.779
+(alignment. A)69.336 732 R .279(\\| will force alignment at that point,\
+ or a \\^ will force alignment at the center of the follo)2.779 F(wing)
+-.25 E EP
+%%Page: 70 76
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-7)274.506 48 S 2.5(0-)-2.5 G(character)
+69.336 96 Q 3.562(.Am)-.55 G 1.062(aximum of one alignment mark)-3.562 F
+1.062(er can be speci\214ed on each line of a pile.)-.1 F -1.1(Yo)6.063
+G 3.563(uc)1.1 G 1.063(annot put)-3.563 F(ne)69.336 108 Q .093
+(wlines \(with \\n\) in the same string with piling.)-.25 F 2.593(An)
+5.093 G .592 -.25(ew l)-2.593 H .092
+(ine of the pile is started at each <space> character).25 F 1.76
+(in the input string.)69.336 120 R 1.76(If you w)6.76 F 1.761(ant an ac\
+tual literal space inside a piled line, it must be preceded with a)-.1 F
+(backslash. As an e)69.336 132 Q(xample:)-.15 E/F1 10/Courier@0 SF
+("Text\\:superscript subscript\\: back to normal.";)105.336 150 Q
+("This pile \\:has\\ literal spaces\\ in\\ it.";)105.336 162 Q
+("This pile \\:h\\^as align\\|ment spec\\^ified.";)105.336 174 Q 171.836
+183.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 104 rlineto 232 0 rlineto 0 104 neg rlineto closepath stroke grestore
+EEND 16 661 232 232 -104 104 170.836 287.6 PBEGIN
+%%BeginDocument: mugex65.ps
+%%BoundingBox: 16 661 248 765
+save
+331503037 331503247 sv
+1.000000 1.000000 scale
+%  S_FEED
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_BLOCKHEAD
+1 linenum
+/Times-Roman findfont
+18 scalefont
+setfont
+36.00 741.42 moveto
+(Text) show
+68.94 750.12 moveto
+/Times-Roman findfont
+11 scalefont
+setfont
+(superscript) show
+77.45 739.28 moveto
+(subscript) show
+117.05 741.42 moveto
+/Times-Roman findfont
+18 scalefont
+setfont
+( back to normal.) show
+/Times-Roman findfont
+8 scalefont
+setfont
+36.00 732.88 moveto
+( ) show
+/Times-Roman findfont
+18 scalefont
+setfont
+36.00 713.65 moveto
+(This pile ) show
+112.71 722.35 moveto
+/Times-Roman findfont
+11 scalefont
+setfont
+(has literal) show
+103.93 711.52 moveto
+(spaces in it.) show
+/Times-Roman findfont
+8 scalefont
+setfont
+36.00 702.97 moveto
+( ) show
+/Times-Roman findfont
+18 scalefont
+setfont
+36.00 683.75 moveto
+(This pile ) show
+117.92 692.44 moveto
+/Times-Roman findfont
+11 scalefont
+setfont
+(has) show
+103.93 681.61 moveto
+(alignment) show
+104.79 670.78 moveto
+(specified.) show
+%  S_FEED
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 307.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(8.5 Slash)72.836 307.6 R(thr)3.5 E
+(ough number)-.252 E 69.336 325.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .688
+(Another thing which is common in \214gured bass notation is to dra)
+72.524 325.6 R 3.187(was)-.15 G .687(lash through a number)-3.187 F
+3.187(.A)-.55 G -.05(ga)-3.187 G .687(in, the).05 F 1.248
+(section on \214gured bass will describe ho)69.336 337.6 R 3.748(wt)-.25
+G 3.748(od)-3.748 G 3.748(ot)-3.748 G 1.248
+(hat inside \214gured bass, b)-3.748 F 1.248
+(ut it is possible to put a slash)-.2 F(through a number else)69.336
+349.6 Q(where by placing a backslashed slash after a number)-.25 E 2.5
+(,l)-.4 G(ik)-2.5 E 2.5(et)-.1 G(his:)-2.5 E/F1 10/Courier@0 SF("6\\/")
+130.336 367.6 Q("10\\/")130.336 379.6 Q 69.336 405.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(8.6 Boxed)72.836 405.6 R(or cir)3.5 E
+(cled text)-.252 E 69.336 423.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF -1.1(Yo)71.906 423.6 S 2.57(uc)1.1 G .07
+(an cause the te)-2.57 F .069
+(xt to be printed inside a box by placing a \\[ at the be)-.15 F .069
+(ginning of the string and a \\] at the)-.15 F .944(end of the string.)
+69.336 435.6 R .944(Similarly you can cause te)5.944 F .945
+(xt to be placed inside a circle \(or ellipse for strings that are)-.15
+F .549(wide\) by placing a \\{ at the be)69.336 447.6 R .549
+(ginning of the string and a \\} at the end of the string.)-.15 F(Box)
+5.549 E .549(ed or circled te)-.15 F(xt)-.15 E(are not allo)69.336 459.6
+Q(wed in lyrics.)-.25 E/F1 10/Courier@0 SF("\\[This is in a box\\]")
+111.336 477.6 Q("\\{This is in an ellipse\\}")111.336 489.6 Q 207.836
+499.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 77 rlineto 160 0 rlineto 0 77 neg rlineto closepath stroke grestore
+EEND 16 687 160 160 -77 77 206.836 576.2 PBEGIN
+%%BeginDocument: mugex66.ps
+%%BoundingBox: 16 687 176 764
+save
+331503037 331503247 sv
+1.000000 1.000000 scale
+%  S_FEED
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_BLOCKHEAD
+1 linenum
+/Times-Roman findfont
+16 scalefont
+setfont
+0.70 setlinewidth
+newpath
+37.50 738.22 moveto
+37.50 755.83 lineto
+140.59 755.83 lineto
+140.59 738.22 lineto
+closepath
+stroke
+39.50 743.04 moveto
+(This is in a box) show
+/Times-Roman findfont
+20 scalefont
+setfont
+36.00 721.68 moveto
+( ) show
+/Times-Roman findfont
+14 scalefont
+setfont
+gsave
+newpath
+3.889609 1.000000 scale
+25.30 710.05 16.05 0 360 arc
+0.257095 1.000000 scale
+4.031292 1.000000 scale
+24.41 710.05 15.55 0 360 arc
+eofill
+grestore
+44.02 706.73 moveto
+(This is in an ellipse) show
+%  S_FEED
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND EP
+%%Page: 71 77
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-7)274.506 48 S 2.5(1-)-2.5 G 69.336 103
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(9. TEMPO,)73.086 103 R -.6(DY)3.75 G -.3
+(NA).6 G(MIC MARKS, ORN).3 E(AMENTS, ETC.)-.3 E 69.336 121 EBEGIN
+0 0 0 setrgbcolor
+EEND 69.336 139 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(9.1 General)72.836 139 R(inf)3.5 E
+(ormation)-.35 E 69.336 157 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .907(There are a number of symbols and othe\
+r markings that appear frequently in music, which are normally)72.743
+157 R .293(associated with a particular time or place in the compositio\
+n. There are se)69.336 169 R -.15(ve)-.25 G .293
+(ral classes of such symbols, all).15 F
+(of which are handled by Mup in a some)69.336 181 Q(what similar f)-.25
+E(ashion. The general format of these statements is:)-.1 E/F1 10
+/Times-Italic@0 SF(mark_type place staf)105.336 199 Q
+(f\(s\) distance : be)-.18 E(gintime te)-.4 E(xt dur)-.2 E(ation;)-.15 E
+F0(The)69.336 225 Q F1(mark_type)2.5 E F0(can be an)2.5 E 2.5(yo)-.15 G
+2.5(ft)-2.5 G(he follo)-2.5 E(wing:)-.25 E 73.6(Mark_type Meaning)
+177.021 243 R .4 LW 393.651 247.5 177.021 247.5 DL 40.27(rom te)177.021
+257 R(xt in roman font)-.15 E 43.6(ital te)177.021 269 R
+(xt in italic font)-.15 E 38.6(bold te)177.021 281 R(xt in bold font)
+-.15 E 25.82(boldital te)177.021 293 R(xt in bold-italic font)-.15 E
+23.04(mussym music)177.021 305 R(symbol \(fermata, coda sign, etc.\))2.5
+E 30.28(phrase phrase)177.021 317 R(mark)2.5 E 53.24(<c)177.021 329 S
+(rescendo "hairpin")-53.24 E 53.24(>d)177.021 341 S
+(ecrescendo "hairpin")-53.24 E(octa)177.021 353 Q 30.93 -.15(ve p)-.2 H
+(lay 1 or more octa).15 E -.15(ve)-.2 G 2.5(sh).15 G(igher or lo)-2.5 E
+(wer)-.25 E 34.72(pedal piano)177.021 365 R(pedal marks)2.5 E(The)69.336
+383 Q F1(place)2.5 E F0(is as for lyrics: abo)2.5 E -.15(ve)-.15 G 2.5
+(,b).15 G(elo)-2.5 E 1.3 -.65(w, o)-.25 H 2.5(rb).65 G 2.5
+(etween. There)-2.5 F(are some restrictions, as summarized belo)2.5 E
+(w:)-.25 E(place allo)265.381 401 Q(wed)-.25 E 12.5(mark_type abo)
+179.571 413 R 12.8 -.15(ve b)-.15 H(elo).15 E 15(wb)-.25 G 12.5
+(etween def)-15 F(ault)-.1 E 391.101 417.5 179.571 417.5 DL 44.285
+(rom yes)179.571 427 R 27.925(yes yes)25.555 F(abo)24.995 E -.15(ve)-.15
+G 42.615(bold yes)179.571 439 R 27.925(yes yes)25.555 F(abo)24.995 E
+-.15(ve)-.15 G 47.615(ital yes)179.571 451 R 27.925(yes yes)25.555 F
+(abo)24.995 E -.15(ve)-.15 G 29.835(boldital yes)179.571 463 R 27.925
+(yes yes)25.555 F(abo)24.995 E -.15(ve)-.15 G 27.055(mussym yes)179.571
+475 R 27.925(yes yes)25.555 F(abo)24.995 E -.15(ve)-.15 G 34.295
+(phrase yes)179.571 487 R 29.59(yes no)25.555 F -.25(va)26.66 G(ries).25
+E 57.255(<y)179.571 499 S 23.055(es yes)-57.255 F 22.495(yes abo)30.425
+F -.15(ve)-.15 G 57.255(>y)179.571 511 S 23.055(es yes)-57.255 F 22.495
+(yes abo)30.425 F -.15(ve)-.15 G(octa)179.571 523 Q 34.945 -.15(ve y)-.2
+H 23.055(es yes).15 F 24.16(no none)32.09 F 40.4(pedal no)179.571 535 R
+29.59(yes no)27.22 F(belo)26.66 E(w)-.25 E(Octa)69.336 553 Q .817 -.15
+(ve m)-.2 H .517(arks must include a).15 F F1(place)3.018 E F0 .518
+(of abo)3.018 F .818 -.15(ve o)-.15 H 3.018(rb).15 G(elo)-3.018 E 4.318
+-.65(w. F)-.25 H .518(or all the other mark_types, the).5 F F1(place)
+3.018 E F0 .518(is optional.)3.018 F -.15(Fo)69.336 565 S 2.562(rp).15 G
+.062(hrase, if)-2.562 F F1(place)2.562 E F0 .062(is not speci\214ed, Mu\
+p determines it on a case-by-case basis depending on the location of)
+2.562 F(the notes.)69.336 577 Q .305
+(As with musical data or lyrics, the)69.336 595 R F1(staf)2.805 E(f)-.18
+E F0 .305
+(can be a single number or may include lists and ranges. In the case)
+2.805 F .025(of "between", staf)69.336 607 R 2.525(fn)-.25 G .024
+(umbers must be in pairs, separated by an "&", with the second staf)
+-2.525 F 2.524(fn)-.25 G .024(umber one greater)-2.524 F
+(than the \214rst.)69.336 619 Q(The)69.336 637 Q F1(staf)3.251 E(f)-.18
+E F0 .751(can also be speci\214ed by the k)3.251 F -.15(ey)-.1 G -.1(wo)
+.15 G .751(rd "all," in which case the mark will be placed abo).1 F
+1.051 -.15(ve t)-.15 H .751(he top).15 F(visible staf)69.336 649 Q 2.5
+(fo)-.25 G 2.5(rb)-2.5 G(elo)-2.5 E 2.5(wt)-.25 G
+(he bottom visible staf)-2.5 E(f.)-.25 E(Here are some e)69.336 667 Q
+(xamples:)-.15 E EP
+%%Page: 72 78
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-7)274.506 48 S 2.5(2-)-2.5 G/F1 10
+/Courier@0 SF(rom 3:)105.336 96 Q(boldital below 1:)105.336 108 Q 6(<b)
+105.336 120 S(etween 3&4:)-6 E(pedal below 2:)105.336 132 Q
+(octave above 3:)105.336 144 Q(phrase 3,4:)105.336 156 Q
+(mussym above 2-3, 5:)105.336 168 Q(ital between 1&2, 3&4:)105.336 180 Q
+F0(The)69.336 206 Q/F2 10/Times-Italic@0 SF(distance)2.7 E F0 .2
+(is optional. It is speci\214ed by the k)2.7 F -.15(ey)-.1 G -.1(wo).15
+G .199(rd "dist" follo).1 F .199(wed by a number)-.25 F 2.699(.T)-.55 G
+.199(his number o)-2.699 F -.15(ve)-.15 G(rrides).15 E .66
+(the dist, chorddist, or dyndist parameter v)69.336 218 R .66
+(alue that w)-.25 F .66(ould normally apply)-.1 F 3.16(,a)-.65 G .66
+(nd is gi)-3.16 F -.15(ve)-.25 G 3.16(ni).15 G 3.16(ns)-3.16 G 3.16
+(tepsizes. If)-3.16 F(the)3.16 E 1.595(number is follo)69.336 230 R
+1.595(wed by a ! the items will be placed at e)-.25 F 1.594
+(xactly that distance from the edge of the staf)-.15 F(f,)-.25 E .211
+(without re)69.336 242 R -.05(ga)-.15 G .211(rd for an).05 F .212
+(ything the)-.15 F 2.712(ym)-.15 G .212(ight o)-2.712 F -.15(ve)-.15 G
+2.712(rwrite. Otherwise).15 F .212
+(the normal rules apply: the dist is a minimum)2.712 F -.25(va)69.336
+254 S .375(lue, and items may be placed f).25 F .375(arther a)-.1 F -.1
+(wa)-.15 G 2.875(yt).1 G .375(han this to a)-2.875 F -.2(vo)-.2 G .375
+(id colliding with other things.).2 F .375(If the ! is used,)5.375 F
+.968(the number is allo)69.336 266 R .968(wed to be ne)-.25 F -.05(ga)
+-.15 G(ti).05 E -.15(ve)-.25 G 3.468(,w).15 G .968(hich allo)-3.468 F
+.969(ws you to place items inside the staf)-.25 F 3.469(f. A)-.25 F .969
+(dist cannot be)3.469 F(speci\214ed with pedal, phrase, or between.)
+69.336 278 Q F1(score)105.336 296 Q(dist=2)130.336 308 Q(music)105.336
+320 Q(rom above 1: 1 "normal dist";)105.336 344 Q
+(rom above 1 dist 4: 2 "dist 4";)105.336 356 Q(// higher than usual)39 E
+(rom above 1 dist 0! : 3 "forced 0";)105.336 368 Q(// lower than normal)
+15 E(mussym above 1 dist -2! : 4.5 "rr";)105.336 380 Q
+(// forced down into staff)15 E(1: c;;;;)105.336 392 Q(endbar)105.336
+404 Q 91.836 413.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 72 rlineto 392 0 rlineto 0 72 neg rlineto closepath stroke grestore
+EEND 128 691 392 392 -72 72 90.836 485.6 PBEGIN
+%%BeginDocument: mugex67.ps
+%%BoundingBox: 128 691 520 763
+save
+331503037 331503247 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+648.29 719.54 936.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+156.08 713.54 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+193.25 701.54 1.000000 4n
+0.70 setlinewidth
+187.02 701.54 moveto
+199.48 701.54 lineto stroke
+196.93 702.29 moveto
+196.93 722.54 lineto stroke
+271.40 701.54 1.000000 4n
+265.17 701.54 moveto
+277.63 701.54 lineto stroke
+275.08 702.29 moveto
+275.08 722.54 lineto stroke
+349.55 701.54 1.000000 4n
+343.32 701.54 moveto
+355.78 701.54 lineto stroke
+353.23 702.29 moveto
+353.23 722.54 lineto stroke
+428.54 701.54 1.000000 4n
+422.31 701.54 moveto
+434.77 701.54 lineto stroke
+432.22 702.29 moveto
+432.22 722.54 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+458.97 726.77 moveto
+464.52 726.77 1.000000 rr
+470.06 726.77 moveto
+/Times-Roman findfont
+12 scalefont
+setfont
+347.57 734.78 moveto
+(forced 0 ) show
+/Times-Roman findfont
+12 scalefont
+setfont
+268.41 746.78 moveto
+(dist 4 ) show
+/Times-Roman findfont
+12 scalefont
+setfont
+190.26 740.78 moveto
+(normal dist ) show
+restore
+%  S_BAR
+12 linenum
+0.70 setlinewidth
+498.50 731.54 moveto
+498.50 707.54 lineto stroke
+3.00 setlinewidth
+502.50 731.54 moveto
+502.50 707.54 lineto stroke
+0.70 setlinewidth
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF 3.202(After the colon comes one or more\
+ items to be printed. Each item contains at least a be)69.336 505.6 R
+(gintime)-.15 E .815(speci\214cation. Some may also contain a te)69.336
+517.6 R .815
+(xt string and/or a duration. Each item ends with a semicolon. A)-.15 F
+(ne)69.336 529.6 Q(wline ends the list of items.)-.25 E 1.169(The be)
+69.336 547.6 R 1.168(gintime describes where in time the item should be\
+ printed. It is a number ranging from 0 to the)-.15 F 1.418
+(numerator \(top number\) of the time signature plus one.)69.336 559.6 R
+3.918(0r)6.418 G 1.418(efers to the bar line at the be)-3.918 F 1.418
+(ginning of the)-.15 F .048(current measure, 1 refers to the \214rst be\
+at of the measure, 2 to the second beat, etc., with the maximum v)69.336
+571.6 R(alue)-.25 E 2.699
+(referring to the bar line which ends the measure. A "beat" is whate)
+69.336 583.6 R -.15(ve)-.25 G 5.199(rt).15 G 2.699(ime v)-5.199 F 2.699
+(alue is gi)-.25 F -.15(ve)-.25 G 5.199(nb).15 G 5.199(yt)-5.199 G(he)
+-5.199 E 1.026(denominator \(bottom number\) of the time signature.)
+69.336 595.6 R -.15(Fo)6.026 G 3.526(re).15 G 1.025
+(xample, in 4/4 or 3/4 time, a beat is a quarter)-3.676 F .157(note, wh\
+ereas in 6/8 or 9/8 time, a beat is an eighth note. Fractional v)69.336
+607.6 R .158(alues can be speci\214ed using a decimal)-.25 F(number)
+69.336 619.6 Q 2.648(.T)-.55 G .148(hus 1.5 is halfw)-2.648 F .148
+(ay between beats 1 and 2, while 2.66 is about 2/3 of the w)-.1 F .147
+(ay between beats 2 and)-.1 F 2.706(3. F)69.336 631.6 R .207
+(or time signatures that are the addition of tw)-.15 F 2.707(oo)-.1 G
+2.707(rm)-2.707 G .207(ore fractions, lik)-2.707 F 2.707(e4)-.1 G .207
+(/4 + 3/8, a "beat" is gi)-2.707 F -.15(ve)-.25 G 2.707(nb).15 G 2.707
+(yt)-2.707 G(he)-2.707 E(lar)69.336 643.6 Q(gest denominator)-.18 E(.)
+-.55 E .518(Since grace notes ef)69.336 661.6 R(fecti)-.25 E -.15(ve)
+-.25 G .518(ly tak).15 F 3.018(ez)-.1 G .518
+(ero time, special notation is used to place something relati)-3.018 F
+.817 -.15(ve t)-.25 H 3.017(oag).15 G(race)-3.017 E .104(note. The)
+69.336 673.6 R/F1 10/Times-Italic@0 SF(be)2.604 E(gintime)-.4 E F0 .104
+(can be follo)2.604 F .104
+(wed by a number of grace notes to "back up" from the beat.)-.25 F .104
+(The number is)5.104 F 2.5(an)69.336 685.6 S -2.25 -.15(eg a)-2.5 H(ti)
+.15 E .3 -.15(ve n)-.25 H(umber enclosed in parentheses.).15 E .279
+(The beat time v)69.336 703.6 R .279(alue can optionally be follo)-.25 F
+.278(wed by an of)-.25 F .278(fset, in stepsizes.)-.25 F .278(This of)
+5.278 F .278(fset is a number in square)-.25 F(brack)69.336 715.6 Q 4.66
+(ets. The)-.1 F 2.16(number must be)4.66 F 2.16(gin with a + or - sign.)
+-.15 F 2.16(It can optionally include a decimal point and)7.16 F .993
+(fractional part.)69.336 727.6 R 3.493(An)5.993 G -2.25 -.15(eg a)-3.493
+H(ti).15 E 1.293 -.15(ve o)-.25 H -.25(ff).15 G .993
+(set will cause the item to be mo).25 F -.15(ve)-.15 G 3.493(dt).15 G
+3.492(ot)-3.493 G .992(he left, while a positi)-3.492 F 1.292 -.15(ve o)
+-.25 H -.25(ff).15 G .992(set will).25 F .401(cause it to be mo)69.336
+739.6 R -.15(ve)-.15 G 2.902(dt).15 G 2.902(ot)-2.902 G .402(he right.)
+-2.902 F .402(This of)5.402 F .402
+(fset is used as a \214nal adjustment after all the other placement has)
+-.25 F EP
+%%Page: 73 79
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-7)274.506 48 S 2.5(3-)-2.5 G .039
+(been done. A common use for this w)69.336 96 R .038(ould be if you w)
+-.1 F .038(ant to place something slightly before the be)-.1 F .038
+(ginning of)-.15 F(the \214rst measure of a song. Y)69.336 108 Q
+(ou could then specify something lik)-1.1 E(e:)-.1 E/F1 10/Courier@0 SF
+(rom above all: 0 [-3.5] "Allegro";)105.336 126 Q F0(which w)69.336 146
+Q(ould place the "Alle)-.1 E(gro" 3.5 stepsizes left of the be)-.15 E
+(ginning of the measure.)-.15 E(The grace note back up, if an)69.336 164
+Q 1.3 -.65(y, m)-.15 H(ust occur before the stepsize of).65 E
+(fset, if an)-.25 E 3.8 -.65(y. F)-.15 H(or e).5 E(xample:)-.15 E F1
+(1: c; [grace] 8d; []e; []f; 2.g;)105.336 182 Q
+(ital above 1: 2\(-3\)[+1] "cresc.";)105.336 194 Q(bar)105.336 206 Q
+127.836 215.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 63 rlineto 320 0 rlineto 0 63 neg rlineto closepath stroke grestore
+EEND 160 698 320 320 -63 63 126.836 278.6 PBEGIN
+%%BeginDocument: mugex68.ps
+%%BoundingBox: 160 698 480 761
+save
+331503037 331503247 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+684.29 726.98 900.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 720.98 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+224.88 708.98 1.000000 4n
+0.70 setlinewidth
+218.65 708.98 moveto
+231.11 708.98 lineto stroke
+228.56 709.73 moveto
+228.56 729.98 lineto stroke
+282.55 711.98 0.583333 4n
+284.55 712.47 moveto
+284.55 727.99 lineto stroke
+289.25 714.98 0.583333 4n
+291.25 715.47 moveto
+291.25 730.42 lineto stroke
+295.95 717.98 0.583333 4n
+297.96 718.47 moveto
+297.96 732.87 lineto stroke
+304.55 720.98 1.000000 2n
+314.03 723.98 1.000000 dot
+308.45 721.73 moveto
+308.45 741.98 lineto stroke
+newpath
+284.32 728.96 moveto
+298.18 733.84 lineto
+298.18 731.89 lineto
+284.32 727.01 lineto
+closepath
+fill
+/Times-Italic findfont
+12 scalefont
+setfont
+282.88 748.22 moveto
+(cresc. ) show
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+467.65 738.98 moveto
+467.65 714.98 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Italic 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF -.1(wo)69.336 292.6 S .693(uld \214nd t\
+he chord at or closest to count 2, and back up 3 grace notes from there\
+, then mo).1 F .993 -.15(ve r)-.15 H .693(ight by 1).15 F(stepsize.)
+69.336 304.6 Q -.15(Fo)69.336 322.6 S 2.5(ri).15 G(tems that include a \
+duration, the duration tells the ending point of the item. A duration i\
+s speci\214ed by:)-2.5 E/F1 10/Times-Bold@0 SF(til)105.336 340.6 Q/F2 10
+/Times-Italic@0 SF(M)6 E F1(m)A/F3 10/Courier@0 SF(+)6 E F2(N)6 E F0
+(where)69.336 360.6 Q F2(M)3.026 E F0 .526
+(is a number of bar lines to cross, and)3.026 F F2(N)3.026 E F0 .526
+(is a number of additional beats.)3.026 F .525
+(If either of them is 0, it)5.526 F(can be omitted, b)69.336 372.6 Q
+(ut at least one of them must be non-zero.)-.2 E(Here are some e)5 E
+(xamples:)-.15 E F3(til 3)105.336 390.6 Q
+(// until beat 3 of current measure)20 E(til 1m+2)105.336 402.6 Q
+(// until beat 2 of next measure)18 E(til 1m)105.336 414.6 Q
+(// until next bar line)18 E F0(Whether the te)69.336 440.6 Q
+(xt and duration are allo)-.15 E
+(wed or required depends on the mark_type, as summarized belo)-.25 E(w:)
+-.25 E 29.52(mark_type te)188.106 458.6 R 49.255(xt duration)-.15 F .4
+LW 382.566 463.1 188.106 463.1 DL 39.16(rom required)188.106 472.6 R
+(optional)30.57 E 37.49(bold required)188.106 484.6 R(optional)30.57 E
+42.49(ital required)188.106 496.6 R(optional)30.57 E 24.71
+(boldital required)188.106 508.6 R(optional)30.57 E 21.93
+(mussym required)188.106 520.6 R(allo)30.57 E(wed on tr only)-.25 E
+29.17(phrase not)188.106 532.6 R(allo)2.5 E 14.7(wed required)-.25 F
+52.13(<n)188.106 544.6 S(ot allo)-52.13 E 14.7(wed required)-.25 F 52.13
+(>n)188.106 556.6 S(ot allo)-52.13 E 14.7(wed required)-.25 F(octa)
+188.106 568.6 Q 29.82 -.15(ve r)-.2 H 28.07(equired optional).15 F 33.61
+(pedal *)188.106 580.6 R(or nothing)2.5 E(not allo)15 E(wed)-.25 E .841
+(If there are se)69.336 598.6 R -.15(ve)-.25 G .841
+(ral items, such that the).15 F 3.341(yh)-.15 G -2.25 -.2(av e)-3.341 H
+.841(to be stack)3.541 F .842(ed on top of each other)-.1 F 3.342(,a)-.4
+G .842(ll items of a particular)-3.342 F .158
+(class are placed from top to bottom according to input order)69.336
+610.6 R 2.658(.T)-.55 G .158(he classes are done in the order sho)-2.658
+F .158(wn in the)-.25 F(table belo)69.336 622.6 Q 1.3 -.65(w, u)-.25 H
+(nless the order is o).65 E -.15(ve)-.15 G(rridden by the abo).15 E -.15
+(ve)-.15 G(order).15 E 2.5(,b)-.4 G(elo)-2.5 E -.1(wo)-.25 G(rder).1 E
+2.5(,o)-.4 G 2.5(rb)-2.5 G(etweenorder parameters.)-2.5 E EP
+%%Page: 74 80
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-7)274.506 48 S 2.5(4-)-2.5 G 35.65
+(Place mark_type)216.501 96 R(order)2.5 E .4 LW 360.001 100.5 210.671
+100.5 DL(abo)210.671 110 Q 22.54 -.15(ve \()-.15 H(from bottom up\)).15
+E(phrase)258.991 122 Q(mussym)258.991 134 Q(octa)258.991 146 Q -.15(ve)
+-.2 G(rom bold ital boldital < >)258.991 158 Q(lyrics)258.991 170 Q
+(endings)258.991 182 Q(rehearsal marks)258.991 194 Q 360.001 198.5
+210.671 198.5 DL(belo)210.671 208 Q 24.13(w\()-.25 G(from top do)-24.13
+E(wn\))-.25 E(phrase)258.991 220 Q(mussym)258.991 232 Q(octa)258.991 244
+Q -.15(ve)-.2 G(rom bold ital boldital < >)258.991 256 Q(lyrics)258.991
+268 Q(pedal)258.991 280 Q 360.001 284.5 210.671 284.5 DL 12.5
+(between \(from)210.671 294 R(bottom up\))2.5 E(mussym)258.991 306 Q
+(rom bold ital boldital < >)258.991 318 Q(lyrics)258.991 330 Q -.15(Fo)
+69.336 348 S 3.091(re).15 G .591(xample, for the abo)-3.241 F .891 -.15
+(ve i)-.15 H .592(tems, all phrases will be placed as close to the staf)
+.15 F 3.092(fa)-.25 G 3.092(sp)-3.092 G .592(ossible, then mussym)-3.092
+F 1.392(items abo)69.336 360 R 1.692 -.15(ve t)-.15 H 1.392
+(hem, then octa).15 F 1.691 -.15(ve m)-.2 H 1.391(arks abo).15 F 1.691
+-.15(ve t)-.15 H 1.391(hem, etc. Ho).15 F(we)-.25 E -.15(ve)-.25 G 2.191
+-.4(r, i).15 H 3.891(ft).4 G 1.391(here are se)-3.891 F -.15(ve)-.25 G
+1.391(ral mussym items that).15 F .717(belong at the same horizontal po\
+sition, the \214rst one entered in the input will be printed abo)69.336
+372 R 1.017 -.15(ve t)-.15 H .717(he second,).15 F .102
+(the second one entered will be printed abo)69.336 384 R .402 -.15(ve t)
+-.15 H .102(he third, etc.).15 F .101(All of the "abo)5.101 F .401 -.15
+(ve a)-.15 H .101(ll" items of a gi).15 F -.15(ve)-.25 G 2.601(nc).15 G
+.101(lass will)-2.601 F .749(be abo)69.336 396 R 1.049 -.15(ve t)-.15 H
+.749(he items of that class for the top visible staf).15 F .749
+(f, and all "belo)-.25 F 3.249(wa)-.25 G .749(ll" items of a gi)-3.249 F
+-.15(ve)-.25 G 3.249(nc).15 G .75(lass will be)-3.249 F(belo)69.336 408
+Q 2.5(wt)-.25 G(he items of that class for the bottom visible staf)-2.5
+E(f.)-.25 E 1.6 -.8(We n)69.336 426 T .5 -.25(ow d).8 H
+(iscuss each of the mark_types in more detail.).25 E 69.336 444 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(9.2 T)72.836 444 R(ext)-1.288 E 69.336
+462 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .209(The four forms of Mup te)72.045 462 R
+.208
+(xt statements \(rom, bold, ital, and boldital\) operate identically e)
+-.15 F .208(xcept for the font)-.15 F(which is used.)69.336 474 Q .372
+(The te)69.336 492 R .373(xt statements can ha)-.15 F .673 -.15(ve s)-.2
+H -2.15 -.25(ev e).15 H .373
+(ral additional quali\214ers. The \214rst is a fontf).25 F(amily)-.1 E
+2.873(,g)-.65 G -2.15 -.25(iv e)-2.873 H 2.873(nb).25 G .373
+(efore the font. It)-2.873 F 2.95(can ha)69.336 504 R 3.25 -.15(ve a)-.2
+H 3.25 -.15(ny o).15 H 5.45(ft).15 G 2.95(he v)-5.45 F 2.95
+(alues of the "fontf)-.25 F 2.95(amily" parameter \(a)-.1 F -.25(va)-.2
+G(ntg).25 E 2.95(arde, bookman, courier)-.05 F 5.45(,h)-.4 G(elv)-5.45 E
+(etica,)-.15 E(ne)69.336 516 Q(wcentury)-.25 E 2.5(,p)-.65 G
+(alatino, or times\), with the def)-2.5 E(ault being the v)-.1 E
+(alue of the "fontf)-.25 E(amily" parameter)-.1 E(.)-.55 E .422(The ne)
+69.336 534 R .422(xt optional quali\214er is a point size, gi)-.15 F
+-.15(ve)-.25 G 2.922(ni).15 G 2.922(np)-2.922 G .422
+(arentheses after the font type of rom, bold, etc.)-2.922 F .422
+(If this)5.422 F .666
+(is omitted, the size is obtained from the "size" parameter for the gi)
+69.336 546 R -.15(ve)-.25 G 3.166(ns).15 G(taf)-3.166 E .666
+(f, or for the score if the staf)-.25 F 3.166(fi)-.25 G(s)-3.166 E
+(speci\214ed by "all.")69.336 558 Q 69.336 575 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(9.2.1 Chor)72.586 575 R
+(d, analysis, \214gur)-.481 E(ed bass, and dynamics)-.481 E 69.336 587
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .229(The \214nal optional quali\214er speci\
+\214es special treatment of the te)72.065 587 R 2.73(xt. The)-.15 F .23
+(quali\214er can be "chord", "analysis",)2.73 F .805
+("\214gbass", or "dyn".)69.336 599 R .804(The "chord" modi\214er is typ\
+ically used for marking chords that might be played by a)5.804 F .701(g\
+uitar or other instrument. The "analysis" modi\214er is typically used \
+when marking harmonic analysis lik)69.336 611 R(e)-.1 E .798
+("IV" or "vii".)69.336 623 R .797
+(The "\214gbass" modi\214er is for \214gured bass notation.)5.798 F -.15
+(Fo)5.797 G 3.297(ra).15 G .797(ll three, distance from the staf)-3.297
+F 3.297(fi)-.25 G(s)-3.297 E(af)69.336 635 Q .869
+(fected by the "chorddist" parameter)-.25 F 5.869(.T)-.55 G .869
+(he "dyn" modi\214er is to mark the te)-5.869 F .87
+(xt as something that speci\214es)-.15 F .178
+(dynamics. Mup only uses it when deciding where to place the te)69.336
+647 R .178(xt; something mark)-.15 F .178(ed "dyn" will be treated)-.1 F
+(lik)69.336 659 Q 4.093(ec)-.1 G 1.593
+(rescendo and decrescendo "hairpins.")-4.093 F 1.593(The def)6.593 F
+(ault)-.1 E/F1 10/Times-Italic@0 SF(place)4.093 E F0 1.594
+(for chord and dyn is abo)4.093 F -.15(ve)-.15 G 4.094(,w).15 G 1.594
+(hereas the)-4.094 F(def)69.336 671 Q(ault for the others is belo)-.1 E
+-.65(w.)-.25 G 2.245(The te)69.336 689 R 2.245(xt strings used with the\
+se chord, analysis, or \214gbass modi\214ers can contain an)-.15 F 4.744
+(yc)-.15 G 2.244(haracters, b)-4.744 F(ut)-.2 E .808(characters that in\
+dicate accidentals \("#", "&", "x", "&&", and "n"\) are translated to t\
+he appropriate music)69.336 701 R(character)69.336 713 Q 4.07(,w)-.4 G
+1.57(hile "o", "o/", and "^" are translated to "\\\(dim\)", "\\\(halfdi\
+m\)", and "\\\(triangle\)" respecti)-4.07 F -.15(ve)-.25 G(ly).15 E(.)
+-.65 E(Ho)69.336 725 Q(we)-.25 E -.15(ve)-.25 G 1.642 -.4(r, w).15 H
+.842(ith "chord," the translation of "n" to natural sign is not done, s\
+o you ha).4 F 1.143 -.15(ve t)-.2 H 3.343(ou).15 G .843
+(se \\\(nat\) if you)-3.343 F -.1(wa)69.336 737 S(nt a natural sign. Th\
+is is because a literal letter n tends to occur more often in chords th\
+an natural signs.).1 E EP
+%%Page: 75 81
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-7)274.506 48 S 2.5(5-)-2.5 G .41(If you w)
+69.336 96 R .41(ant to turn of)-.1 F 2.91(ft)-.25 G .41
+(he translation, to treat one of these characters literally)-2.91 F
+2.909(,y)-.65 G .409(ou can precede it with tw)-2.909 F(o)-.1 E 2.5
+(backslashes. Thus,)69.336 108 R(for e)2.5 E(xample, "\\\\&" w)-.15 E
+(ould yield a literal ampersand rather than a \215at symbol.)-.1 E .382
+(If the transpose or addtranspose parameters are set, chords are transp\
+osed to match the ne)69.336 126 R 2.883(wk)-.25 G -.15(ey)-2.983 G 2.883
+(:t).15 G .383(he letters)-2.883 F 1.32("A" through "G" and an)69.336
+138 R 3.82(yf)-.15 G(ollo)-3.82 E 1.32
+(wing accidentals will be transposed appropriately)-.25 F 6.32(.T)-.65 G
+1.32(he accidental can be)-6.32 F 1.383(either something lik)69.336 150
+R 3.883(e")-.1 G 1.383(#" or "&" or an)-3.883 F 3.883(yo)-.15 G 3.883
+(ft)-3.883 G 1.383(he special music characters for accidentals \(\\\(sh\
+arp\), \\\(\215at\),)-3.883 F 3.057(etc.\). If)69.336 162 R .556
+(the staf)3.057 F 3.056(fi)-.25 G 3.056(ss)-3.056 G .556
+(peci\214ed as "all," the score transposition v)-3.056 F .556
+(alue is used.)-.25 F -.35(Tr)5.556 G .556(ansposition has no ef).35 F
+.556(fect on)-.25 F(analysis or \214gbass.)69.336 174 Q .546(In \214gba\
+ss, the string starts out in piled mode, which means that each space in\
+ the input string will cause a)69.336 192 R(ne)69.336 204 Q 2.573(wl)
+-.25 G .072(ine on output, and, unless you specify other alignment, eac\
+h line will be aligned on the last digit in the)-2.573 F 1.044
+(line. Also, the meanings of / and \\/ are re)69.336 216 R -.15(ve)-.25
+G 1.044(rsed from the normal meaning. This is done since dra).15 F 1.045
+(wing a)-.15 F .588(slash through a number is v)69.336 228 R .588(ery c\
+ommon in \214gured bass, so you can just use a / to indicate this, b)
+-.15 F .587(ut if you)-.2 F(really w)69.336 240 Q
+(ant a real slash, you can still get one by entering \\/.)-.1 E -.4(Wi)
+69.336 258 S .67(th all three special quali\214ers, the usual meanings \
+of : and \\: are re).4 F -.15(ve)-.25 G .671
+(rsed. This is because piling is v).15 F(ery)-.15 E .798
+(common in these strings, so it')69.336 270 R 3.298(sh)-.55 G .798(andi\
+er to just put a : to indicate this, and for those rare cases when you)
+-3.298 F -.1(wa)69.336 282 S
+(nt a literal colon, you can still get one by entering a \\:.).1 E
+(Here is an e)69.336 300 Q(xample sho)-.15 E
+(wing chord, analysis, and \214gbass:)-.25 E/F1 10/Courier@0 SF
+(1: egc+;dgb;dfa;dgb;)105.336 318 Q
+(bold chord above 1: 1 "C"; 2 "G"; 3 "Dm"; 4 "G";)105.336 330 Q
+(rom analysis below 1: 1 "I"; 2 "V"; 3 "ii"; 4 "V";)105.336 342 Q(bar)
+105.336 354 Q(1: egc+;dgb;df#a;dgb;)105.336 378 Q
+(rom figbass below 1: 1 "6 3"; 2 "6 4"; 3 "3/"; 4 "6 4";)105.336 390 Q
+(bar)105.336 402 Q(1: 1cegb;)105.336 426 Q(rom chord above 1: 1 "C^7";)
+105.336 438 Q(bar)105.336 450 Q(1: 1ce&g&b&;)105.336 462 Q
+(rom chord above 1: 1 "Co/";)105.336 474 Q(bar)105.336 486 Q
+(1: 1ce&g&b&&;)105.336 498 Q(rom chord above 1: 1 "Co:7";)105.336 510 Q
+(bar)105.336 522 Q(1: 1e&g&b&;)105.336 534 Q
+(rom chord above 1: 1 "E&m";)105.336 546 Q(bar)105.336 558 Q 71.836
+567.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 159 rlineto 432 0 rlineto 0 159 neg rlineto closepath stroke grestore
+EEND 88 603 432 432 -159 159 70.836 726.6 PBEGIN
+%%BeginDocument: mugex69.ps
+%%BoundingBox: 88 603 520 762
+save
+331503037 331503247 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+625.58 716.47 936.00 5 1.000000 1.000000 stf
+/Times-Roman findfont
+14 scalefont
+setfont
+108.00 713.82 moveto
+(   ) show
+%  S_CLEFSIG
+133.38 710.47 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+164.38 719.47 1.000000 4n
+164.38 710.47 1.000000 4n
+164.38 704.47 1.000000 4n
+0.70 setlinewidth
+168.06 705.22 moveto
+168.06 740.47 lineto stroke
+205.49 716.47 1.000000 4n
+205.49 710.47 1.000000 4n
+205.49 701.47 1.000000 4n
+209.17 702.22 moveto
+209.17 737.47 lineto stroke
+246.60 713.47 1.000000 4n
+246.60 707.47 1.000000 4n
+246.60 701.47 1.000000 4n
+250.29 702.22 moveto
+250.29 734.47 lineto stroke
+288.56 716.47 1.000000 4n
+288.56 710.47 1.000000 4n
+288.56 701.47 1.000000 4n
+292.24 702.22 moveto
+292.24 737.47 lineto stroke
+/Times-Bold findfont
+14 scalefont
+setfont
+283.10 742.25 moveto
+(G ) show
+/Times-Bold findfont
+14 scalefont
+setfont
+241.56 741.25 moveto
+(Dm ) show
+/Times-Bold findfont
+14 scalefont
+setfont
+200.03 742.25 moveto
+(G ) show
+/Times-Bold findfont
+14 scalefont
+setfont
+159.34 745.25 moveto
+(C ) show
+/Times-Roman findfont
+14 scalefont
+setfont
+162.07 684.97 moveto
+(I ) show
+/Times-Roman findfont
+14 scalefont
+setfont
+200.45 684.97 moveto
+(V ) show
+/Times-Roman findfont
+14 scalefont
+setfont
+244.67 684.72 moveto
+(ii ) show
+/Times-Roman findfont
+14 scalefont
+setfont
+283.52 684.97 moveto
+(V ) show
+restore
+%  S_BAR
+13 linenum
+0.70 setlinewidth
+327.16 728.47 moveto
+327.16 704.47 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+340.87 719.47 1.000000 4n
+340.87 710.47 1.000000 4n
+340.87 704.47 1.000000 4n
+344.55 705.22 moveto
+344.55 740.47 lineto stroke
+380.54 716.47 1.000000 4n
+380.54 710.47 1.000000 4n
+380.54 701.47 1.000000 4n
+384.22 702.22 moveto
+384.22 737.47 lineto stroke
+423.10 713.47 1.000000 4n
+423.10 707.47 1.000000 4n
+413.74 707.47 1.000000 sharp
+423.10 701.47 1.000000 4n
+426.78 702.22 moveto
+426.78 734.47 lineto stroke
+465.05 716.47 1.000000 4n
+465.05 710.47 1.000000 4n
+465.05 701.47 1.000000 4n
+468.73 702.22 moveto
+468.73 737.47 lineto stroke
+/Times-Roman findfont
+14 scalefont
+setfont
+338.63 681.83 moveto
+338.63 688.56 moveto
+/Times-Roman findfont
+9 scalefont
+setfont
+(6) show
+338.63 679.69 moveto
+(3) show
+343.11 681.83 moveto
+/Times-Roman findfont
+14 scalefont
+setfont
+( ) show
+/Times-Roman findfont
+14 scalefont
+setfont
+378.30 681.83 moveto
+378.30 688.56 moveto
+/Times-Roman findfont
+9 scalefont
+setfont
+(6) show
+378.30 679.69 moveto
+(4) show
+382.78 681.83 moveto
+/Times-Roman findfont
+14 scalefont
+setfont
+( ) show
+/Times-Roman findfont
+14 scalefont
+setfont
+420.85 681.83 moveto
+420.85 688.56 moveto
+/Times-Roman findfont
+9 scalefont
+setfont
+(3) show
+gsave
+0.58 setlinewidth
+420.85 690.01 moveto
+425.34 692.93 lineto stroke
+grestore
+425.34 688.56 moveto
+425.34 681.83 moveto
+/Times-Roman findfont
+14 scalefont
+setfont
+( ) show
+/Times-Roman findfont
+14 scalefont
+setfont
+462.81 681.83 moveto
+462.81 688.56 moveto
+/Times-Roman findfont
+9 scalefont
+setfont
+(6) show
+462.81 679.69 moveto
+(4) show
+467.29 681.83 moveto
+/Times-Roman findfont
+14 scalefont
+setfont
+( ) show
+restore
+%  S_BAR
+17 linenum
+0.70 setlinewidth
+503.65 728.47 moveto
+503.65 704.47 lineto stroke
+%  S_FEED
+18 linenum
+612.00 632.47 936.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+119.79 626.47 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+156.35 632.47 1.000000 1n
+156.35 626.47 1.000000 1n
+156.35 620.47 1.000000 1n
+156.35 614.47 1.000000 1n
+148.93 614.47 moveto
+163.77 614.47 lineto stroke
+/Times-Roman findfont
+14 scalefont
+setfont
+151.68 657.25 moveto
+(C) show
+166.64 657.93 1.166667 triangle
+172.26 657.25 moveto
+(7 ) show
+restore
+%  S_BAR
+23 linenum
+0.70 setlinewidth
+213.78 644.47 moveto
+213.78 620.47 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+251.00 632.47 1.000000 1n
+241.04 632.47 1.000000 flat
+251.00 626.47 1.000000 1n
+230.56 626.47 1.000000 flat
+251.00 620.47 1.000000 1n
+238.05 620.47 1.000000 flat
+251.00 614.47 1.000000 1n
+243.58 614.47 moveto
+258.42 614.47 lineto stroke
+/Times-Roman findfont
+14 scalefont
+setfont
+246.34 657.25 moveto
+(C) show
+261.08 657.42 1.166667 halfdim
+266.50 657.25 moveto
+( ) show
+restore
+%  S_BAR
+26 linenum
+0.70 setlinewidth
+308.43 644.47 moveto
+308.43 620.47 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+351.56 632.47 1.000000 1n
+338.65 632.47 1.000000 dblflat
+351.56 626.47 1.000000 1n
+325.22 626.47 1.000000 flat
+351.56 620.47 1.000000 1n
+332.71 620.47 1.000000 flat
+351.56 614.47 1.000000 1n
+344.14 614.47 moveto
+358.98 614.47 lineto stroke
+/Times-Roman findfont
+14 scalefont
+setfont
+346.90 657.25 moveto
+(C) show
+360.34 657.42 1.166667 dim
+364.46 657.25 moveto
+364.46 663.97 moveto
+/Times-Roman findfont
+9 scalefont
+setfont
+(7) show
+368.94 657.25 moveto
+/Times-Roman findfont
+14 scalefont
+setfont
+( ) show
+restore
+%  S_BAR
+29 linenum
+0.70 setlinewidth
+408.99 644.47 moveto
+408.99 620.47 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+446.22 632.47 1.000000 1n
+436.26 632.47 1.000000 flat
+446.22 626.47 1.000000 1n
+425.78 626.47 1.000000 flat
+446.22 620.47 1.000000 1n
+433.27 620.47 1.000000 flat
+/Times-Roman findfont
+14 scalefont
+setfont
+441.94 657.25 moveto
+(E) show
+453.00 659.61 0.666667 flat
+455.50 657.25 moveto
+(m ) show
+restore
+%  S_BAR
+32 linenum
+0.70 setlinewidth
+503.65 644.47 moveto
+503.65 620.47 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /Times-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND EP
+%%Page: 76 82
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-7)274.506 48 S 2.5(6-)-2.5 G 1.295(If a mu\
+sic symbol occurs inside an ital or boldital string, the music symbol w\
+ill automatically be made)69.336 96 R
+(italics, to match the rest of the string.)69.336 108 Q .339
+(It is possible to supply a duration on te)69.336 126 R .338
+(xt statements. When this is done, Mup will dra)-.15 F 2.838(wad)-.15 G
+.338(ashed line from)-2.838 F .074(the end of the te)69.336 138 R .075
+(xt to the end of the duration.)-.15 F .075(This may be useful if you w)
+5.075 F .075(ant to indicate ho)-.1 F 2.575(wl)-.25 G .075
+(ong an action)-2.575 F .233
+(such as an accelerando or crescendo is to last.)69.336 150 R .233
+(If the last character of the string is a "~", a w)5.233 F -.2(av)-.1 G
+2.733(yl).2 G .233(ine will be)-2.733 F(dra)69.336 162 Q .615
+(wn instead of a dashed line.)-.15 F .616(If the last character of the \
+string is an underscore, an underscore line will)5.616 F(be dra)69.336
+174 Q(wn.)-.15 E(Here are some e)69.336 192 Q(xamples of te)-.15 E(xt:)
+-.15 E/F1 10/Courier@0 SF(1: e;g;b;d+;)105.336 210 Q(2: 2e;b-;)105.336
+222 Q(rom \(12\) above 1: 0 "Andante \( \\\(smup4n\) = 88 \)";)105.336
+234 Q(boldital \(12\) below 1: 1 "mf"; 3.5 "mp";)105.336 246 Q
+(newcentury bold \(12\) chord above 1: 1 "E&7"; 3 "B&9";)105.336 258 Q
+(ital between 1&2: 2 "rit.";)105.336 270 Q
+(palatino ital below 2: 2 "cresc." til 1m+2;)105.336 282 Q(bar)105.336
+294 Q(1: 1egc+;)105.336 306 Q(2: 1c;)105.336 318 Q
+(bold \(12\) chord above 1: 1 "Cm";)105.336 330 Q(bar)105.336 342 Q
+127.836 351.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 155 rlineto 320 0 rlineto 0 155 neg rlineto closepath stroke grestore
+EEND 160 607 320 320 -155 155 126.836 506.6 PBEGIN
+%%BeginDocument: mugex70.ps
+%%BoundingBox: 160 607 480 762
+save
+331503037 331503247 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+2 linenum
+%  S_FEED
+684.29 703.28 900.00 5 1.000000 1.000000 stf
+684.29 639.44 900.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+180.29 715.28 moveto
+180.29 627.44 lineto stroke
+%  S_CLEFSIG
+192.08 697.28 1.000000 gclef
+192.33 645.44 1.000000 fclef
+206.12 703.28 1.000000 flat
+211.61 712.28 1.000000 flat
+217.10 700.28 1.000000 flat
+206.12 633.44 1.000000 flat
+211.61 642.44 1.000000 flat
+217.10 630.44 1.000000 flat
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+240.48 691.28 1.000000 4n
+244.16 692.03 moveto
+244.16 712.28 lineto stroke
+270.89 697.28 1.000000 4n
+274.57 698.03 moveto
+274.57 718.28 lineto stroke
+301.30 703.28 1.000000 4n
+297.62 702.53 moveto
+297.62 682.28 lineto stroke
+332.55 709.28 1.000000 4n
+328.87 708.53 moveto
+328.87 688.28 lineto stroke
+/Times-Italic findfont
+12 scalefont
+setfont
+268.55 663.68 moveto
+(rit. ) show
+/NewCenturySchlbk-Bold findfont
+12 scalefont
+setfont
+296.62 727.52 moveto
+(B) show
+308.17 729.46 0.583333 flat
+310.35 727.52 moveto
+(9 ) show
+/NewCenturySchlbk-Bold findfont
+12 scalefont
+setfont
+235.94 727.52 moveto
+(E) show
+247.20 729.46 0.583333 flat
+249.38 727.52 moveto
+(7 ) show
+/Times-Roman findfont
+12 scalefont
+setfont
+227.52 740.67 moveto
+(Andante \( ) show
+281.02 742.19 0.583333 up4n
+283.99 740.67 moveto
+( = 88 \) ) show
+/Times-BoldItalic findfont
+12 scalefont
+setfont
+235.80 676.06 moveto
+(mf ) show
+/Times-BoldItalic findfont
+12 scalefont
+setfont
+312.25 677.50 moveto
+(mp ) show
+restore
+%  S_STAFF
+% staff 2
+save
+240.48 642.44 1.000000 2n
+0.70 setlinewidth
+236.58 641.69 moveto
+236.58 621.44 lineto stroke
+301.30 633.44 1.000000 2n
+305.20 634.19 moveto
+305.20 654.44 lineto stroke
+/Palatino-Italic findfont
+12 scalefont
+setfont
+306.24 613.66 moveto
+(-) show
+/Palatino-Italic findfont
+12 scalefont
+setfont
+318.12 613.66 moveto
+(-) show
+/Palatino-Italic findfont
+12 scalefont
+setfont
+330.00 613.66 moveto
+(-) show
+/Palatino-Italic findfont
+12 scalefont
+setfont
+341.88 613.66 moveto
+(-) show
+/Palatino-Italic findfont
+12 scalefont
+setfont
+353.76 613.66 moveto
+(-) show
+/Palatino-Italic findfont
+12 scalefont
+setfont
+365.64 613.66 moveto
+(-) show
+/Palatino-Italic findfont
+12 scalefont
+setfont
+377.52 613.66 moveto
+(-) show
+/Palatino-Italic findfont
+12 scalefont
+setfont
+389.40 613.66 moveto
+(-) show
+/Palatino-Italic findfont
+12 scalefont
+setfont
+401.28 613.66 moveto
+(-) show
+/Palatino-Italic findfont
+12 scalefont
+setfont
+268.44 613.66 moveto
+(cresc. ) show
+restore
+%  S_BAR
+12 linenum
+0.70 setlinewidth
+362.24 715.28 moveto
+362.24 691.28 lineto stroke
+362.24 651.44 moveto
+362.24 627.44 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+386.29 706.28 1.000000 1n
+386.29 697.28 1.000000 1n
+386.29 691.28 1.000000 1n
+/Times-Bold findfont
+12 scalefont
+setfont
+381.97 727.52 moveto
+(Cm ) show
+restore
+%  S_STAFF
+% staff 2
+save
+386.29 636.44 1.000000 1n
+restore
+%  S_BAR
+16 linenum
+0.70 setlinewidth
+467.65 715.28 moveto
+467.65 691.28 lineto stroke
+467.65 651.44 moveto
+467.65 627.44 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic /NewCenturySchlbk-Bold /Palatino-Italic 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 526.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(9.3 Grids)72.836 526.6 R 69.336 544.6
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .426
+(If the gridswhereused parameter is set to "y" chords will also ha)
+72.263 544.6 R .726 -.15(ve a g)-.2 H .426(rid printed.).15 F -.15(Fo)
+5.426 G 2.926(rt).15 G .426(his to w)-2.926 F .426(ork, a grid)-.1 F
+(with the same name as the chord must be de\214ned in "grids" conte)
+69.336 556.6 Q(xt else)-.15 E(where in the input \214le.)-.25 E 1.323
+(The grids conte)69.336 574.6 R 1.324
+(xt contains lines each consisting of tw)-.15 F 3.824(ot)-.1 G -.15(ex)
+-3.824 G 3.824(ts).15 G 3.824(trings. The)-3.824 F 1.324
+(\214rst is the name of the chord,)3.824 F .184(matching the name you w)
+69.336 586.6 R .184(ant to use in printing te)-.1 F .184
+(xt with the "chord" quali\214er)-.15 F 2.684(.T)-.55 G .184
+(he second describes the fret)-2.684 F .049(pattern for that chord. It \
+is a space-separated list, with each list element being either a fret n\
+umber from 1 to)69.336 598.6 R .864(99, which will result in a dot bein\
+g printed at that fret, or an "o" or "x" which will result in a circle \
+or x)69.336 610.6 R(respecti)69.336 622.6 Q -.15(ve)-.25 G 1.328
+(ly being printed abo).15 F 1.628 -.15(ve t)-.15 H 1.329
+(he grid, or a "-" in which case no mark at all will be made.).15 F
+1.329(The fret)6.329 F .487(pattern may also contain an open and closin\
+g parenthesis to mark where a curv)69.336 634.6 R 2.987(ei)-.15 G 2.987
+(st)-2.987 G 2.987(ob)-2.987 G 2.987(ed)-2.987 G(ra)-2.987 E .487
+(wn, indicating)-.15 F(the use of a single \214nger to span se)69.336
+646.6 Q -.15(ve)-.25 G(ral strings. F).15 E(or e)-.15 E(xample:)-.15 E
+EP
+%%Page: 77 83
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-7)274.506 48 S 2.5(7-)-2.5 G/F1 10
+/Courier@0 SF(score)105.336 96 Q(gridswhereused=y)141.336 108 Q
+(gridfret=3)141.336 120 Q(grids)105.336 132 Q 24("C" ")141.336 144 R 12
+(-32o1o)6 G(")-6 E 24("C5" ")141.336 156 R 12(-3xo13)6 G(")-6 E 24
+("Em" ")141.336 168 R 12(o22ooo)6 G(")-6 E 24("A&" "\(4)141.336 180 R 12
+(66544)12 G(\)")-12 E 18("A11" ")141.336 192 R 12(-ooooo)6 G(")-6 E
+(music)105.336 204 Q(rom chord 1: 1 "C"; 2 "C5"; 3 "Em";)105.336 228 Q
+(1: 2c;e;)105.336 240 Q(bar)105.336 252 Q(rom chord 1: 1 "A&"; 3 "A11";)
+105.336 276 Q(1: 2a&;an;)105.336 288 Q(bar)105.336 300 Q 79.836 309.6
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 95 rlineto 416 0 rlineto 0 95 neg rlineto closepath stroke grestore
+EEND 112 667 416 416 -95 95 78.836 404.6 PBEGIN
+%%BeginDocument: mugex71.ps
+%%BoundingBox: 112 667 528 762
+save
+331503037 331503247 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+633.89 696.17 950.40 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+141.68 690.17 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+179.60 678.17 1.000000 2n
+0.70 setlinewidth
+173.15 678.17 moveto
+186.05 678.17 lineto stroke
+183.50 678.92 moveto
+183.50 699.17 lineto stroke
+262.25 684.17 1.000000 2n
+266.15 684.92 moveto
+266.15 705.17 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+253.90 746.09 moveto
+(Em) show
+250.25 738.77 4.80 5 0 0 0 0 [ 0 2 2 0 0 0 ] grid
+/Times-Roman findfont
+12 scalefont
+setfont
+213.94 746.09 moveto
+(C5) show
+208.92 738.77 4.80 5 0 0 0 0 [ -2 3 -1 0 1 3 ] grid
+/Times-Roman findfont
+12 scalefont
+setfont
+175.60 746.09 moveto
+(C) show
+167.60 738.77 4.80 5 0 0 0 0 [ -2 3 2 0 1 0 ] grid
+restore
+%  S_BAR
+17 linenum
+0.70 setlinewidth
+334.77 708.17 moveto
+334.77 684.17 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+361.74 693.17 1.000000 2n
+352.75 693.17 1.000000 flat
+365.64 693.92 moveto
+365.64 714.17 lineto stroke
+445.53 693.17 1.000000 2n
+436.86 693.17 1.000000 nat
+449.43 693.92 moveto
+449.43 714.17 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+435.23 746.09 moveto
+(A11) show
+433.53 738.77 4.80 5 0 0 0 0 [ -2 0 0 0 0 0 ] grid
+/Times-Roman findfont
+12 scalefont
+setfont
+355.24 746.09 moveto
+(A) show
+366.06 748.03 0.583333 flat
+368.25 746.09 moveto
+349.74 738.77 4.80 5 4 1 1 6 [ 1 3 3 2 1 1 ] grid
+restore
+%  S_BAR
+21 linenum
+0.70 setlinewidth
+518.05 708.17 moveto
+518.05 684.17 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .557(If transposition is in ef)69.336
+424.6 R .557(fect, the chord names in the grids conte)-.25 F .557(xt ha)
+-.15 F .857 -.15(ve t)-.2 H 3.057(om).15 G .558
+(atch the transposed names.)-3.057 F(So,)5.558 E .23(for e)69.336 436.6
+R .23(xample, if you use an "A" chord in a chord statement, then transp\
+ose the staf)-.15 F 2.73(fu)-.25 G 2.73(pam)-2.73 G .23
+(ajor second, Mup)-2.73 F(will look for and use the grid de\214nition c\
+alled "B" to match the transposed chord name.)69.336 448.6 Q .808(If yo\
+u supply more than one grid de\214nition for the same chord name, Mup u\
+ses the last one. This allo)69.336 466.6 R(ws)-.25 E .72
+(you to easily "include" a \214le of standard chords, b)69.336 478.6 R
+.72(ut o)-.2 F -.15(ve)-.15 G .719(rride a fe).15 F 3.219(wo)-.25 G
+3.219(ft)-3.219 G .719(hem with a special \214ngering for a)-3.219 F
+.712(particular song. If you really w)69.336 490.6 R .713
+(ant to use more than one \214ngering in dif)-.1 F .713
+(ferent places in the same song for)-.25 F 1.569
+(the same chord name, you need to mak)69.336 502.6 R 4.068(et)-.1 G
+1.568(he names look dif)-4.068 F 1.568
+(ferent, so Mup will treat them as dif)-.25 F(ferent)-.25 E 2.504
+(chords. One)69.336 514.6 R -.1(wa)2.504 G 2.504(yt).1 G 2.504(od)-2.504
+G 2.504(ot)-2.504 G .005(his w)-2.504 F .005
+(ould be to put a space and backspace in the name.)-.1 F .005(So, for e)
+5.005 F .005(xample, "Am" and)-.15 F 1.429("Am \\b" w)69.336 526.6 R
+1.429(ould count as separate chords and could ha)-.1 F 1.729 -.15(ve d)
+-.2 H(if).15 E 1.429(ferent grid de\214nitions, b)-.25 F 1.428
+(ut the chord names)-.2 F -.1(wo)69.336 538.6 S
+(uld still look the same on output.).1 E 69.336 556.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(9.4 Mussym)72.836 556.6 R 69.336 574.6
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .699(While it is possible to place musical \
+symbols such as fermatas and coda signs using te)72.534 574.6 R .699
+(xt statements, it is)-.15 F 2.037
+(perhaps a bit confusing, since music symbols are really not part of an)
+69.336 586.6 R 4.536(yp)-.15 G 2.036(articular font. So there is a)
+-4.536 F 1.708("mussym" statement which can be used. The te)69.336 598.6
+R 1.708(xt strings after the colon must each consist of a single)-.15 F
+.679(musical symbol whose name can be gi)69.336 610.6 R -.15(ve)-.25 G
+3.179(nw).15 G .679(ithout the usual \\\(\) wrapper)-3.179 F 3.179(.T)
+-.55 G .678(he follo)-3.179 F .678(wing tw)-.25 F 3.178(ol)-.1 G .678
+(ines produce)-3.178 F(identical results, b)69.336 622.6 Q
+(ut the second is perhaps a bit clearer:)-.2 E/F1 10/Courier@0 SF
+(rom above 1: 1 "\\\(ferm\)";)105.336 640.6 Q(mussym above 1: 1 "ferm";)
+105.336 652.6 Q F0 2.845(Ad)69.336 678.6 S .345(uration is not allo)
+-2.845 F .345(wed on mussym statements e)-.25 F .346
+(xcept in one special case\212if the symbol is "tr" \(trill\). In)-.15 F
+(that case, the duration tells Mup ho)69.336 690.6 Q 2.5(wl)-.25 G
+(ong a w)-2.5 E -.2(av)-.1 G 2.5(yl).2 G(ine to dra)-2.5 E 2.5(wf)-.15 G
+(rom the end of the "tr" symbol.)-2.5 E F1(1: 2e;g;)105.336 708.6 Q
+(mussym above 1: 1 "tr" til 2; 3 "ferm";)105.336 720.6 Q(endbar)105.336
+732.6 Q EP
+%%Page: 78 84
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-7)274.506 48 S 2.5(8-)-2.5 G 127.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 64 rlineto 320 0 rlineto 0 64 neg rlineto closepath stroke grestore
+EEND 160 699 320 320 -64 64 126.836 160 PBEGIN
+%%BeginDocument: mugex72.ps
+%%BoundingBox: 160 699 480 763
+save
+331503037 331503247 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+684.29 728.05 900.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 722.05 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+232.52 716.05 1.000000 2n
+0.70 setlinewidth
+236.42 716.80 moveto
+236.42 737.05 lineto stroke
+352.71 722.05 1.000000 2n
+356.61 722.80 moveto
+356.61 743.05 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+343.67 745.06 moveto
+352.71 745.06 1.000000 ferm
+361.75 745.06 moveto
+240.55 748.06 moveto
+292.62 748.06 1.000000 wavy
+/Times-Roman findfont
+12 scalefont
+setfont
+224.49 742.06 moveto
+232.52 742.06 1.000000 tr
+240.55 742.06 moveto
+restore
+%  S_BAR
+5 linenum
+0.70 setlinewidth
+462.50 740.05 moveto
+462.50 716.05 lineto stroke
+3.00 setlinewidth
+466.50 740.05 moveto
+466.50 716.05 lineto stroke
+0.70 setlinewidth
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF 2.5(As)69.336 180 S
+(ize can optionally be speci\214ed, inside parentheses:)-2.5 E/F1 10
+/Courier@0 SF(mussym \(15\) above 2: "turn";)105.336 198 Q 69.336 224
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(9.5 Phrase)72.836 224 R(marks)3.5 E
+69.336 242 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .686(If there is only one v)72.522 242 R
+.685(oice, specifying)-.2 F/F1 10/Times-Italic@0 SF(place)3.185 E F0
+.685(for a phrase just tells Mup where to dra)3.185 F 3.185(wt)-.15 G
+.685(he phrase mark. If)-3.185 F .018(there are tw)69.336 254 R 2.519
+(oo)-.1 G 2.519(rm)-2.519 G .019(ore v)-2.519 F .019(oices, and a)-.2 F
+F1(place)2.519 E F0 .019(is speci\214ed, "abo)2.519 F -.15(ve)-.15 G
+2.519("i).15 G .019(ndicates to Mup that the phrase is associated)-2.519
+F(with v)69.336 266 Q(oice 1, and "belo)-.2 E
+(w" indicates to Mup that the phrase is associated with v)-.25 E
+(oice 2.)-.2 E .354(If no)69.336 284 R F1(place)2.854 E F0 .354
+(is speci\214ed and there is only one v)2.854 F .354
+(oice with notes, Mup will decide which side w)-.2 F .354
+(ould be better)-.1 F .539(based on the musical data.)69.336 296 R .539
+(This means the phrase mark may come out abo)5.539 F .839 -.15(ve o)-.15
+H 3.039(rb).15 G(elo)-3.039 E 4.339 -.65(w. I)-.25 H 3.039(nt).65 G .539
+(he case where)-3.039 F .307(there are tw)69.336 308 R 2.807(ov)-.1 G
+.307(oices and there are notes present in both v)-3.007 F .307
+(oices, phrase marks will be dra)-.2 F .306(wn both abo)-.15 F .606 -.15
+(ve a)-.15 H(nd).15 E(belo)69.336 320 Q -.65(w.)-.25 G .007
+(Each phrase statement item must include a be)69.336 338 R .008
+(gintime and duration.)-.15 F 2.508(Ap)5.008 G .008(hrase mark must be)
+-2.508 F .008(gin and end on a)-.15 F .75(chord, so Mup \214rst tak)
+69.336 350 R .75(es the be)-.1 F .75(gintime and duration and \214nds t\
+he chords nearest to each of them. It then)-.15 F(dra)69.336 362 Q .427
+(ws a phrase mark between them, shaping it to be out of the w)-.15 F
+.428(ay of other things as much as possible.)-.1 F(It)5.428 E .061
+(is possible to specify a "grace back up" on the be)69.336 374 R .06
+(gintime \(a ne)-.15 F -.05(ga)-.15 G(ti).05 E .36 -.15(ve n)-.25 H .06
+(umber in parentheses, specifying ho).15 F(w)-.25 E(man)69.336 386 Q
+4.042(yg)-.15 G 1.542(race notes to back up\), to mak)-4.042 F 4.043(et)
+-.1 G 1.543(he phrase include leading grace notes.)-4.043 F 1.543
+(It is possible to "nest")6.543 F(phrase marks \(i.e., ha)69.336 398 Q
+.3 -.15(ve o)-.2 H
+(ne phrase on a subset of the chords of another phrase\).).15 E(Some e)
+69.336 416 Q(xamples:)-.15 E/F2 10/Courier@0 SF(staff 2)105.336 434 Q
+(vscheme=2o)117.336 446 Q(music)105.336 470 Q(1: d;f;a;b;)105.336 494 Q
+(2,3 1: a;f;d;g;)105.336 506 Q 6(22)105.336 518 S 6(:4)-6 G
+(.c;8b-;4d;g;)-6 E(phrase 1: 1 til 4;)105.336 530 Q
+(phrase above 2,3: 1 til 2; 3 til 4;)105.336 542 Q
+(phrase below 2: 2.5 til 1m + 1.5;)105.336 554 Q(bar)105.336 566 Q
+(1: b;c+;d+;e+;)105.336 578 Q(2,3 1: g;a;f;c;)105.336 590 Q 6(22)105.336
+602 S 6(:4)-6 G(.e;8f;4b-;g;)-6 E(bar)105.336 614 Q EP
+%%Page: 79 85
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-7)274.506 48 S 2.5(9-)-2.5 G 127.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 190 rlineto 320 0 rlineto 0 190 neg rlineto closepath stroke grestore
+EEND 160 573 320 320 -190 190 126.836 286 PBEGIN
+%%BeginDocument: mugex73.ps
+%%BoundingBox: 160 573 480 763
+save
+331503037 331503247 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+3 linenum
+%  S_FEED
+684.29 731.00 900.00 5 1.000000 1.000000 stf
+684.29 676.24 900.00 5 1.000000 1.000000 stf
+684.29 601.56 900.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+180.29 743.00 moveto
+180.29 589.56 lineto stroke
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+192.08 670.24 1.000000 gclef
+192.08 595.56 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+220.93 716.00 1.000000 4n
+224.61 716.75 moveto
+224.61 737.00 lineto stroke
+247.33 722.00 1.000000 4n
+251.02 722.75 moveto
+251.02 743.00 lineto stroke
+281.58 728.00 1.000000 4n
+285.27 728.75 moveto
+285.27 749.00 lineto stroke
+310.65 731.00 1.000000 4n
+306.97 730.25 moveto
+306.97 710.00 lineto stroke
+221.68 709.72 moveto
+221.71 709.87 lineto
+236.01 705.42 250.64 702.96 265.61 702.50 curveto
+280.58 702.03 295.34 703.58 309.88 707.15 curveto
+309.92 706.85 lineto
+295.45 702.48 280.67 700.53 265.56 701.00 curveto
+250.46 701.46 235.82 704.32 221.65 709.58 curveto
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+220.93 673.24 1.000000 4n
+0.70 setlinewidth
+224.61 673.99 moveto
+224.61 694.24 lineto stroke
+247.33 667.24 1.000000 4n
+251.02 667.99 moveto
+251.02 688.24 lineto stroke
+281.58 661.24 1.000000 4n
+285.27 661.99 moveto
+285.27 682.24 lineto stroke
+310.65 670.24 1.000000 4n
+314.33 670.99 moveto
+314.33 691.24 lineto stroke
+220.93 658.24 1.000000 4n
+230.20 655.24 1.000000 dot
+214.70 658.24 moveto
+227.16 658.24 lineto stroke
+217.25 657.49 moveto
+217.25 637.24 lineto stroke
+263.37 655.24 1.000000 4n
+257.14 658.24 moveto
+269.60 658.24 lineto stroke
+259.69 654.49 moveto
+259.69 634.24 lineto stroke
+262.71 634.24 1.000000 upflag
+281.58 661.24 1.000000 4n
+277.90 660.49 moveto
+277.90 640.24 lineto stroke
+310.65 670.24 1.000000 4n
+306.97 669.49 moveto
+306.97 649.24 lineto stroke
+282.33 685.24 moveto
+282.23 685.42 lineto
+285.99 688.83 290.27 691.32 295.09 692.89 curveto
+299.91 694.46 304.83 694.98 309.87 694.45 curveto
+309.93 694.03 lineto
+304.99 694.03 300.17 693.26 295.47 691.72 curveto
+290.77 690.19 286.43 687.97 282.43 685.06 curveto
+fill
+221.68 697.24 moveto
+221.69 697.46 lineto
+226.09 698.53 230.50 698.53 234.91 697.47 curveto
+239.32 696.40 243.24 694.39 246.68 691.44 curveto
+246.49 691.04 lineto
+242.85 693.50 238.89 695.24 234.62 696.27 curveto
+230.35 697.29 226.04 697.55 221.67 697.02 curveto
+fill
+264.12 631.24 moveto
+264.13 631.39 lineto
+278.46 629.00 292.86 628.57 307.32 630.10 curveto
+321.77 631.62 335.76 635.05 349.28 640.39 curveto
+349.36 640.10 lineto
+336.02 633.98 322.06 630.15 307.47 628.61 curveto
+292.88 627.06 278.43 627.89 264.11 631.09 curveto
+fill
+restore
+%  S_STAFF
+% staff 3
+save
+220.93 598.56 1.000000 4n
+0.70 setlinewidth
+224.61 599.31 moveto
+224.61 619.56 lineto stroke
+247.33 592.56 1.000000 4n
+251.02 593.31 moveto
+251.02 613.56 lineto stroke
+281.58 586.56 1.000000 4n
+285.27 587.31 moveto
+285.27 607.56 lineto stroke
+310.65 595.56 1.000000 4n
+314.33 596.31 moveto
+314.33 616.56 lineto stroke
+282.33 610.56 moveto
+282.23 610.74 lineto
+285.99 614.15 290.27 616.64 295.09 618.21 curveto
+299.91 619.78 304.83 620.30 309.87 619.77 curveto
+309.93 619.35 lineto
+304.99 619.35 300.17 618.58 295.47 617.04 curveto
+290.77 615.51 286.43 613.29 282.43 610.38 curveto
+fill
+221.68 622.56 moveto
+221.69 622.78 lineto
+226.09 623.85 230.50 623.85 234.91 622.79 curveto
+239.32 621.72 243.24 619.71 246.68 616.76 curveto
+246.49 616.36 lineto
+242.85 618.82 238.89 620.56 234.62 621.59 curveto
+230.35 622.61 226.04 622.87 221.67 622.34 curveto
+fill
+restore
+%  S_BAR
+14 linenum
+0.70 setlinewidth
+338.51 743.00 moveto
+338.51 719.00 lineto stroke
+338.51 688.24 moveto
+338.51 664.24 lineto stroke
+338.51 613.56 moveto
+338.51 589.56 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+350.07 731.00 1.000000 4n
+346.39 730.25 moveto
+346.39 710.00 lineto stroke
+376.47 734.00 1.000000 4n
+372.79 733.25 moveto
+372.79 713.00 lineto stroke
+410.47 737.00 1.000000 4n
+406.79 736.25 moveto
+406.79 716.00 lineto stroke
+439.54 740.00 1.000000 4n
+435.86 739.25 moveto
+435.86 719.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+350.07 670.24 1.000000 4n
+0.70 setlinewidth
+353.75 670.99 moveto
+353.75 691.24 lineto stroke
+376.47 673.24 1.000000 4n
+380.15 673.99 moveto
+380.15 694.24 lineto stroke
+410.47 667.24 1.000000 4n
+414.15 667.99 moveto
+414.15 688.24 lineto stroke
+441.04 658.24 1.000000 4n
+434.81 658.24 moveto
+447.27 658.24 lineto stroke
+444.72 658.99 moveto
+444.72 679.24 lineto stroke
+350.07 664.24 1.000000 4n
+359.33 661.24 1.000000 dot
+346.39 663.49 moveto
+346.39 643.24 lineto stroke
+392.51 667.24 1.000000 4n
+388.83 666.49 moveto
+388.83 646.24 lineto stroke
+391.85 646.24 1.000000 upflag
+410.47 655.24 1.000000 4n
+404.24 658.24 moveto
+416.70 658.24 lineto stroke
+406.79 654.49 moveto
+406.79 634.24 lineto stroke
+438.04 670.24 1.000000 4n
+434.36 669.49 moveto
+434.36 649.24 lineto stroke
+restore
+%  S_STAFF
+% staff 3
+save
+350.07 595.56 1.000000 4n
+0.70 setlinewidth
+353.75 596.31 moveto
+353.75 616.56 lineto stroke
+376.47 598.56 1.000000 4n
+380.15 599.31 moveto
+380.15 619.56 lineto stroke
+410.47 592.56 1.000000 4n
+414.15 593.31 moveto
+414.15 613.56 lineto stroke
+439.54 583.56 1.000000 4n
+433.31 583.56 moveto
+445.77 583.56 lineto stroke
+443.22 584.31 moveto
+443.22 604.56 lineto stroke
+restore
+%  S_BAR
+18 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+467.65 688.24 moveto
+467.65 664.24 lineto stroke
+467.65 613.56 moveto
+467.65 589.56 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF
+(Phrase marks are sometimes used on tablature staf)69.336 306 Q
+(fs in conjunction with slides.)-.25 E/F1 10/Courier@0 SF
+(score staffs=2)105.336 324 Q(staff 2 stafflines=tab)105.336 336 Q
+(music)105.336 348 Q(2: a3<>;a4;e4<>;e2;)105.336 372 Q
+(phrase above 2: 1 til 2; 3 til 4;)105.336 384 Q(bar)105.336 396 Q
+127.836 405.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 135 rlineto 320 0 rlineto 0 135 neg rlineto closepath stroke grestore
+EEND 160 628 320 320 -135 135 126.836 540.6 PBEGIN
+%%BeginDocument: mugex74.ps
+%%BoundingBox: 160 628 480 763
+save
+331503037 331503247 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+3 linenum
+%  S_FEED
+684.29 730.70 900.00 5 1.000000 1.000000 stf
+684.29 661.40 900.00 6 1.735000 1.000000 stf
+0.70 setlinewidth
+180.29 742.70 moveto
+180.29 635.37 lineto stroke
+%  S_CLEFSIG
+192.08 724.70 1.000000 gclef
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+183.29 671.34 moveto
+(T) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+183.29 653.46 moveto
+(A) show
+/Helvetica-Bold findfont
+20 scalefont
+setfont
+183.29 635.58 moveto
+(B) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+225.05 712.70 1.000000 4n
+218.81 712.70 moveto
+231.28 712.70 lineto stroke
+228.73 713.45 moveto
+228.73 733.70 lineto stroke
+286.61 712.70 1.000000 4n
+277.26 712.70 1.000000 sharp
+280.38 712.70 moveto
+292.84 712.70 lineto stroke
+290.29 713.45 moveto
+290.29 733.70 lineto stroke
+348.17 745.70 1.000000 4n
+338.82 745.70 1.000000 sharp
+344.49 744.95 moveto
+344.49 724.70 lineto stroke
+412.01 742.70 1.000000 4n
+402.66 742.70 1.000000 sharp
+408.33 741.95 moveto
+408.33 721.70 lineto stroke
+353.20 745.70 moveto
+397.34 742.70 lineto stroke
+230.08 709.70 moveto
+271.94 715.70 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+221.70 641.53 moveto
+(3) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+283.26 641.53 moveto
+(4) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+344.82 683.17 moveto
+(4) show
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+408.66 682.99 moveto
+(2) show
+0.70 setlinewidth
+352.52 690.42 moveto
+406.66 684.42 lineto stroke
+229.39 642.78 moveto
+281.26 648.78 lineto stroke
+348.92 695.68 moveto
+348.90 695.83 lineto
+358.99 699.36 369.39 701.14 380.08 701.16 curveto
+390.78 701.18 401.18 699.44 411.28 695.93 curveto
+411.24 695.64 lineto
+401.03 698.34 390.64 699.68 380.08 699.66 curveto
+369.52 699.64 359.14 698.26 348.94 695.53 curveto
+fill
+225.80 654.25 moveto
+225.78 654.40 lineto
+235.52 657.77 245.54 659.44 255.85 659.40 curveto
+266.15 659.36 276.16 657.63 285.88 654.19 curveto
+285.84 653.89 lineto
+276.01 656.53 266.01 657.86 255.84 657.90 curveto
+245.67 657.94 235.66 656.67 225.82 654.11 curveto
+fill
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+467.65 742.70 moveto
+467.65 718.70 lineto stroke
+467.65 687.42 moveto
+467.65 635.37 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Helvetica-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .471(The w)69.336 560.6 R .471(ord "phr\
+ase" can be preceded by a line type modi\214er: dotted or dashed.)-.1 F
+.47(The dotted or dashed styles)5.47 F .318(might be used for phrase ma\
+rks that were added by an editor rather than the composer)69.336 572.6 R
+2.818(,o)-.4 G 2.818(rt)-2.818 G 2.818(os)-2.818 G(ho)-2.818 E 2.818
+(wap)-.25 G(hrase)-2.818 E(that doesn')69.336 584.6 Q 2.5(ta)-.18 G
+(pply to all v)-2.5 E(erses.)-.15 E 69.336 602.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(9.6 Cr)72.836 602.6 R(escendo and decr)
+-.252 E(escendo marks)-.252 E 69.336 620.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .4(The "<" and ">" statements are used to s\
+pecify crescendo and decrescendo marks respecti)72.236 620.6 R -.15(ve)
+-.25 G(ly).15 E 2.9(.E)-.65 G .4(ach mark)-2.9 F .623(must include a be)
+69.336 632.6 R .623(gintime and duration.)-.15 F .623(The be)5.623 F
+.623(gintime can include a grace back up speci\214cation, to mak)-.15 F
+(e)-.1 E(the mark apply to grace notes.)69.336 644.6 Q(Some e)5 E
+(xamples:)-.15 E EP
+%%Page: 80 86
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-8)274.506 48 S 2.5(0-)-2.5 G/F1 10
+/Courier@0 SF(1-2: c;d;e;f;)105.336 96 Q 6(<b)105.336 108 S
+(elow 1: 1 til 2; 3 til 4.5;)-6 E(3: 2c;g;)105.336 120 Q 6(>b)105.336
+132 S(etween 2&3: 1.7 til 2m + 1;)-6 E(bar)105.336 144 Q(1-2: d;e;2g;)
+105.336 156 Q(3: 2d;a;)105.336 168 Q 6(<2)105.336 180 S(,3: 2 til 3.8;)
+-6 E(bar)105.336 192 Q(1-2: e;g;2c;)105.336 204 Q(3: 2.e;4c;)105.336 216
+Q(endbar)105.336 228 Q 91.836 237.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 178 rlineto 392 0 rlineto 0 178 neg rlineto closepath stroke grestore
+EEND 128 585 392 392 -178 178 90.836 415.6 PBEGIN
+%%BeginDocument: mugex75.ps
+%%BoundingBox: 128 585 520 763
+save
+331503037 331503247 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+2 linenum
+%  S_FEED
+648.29 731.00 936.00 5 1.000000 1.000000 stf
+648.29 674.71 936.00 5 1.000000 1.000000 stf
+648.29 613.95 936.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+144.29 743.00 moveto
+144.29 601.95 lineto stroke
+%  S_CLEFSIG
+156.08 725.00 1.000000 gclef
+156.08 668.71 1.000000 gclef
+156.33 619.95 1.000000 fclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+185.03 713.00 1.000000 4n
+178.79 713.00 moveto
+191.26 713.00 lineto stroke
+188.71 713.75 moveto
+188.71 734.00 lineto stroke
+209.50 716.00 1.000000 4n
+213.18 716.75 moveto
+213.18 737.00 lineto stroke
+233.98 719.00 1.000000 4n
+237.66 719.75 moveto
+237.66 740.00 lineto stroke
+259.29 722.00 1.000000 4n
+262.98 722.75 moveto
+262.98 743.00 lineto stroke
+185.03 704.72 moveto
+209.50 707.72 lineto stroke
+185.03 704.72 moveto
+209.50 701.72 lineto stroke
+233.98 709.72 moveto
+271.66 713.72 lineto stroke
+233.98 709.72 moveto
+271.66 705.71 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+185.03 656.71 1.000000 4n
+0.70 setlinewidth
+178.79 656.71 moveto
+191.26 656.71 lineto stroke
+188.71 657.46 moveto
+188.71 677.71 lineto stroke
+209.50 659.71 1.000000 4n
+213.18 660.46 moveto
+213.18 680.71 lineto stroke
+233.98 662.71 1.000000 4n
+237.66 663.46 moveto
+237.66 683.71 lineto stroke
+259.29 665.71 1.000000 4n
+262.98 666.46 moveto
+262.98 686.71 lineto stroke
+202.16 651.33 moveto
+399.00 646.33 lineto stroke
+202.16 641.34 moveto
+399.00 646.34 lineto stroke
+restore
+%  S_STAFF
+% staff 3
+save
+185.03 610.95 1.000000 2n
+0.70 setlinewidth
+188.92 611.70 moveto
+188.92 631.95 lineto stroke
+233.98 622.95 1.000000 2n
+230.08 622.20 moveto
+230.08 601.95 lineto stroke
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+284.03 743.00 moveto
+284.03 719.00 lineto stroke
+284.03 686.71 moveto
+284.03 662.71 lineto stroke
+284.03 625.95 moveto
+284.03 601.95 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+295.18 716.00 1.000000 4n
+298.86 716.75 moveto
+298.86 737.00 lineto stroke
+319.62 719.00 1.000000 4n
+323.30 719.75 moveto
+323.30 740.00 lineto stroke
+347.96 725.00 1.000000 2n
+351.86 725.75 moveto
+351.86 746.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+295.18 659.71 1.000000 4n
+0.70 setlinewidth
+298.86 660.46 moveto
+298.86 680.71 lineto stroke
+319.62 662.71 1.000000 4n
+323.30 663.46 moveto
+323.30 683.71 lineto stroke
+347.96 668.71 1.000000 2n
+351.86 669.46 moveto
+351.86 689.71 lineto stroke
+319.62 695.72 moveto
+363.91 699.72 lineto stroke
+319.62 695.72 moveto
+363.91 691.71 lineto stroke
+restore
+%  S_STAFF
+% staff 3
+save
+295.18 613.95 1.000000 2n
+0.70 setlinewidth
+291.28 613.20 moveto
+291.28 592.95 lineto stroke
+347.96 625.95 1.000000 2n
+344.06 625.20 moveto
+344.06 604.95 lineto stroke
+319.62 635.33 moveto
+363.91 639.34 lineto stroke
+319.62 635.33 moveto
+363.91 631.33 lineto stroke
+restore
+%  S_BAR
+13 linenum
+0.70 setlinewidth
+387.85 743.00 moveto
+387.85 719.00 lineto stroke
+387.85 686.71 moveto
+387.85 662.71 lineto stroke
+387.85 625.95 moveto
+387.85 601.95 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+399.00 719.00 1.000000 4n
+402.68 719.75 moveto
+402.68 740.00 lineto stroke
+423.44 725.00 1.000000 4n
+427.12 725.75 moveto
+427.12 746.00 lineto stroke
+448.13 713.00 1.000000 2n
+441.68 713.00 moveto
+454.57 713.00 lineto stroke
+452.02 713.75 moveto
+452.02 734.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+399.00 662.71 1.000000 4n
+0.70 setlinewidth
+402.68 663.46 moveto
+402.68 683.71 lineto stroke
+423.44 668.71 1.000000 4n
+427.12 669.46 moveto
+427.12 689.71 lineto stroke
+448.13 656.71 1.000000 2n
+441.68 656.71 moveto
+454.57 656.71 lineto stroke
+452.02 657.46 moveto
+452.02 677.71 lineto stroke
+restore
+%  S_STAFF
+% staff 3
+save
+399.00 616.95 1.000000 2n
+408.48 616.95 1.000000 dot
+0.70 setlinewidth
+395.10 616.20 moveto
+395.10 595.95 lineto stroke
+473.26 610.95 1.000000 4n
+476.95 611.70 moveto
+476.95 631.95 lineto stroke
+restore
+%  S_BAR
+15 linenum
+0.70 setlinewidth
+498.50 743.00 moveto
+498.50 719.00 lineto stroke
+3.00 setlinewidth
+502.50 743.00 moveto
+502.50 719.00 lineto stroke
+0.70 setlinewidth
+498.50 686.71 moveto
+498.50 662.71 lineto stroke
+3.00 setlinewidth
+502.50 686.71 moveto
+502.50 662.71 lineto stroke
+0.70 setlinewidth
+498.50 625.95 moveto
+498.50 601.95 lineto stroke
+3.00 setlinewidth
+502.50 625.95 moveto
+502.50 601.95 lineto stroke
+0.70 setlinewidth
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF(The placement of crescendo and decresce\
+ndo marks can be controlled by setting the dyndist parameter)69.336
+435.6 Q(.)-.55 E 69.336 453.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(9.7 Octa)72.836 453.6 R .28 -.14(ve m)
+-.35 H(arks).14 E 69.336 471.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(Octa)72.544 471.6 Q 1.008 -.15(ve s)-.2 H
+.708(tatements are used to mark notes that are to be played one or more\
+ octa).15 F -.15(ve)-.2 G 3.208(sh).15 G .708(igher or lo)-3.208 F .708
+(wer than)-.25 F 2.955(written. An)69.336 483.6 R("octa)2.955 E .755
+-.15(ve a)-.2 H(bo).15 E -.15(ve)-.15 G 2.955("s).15 G .455
+(tatement is used to specify playing higher than written, or "octa)
+-2.955 F .755 -.15(ve b)-.2 H(elo).15 E .455(w" for)-.25 F .954
+(playing lo)69.336 495.6 R .954
+(wer than written. Each item must include a be)-.25 F .954
+(gintime and a te)-.15 F .954(xt string. The te)-.15 F .953
+(xt string is most)-.15 F 1.352(typically "8v)69.336 507.6 R 3.853
+(a". It)-.25 F 1.353(will al)3.853 F -.1(wa)-.1 G 1.353
+(ys be printed in 12-point times italics font. If the octa).1 F 1.653
+-.15(ve s)-.2 H 1.353(hifting applies to).15 F 1.199(more than a single\
+ chord, there should also be a duration speci\214ed, reaching to includ\
+e the last af)69.336 519.6 R(fected)-.25 E 3.325(note. In)69.336 531.6 R
+.825(this case, Mup will dra)3.325 F 3.326(wad)-.15 G .826
+(ashed line to mark the span af)-3.326 F .826
+(fected. Note that specifying the e)-.25 F(xact)-.15 E .062(beat of a c\
+hord indicates the horizontal center of the chord, so if you w)69.336
+543.6 R .062(ant the dashed line to reach a bit past)-.1 F .137
+(the note, it will be necessary to specify a duration slightly be)69.336
+555.6 R .138(yond the point of the last chord to be included.)-.15 F
+(Examples:)69.336 567.6 Q/F1 10/Courier@0 SF(1: 2f;g;)105.336 585.6 Q
+(2: 2d+;g;)105.336 597.6 Q(3: 2g;ce;)105.336 609.6 Q
+(octave above 1: 2 "8va" til 1m + 1.3;)105.336 621.6 Q(bar)105.336 633.6
+Q(1: 2a;c;)105.336 645.6 Q(2: 2f;e;)105.336 657.6 Q(3: 4f;;c;;)105.336
+669.6 Q(octave below 2: 1 "8va";)105.336 681.6 Q
+(octave below 3: 1 "8va" til 2.5; 3 "15" til 4.5;)105.336 693.6 Q(bar)
+105.336 705.6 Q EP
+%%Page: 81 87
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-8)274.506 48 S 2.5(1-)-2.5 G 127.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 183 rlineto 320 0 rlineto 0 183 neg rlineto closepath stroke grestore
+EEND 160 580 320 320 -183 183 126.836 279 PBEGIN
+%%BeginDocument: mugex76.ps
+%%BoundingBox: 160 580 480 763
+save
+1216322504 1216321786 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+324.29 1230.85 468.00 5 1.000000 1.000000 stf
+324.29 1176.85 468.00 5 1.000000 1.000000 stf
+324.29 1122.85 468.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+180.29 738.85 moveto
+180.29 606.85 lineto stroke
+%  S_CLEFSIG
+192.08 720.85 1.000000 gclef
+192.08 666.85 1.000000 gclef
+192.08 612.85 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+225.44 717.85 1.000000 2n
+229.34 718.60 moveto
+229.34 738.85 lineto stroke
+280.71 720.85 1.000000 2n
+284.61 721.60 moveto
+284.61 741.85 lineto stroke
+1.00 setlinewidth
+[3 3] 0 setdash
+273.37 751.50 moveto
+352.07 751.50 lineto stroke
+352.07 751.50 moveto
+352.07 742.50 lineto stroke
+0.70 setlinewidth
+[] 0 setdash
+0 setlinecap
+0 setlinejoin
+/Times-Italic findfont
+12 scalefont
+setfont
+250.09 747.00 moveto
+(8va) show
+restore
+%  S_STAFF
+% staff 2
+save
+225.44 678.85 1.000000 2n
+0.70 setlinewidth
+221.54 678.10 moveto
+221.54 657.85 lineto stroke
+280.71 666.85 1.000000 2n
+284.61 667.60 moveto
+284.61 687.85 lineto stroke
+restore
+%  S_STAFF
+% staff 3
+save
+225.44 612.85 1.000000 2n
+0.70 setlinewidth
+229.34 613.60 moveto
+229.34 633.85 lineto stroke
+280.71 606.85 1.000000 2n
+280.71 600.85 1.000000 2n
+274.26 600.85 moveto
+287.16 600.85 lineto stroke
+284.61 601.60 moveto
+284.61 627.85 lineto stroke
+restore
+%  S_BAR
+8 linenum
+0.70 setlinewidth
+330.42 738.85 moveto
+330.42 714.85 lineto stroke
+330.42 684.85 moveto
+330.42 660.85 lineto stroke
+330.42 630.85 moveto
+330.42 606.85 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+342.70 723.85 1.000000 2n
+346.60 724.60 moveto
+346.60 744.85 lineto stroke
+405.19 708.85 1.000000 2n
+398.74 708.85 moveto
+411.64 708.85 lineto stroke
+409.09 709.60 moveto
+409.09 729.85 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+342.70 663.85 1.000000 2n
+0.70 setlinewidth
+346.60 664.60 moveto
+346.60 684.85 lineto stroke
+405.19 660.85 1.000000 2n
+409.09 661.60 moveto
+409.09 681.85 lineto stroke
+/Times-Italic findfont
+12 scalefont
+setfont
+339.71 650.46 moveto
+(8va) show
+restore
+%  S_STAFF
+% staff 3
+save
+342.70 609.85 1.000000 4n
+0.70 setlinewidth
+346.38 610.60 moveto
+346.38 630.85 lineto stroke
+373.94 609.85 1.000000 4n
+377.63 610.60 moveto
+377.63 630.85 lineto stroke
+405.19 600.85 1.000000 4n
+398.96 600.85 moveto
+411.42 600.85 lineto stroke
+408.87 601.60 moveto
+408.87 621.85 lineto stroke
+437.27 600.85 1.000000 4n
+431.04 600.85 moveto
+443.51 600.85 lineto stroke
+440.96 601.60 moveto
+440.96 621.85 lineto stroke
+1.00 setlinewidth
+[3 3] 0 setdash
+362.99 601.07 moveto
+389.57 601.07 lineto stroke
+389.57 601.07 moveto
+389.57 610.07 lineto stroke
+0.70 setlinewidth
+[] 0 setdash
+0 setlinecap
+0 setlinejoin
+/Times-Italic findfont
+12 scalefont
+setfont
+339.71 596.57 moveto
+(8va) show
+1.00 setlinewidth
+[3 3] 0 setdash
+420.15 592.00 moveto
+452.46 592.00 lineto stroke
+452.46 592.00 moveto
+452.46 601.00 lineto stroke
+0.70 setlinewidth
+[] 0 setdash
+0 setlinecap
+0 setlinejoin
+/Times-Italic findfont
+12 scalefont
+setfont
+402.20 587.50 moveto
+(15) show
+restore
+%  S_BAR
+14 linenum
+0.70 setlinewidth
+467.65 738.85 moveto
+467.65 714.85 lineto stroke
+467.65 684.85 moveto
+467.65 660.85 lineto stroke
+467.65 630.85 moveto
+467.65 606.85 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Italic 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 299 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(9.8 Piano)72.836 299 R(pedal marks)3.5 E
+69.336 317 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.412(Piano pedal marks are some)73.248 317
+R 1.412(what dif)-.25 F 1.412
+(ferent than other statements described in this section.)-.25 F 1.412
+(Rather than)6.412 F(ha)69.336 329 Q .461(ving be)-.2 F .461
+(gintime, te)-.15 F .461(xt, and duration, each item is just a time of)
+-.15 F .462(fset v)-.25 F .462(alue, plus an optional "*". If no pedal)
+-.25 F 2.219(mark is currently in progress, the \214rst time of)69.336
+341 R 2.219(fset v)-.25 F 2.218
+(alue indicates where the pedal is depressed. An)-.25 F(y)-.15 E .034
+(subsequent pedal items on that staf)69.336 353 R 2.534(fw)-.25 G .034(\
+ill then indicate a "blip"\212lifting and then immediately depressing t\
+he)-2.534 F .286(pedal \(which is indicated on the printed music by a "\
+^"\), unless there is a "*", in which case it means to lift)69.336 365 R
+(the pedal and lea)69.336 377 Q .3 -.15(ve i)-.2 H 2.5(tu).15 G(p.)-2.5
+E(Some e)69.336 395 Q(xamples may help:)-.15 E/F1 10/Courier@0 SF
+(1: c;d;e;2.g;)105.336 413 Q(2: 1.ceg;)105.336 425 Q
+(// depress pedal on beat 1, release on 3)105.336 437 Q(pedal 2: 1; 3*;)
+105.336 449 Q(bar)105.336 461 Q(1: g;d;e;f;g;;)105.336 485 Q(2: 1.gdb-;)
+105.336 497 Q(// depress pedal on 2, release and depress)105.336 509 Q
+(// on 4, release on 6)105.336 521 Q(pedal below 2: 2; 4; 6*;)105.336
+533 Q(bar)105.336 545 Q 127.836 554.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 113 rlineto 320 0 rlineto 0 113 neg rlineto closepath stroke grestore
+EEND 160 650 320 320 -113 113 126.836 667.6 PBEGIN
+%%BeginDocument: mugex77.ps
+%%BoundingBox: 160 650 480 763
+save
+1216322504 1216321786 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+2 linenum
+%  S_FEED
+334.29 1235.00 468.00 5 1.000000 1.000000 stf
+334.29 1181.00 468.00 5 1.000000 1.000000 stf
+189.79 743.00 665.00 brace
+0.70 setlinewidth
+190.29 743.00 moveto
+190.29 665.00 lineto stroke
+%  S_CLEFSIG
+202.08 725.00 1.000000 gclef
+202.33 683.00 1.000000 fclef
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+214.38 731.00 moveto
+(6) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+214.38 718.98 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+214.38 677.00 moveto
+(6) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+214.38 664.98 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+242.20 713.00 1.000000 4n
+235.97 713.00 moveto
+248.44 713.00 lineto stroke
+245.89 713.75 moveto
+245.89 734.00 lineto stroke
+260.62 716.00 1.000000 4n
+264.30 716.75 moveto
+264.30 737.00 lineto stroke
+279.00 719.00 1.000000 4n
+282.69 719.75 moveto
+282.69 740.00 lineto stroke
+301.21 725.00 1.000000 2n
+310.69 728.00 1.000000 dot
+305.11 725.75 moveto
+305.11 746.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+242.20 686.00 1.000000 1n
+252.66 686.00 1.000000 dot
+242.20 680.00 1.000000 1n
+252.66 680.00 1.000000 dot
+242.20 674.00 1.000000 1n
+252.66 674.00 1.000000 dot
+0.70 setlinewidth
+242.20 664.00 moveto
+242.20 657.02 lineto stroke
+242.20 657.02 moveto
+244.73 657.02 lineto stroke
+244.07 657.02 moveto
+277.11 657.02 lineto stroke
+276.44 657.02 moveto
+279.00 657.02 lineto stroke
+279.00 664.00 moveto
+279.00 657.02 lineto stroke
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+343.92 743.00 moveto
+343.92 719.00 lineto stroke
+343.92 689.00 moveto
+343.92 665.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+355.03 725.00 1.000000 4n
+358.72 725.75 moveto
+358.72 746.00 lineto stroke
+373.45 716.00 1.000000 4n
+377.13 716.75 moveto
+377.13 737.00 lineto stroke
+391.87 719.00 1.000000 4n
+395.55 719.75 moveto
+395.55 740.00 lineto stroke
+410.29 722.00 1.000000 4n
+413.97 722.75 moveto
+413.97 743.00 lineto stroke
+428.71 725.00 1.000000 4n
+432.39 725.75 moveto
+432.39 746.00 lineto stroke
+447.96 725.00 1.000000 4n
+451.64 725.75 moveto
+451.64 746.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+355.03 686.00 1.000000 1n
+365.49 686.00 1.000000 dot
+355.03 677.00 1.000000 1n
+365.49 680.00 1.000000 dot
+355.03 671.00 1.000000 1n
+365.49 674.00 1.000000 dot
+0.70 setlinewidth
+373.45 664.00 moveto
+373.45 657.02 lineto stroke
+373.45 657.02 moveto
+375.98 657.02 lineto stroke
+375.31 657.02 moveto
+405.58 657.02 lineto stroke
+405.25 657.02 moveto
+410.29 664.00 lineto stroke
+410.29 664.00 moveto
+415.33 657.02 lineto stroke
+414.99 657.02 moveto
+446.06 657.02 lineto stroke
+445.40 657.02 moveto
+447.96 657.02 lineto stroke
+447.96 664.00 moveto
+447.96 657.02 lineto stroke
+restore
+%  S_BAR
+16 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+467.65 689.00 moveto
+467.65 665.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF(See also the "pedstyle" parameter)69.336
+687.6 Q(.)-.55 E 69.336 705.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(9.9 Rolls)72.836 705.6 R 69.336 723.6
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(Rolls can be speci\214ed with the "roll" st\
+atement, which has a format:)71.836 723.6 Q EP
+%%Page: 82 88
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-8)274.506 48 S 2.5(2-)-2.5 G/F1 10
+/Times-Bold@0 SF -.18(ro)105.336 96 S(ll).18 E/F2 10/Times-Italic@0 SF
+(staf)6 E 2.5(fv)-.18 G(oice)-2.5 E F1(:)6 E F2(time)6 E(val)-.15 E F1
+(;)A F0 2.5(As)69.336 122 S(imple e)-2.5 E(xample w)-.15 E(ould be:)-.1
+E/F3 10/Courier@0 SF(roll 2 1: 3;)105.336 140 Q F0 .145(which indicates\
+ that a roll is to be placed on the chord at count 3 of staf)69.336 160
+R 2.645(f2v)-.25 G .145(oice 1.)-2.845 F .146(As usual, if the)5.145 F
+F2(voice)2.646 E F0(is)2.646 E(omitted, v)69.336 172 Q
+(oice 1 is assumed.)-.2 E .741
+(Multiple rolls in a measure can be listed on a single statement if the)
+69.336 190 R 3.241(ya)-.15 G .741(re associated with the same v)-3.241 F
+(oice.)-.2 E -.15(Fo)69.336 202 S 2.5(re).15 G(xample:)-2.65 E F3
+(1: ceg;dfa;egb;fac+;)105.336 220 Q(// rolls on 3 chords: on the first,)
+105.336 232 Q(// second, and third beats of the measure)105.336 244 Q
+(roll 1: 1;2;3;)105.336 256 Q(bar)105.336 268 Q 127.836 277.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 66 rlineto 320 0 rlineto 0 66 neg rlineto closepath stroke grestore
+EEND 160 697 320 320 -66 66 126.836 343.6 PBEGIN
+%%BeginDocument: mugex78.ps
+%%BoundingBox: 160 697 480 763
+save
+1216322504 1216321786 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+324.29 1235.00 468.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+235.99 725.00 1.000000 4n
+235.99 719.00 1.000000 4n
+235.99 713.00 1.000000 4n
+0.70 setlinewidth
+229.75 713.00 moveto
+242.22 713.00 lineto stroke
+239.67 713.75 moveto
+239.67 746.00 lineto stroke
+224.95 728.28 moveto
+224.95 709.72 1.000000 wavy
+294.55 728.00 1.000000 4n
+294.55 722.00 1.000000 4n
+294.55 716.00 1.000000 4n
+298.23 716.75 moveto
+298.23 749.00 lineto stroke
+283.52 731.28 moveto
+283.52 712.72 1.000000 wavy
+355.11 731.00 1.000000 4n
+355.11 725.00 1.000000 4n
+355.11 719.00 1.000000 4n
+358.79 719.75 moveto
+358.79 752.00 lineto stroke
+344.08 734.28 moveto
+344.08 715.72 1.000000 wavy
+414.51 734.00 1.000000 4n
+414.51 728.00 1.000000 4n
+414.51 722.00 1.000000 4n
+418.19 722.75 moveto
+418.19 755.00 lineto stroke
+restore
+%  S_BAR
+8 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF -.1(wo)69.336 357.6 S
+(uld produce rolls on the chords on counts 1, 2, and 3.).1 E 2.567(Ar)
+69.336 375.6 S .067(oll can e)-2.567 F .067(xtend o)-.15 F -.15(ve)-.15
+G 2.567(rs).15 G -2.15 -.25(ev e)-2.567 H .067(ral chords on dif).25 F
+.067(ferent v)-.25 F .067(oices, or e)-.2 F -.15(ve)-.25 G 2.567(nd).15
+G(if)-2.567 E .067(ferent staf)-.25 F .068
+(fs. This is speci\214ed by gi)-.25 F(ving)-.25 E
+(the top and bottom staf)69.336 387.6 Q(fs and v)-.25 E
+(oices, with the k)-.2 E -.15(ey)-.1 G -.1(wo).15 G
+(rd "to" between them. F).1 E(or e)-.15 E(xample:)-.15 E/F1 10/Courier@0
+SF(1: 4.r;8g+b+d++ tie;2;)105.336 405.6 Q(2-3: 4.ceg;8gbd+ tie;2;)
+105.336 417.6 Q(roll 1 1 to 3 1: 2.5;)105.336 429.6 Q(bar)105.336 441.6
+Q 127.836 451.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 190 rlineto 320 0 rlineto 0 190 neg rlineto closepath stroke grestore
+EEND 160 573 320 320 -190 190 126.836 641.2 PBEGIN
+%%BeginDocument: mugex79.ps
+%%BoundingBox: 160 573 480 763
+save
+1216322504 1216321786 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_SSV
+2 linenum
+%  S_FEED
+324.29 1222.50 468.00 5 1.000000 1.000000 stf
+324.29 1168.50 468.00 5 1.000000 1.000000 stf
+324.29 1109.00 468.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+180.29 730.50 moveto
+180.29 593.00 lineto stroke
+%  S_CLEFSIG
+192.08 712.50 1.000000 gclef
+192.08 658.50 1.000000 gclef
+192.33 611.00 1.000000 fclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+228.68 718.50 1.000000 4rest
+236.98 721.50 1.000000 dot
+313.51 745.50 1.000000 4n
+307.28 742.50 moveto
+319.75 742.50 lineto stroke
+307.28 736.50 moveto
+319.75 736.50 lineto stroke
+313.51 739.50 1.000000 4n
+307.28 736.50 moveto
+319.75 736.50 lineto stroke
+313.51 733.50 1.000000 4n
+309.83 744.75 moveto
+309.83 712.50 lineto stroke
+312.86 712.50 1.000000 upflag
+302.48 748.77 moveto
+302.48 610.72 1.000000 wavy
+362.87 745.50 1.000000 2n
+356.42 742.50 moveto
+369.32 742.50 lineto stroke
+356.42 736.50 moveto
+369.32 736.50 lineto stroke
+362.87 739.50 1.000000 2n
+356.42 736.50 moveto
+369.32 736.50 lineto stroke
+362.87 733.50 1.000000 2n
+358.97 744.75 moveto
+358.97 712.50 lineto stroke
+313.51 728.40 moveto
+313.54 728.56 lineto
+320.44 726.80 327.45 725.92 334.57 725.92 curveto
+341.69 725.92 348.70 726.80 355.60 728.56 curveto
+355.65 728.23 lineto
+348.83 725.78 341.81 724.56 334.57 724.56 curveto
+327.33 724.56 320.30 725.78 313.49 728.23 curveto
+fill
+319.55 739.50 moveto
+319.52 739.68 lineto
+325.36 741.77 331.38 742.82 337.58 742.82 curveto
+343.79 742.82 349.81 741.77 355.65 739.68 curveto
+355.59 739.31 lineto
+349.69 740.83 343.68 741.59 337.58 741.59 curveto
+331.48 741.59 325.48 740.83 319.57 739.31 curveto
+fill
+315.51 750.60 moveto
+315.49 750.75 lineto
+322.83 753.40 330.39 754.72 338.19 754.72 curveto
+345.99 754.72 353.56 753.40 360.89 750.75 curveto
+360.85 750.44 lineto
+353.41 752.33 345.86 753.28 338.19 753.28 curveto
+330.52 753.28 322.97 752.33 315.54 750.44 curveto
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+228.68 658.50 1.000000 4n
+237.94 661.50 1.000000 dot
+228.68 652.50 1.000000 4n
+237.94 655.50 1.000000 dot
+228.68 646.50 1.000000 4n
+237.94 649.50 1.000000 dot
+0.70 setlinewidth
+222.44 646.50 moveto
+234.91 646.50 lineto stroke
+232.36 647.25 moveto
+232.36 679.50 lineto stroke
+313.51 670.50 1.000000 4n
+313.51 664.50 1.000000 4n
+313.51 658.50 1.000000 4n
+309.83 669.75 moveto
+309.83 637.50 lineto stroke
+312.86 637.50 1.000000 upflag
+362.87 670.50 1.000000 2n
+362.87 664.50 1.000000 2n
+362.87 658.50 1.000000 2n
+358.97 669.75 moveto
+358.97 637.50 lineto stroke
+313.51 653.40 moveto
+313.54 653.56 lineto
+320.44 651.80 327.45 650.92 334.57 650.92 curveto
+341.69 650.92 348.70 651.80 355.60 653.56 curveto
+355.65 653.23 lineto
+348.83 650.78 341.81 649.56 334.57 649.56 curveto
+327.33 649.56 320.30 650.78 313.49 653.23 curveto
+fill
+319.55 664.50 moveto
+319.52 664.68 lineto
+325.36 666.77 331.38 667.82 337.58 667.82 curveto
+343.79 667.82 349.81 666.77 355.65 664.68 curveto
+355.59 664.31 lineto
+349.69 665.83 343.68 666.59 337.58 666.59 curveto
+331.48 666.59 325.48 665.83 319.57 664.31 curveto
+fill
+315.51 675.60 moveto
+315.49 675.75 lineto
+322.83 678.40 330.39 679.72 338.19 679.72 curveto
+345.99 679.72 353.56 678.40 360.89 675.75 curveto
+360.85 675.44 lineto
+353.41 677.33 345.86 678.28 338.19 678.28 curveto
+330.52 678.28 322.97 677.33 315.54 675.44 curveto
+fill
+restore
+%  S_STAFF
+% staff 3
+save
+228.68 614.00 1.000000 4n
+237.94 614.00 1.000000 dot
+228.68 608.00 1.000000 4n
+237.94 608.00 1.000000 dot
+228.68 602.00 1.000000 4n
+237.94 602.00 1.000000 dot
+0.70 setlinewidth
+224.99 613.25 moveto
+224.99 581.00 lineto stroke
+313.51 626.00 1.000000 4n
+307.28 623.00 moveto
+319.75 623.00 lineto stroke
+313.51 620.00 1.000000 4n
+313.51 614.00 1.000000 4n
+309.83 625.25 moveto
+309.83 593.00 lineto stroke
+312.86 593.00 1.000000 upflag
+362.87 626.00 1.000000 2n
+356.42 623.00 moveto
+369.32 623.00 lineto stroke
+362.87 620.00 1.000000 2n
+362.87 614.00 1.000000 2n
+358.97 625.25 moveto
+358.97 593.00 lineto stroke
+313.51 608.90 moveto
+313.54 609.06 lineto
+320.44 607.30 327.45 606.42 334.57 606.42 curveto
+341.69 606.42 348.70 607.30 355.60 609.06 curveto
+355.65 608.73 lineto
+348.83 606.28 341.81 605.05 334.57 605.05 curveto
+327.33 605.05 320.30 606.28 313.49 608.73 curveto
+fill
+319.55 620.00 moveto
+319.52 620.18 lineto
+325.36 622.27 331.38 623.32 337.58 623.32 curveto
+343.79 623.32 349.81 622.27 355.65 620.18 curveto
+355.59 619.81 lineto
+349.69 621.33 343.68 622.09 337.58 622.09 curveto
+331.48 622.09 325.48 621.33 319.57 619.81 curveto
+fill
+315.51 631.10 moveto
+315.49 631.25 lineto
+322.83 633.90 330.39 635.22 338.19 635.22 curveto
+345.99 635.22 353.56 633.90 360.89 631.25 curveto
+360.85 630.94 lineto
+353.41 632.83 345.86 633.77 338.19 633.77 curveto
+330.52 633.77 322.97 632.83 315.54 630.94 curveto
+fill
+restore
+%  S_BAR
+8 linenum
+0.70 setlinewidth
+467.65 730.50 moveto
+467.65 706.50 lineto stroke
+467.65 676.50 moveto
+467.65 652.50 lineto stroke
+467.65 617.00 moveto
+467.65 593.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF(The roll w)69.336 655.2 Q(ould e)-.1 E
+(xtend from v)-.15 E(oice 1 of staf)-.2 E 2.5(f1t)-.25 G 2.5(ov)-2.5 G
+(oice 1 of staf)-2.7 E 2.5(f3)-.25 G(.)-2.5 E .835
+(If you wish the roll to be do)69.336 673.2 R(wnw)-.25 E .835
+(ard, the k)-.1 F -.15(ey)-.1 G -.1(wo).15 G .835(rd "do).1 F .835
+(wn" can be placed after "roll." This will result in a)-.25 F(do)69.336
+685.2 Q(wnw)-.25 E(ard arro)-.1 E 2.5(wb)-.25 G(eing dra)-2.5 E
+(wn on the bottom end of the roll.)-.15 E EP
+%%Page: 83 89
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-8)274.506 48 S 2.5(3-)-2.5 G/F1 10
+/Courier@0 SF(score)105.336 96 Q(vscheme=2o)117.336 108 Q(music)105.336
+120 Q 6(11)105.336 132 S 6(:c)-6 G(+e+g+;;;;)-6 E 6(12)105.336 144 S 6
+(:c)-6 G(eg;;;;)-6 E(// downward roll on staff 1)105.336 156 Q
+(// on beats 2 and 4)105.336 168 Q(roll down 1 1 to 1 2: 2; 4;)105.336
+180 Q(bar)105.336 192 Q 127.836 201.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 91 rlineto 320 0 rlineto 0 91 neg rlineto closepath stroke grestore
+EEND 160 672 320 320 -91 91 126.836 292.6 PBEGIN
+%%BeginDocument: mugex80.ps
+%%BoundingBox: 160 672 480 763
+save
+1216322504 1216321786 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+324.29 1223.00 468.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 713.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+224.49 734.00 1.000000 4n
+224.49 728.00 1.000000 4n
+224.49 722.00 1.000000 4n
+0.70 setlinewidth
+228.17 722.75 moveto
+228.17 755.00 lineto stroke
+288.05 734.00 1.000000 4n
+288.05 728.00 1.000000 4n
+288.05 722.00 1.000000 4n
+291.73 722.75 moveto
+291.73 755.00 lineto stroke
+277.02 737.28 moveto
+277.02 697.72 1.000000 wavy
+277.02 694.72 moveto
+273.02 702.72 lineto stroke
+277.02 694.72 moveto
+281.02 702.72 lineto stroke
+347.61 734.00 1.000000 4n
+347.61 728.00 1.000000 4n
+347.61 722.00 1.000000 4n
+351.29 722.75 moveto
+351.29 755.00 lineto stroke
+412.01 734.00 1.000000 4n
+412.01 728.00 1.000000 4n
+412.01 722.00 1.000000 4n
+415.69 722.75 moveto
+415.69 755.00 lineto stroke
+400.98 737.28 moveto
+400.98 697.72 1.000000 wavy
+400.98 694.72 moveto
+396.98 702.72 lineto stroke
+400.98 694.72 moveto
+404.98 702.72 lineto stroke
+224.49 713.00 1.000000 4n
+224.49 707.00 1.000000 4n
+224.49 701.00 1.000000 4n
+218.25 701.00 moveto
+230.72 701.00 lineto stroke
+220.80 712.25 moveto
+220.80 680.00 lineto stroke
+288.05 713.00 1.000000 4n
+288.05 707.00 1.000000 4n
+288.05 701.00 1.000000 4n
+281.82 701.00 moveto
+294.28 701.00 lineto stroke
+284.37 712.25 moveto
+284.37 680.00 lineto stroke
+347.61 713.00 1.000000 4n
+347.61 707.00 1.000000 4n
+347.61 701.00 1.000000 4n
+341.38 701.00 moveto
+353.84 701.00 lineto stroke
+343.93 712.25 moveto
+343.93 680.00 lineto stroke
+412.01 713.00 1.000000 4n
+412.01 707.00 1.000000 4n
+412.01 701.00 1.000000 4n
+405.78 701.00 moveto
+418.24 701.00 lineto stroke
+408.33 712.25 moveto
+408.33 680.00 lineto stroke
+restore
+%  S_BAR
+11 linenum
+0.70 setlinewidth
+467.65 731.00 moveto
+467.65 707.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF -1.1(Yo)69.336 312.6 S 2.921(uc)1.1 G
+.421(an also e)-2.921 F .422(xplicitly say "up" which will cause an upw)
+-.15 F .422(ard arro)-.1 F 2.922(wt)-.25 G 2.922(ob)-2.922 G 2.922(ed)
+-2.922 G(ra)-2.922 E .422(wn at the top of the roll. If no)-.15 F
+(direction is speci\214ed, no arro)69.336 324.6 Q 2.5(wi)-.25 G 2.5(sd)
+-2.5 G(ra)-2.5 E(wn.)-.15 E EP
+%%Page: 84 90
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-8)274.506 48 S 2.5(4-)-2.5 G 69.336 103
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(10. T)73.086 103 R -.825(AG)-1.35 G
+(S, PRINTING, LINES, AND CUR).825 E(VES)-.825 E 69.336 121 EBEGIN
+0 0 0 setrgbcolor
+EEND 69.336 139 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(10.1 Location)72.836 139 R(tags)3.5 E
+69.336 157 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.008
+(The concept of "location tags" has been mentioned se)72.844 157 R -.15
+(ve)-.25 G 1.008(ral times. W).15 F 3.507(en)-.8 G 1.507 -.25(ow d)
+-3.507 H 1.007(escribe this f).25 F 1.007(acility in more)-.1 F(detail.)
+69.336 169 Q 3.661(Al)69.336 187 S 1.161
+(ocation tag is associated with a note, chord, or barline.)-3.661 F
+1.161(It can then be referenced in order to place a)6.161 F
+(second object, lik)69.336 199 Q 2.5(eac)-.1 G
+(omment or dotted line, relati)-2.5 E .3 -.15(ve t)-.25 H 2.5(ot).15 G
+(he \214rst object.)-2.5 E 2.748(At)69.336 217 S .248
+(ag name can be either a single lo)-2.748 F .248(wer case letter)-.25 F
+2.747(,o)-.4 G 2.747(ra)-2.747 G 2.747(nu)-2.747 G .247(nderscore folo)
+-2.747 F .247(wed by one or more letters, digits,)-.25 F .252
+(or underscores.)69.336 229 R .252
+(Each location tag is really a collection of six v)5.252 F .253
+(alues, namely the north, south, east, west, x,)-.25 F .295(and y v)
+69.336 241 R .295
+(alues of the tagged object. These are referenced by gi)-.25 F .295
+(ving the tag name follo)-.25 F .294(wed by a dot, follo)-.25 F(wed)-.25
+E(by the letter n, s, e, w)69.336 253 Q 2.5(,x)-.65 G 2.5(,o)-2.5 G 2.5
+(ry)-2.5 G 5(.F)-3.15 G(or e)-5.15 E(xample:)-.15 E/F1 10/Courier@0 SF 1
+(c.n //)105.336 271 R(north of tag c)6 E 8(_xyz.e //)105.336 283 R
+(east of tag _xyz)6 E 1(x.x //)105.336 295 R 6(xc)6 G
+(oordinate of tag x)-6 E F0 1.607(The n, s, e, and w v)69.336 321 R
+1.607(alues describe the smallest rectangle that will completely enclos\
+e the object being)-.25 F 2.91(tagged. The)69.336 333 R .409(north refe\
+rs to the top of the object, the south to the bottom, the west to the l\
+eft edge, and the)2.91 F 1.432(east the right edge. The x and y v)69.336
+345 R 1.433
+(alues correspond to the "center" coordinate of the object. This is not)
+-.25 F 1.395(necessarily the geometric center)69.336 357 R 3.895(,b)-.4
+G 1.395(ut more of a "logical center)-4.095 F 1.394
+(." In the case of a tag associated with an)-.55 F(indi)69.336 369 Q
+.207(vidual note, it is the geometric center of the note head.)-.25 F
+(Ho)5.207 E(we)-.25 E -.15(ve)-.25 G 1.007 -.4(r, o).15 H 2.707(nt).4 G
+.207(ags associated with a chord, the x)-2.707 F .523(is at the center \
+line of note heads that are on the "normal" side of the stem. \(Normall\
+y)69.336 381 R 3.022(,w)-.65 G .522(hen a stem is up,)-3.022 F 1.198
+(notes are put on the left side of the stem, and when the stem is do)
+69.336 393 R 1.198(wn the)-.25 F 3.698(ya)-.15 G 1.198
+(re placed on the right side.)-3.698 F(Ho)69.336 405 Q(we)-.25 E -.15
+(ve)-.25 G 1.063 -.4(r, w).15 H .263(hen tw).4 F 2.763(on)-.1 G .263
+(otes adjacent on the staf)-2.763 F 2.763(fh)-.25 G -2.25 -.2(av e)
+-2.763 H .263(to be printed in a single chord, one has to be mo)2.963 F
+-.15(ve)-.15 G 2.762(dt).15 G(o)-2.762 E .569
+(the opposite side.\) The y of a chord is al)69.336 417 R -.1(wa)-.1 G
+.569(ys the middle line of the staf).1 F 3.069(fc)-.25 G .569
+(ontaining the chord. The x of a)-3.069 F
+(bar line is its geometric center)69.336 429 Q 2.5(.T)-.55 G
+(he y of a bar line is the center line of the top visible staf)-2.5 E
+(f.)-.25 E -.8(Ta)69.336 447 S 2.5(gn).8 G(ames can be re-used. The v)
+-2.5 E(alue of a tag will al)-.25 E -.1(wa)-.1 G
+(ys be its most recent de\214nition.).1 E(There are also se)69.336 465 Q
+-.15(ve)-.25 G(ral "pre-de\214ned" tags. The).15 E 2.5(ya)-.15 G(re:)
+-2.5 E 12.5(_page the)69.336 483 R(entire page)2.5 E 16.38(_win the)
+69.336 495 R -.2(av)2.5 G(ailable part of the page)-.05 E 18.61
+(_cur the)69.336 507 R(current location)2.5 E .02
+(The _page tag refers to the entire page.)69.336 525 R .02
+(The x and y v)5.02 F .02
+(alues of _page are at the geometric center of the page.)-.25 F .159
+(This tag is seldom useful, b)69.336 537 R .159(ut is pro)-.2 F .159
+(vided in case you w)-.15 F .159
+(ant to force something to a speci\214c place on a page.)-.1 F .989
+(The _win tag refers to the area of the page a)69.336 555 R -.25(va)-.2
+G .988(ilable for printing.).25 F .988
+(The name comes from the idea that it)5.988 F(pro)69.336 567 Q 1.03
+(vides a vie)-.15 F 2.33 -.65(w, a)-.25 H 3.53(si).65 G 3.53(ft)-3.53 G
+1.03(hrough a windo)-3.53 F 2.33 -.65(w, o)-.25 H -6.029 3.53(fa p).65 H
+1.031(ortion of the page. Its precise meaning depends upon the)-3.53 F
+1.655(current conte)69.336 579 R 4.155(xt. In)-.15 F(header)4.155 E
+4.155(,f)-.4 G(ooter)-4.155 E 4.154(,t)-.4 G 1.654
+(op, bottom, header2, footer2,)-4.154 F 1.654
+(top2, bottom2, and block conte)6.654 F 1.654(xts, it)-.15 F .451
+(refers to the area of the page tak)69.336 591 R .452
+(en up by the corresponding element. In music conte)-.1 F .452
+(xt, it refers to the area)-.15 F .935(of the page that remains after e)
+69.336 603 R .935(xcluding the mar)-.15 F .935(gins and the header)-.18
+F 3.435(,f)-.4 G(ooter)-3.435 E 3.435(,t)-.4 G .935
+(op and bottom for the page.)-3.435 F 1.416(There is no w)69.336 615 R
+1.417(ay to access location tags in an)-.1 F 3.917(yo)-.15 G 1.417
+(ther conte)-3.917 F 1.417
+(xts, so _win \(and all other location tags\) are)-.15 F
+(meaningless in other conte)69.336 627 Q(xts.)-.15 E .203(The _cur tag \
+refers to the current location on the page. This is a single point, suc\
+h that east and west v)69.336 645 R(alues)-.25 E 1.61
+(are the same as x, and north and south v)69.336 657 R 1.61
+(alues are the same as y)-.25 F 4.11(.I)-.65 G 4.11(ti)-4.11 G 4.11(so)
+-4.11 G 1.61(nly useful immediately after a)-4.11 F 2.37(command that e)
+69.336 669 R 2.369(xplicitly sets the current location, that is, after \
+a printing command or line or curv)-.15 F(e)-.15 E .237
+(command. Since Mup places musical data in an arbitrary order)69.336 681
+R 2.737(,t)-.4 G .237(rying to use _cur at other times is lik)-2.737 F
+.237(ely to)-.1 F(cause output at a seemingly random place.)69.336 693 Q
+.948(Location tags can be referenced by a number of commands, including\
+ those for printing te)69.336 711 R .947(xt, or dra)-.15 F(wing)-.15 E
+.217(lines or curv)69.336 723 R 2.718(es. In)-.15 F .218
+(the simplest case, tw)2.718 F 2.718(ot)-.1 G .218(ag references are gi)
+-2.718 F -.15(ve)-.25 G 2.718(ni).15 G 2.718(np)-2.718 G .218
+(arentheses. The \214rst tag must refer to)-2.718 F 3.34(ah)69.336 735 S
+.84(orizontal direction \(the "x" direction for mathematicians\), namel\
+y a tag with a w)-3.34 F 3.34(,e)-.65 G 3.34(,o)-3.34 G 3.34(rxa)-3.34 G
+.84(fter the dot.)-3.34 F EP
+%%Page: 85 91
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-8)274.506 48 S 2.5(5-)-2.5 G
+(The second tag is then a v)69.336 96 Q(ertical tag, ha)-.15 E
+(ving n, s, or y)-.2 E 2.5(.F)-.65 G(or e)-2.65 E(xample:)-.15 E/F1 10
+/Courier@0 SF(\(g.x, g.y\))105.336 114 Q(// x and y of tag "g")15 E
+(\(_tag.w, _item.n\))105.336 126 Q(// west of tag "_tag" and)18 E
+(// north of tag "_item")219.336 138 Q F0 .584(The \214rst e)69.336 158
+R .584(xample refers to the x,y coordinate of tag "g". The second item \
+refers to tw)-.15 F 3.085(od)-.1 G(if)-3.085 E .585(ferent tags. The)
+-.25 F .764(point referenced has its horizontal location aligned with t\
+he west side of the object ha)69.336 170 R .764(ving the tag "_tag,")-.2
+F .174(while its v)69.336 182 R .174
+(ertical position is in line with the north side of the object ha)-.15 F
+.174(ving the tag "_item".)-.2 F .174(In other w)5.174 F(ords,)-.1 E
+.129(if a line were dra)69.336 194 R .128(wn along the west side of the\
+ object tagged with "_tag" and another line were dra)-.15 F .128
+(wn along)-.15 F 1.209
+(the top edge of the object with tag "_item", the point where those tw)
+69.336 206 R 3.709(ol)-.1 G 1.209(ines crossed w)-3.709 F 1.209
+(ould be the point)-.1 F(referenced.)69.336 218 Q(Frequently)69.336 236
+Q 2.799(,y)-.65 G .299(ou may w)-2.799 F .299
+(ant to place something relati)-.1 F .599 -.15(ve t)-.25 H 2.798(oat).15
+G .298(agged object.)-2.798 F -1.1(Yo)5.298 G 2.798(uc)1.1 G .298
+(an add of)-2.798 F .298(fsets in both the x)-.25 F 1.317
+(and y dimensions. These of)69.336 248 R 1.317(fsets are gi)-.25 F -.15
+(ve)-.25 G 3.817(ni).15 G 3.817(ns)-3.817 G 3.817(tepsizes. As)-3.817 F
+-.1(wa)3.817 G 3.817(sm).1 G 1.317(entioned earlier)-3.817 F 3.817(,as)
+-.4 G 1.317(tepsize is half the)-3.817 F(distance between tw)69.336 260
+Q 2.5(os)-.1 G(taf)-2.5 E 2.5(fl)-.25 G(ines.)-2.5 E F1
+(\(g.x + 4.5, g.y + 4.5\))105.336 278 Q F0 .701
+(refers to the point 4.5 stepsizes to the right and abo)69.336 298 R 1
+-.15(ve t)-.15 H .7(he point \(g.x, g.y\).).15 F .7(Adding an of)5.7 F
+.7(fset mo)-.25 F -.15(ve)-.15 G 3.2(st).15 G 3.2(ot)-3.2 G(he)-3.2 E
+(right in the horizontal direction and upw)69.336 310 Q(ard in the v)-.1
+E(ertical direction. Y)-.15 E(ou can also subtract an of)-1.1 E(fset:)
+-.25 E F1(\(k.w - 1.3, m.n - 2\))105.336 328 Q F0(refers to a point 1.3\
+ stepsizes to the left of the west edge of k and 2 stepsizes belo)69.336
+348 Q 2.5(wt)-.25 G(he top of m.)-2.5 E .611
+(In the horizontal direction, of)69.336 366 R .611(fsets can be gi)-.25
+F -.15(ve)-.25 G 3.111(ni).15 G 3.111(nt)-3.111 G .611
+(erms of "time". This is speci\214ed by using the k)-3.111 F -.15(ey)-.1
+G -.1(wo).15 G(rd).1 E("time" follo)69.336 378 Q
+(wed by a number of beats.)-.25 E(As an e)5 E(xample, suppose we ha)-.15
+E .3 -.15(ve t)-.2 H(he tag reference:).15 E F1
+(\(q.x + time 1, q.y + 2\))105.336 396 Q F0 .604(If the time signature \
+is 4/4 and tag "q" happens to be associated with a half note, this tag \
+reference w)69.336 416 R(ould)-.1 E .639(refer to a point halfw)69.336
+428 R .639(ay between that note and the follo)-.1 F .639
+(wing chord, since it includes an of)-.25 F .639(fset of a quarter)-.25
+F .077(note. If "q" had been associated with a whole note, the point w)
+69.336 440 R .076(ould be only 1/4 of the w)-.1 F .076
+(ay between the note)-.1 F .7(and the follo)69.336 452 R .7
+(wing chord. Since notes are placed based on v)-.25 F .7
+(arious constraints and aesthetic considerations,)-.25 F
+(the actual distance will v)69.336 464 Q
+(ary depending on which tag is referenced.)-.25 E .654(In the case of a\
+ tag associated with a bar line, the time to distance mapping is done b\
+ased on the distance)69.336 482 R .003(between the bar \(at count "0"\)\
+ and the \214rst chord in the measure \(at count "1"\). So, for e)69.336
+494 R .004(xample, in 4/4 time,)-.15 F 3.453(ar)69.336 506 S .953
+(eference to a bar line tag + time 0.5 w)-3.453 F .952
+(ould indicate a place halfw)-.1 F .952
+(ay between the bar line and the \214rst)-.1 F
+(chord, whereas tag + time 0.25 w)69.336 518 Q
+(ould be one fourth of the w)-.1 E(ay)-.1 E(.)-.65 E .052(The mapping o\
+f time to distance is done based only on the note, rest, or bar line as\
+sociated with the tag. F)69.336 536 R(or)-.15 E -.15(ex)69.336 548 S
+.027(ample, if the tag is associated with a quarter note, and the dista\
+nce between that note and the ne).15 F .027(xt w)-.15 F .027(as 0.5)-.1
+F .125(inches, specifying)69.336 560 R .125
+("+ time 2" \(a half note\) w)5.125 F .126
+(ould mean 1.0 inch to the right, or specifying "- time 2" w)-.1 F(ould)
+-.1 E .621(mean 1.0 inch to the left, e)69.336 572 R -.15(ve)-.25 G
+3.121(ni).15 G 3.121(ft)-3.121 G .621
+(he notes to the left or right happened to be spread some)-3.121 F .621
+(what dif)-.25 F(ferently)-.25 E .955(than 0.5 inches per quarter note.\
+ Thus it is usually advisable not to specify a time of)69.336 584 R .956
+(fset greater than the)-.25 F .125(time v)69.336 596 R .125(alue of the\
+ note or rest associated with the tag, nor to subtract a time v)-.25 F
+.124(alue. Stated another w)-.25 F(ay)-.1 E 2.624(,w)-.65 G(hen)-2.624 E
+1.851(specifying the X portion of a coordinate using a time of)69.336
+608 R 1.851(fset, it is best to use a location tag based on)-.25 F
+(whiche)69.336 620 Q -.15(ve)-.25 G 2.5(rn).15 G(ote, rest, or bar is i\
+mmediately to the left of the X location you are trying to specify)-2.5
+E(.)-.65 E(The v)69.336 638 Q(arious kinds of of)-.25 E
+(fsets can be combined.)-.25 E F1 6(\(_)105.336 656 S
+(pp + 1.2 - time 3.5, _zz + 2\))-6 E F0 1.237
+(At least one of the three possible items\212tag, stepsize of)69.336 682
+R 1.237(fset, or time of)-.25 F 1.237
+(fset\212must be speci\214ed for each)-.25 F 1.837
+(direction. Only one tag is allo)69.336 694 R 1.838(wed for each direct\
+ion. If no tag is speci\214ed, the reference becomes an)-.25 F
+(absolute reference, gi)69.336 706 Q(ving an e)-.25 E
+(xact page location. F)-.15 E(or e)-.15 E(xample:)-.15 E F1(\(10, 20\))
+105.336 724 Q EP
+%%Page: 86 92
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-8)274.506 48 S 2.5(6-)-2.5 G 1.458
+(is 10 stepsizes from the left edge and 20 stepsizes abo)69.336 96 R
+1.757 -.15(ve t)-.15 H 1.457(he bottom of the page.).15 F -.35(Ti)6.457
+G 1.457(me of).35 F 1.457(fsets are not)-.25 F(allo)69.336 108 Q
+(wed on absolute references, and must follo)-.25 E 2.5(wt)-.25 G
+(he tag reference.)-2.5 E .854(It is possible to specify multiple of)
+69.336 126 R .855(fsets of the same type, although this is rarely)-.25 F
+3.355(,i)-.65 G 3.355(fe)-3.355 G -.15(ve)-3.605 G 1.655 -.4(r, u).15 H
+.855(seful. Thus the).4 F(follo)69.336 138 Q(wing are equi)-.25 E -.25
+(va)-.25 G(lent:).25 E/F1 10/Courier@0 SF 6(\(f)105.336 156 S
+(.x + 1 - 0.5 + time 1 - time 0.5, f.s + .3 - .1\))-6 E 6(\(f)105.336
+168 S(.x + 0.5 + time 0.5, f.s + .2\))-6 E 69.336 194 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(10.2 Printing)72.836 194 R(commands)3.5 E
+69.336 212 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 2.311(There are se)74.147 212 R -.15(ve)-.25
+G 2.311(ral commands for printing te).15 F 4.811(xt. There)-.15 F 2.31
+(are four commands that ha)4.811 F 2.61 -.15(ve s)-.2 H 2.31
+(imilar formats,).15 F(dif)69.336 224 Q(fering only in ho)-.25 E 2.5(wt)
+-.25 G(he)-2.5 E 2.5(yj)-.15 G(ustify te)-2.5 E(xt.)-.15 E/F1 10
+/Times-Bold@0 SF(print)105.336 242 Q/F2 10/Times-Italic@0 SF(location)6
+E/F3 10/Courier@0 SF(")6 E F2(te)A(xt)-.2 E F3(")A F1(left)105.336 254 Q
+F2(location)6 E F3(")6 E F2(te)A(xt)-.2 E F3(")A F1(right)105.336 266 Q
+F2(location)6 E F3(")6 E F2(te)A(xt)-.2 E F3(")A F1(center)105.336 278 Q
+F2(location)6 E F3(")6 E F2(te)A(xt)-.2 E F3(")A F0(The)69.336 304 Q F2
+(location)3.435 E F0 .935(is optional. If the)3.435 F F2(location)3.435
+E F0 .936(is omitted, the "print" command will cause the)3.435 F F2(te)
+3.436 E(xt)-.2 E F0 .936(to be printed)3.436 F(be)69.336 316 Q 1.46
+(ginning at the current horizontal and v)-.15 F 1.459
+(ertical location. The other commands will cause the te)-.15 F 1.459
+(xt to be)-.15 F 1.614(placed v)69.336 328 R 1.614
+(ertically at the current v)-.15 F 1.614(ertical position, b)-.15 F
+1.614(ut left justi\214ed, right justi\214ed, or centered within the)-.2
+F(current mar)69.336 340 Q(gins of the page.)-.18 E(The)69.336 358 Q F2
+(location)3.277 E F0 .777(can be speci\214ed using the special k)3.277 F
+-.15(ey)-.1 G -.1(wo).15 G .776(rd of "nl" which means "ne).1 F .776
+(xt line." This mo)-.15 F -.15(ve)-.15 G 3.276(st).15 G(he)-3.276 E .83
+(current location to the be)69.336 370 R .83(ginning of the follo)-.15 F
+.83(wing line before placing the te)-.25 F .83(xt. In other w)-.15 F .83
+(ords, the current)-.1 F -.15(ve)69.336 382 S .028
+(rtical position is mo).15 F -.15(ve)-.15 G 2.528(dd).15 G -.25(ow)
+-2.528 G(nw).25 E .027(ard by the height of the current te)-.1 F .027
+(xt point size \(or by as much as necessary)-.15 F
+(if the string is taller than that\). Then the)69.336 394 Q F2(te)2.5 E
+(xt)-.2 E F0(is printed on that line with the gi)2.5 E -.15(ve)-.25 G
+2.5(nj).15 G(usti\214cation style.)-2.5 E .858(The other w)69.336 412 R
+.859(ay to specify a)-.1 F F2(location)3.359 E F0 .859
+(is by using coordinates.)3.359 F .859(The justi\214cation then tak)
+5.859 F .859(es place relati)-.1 F 1.159 -.15(ve t)-.25 H(o).15 E .222
+(the referenced location.)69.336 424 R -.15(Fo)5.222 G 2.722(re).15 G
+.222(xample, consider the follo)-2.872 F .221
+(wing "right" command containing a reference to an)-.25 F
+(absolute location:)69.336 436 Q F3(right \(25, 4\) "something")105.336
+454 Q F0 1.246(The y location gi)69.336 474 R -.15(ve)-.25 G 3.746(ni)
+.15 G 3.746(s4)-3.746 G 3.746(.S)-3.746 G 1.247(ince this is an absolut\
+e location with no location tags being referenced, this)-3.746 F 1.233
+(means the v)69.336 486 R 1.233(ertical position will be 4 stepsizes fr\
+om the bottom of the page. The x location gi)-.15 F -.15(ve)-.25 G 3.732
+(ni).15 G 3.732(s2)-3.732 G(5.)-3.732 E(Ag)69.336 498 Q .271(ain, this \
+is an absolute location, so the current horizontal position will be 25 \
+stepsizes from the left edge)-.05 F .904
+(of the page. Since right justi\214cation is indicated, the w)69.336 510
+R .903(ord "something" will be placed such that the right)-.1 F .473(ed\
+ge of the \214nal "g" will be 25 stepsizes from the left edge of the pa\
+ge. If "center" had been speci\214ed, the)69.336 522 R(middle of the w)
+69.336 534 Q(ord "something" w)-.1 E(ould be at the 25 stepsize point.)
+-.1 E(Here are some other e)69.336 552 Q(xamples:)-.15 E F3
+(print "Author unknown")105.336 570 Q(center nl "subtitle")105.336 582 Q
+(left \(h.x - 1.5, h.n + 2.3\) "Ad lib")105.336 594 Q
+(right \(_fine.e + time 3, _note.n + 5\) "Duet")105.336 606 Q F0(Anothe\
+r type of print command is "title." The full format of this command is:)
+69.336 632 Q F1(title)105.336 650 Q F2(fontfamily font size)6 E("te)5 E
+2.5(xt1" "te)-.2 F 2.5(xt2" "te)-.2 F(xt3")-.2 E F0(Ho)69.336 670 Q(we)
+-.25 E -.15(ve)-.25 G .943 -.4(r, o).15 H .143(nly the w).4 F .143
+(ord "title" and one quoted te)-.1 F .143(xt string are required.)-.15 F
+(The)5.143 E F2(fontfamily)2.643 E F0 2.643(,i)C 2.643(fs)-2.643 G .143
+(peci\214ed, has one)-2.643 F 1.351(of the v)69.336 682 R 1.351(alues v)
+-.25 F 1.352(alid for the "fontf)-.25 F 1.352(amily" parameter \(a)-.1 F
+-.25(va)-.2 G(ntg).25 E 1.352(arde, bookman, courier)-.05 F 3.852(,h)-.4
+G(elv)-3.852 E 1.352(etica, ne)-.15 F(wcentury)-.25 E(,)-.65 E .212
+(palatino, or times\). The def)69.336 694 R .211(ault is the v)-.1 F
+.211(alue of the "fontf)-.25 F .211(amily" parameter)-.1 F 5.211(.T)-.55
+G(he)-5.211 E F2(font)2.711 E F0 2.711(,i)C 2.711(fs)-2.711 G .211
+(peci\214ed, has one of)-2.711 F .058(the v)69.336 706 R .058(alues v)
+-.25 F .058
+(alid for the "font" parameter \(rom, bold, ital, or boldital\). If no)
+-.25 F F2(font)2.558 E F0 .058(is speci\214ed the def)2.558 F .058
+(ault is the)-.1 F -.25(va)69.336 718 S 1.257
+(lue of the "font" parameter).25 F 6.257(.T)-.55 G 1.257(he optional)
+-6.257 F F2(size)3.757 E F0 1.257(is a point size within parentheses.)
+3.757 F 1.257(If not speci\214ed, the)6.257 F(def)69.336 730 Q
+(ault is the v)-.1 E(alue of the "size" parameter)-.25 E(.)-.55 E EP
+%%Page: 87 93
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-8)274.506 48 S 2.5(7-)-2.5 G .246
+(In all cases, the location will be lik)69.336 96 R 2.746(et)-.1 G .246
+(hat obtained via the "nl" location to a print command. In other w)
+-2.746 F(ords,)-.1 E .09(the title te)69.336 108 R .09
+(xt string\(s\) will be printed on the line belo)-.15 F 2.59(wt)-.25 G
+.09(he location that w)-2.59 F .09(as current when the title command)-.1
+F -.1(wa)69.336 120 S 2.504(se).1 G .004
+(ncountered. If there is only one string gi)-2.504 F -.15(ve)-.25 G .005
+(n, it will be centered between the mar).15 F .005(gins. If tw)-.18 F
+2.505(os)-.1 G .005(trings are)-2.505 F(gi)69.336 132 Q -.15(ve)-.25 G
+.694(n, both will be printed on the same line, b).15 F .693
+(ut the \214rst will be left justi\214ed and the second will be right)
+-.2 F .545(justi\214ed. If three strings are gi)69.336 144 R -.15(ve)
+-.25 G .545(n, the).15 F 3.045(yw)-.15 G .546(ill all be printed on the\
+ same line, with the \214rst left justi\214ed, the)-3.045 F
+(second centered, and the last right justi\214ed.)69.336 156 Q
+(Some samples:)69.336 174 Q/F1 10/Courier@0 SF
+(title bold \(12\) "Sonata 12")105.336 192 Q
+(title \(18\) "Song Without Words")105.336 204 Q
+(title ital \(12\) "Text: John Doe" "Tune: Jane Doe")105.336 216 Q
+(title "Suite in C" "Trumpet I" "Waltz")105.336 228 Q 18(title "" "A.)
+105.336 240 R(Composer")6 E F0 1.582
+(The \214nal command for printing te)69.336 266 R 1.582
+(xt is the "paragraph" command.)-.15 F 1.582(This is used when you ha)
+6.582 F 1.881 -.15(ve a l)-.2 H(ong).15 E .748(section of te)69.336 278
+R .748(xt, and you w)-.15 F .748(ould lik)-.1 F 3.248(ei)-.1 G 3.248(tt)
+-3.248 G 3.248(oa)-3.248 G .748(utomatically wrap around onto as man)
+-3.248 F 3.249(yl)-.15 G .749(ines as necessary)-3.249 F 5.749(.Y)-.65 G
+(ou)-6.849 E .52(can specify whether you w)69.336 290 R .52
+(ant the right mar)-.1 F .52(gin to be "justi\214ed" or "ragged.")-.18 F
+.52(If you don')5.52 F 3.02(ts)-.18 G(pecify)-3.02 E 3.02(,t)-.65 G .52
+(he type)-3.02 F .228(of the pre)69.336 302 R .228
+(vious paragraph is used.)-.25 F .228(The def)5.228 F .228
+(ault for the v)-.1 F .229(ery \214rst paragraph is to be justi\214ed.)
+-.15 F .229(By def)5.229 F .229(ault, the)-.1 F -.25(va)69.336 314 S
+1.154(lues of the fontf).25 F(amily)-.1 E 3.653(,f)-.65 G 1.153
+(ont, and size parameters are used to determine the te)-3.653 F 1.153
+(xt style, b)-.15 F 1.153(ut an)-.2 F 3.653(yo)-.15 G 3.653(ra)-3.653 G
+1.153(ll of)-3.653 F(those parameters can be o)69.336 326 Q -.15(ve)-.15
+G(rridden on the paragraph command. The complete syntax is:).15 E/F2 10
+/Times-Italic@0 SF(justify_type)71.836 344 Q/F3 10/Times-Bold@0 SF
+(paragraph)2.5 E F2(fontfamily font)2.5 E F3(\()2.5 E F2(size)A F3 2.5
+(\)")C F2(string)-2.5 E F3(")A F0(Only the k)69.336 362 Q -.15(ey)-.1 G
+-.1(wo).15 G(rd "paragraph" and the string are required.).1 E
+(Here are some e)5 E(xample paragraphs:)-.15 E F1
+(paragraph "This is an example of a paragraph. Since no justification)
+105.336 380 Q
+(type was specified, and this is the very first paragraph, the default)
+105.336 392 Q(\(justified\) is used. A paragraph will wrap around)
+105.336 404 Q(to as many lines as needed.)105.336 416 Q
+(An explicit newline is given at the end of this paragraph,)105.336 428
+Q(to force a blank line between it and the following paragraph.\\n")
+105.336 440 Q(ragged paragraph avantgarde ital \(15\) "This paragraph)
+105.336 464 Q
+(is ragged rather than flush right. It is in a different font and size.)
+105.336 476 Q
+(Ragged paragraphs are split onto multiple lines if necessary,)105.336
+488 Q(but they are not spread out to make lines go all the way to)
+105.336 500 Q(the right margin.")105.336 512 Q
+(justified paragraph \(14\) ")105.336 536 Q(Here is another paragraph.)
+30 E(This one is justified.)105.336 548 Q
+(Only the size was specified for this paragraph; the font was not,)
+105.336 560 Q(so the current default will be used.)105.336 572 Q
+(Some spaces are included at the beginning of the paragraph text,)
+105.336 584 Q(to create an indented first line for the paragraph.")
+105.336 596 Q(paragraph "Here is the final paragraph.)105.336 620 Q
+(Since no justification type was given,)105.336 632 Q
+(that of the previous paragraph \(justified in this case\) was used.)
+105.336 644 Q 6(Ap)105.336 656 S(aragraph may be used for many things,)
+-6 E(such as describing how you want a piece to be performed,)105.336
+668 Q(or a biography of the composer.")105.336 680 Q EP
+%%Page: 88 94
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-8)274.506 48 S 2.5(8-)-2.5 G 111.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 316 rlineto 352 0 rlineto 0 316 neg rlineto closepath stroke grestore
+EEND 128 447 352 352 -316 316 110.836 412 PBEGIN
+%%BeginDocument: mugex81.ps
+%%BoundingBox: 128 447 480 763
+save
+1216322504 1216321786 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+4 linenum
+%  S_BLOCKHEAD
+4 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+144.00 746.28 moveto
+(This is an example of a paragraph. Since no justification type was) 0.77 0.00 32 4 -1 roll
+widthshow
+144.00 733.46 moveto
+(specified, and this is the very first paragraph, the default \(justified\)) 0.42 0.00 32 4 -1 roll
+widthshow
+144.00 720.65 moveto
+(is used. A paragraph will wrap around to as many lines as needed.) 0.59 0.00 32 4 -1 roll
+widthshow
+144.00 707.83 moveto
+(An explicit newline is given at the end of this paragraph, to force a) 0.31 0.00 32 4 -1 roll
+widthshow
+144.00 695.02 moveto
+(blank line between it and the following paragraph.) show
+/Times-Roman findfont
+12 scalefont
+setfont
+144.00 682.20 moveto
+/AvantGarde-BookOblique findfont
+15 scalefont
+setfont
+144.00 665.64 moveto
+(This paragraph is ragged rather than flush) show
+144.00 649.08 moveto
+(right. It is in a different font and size. Ragged) show
+144.00 632.52 moveto
+(paragraphs are split onto multiple lines if) show
+144.00 615.96 moveto
+(necessary, but they are not spread out to) show
+144.00 599.40 moveto
+(make lines go all the way to the right) show
+144.00 582.84 moveto
+(margin.) show
+/Times-Roman findfont
+14 scalefont
+setfont
+144.00 567.89 moveto
+(     Here is another paragraph. This one is justified. Only) 0.70 0.00 32 4 -1 roll
+widthshow
+144.00 552.94 moveto
+(the size was specified for this paragraph; the font was) 2.67 0.00 32 4 -1 roll
+widthshow
+144.00 537.98 moveto
+(not, so the current default will be used. Some spaces are) 1.02 0.00 32 4 -1 roll
+widthshow
+144.00 523.03 moveto
+(included at the beginning of the paragraph text, to create) 0.92 0.00 32 4 -1 roll
+widthshow
+144.00 508.08 moveto
+(an indented first line for the paragraph.) show
+/Times-Roman findfont
+12 scalefont
+setfont
+144.00 495.26 moveto
+(Here is the final paragraph. Since no justification type was given,) 1.07 0.00 32 4 -1 roll
+widthshow
+144.00 482.45 moveto
+(that of the previous paragraph \(justified in this case\) was used. A) 1.15 0.00 32 4 -1 roll
+widthshow
+144.00 469.63 moveto
+(paragraph may be used for many things, such as describing how) 1.68 0.00 32 4 -1 roll
+widthshow
+144.00 456.82 moveto
+(you want a piece to be performed, or a biography of the composer.) show
+%  S_FEED
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /AvantGarde-BookOblique 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF 1.37(Sometimes you may w)69.336 432 R
+1.37(ant to mix blocks of te)-.1 F 1.371(xt with music.)-.15 F 1.371
+(This can be done by specifying a "block")6.371 F(conte)69.336 444 Q
+.568(xt. The block conte)-.15 F .568(xt will typically contain one or m\
+ore "paragraph" commands, although an)-.15 F 3.068(yo)-.15 G 3.068(ft)
+-3.068 G(he)-3.068 E 1.092
+(printing commands \(paragraph, print, left, center)69.336 456 R 3.592
+(,r)-.4 G 1.093
+(ight, or title\) can be used. The block can also contain)-3.592 F 1.078
+(changes in certain parameters, namely font, size, and fontf)69.336 468
+R(amily)-.1 E 3.578(,w)-.65 G 1.078(hich will af)-3.578 F 1.078
+(fect the appearance of the)-.25 F(follo)69.336 480 Q 1.826(wing te)-.25
+F 1.826(xt. A block can also contain "ne)-.15 F 1.826(wscore" or "ne)
+-.25 F 1.826(wpage" commands.)-.25 F 1.827(Using "ne)6.826 F 1.827
+(wscore" will)-.25 F .679(cause v)69.336 492 R .679
+(ertical space to be added, as w)-.15 F .679
+(ould be used to separate scores. The amount of space is af)-.1 F .678
+(fected by)-.25 F .245(the scoresep and scorepad parameters. Using "ne)
+69.336 504 R .245(wpage" will cause a ne)-.25 F 2.745(wp)-.25 G .246
+(age to be started.)-2.745 F .246(If a ne)5.246 F(wscore)-.25 E 1.975
+(or ne)69.336 516 R 1.975(wpage includes a "leftmar)-.25 F 1.975
+(gin" speci\214cation, that will alter the left mar)-.18 F 1.975
+(gin on the block te)-.18 F 1.975(xt that)-.15 F(follo)69.336 528 Q 2.5
+(ws. A)-.25 F("rightmar)2.5 E
+(gin" speci\214cation will alter the right mar)-.18 E
+(gin of the block te)-.18 E(xt that precedes it.)-.15 E(Here is an e)
+69.336 546 Q(xample of a block.)-.15 E EP
+%%Page: 89 95
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-8)274.506 48 S 2.5(9-)-2.5 G/F1 10
+/Courier@0 SF(block)105.336 96 Q
+(title bold "Notation in Simple and Compound Meters")105.336 108 Q
+(title "")105.336 120 Q(paragraph "It is common for a person familiar)
+105.336 132 Q(with mathematics but not with music to assume)105.336 144
+Q(that 3/4 and 6/8 time are equivalent,)105.336 156 Q
+(but that is not the case.)105.336 168 Q
+(In 3/4 time \(which is known as simple triple meter\),)105.336 180 Q 6
+(am)105.336 192 S(easure containing 3 quarter notes)-6 E
+(would be notated like this:")105.336 204 Q(score time=3/4)105.336 216 Q
+(music)105.336 228 Q(1: c;;;)105.336 240 Q(bar)105.336 252 Q(block)
+105.336 264 Q(paragraph "whereas in 6/8 time)105.336 276 Q
+(\(which is compound duple meter\),)105.336 288 Q 6(am)105.336 300 S
+(easure with 3 quarter notes should be notated thus:")-6 E
+(score time=6/8)105.336 312 Q(music)105.336 324 Q(1: 4c;8~;;4;)105.336
+336 Q(bar)105.336 348 Q 111.836 357.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 271 rlineto 352 0 rlineto 0 271 neg rlineto closepath stroke grestore
+EEND 128 492 352 352 -271 271 110.836 628.6 PBEGIN
+%%BeginDocument: mugex82.ps
+%%BoundingBox: 128 492 480 763
+save
+1216322504 1216321786 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+7 linenum
+%  S_BLOCKHEAD
+7 linenum
+/Helvetica-Bold findfont
+12 scalefont
+setfont
+186.70 745.85 moveto
+(Notation in Simple and Compound Meters) show
+/Helvetica findfont
+12 scalefont
+setfont
+306.00 732.53 moveto
+/Helvetica findfont
+12 scalefont
+setfont
+144.00 719.21 moveto
+(It is common for a person familiar with mathematics but not) 1.07 0.00 32 4 -1 roll
+widthshow
+144.00 705.89 moveto
+(with music to assume that 3/4 and 6/8 time are equivalent,) 1.45 0.00 32 4 -1 roll
+widthshow
+144.00 692.57 moveto
+(but that is not the case. In 3/4 time \(which is known as) 3.07 0.00 32 4 -1 roll
+widthshow
+144.00 679.25 moveto
+(simple triple meter\), a measure containing 3 quarter notes) 2.07 0.00 32 4 -1 roll
+widthshow
+144.00 665.93 moveto
+(would be notated like this:) show
+%  S_SSV
+17 linenum
+%  S_FEED
+291.00 1129.26 468.00 5 1.000000 1.000000 stf
+/Times-Roman findfont
+12 scalefont
+setfont
+144.00 625.26 moveto
+%  S_CLEFSIG
+158.79 619.26 1.000000 gclef
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+170.58 625.26 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+170.58 613.24 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+208.26 607.26 1.000000 4n
+0.70 setlinewidth
+202.03 607.26 moveto
+214.50 607.26 lineto stroke
+211.95 608.01 moveto
+211.95 628.26 lineto stroke
+292.91 607.26 1.000000 4n
+286.68 607.26 moveto
+299.15 607.26 lineto stroke
+296.60 608.01 moveto
+296.60 628.26 lineto stroke
+378.40 607.26 1.000000 4n
+372.17 607.26 moveto
+384.64 607.26 lineto stroke
+382.09 608.01 moveto
+382.09 628.26 lineto stroke
+restore
+%  S_BAR
+21 linenum
+0.70 setlinewidth
+453.28 637.26 moveto
+453.28 613.26 lineto stroke
+%  S_CLEFSIG
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+456.78 625.26 moveto
+(6) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+456.78 613.05 moveto
+(8) show
+%  S_FEED
+21 linenum
+%  S_BLOCKHEAD
+21 linenum
+/Helvetica findfont
+12 scalefont
+setfont
+144.00 579.03 moveto
+(whereas in 6/8 time \(which is compound duple meter\), a) 2.95 0.00 32 4 -1 roll
+widthshow
+144.00 565.71 moveto
+(measure with 3 quarter notes should be notated thus:) show
+%  S_SSV
+25 linenum
+%  S_FEED
+288.00 1030.18 468.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+155.79 520.18 1.000000 gclef
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+167.58 526.18 moveto
+(6) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+167.58 513.98 moveto
+(8) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+205.52 508.18 1.000000 4n
+199.28 508.18 moveto
+211.75 508.18 lineto stroke
+209.20 508.93 moveto
+209.20 529.18 lineto stroke
+284.73 508.18 1.000000 4n
+278.50 508.18 moveto
+290.96 508.18 lineto stroke
+288.41 508.93 moveto
+288.41 529.18 lineto stroke
+291.44 529.18 1.000000 dnflag
+334.22 508.18 1.000000 4n
+327.99 508.18 moveto
+340.45 508.18 lineto stroke
+337.90 508.93 moveto
+337.90 529.18 lineto stroke
+340.93 529.18 1.000000 dnflag
+391.50 508.18 1.000000 4n
+385.27 508.18 moveto
+397.74 508.18 lineto stroke
+395.19 508.93 moveto
+395.19 529.18 lineto stroke
+286.73 503.08 moveto
+286.75 503.24 lineto
+294.21 501.34 301.78 500.40 309.48 500.40 curveto
+317.17 500.40 324.74 501.34 332.20 503.24 curveto
+332.24 502.93 lineto
+324.89 500.27 317.30 498.95 309.48 498.95 curveto
+301.65 498.95 294.06 500.27 286.71 502.93 curveto
+fill
+restore
+%  S_BAR
+29 linenum
+0.70 setlinewidth
+467.65 538.18 moveto
+467.65 514.18 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /Helvetica /Helvetica-Bold /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF 1.751
+(The printing commands may occur in the header)69.336 648.6 R 4.251(,f)
+-.4 G(ooter)-4.251 E 4.252(,h)-.4 G 1.752
+(eader2, footer2, top, bottom, top2, bottom2,)-4.252 F .216
+(block, and music conte)69.336 660.6 R 2.716(xts. After)-.15 F .215(eac\
+h printing command, the current location is set to the right edge of th\
+e)2.716 F(last character printed horizontally and at the baseline of th\
+e current line v)69.336 672.6 Q(ertically)-.15 E(.)-.65 E 69.336 690.6
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(10.3 Including)72.836 690.6 R(raw P)3.5 E
+(ostScript)-.28 E 69.336 708.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .608
+(There is another command that looks a lot lik)72.444 708.6 R 3.108(et)
+-.1 G .608(he printing commands, b)-3.108 F .608(ut gi)-.2 F -.15(ve)
+-.25 G 3.108(sy).15 G .608(ou a w)-3.108 F .608(ay to insert ra)-.1 F(w)
+-.15 E .769(PostScript into the Mup output.)69.336 720.6 R .768
+(This might be used, for e)5.769 F .768
+(xample, to include a picture or logo along with)-.15 F(your music.)
+69.336 732.6 Q(The syntax is)5 E EP
+%%Page: 90 96
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-9)274.506 48 S 2.5(0-)-2.5 G/F1 10
+/Times-Bold@0 SF(postscript)105.336 96 Q/F2 10/Times-Italic@0 SF
+(optional_location)6 E F1(")6 E F2 -.15(ra)C 2.5(wP).15 G(ostScript)-3.3
+E F1(")A F0(As with the other print commands, if the location is omitte\
+d, the current location is used.)69.336 116 Q .762
+(The string is copied directly to the Mup output.)69.336 134 R -1.1(Yo)
+5.762 G 3.262(uc)1.1 G .762
+(an use the usual \\" to embed a double quote in the)-3.262 F .146
+(string, b)69.336 146 R .146(ut otherwise the string is copied e)-.2 F
+.145(xactly as it is, enclosed inside a PostScript sa)-.15 F -.15(ve)-.2
+G 2.645(/restore. After).15 F(the)2.645 E
+(restore, the current location is reset back to where it w)69.336 158 Q
+(as originally)-.1 E(.)-.65 E .834
+(Since the string is copied without an)69.336 176 R 3.334(yi)-.15 G .834
+(nterpretation, Mup does not reserv)-3.334 F 3.335(ea)-.15 G 1.135 -.15
+(ny s)-3.335 H .835(pace on the page for the).15 F .429
+(PostScript, and it is your responsibility to pro)69.336 188 R .429
+(vide v)-.15 F .429(alid PostScript.)-.25 F .428
+(The PostScript language is be)5.429 F .428(yond the)-.15 F
+(scope of this User')69.336 200 Q 2.5(sG)-.55 G
+(uide; consult a book on PostScript if you need more information.)-2.5 E
+.896(As a simple e)69.336 218 R .896(xample, you might include an Encap\
+sulated PostScript \214le near the lo)-.15 F .897
+(wer left corner of the)-.25 F(current page using)69.336 230 Q/F3 10
+/Courier@0 SF(postscript "50 50 translate \(file.eps\) run")105.336 248
+Q F0(Or you could print a message in red italics near the bottom of the\
+ page lik)69.336 274 Q 2.5(et)-.1 G(his:)-2.5 E F3
+(postscript \(70, 20\) ")105.336 292 Q 6(100s)189.336 304 S(etrgbcolor)
+-6 E(/NewCenturySchlbk-Italic findfont)189.336 316 Q
+(16 scalefont setfont)189.336 328 Q(\(Photocopying prohibited\) show)
+189.336 340 Q(")189.336 352 Q 69.336 378 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(10.4 Lines)72.836 378 R(and cur)3.5 E
+-.14(ve)-.14 G(s).14 E 69.336 396 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(The "line" statement is used for dra)71.836
+396 Q(wing lines. Its format is:)-.15 E/F1 10/Times-Italic@0 SF
+(linetype)105.336 414 Q/F2 10/Times-Bold@0 SF(line \()6 E F1(X1, Y1)A F2
+2.5(\)t)C 2.5(o\()-2.5 G F1(X2, Y2)-2.5 E F2(\))A F0(The)69.336 434 Q F1
+(linetype)4.148 E F0 1.648(can be "wide," "medium," "w)4.148 F -.2(av)
+-.1 G -.65(y,).2 G 4.147("").65 G 1.647
+(dotted," "dashed," or it can be omitted, which means)-4.147 F(narro)
+69.336 446 Q 4.406 -.65(w. T)-.25 H .606(he w).65 F -.2(av)-.1 G 3.106
+(yl).2 G .607(ine could be used for glissandos. It could also be used f\
+or manually dra)-3.106 F .607(wing rolls and)-.15 F .691
+(trills, although it should rarely if e)69.336 458 R -.15(ve)-.25 G
+3.191(rb).15 G 3.191(en)-3.191 G .691
+(ecessary to resort to this, since the roll and mussym statements)-3.191
+F .215(will usually suf)69.336 470 R .215
+(\214ce and are much easier to use.)-.25 F(Narro)5.216 E 1.516 -.65
+(w, d)-.25 H .216(ashed, or dotted lines w).65 F .216
+(ould typically be used for)-.1 F -.2(vo)69.336 482 S .173
+(ice crossings.).2 F .173
+(The medium line is about twice as wide as a narro)5.173 F 2.673(wl)-.25
+G .173(ine, and a wide line is about twice as)-2.673 F
+(wide as a medium line.)69.336 494 Q
+(The X and Y coordinates are speci\214ed as w)69.336 512 Q
+(as described in the section on "Location tags.")-.1 E/F3 10/Courier@0
+SF(score)105.336 530 Q(vscheme=2f)117.336 542 Q(staff2 clef=bass)117.336
+554 Q(music)105.336 578 Q 6(11)105.336 590 S 6(:c)-6 G 6(+=)-6 G
+(c;e =e;g;c+;)-6 E 6(12)105.336 602 S 6(:e=)-6 G(_e;g =_g;c =_c;s;)-6 E
+6(21)105.336 614 S 6(:2)-6 G(.s;4g =_gg;)-6 E 6(22)105.336 626 S 6(:1)-6
+G(ce;)-6 E(line \(c.e + 2, c.y\) to \(e.w - 2, e.y\))105.336 638 Q
+(line \(_e.e + 2, _e.y\) to \(_g.w - 2, _g.y\))105.336 650 Q
+(dashed line \(_c.e + 1, _c.y\) to \(_gg.w - 1, _gg.y\))105.336 662 Q
+(bar)105.336 674 Q EP
+%%Page: 91 97
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-9)274.506 48 S 2.5(1-)-2.5 G 127.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 123 rlineto 320 0 rlineto 0 123 neg rlineto closepath stroke grestore
+EEND 160 640 320 320 -123 123 126.836 219 PBEGIN
+%%BeginDocument: mugex83.ps
+%%BoundingBox: 160 640 480 763
+save
+1216322504 1216321786 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_SSV
+4 linenum
+%  S_FEED
+324.29 1235.00 468.00 5 1.000000 1.000000 stf
+324.29 1164.00 468.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+180.29 743.00 moveto
+180.29 648.00 lineto stroke
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+192.33 666.00 1.000000 fclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+227.86 734.00 1.000000 4n
+231.54 734.75 moveto
+231.54 755.00 lineto stroke
+290.50 719.00 1.000000 4n
+294.18 719.75 moveto
+294.18 740.00 lineto stroke
+350.39 725.00 1.000000 4n
+354.07 725.75 moveto
+354.07 746.00 lineto stroke
+412.36 734.00 1.000000 4n
+408.68 733.25 moveto
+408.68 713.00 lineto stroke
+227.86 719.00 1.000000 4n
+224.18 718.25 moveto
+224.18 698.00 lineto stroke
+287.50 725.00 1.000000 4n
+283.81 724.25 moveto
+283.81 704.00 lineto stroke
+350.39 713.00 1.000000 4n
+344.15 713.00 moveto
+356.62 713.00 lineto stroke
+346.70 712.25 moveto
+346.70 692.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+412.36 669.00 1.000000 4n
+0.70 setlinewidth
+416.04 669.75 moveto
+416.04 690.00 lineto stroke
+227.86 663.00 1.000000 1n
+227.86 657.00 1.000000 1n
+restore
+%  S_LINE
+11 linenum
+0.70 setlinewidth
+237.89 734.00 moveto
+280.46 719.00 lineto stroke
+%  S_LINE
+12 linenum
+237.89 719.00 moveto
+277.46 725.00 lineto stroke
+%  S_LINE
+13 linenum
+1.00 setlinewidth
+[3 3] 0 setdash
+357.42 713.00 moveto
+405.33 669.00 lineto stroke
+0.70 setlinewidth
+[] 0 setdash
+0 setlinecap
+0 setlinejoin
+%  S_BAR
+15 linenum
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+467.65 672.00 moveto
+467.65 648.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF(It is possible to print a te)69.336 239
+Q(xt string by the line by adding)-.15 E/F1 10/Times-Bold@0 SF(with)
+105.336 257 Q/F2 10/Times-Italic@0 SF(fontfamily font)2.5 E F1(\()2.5 E
+F2(size)A F1 2.5(\)")C F2(string)-2.5 E F1(")A F0 .65
+(at the end of the "line" statement. Only the k)69.336 277 R -.15(ey)-.1
+G -.1(wo).15 G .65(rd "with" and the te).1 F .65
+(xt string itself are required; the font)-.15 F .736
+(and size information is optional.)69.336 289 R .736
+(As usual, the fontf)5.736 F(amily)-.1 E 3.236(,f)-.65 G .736
+(ont, and size parameter v)-3.236 F .736(alues are used to get)-.25 F
+-.25(va)69.336 301 S 2.024(lues if the optional items are omitted. The \
+most common usage for printing a string with a line is).25 F
+(probably for glissandos.)69.336 313 Q/F3 10/Courier@0 SF
+(1: 2d =n; g+ =m;)105.336 331 Q(wavy line \(n.e + 1.5, n.y\) to \(m.w -\
+ 1.5, m.y\) with ital \(9\) "gliss.")105.336 343 Q(bar)105.336 355 Q
+127.836 364.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 320 0 rlineto 0 61 neg rlineto closepath stroke grestore
+EEND 160 702 320 320 -61 61 126.836 425.6 PBEGIN
+%%BeginDocument: mugex84.ps
+%%BoundingBox: 160 702 480 763
+save
+1216322504 1216321786 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+324.29 1235.00 468.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+232.52 716.00 1.000000 2n
+0.70 setlinewidth
+236.42 716.75 moveto
+236.42 737.00 lineto stroke
+355.53 746.00 1.000000 2n
+351.64 745.25 moveto
+351.64 725.00 lineto stroke
+restore
+%  S_LINE
+6 linenum
+gsave
+241.27 716.00 translate
+15.9 rotate
+/Times-Italic findfont
+9 scalefont
+setfont
+45.48 5.70 moveto
+(gliss.) show
+grestore
+241.27 716.00 moveto
+346.79 746.00 1.000000 wavy
+%  S_BAR
+8 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Italic 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF(Arbitrary curv)69.336 445.6 Q
+(es can be dra)-.15 E(wn using the "curv)-.15 E(e" statement:)-.15 E/F1
+10/Times-Italic@0 SF(linetype)105.336 463.6 Q/F2 10/Times-Bold@0 SF(cur)
+6 E .2 -.1(ve \()-.1 H F1(X1,Y1).1 E F2 2.5(\)t)C 2.5(o\()-2.5 G F1
+(X2,Y2)-2.5 E F2 2.5(\)t)C 2.5(o\()-2.5 G F1(X3,Y3)-2.5 E F2(\))A F1
+(...)6 E F0 1.834(When using this form of the "curv)69.336 483.6 R 1.834
+(e" statement, at least three coordinates must be speci\214ed; more are)
+-.15 F 4.267(permitted. The)69.336 495.6 R F1(linetype)4.267 E F0 1.767
+(can be "medium," "wide," "dashed," or "dotted," or omitted.)4.267 F
+4.268(Ac)6.768 G(urv)-4.268 E 4.268(ew)-.15 G 1.768(ill be)-4.268 F(dra)
+69.336 507.6 Q
+(wn through the speci\214ed points in the speci\214ed order)-.15 E(.)
+-.55 E/F3 10/Courier@0 SF(score)105.336 525.6 Q(staffs=2)105.336 537.6 Q
+(staff 2)105.336 561.6 Q(clef=bass)117.336 573.6 Q(music)105.336 597.6 Q
+(1: 4.s;[=c] 8e; [=d] g; [=e] e;4s;)105.336 609.6 Q
+(2: [=a] 8c;g; [=b] c+;4.s; [=f] 8c+; [=g] c;)105.336 621.6 Q
+(medium curve \(a.x, a.n+1\) to \(b.x, b.n+15\) to \(c.x, c.n+4\) \\)
+105.336 633.6 Q(to \(d.x, d.n+3\) to \(e.x, e.n+3\) \\)155.336 645.6 Q
+(to \(f.x, f.n+11\) to \(g.x, g.n+1\))155.336 657.6 Q(bar)105.336 669.6
+Q EP
+%%Page: 92 98
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-9)274.506 48 S 2.5(2-)-2.5 G 127.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 108 rlineto 320 0 rlineto 0 108 neg rlineto closepath stroke grestore
+EEND 160 657 320 320 -108 108 126.836 204 PBEGIN
+%%BeginDocument: mugex85.ps
+%%BoundingBox: 160 657 480 765
+save
+1216322504 1216321786 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_SSV
+6 linenum
+%  S_FEED
+324.29 1235.00 468.00 5 1.000000 1.000000 stf
+324.29 1181.00 468.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+180.29 743.00 moveto
+180.29 665.00 lineto stroke
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+192.33 683.00 1.000000 fclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+313.16 719.00 1.000000 4n
+316.84 719.75 moveto
+316.84 740.00 lineto stroke
+319.87 740.00 1.000000 dnflag
+343.88 725.00 1.000000 4n
+347.56 725.75 moveto
+347.56 746.00 lineto stroke
+350.59 746.00 1.000000 dnflag
+374.69 719.00 1.000000 4n
+378.37 719.75 moveto
+378.37 740.00 lineto stroke
+381.39 740.00 1.000000 dnflag
+restore
+%  S_STAFF
+% staff 2
+save
+221.01 674.00 1.000000 4n
+0.70 setlinewidth
+224.69 674.75 moveto
+224.69 695.00 lineto stroke
+227.71 695.00 1.000000 dnflag
+252.57 686.00 1.000000 4n
+248.89 685.25 moveto
+248.89 665.00 lineto stroke
+251.91 665.00 1.000000 upflag
+283.37 695.00 1.000000 4n
+277.14 695.00 moveto
+289.61 695.00 lineto stroke
+279.69 694.25 moveto
+279.69 674.00 lineto stroke
+282.72 674.00 1.000000 upflag
+406.16 695.00 1.000000 4n
+399.92 695.00 moveto
+412.39 695.00 lineto stroke
+402.47 694.25 moveto
+402.47 674.00 lineto stroke
+405.50 674.00 1.000000 upflag
+436.87 674.00 1.000000 4n
+440.55 674.75 moveto
+440.55 695.00 lineto stroke
+443.58 695.00 1.000000 dnflag
+restore
+%  S_CURVE
+11 linenum
+221.01 699.00 moveto
+220.92 699.12 lineto
+238.91 718.05 259.60 733.32 283.00 744.92 curveto
+292.48 749.63 302.73 751.74 313.02 753.74 curveto
+323.22 755.71 333.47 757.25 343.92 756.75 curveto
+354.56 756.24 364.93 754.39 374.95 750.70 curveto
+386.47 746.46 397.05 740.54 406.63 732.86 curveto
+418.60 723.27 428.71 712.01 436.98 699.10 curveto
+436.76 698.90 lineto
+428.05 711.39 417.69 722.33 405.68 731.70 curveto
+396.15 739.14 385.79 745.12 374.42 749.30 curveto
+364.55 752.93 354.32 754.75 343.84 755.25 curveto
+333.52 755.74 323.39 754.21 313.30 752.26 curveto
+303.18 750.31 293.12 748.18 283.75 743.63 curveto
+260.34 732.25 239.45 717.34 221.10 698.88 curveto
+fill
+%  S_BAR
+15 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+467.65 689.00 moveto
+467.65 665.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF 1.551(An alternati)69.336 224 R 1.851
+-.15(ve w)-.25 H 1.551(ay to specify a curv).05 F 4.051(ei)-.15 G 4.051
+(st)-4.051 G 4.051(oo)-4.051 G 1.55(nly specify the tw)-4.051 F 4.05(oe)
+-.1 G 1.55(ndpoints, along one or more "b)-4.05 F(ulge")-.2 E -.25(va)
+69.336 236 S .98(lues, gi).25 F -.15(ve)-.25 G 3.48(ni).15 G 3.48(ns)
+-3.48 G 3.48(tepsizes. Suppose)-3.48 F 3.48(as)3.48 G .98(ingle b)-3.48
+F .98(ulge v)-.2 F(alue)-.25 E/F1 10/Times-Italic@0 SF(n)3.481 E F0 .981
+(is gi)3.481 F -.15(ve)-.25 G .981(n. T).15 F 3.481<6f8c>-.8 G .981
+(nd the midpoint of the resulting)-3.481 F(curv)69.336 248 Q 1.894
+(e, imagine a line is dra)-.15 F 1.894(wn between the tw)-.15 F 4.394
+(oe)-.1 G 1.893(ndpoints, then from the midpoint of that line, mo)-4.394
+F -.15(ve)-.15 G .399(perpendicular to the line for)69.336 260 R F1(n)
+2.899 E F0 2.899(stepsizes. A)2.899 F(positi)2.899 E -.15(ve)-.25 G F1
+(n)3.049 E F0 .4(will cause the curv)2.899 F 2.9(et)-.15 G 2.9(ob)-2.9 G
+.4(ulge to the left as you mo)-3.1 F -.15(ve)-.15 G .348
+(from the start point to the end point, while a ne)69.336 272 R -.05(ga)
+-.15 G(ti).05 E -.15(ve)-.25 G F1(n)2.998 E F0 .348(will mak)2.848 F
+2.848(ei)-.1 G 2.848(tb)-2.848 G .347(ulge to the right.)-3.048 F .347
+(If tw)5.347 F 2.847(ob)-.1 G .347(ulge v)-3.047 F(alues)-.25 E 1.058
+(are gi)69.336 284 R -.15(ve)-.25 G 1.058(n, b).15 F 1.059(ulges are ca\
+lculated from the 1/3 and 2/3 point of the line between the endpoints; \
+with three)-.2 F(points, at 1/4, 1/2, and 3/4, and so forth. Multiple b)
+69.336 296 Q(ulge v)-.2 E(alues are separated by commas.)-.25 E/F2 10
+/Courier@0 SF(1: c =_c1; f; f; d =_d1;)105.336 314 Q
+(medium curve \(_c1.x, _c1.y + 8\) to \(_d1.x, _d1.y + 10\) bulge 3)
+105.336 326 Q(bar)105.336 338 Q(1: g =_g1; e+; d+; a =_a1;)105.336 362 Q
+(dotted curve \(_g1.x, _g1.y - 2\) to \(_a1.x, _a1.y - 2\) bulge -4.3)
+105.336 374 Q(bar)105.336 386 Q(1: g =_g2; a; d+; c+ =_c2;)105.336 410 Q
+6(curve \(_g2.x,)105.336 422 R
+(_g2.y - 2\) to \(_c2.x, _c2.y + 2\) bulge -2.5, 4)6 E(bar)105.336 434 Q
+103.836 443.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 63 rlineto 368 0 rlineto 0 63 neg rlineto closepath stroke grestore
+EEND 136 700 368 368 -63 63 102.836 506.6 PBEGIN
+%%BeginDocument: mugex86.ps
+%%BoundingBox: 136 700 504 763
+save
+1216322504 1216321786 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+302.69 1235.00 489.60 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+170.48 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+198.31 713.00 1.000000 4n
+0.70 setlinewidth
+192.08 713.00 moveto
+204.54 713.00 lineto stroke
+201.99 713.75 moveto
+201.99 734.00 lineto stroke
+220.43 722.00 1.000000 4n
+224.11 722.75 moveto
+224.11 743.00 lineto stroke
+242.54 722.00 1.000000 4n
+246.22 722.75 moveto
+246.22 743.00 lineto stroke
+265.50 716.00 1.000000 4n
+269.18 716.75 moveto
+269.18 737.00 lineto stroke
+restore
+%  S_CURVE
+6 linenum
+198.31 737.00 moveto
+198.26 737.14 lineto
+207.72 744.87 218.50 749.54 230.61 751.16 curveto
+242.72 752.79 254.35 751.11 265.52 746.15 curveto
+265.48 745.85 lineto
+254.24 749.99 242.68 751.27 230.81 749.68 curveto
+218.94 748.09 208.12 743.81 198.37 736.86 curveto
+fill
+%  S_BAR
+8 linenum
+0.70 setlinewidth
+288.26 743.00 moveto
+288.26 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+298.81 725.00 1.000000 4n
+302.49 725.75 moveto
+302.49 746.00 lineto stroke
+320.92 740.00 1.000000 4n
+317.24 739.25 moveto
+317.24 719.00 lineto stroke
+343.04 737.00 1.000000 4n
+339.35 736.25 moveto
+339.35 716.00 lineto stroke
+365.99 728.00 1.000000 4n
+369.67 728.75 moveto
+369.67 749.00 lineto stroke
+restore
+%  S_CURVE
+10 linenum
+1.00 setlinewidth
+[0.1 5] 0 setdash
+1 setlinecap
+1 setlinejoin
+298.81 719.00 moveto
+308.74 710.83 320.13 707.04 332.97 707.61 curveto
+345.82 708.19 356.82 712.98 365.99 722.00 curveto
+stroke
+0.70 setlinewidth
+[] 0 setdash
+0 setlinecap
+0 setlinejoin
+%  S_BAR
+12 linenum
+388.76 743.00 moveto
+388.76 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+399.30 725.00 1.000000 4n
+402.98 725.75 moveto
+402.98 746.00 lineto stroke
+421.41 728.00 1.000000 4n
+425.10 728.75 moveto
+425.10 749.00 lineto stroke
+443.53 737.00 1.000000 4n
+439.85 736.25 moveto
+439.85 716.00 lineto stroke
+466.48 734.00 1.000000 4n
+462.80 733.25 moveto
+462.80 713.00 lineto stroke
+restore
+%  S_CURVE
+14 linenum
+399.30 719.00 moveto
+399.30 719.07 lineto
+407.46 714.68 415.61 714.70 423.75 719.14 curveto
+433.91 724.68 429.14 739.91 440.35 744.77 curveto
+450.11 749.00 458.82 747.43 466.49 740.07 curveto
+466.47 739.93 lineto
+458.79 746.96 450.18 748.36 440.66 744.14 curveto
+429.57 739.22 434.36 724.02 424.11 718.54 curveto
+415.77 714.09 407.50 714.22 399.30 718.93 curveto
+fill
+%  S_BAR
+16 linenum
+0.70 setlinewidth
+489.25 743.00 moveto
+489.25 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND EP
+%%Page: 93 99
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-9)274.506 48 S 2.5(3-)-2.5 G 69.336 103
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(11. MISCELLANEOUS)73.086 103 R(FEA)3.75
+E(TURES)-1.425 E 69.336 121 EBEGIN
+0 0 0 setrgbcolor
+EEND 69.336 139 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(11.1 Newscor)72.836 139 R 3.5(ea)-.252 G
+(nd newpage)-3.5 E 69.336 157 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(Normally)72.256 157 Q 2.92(,M)-.65 G .42
+(up determines ho)-2.92 F 2.92(wm)-.25 G(an)-2.92 E 2.92(ym)-.15 G .419
+(easures to put on each score and ho)-2.92 F 2.919(wm)-.25 G(an)-2.919 E
+2.919(ys)-.15 G .419(cores to put on each)-2.919 F .238(page. Y)69.336
+169 R .238(ou can force Mup to mo)-1.1 F .538 -.15(ve t)-.15 H 2.738(ot)
+.15 G .238(he ne)-2.738 F .238(xt score with the "ne)-.15 F .238
+(wscore" statement, or to the ne)-.25 F .238(xt page with)-.15 F 2.5(a")
+69.336 181 S(ne)-2.5 E(wpage" statement.)-.25 E(Here is an e)5 E
+(xample:)-.15 E/F1 10/Courier@0 SF(1: c;d;e;f;)105.336 199 Q(bar)105.336
+211 Q(1: e;f;g;;)105.336 223 Q(bar)105.336 235 Q 12(newscore //)105.336
+247 R(go to next score)6 E(1: 2c;;)105.336 259 Q(bar)105.336 271 Q
+(1: e;f;g;;)105.336 283 Q(bar)105.336 295 Q 12(newpage //)105.336 307 R
+(go to next page)6 E(1: e;g;2c;)105.336 319 Q(bar)105.336 331 Q F0 -1.1
+(Yo)69.336 357 S 3.062(uc)1.1 G .562
+(an temporarily change the indent for the ne)-3.062 F 3.062(ws)-.25 G
+.562(core by specifying "leftmar)-3.062 F(gin=)-.18 E/F2 10
+/Times-Italic@0 SF(num)A F0 .562(," where)B F2(num)3.062 E F0 .561(is a)
+3.061 F 1.137(\215oating point number of inches or centimeters \(depend\
+ing on the current setting of the units parameter)69.336 369 R(.\))-.55
+E(The ne)69.336 381 Q 2.5(ws)-.25 G
+(core will then be indented by that much, o)-2.5 E -.15(ve)-.15 G
+(rriding the v).15 E(alue of the leftmar)-.25 E(gin parameter)-.18 E(.)
+-.55 E .9(In a similar w)69.336 399 R(ay)-.1 E 3.4(,y)-.65 G .9
+(ou can specify "rightmar)-3.4 F(gin=)-.18 E F2(num)A F0 .899
+(," which will af)B .899(fect the right mar)-.25 F .899(gin on the)-.18
+F/F3 10/Times-Bold@0 SF(pr)3.399 E -.15(ev)-.18 G(ious).15 E F0
+(score. This might be used, for e)69.336 411 Q(xample, if you w)-.15 E
+(ant a piece to end with a shorter than normal score.)-.1 E F1
+(newscore leftmargin=1.2 rightmargin=2.7)105.336 429 Q F0
+(The equals sign is optional in these mar)69.336 449 Q(gin o)-.18 E -.15
+(ve)-.15 G(rrides.).15 E 69.336 467 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(11.2 Headers)72.836 467 R(and f)3.5 E
+(ooters)-.35 E 69.336 485 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .565(Mup pro)72.401 485 R .565(vides w)-.15
+F .565(ays to put headers and footers on pages of output.)-.1 F .566
+(Often you may w)5.566 F .566(ant a certain kind of)-.1 F .528
+(header and footer on the \214rst page, b)69.336 497 R .528(ut a dif)-.2
+F .527(ferent kind on an)-.25 F 3.027(ys)-.15 G .527
+(ubsequent pages, so Mup mak)-3.027 F .527(es it easy to)-.1 F 1.325
+(do that. Mup also of)69.336 509 R 1.325(fers tw)-.25 F 3.825(od)-.1 G
+(if)-3.825 E 1.326(ferent "layers" of headers and footers. These layers\
+ may be particularly)-.25 F .316(useful if you ha)69.336 521 R .616 -.15
+(ve a s)-.2 H .316
+(ingle Mup \214le that contains multiple songs, or multiple mo).15 F
+-.15(ve)-.15 G .315(ments of a song.).15 F .315(In that)5.315 F .673
+(case, there may be certain things that you w)69.336 533 R .674
+(ant printed in headers and footers throughout, lik)-.1 F 3.174(et)-.1 G
+.674(he current)-3.174 F .202
+(page number and the name of the entire collection, b)69.336 545 R .202
+(ut other things that you w)-.2 F .202(ant to ha)-.1 F .502 -.15(ve c)
+-.2 H .202(hange with each).15 F(ne)69.336 557 Q 2.5(ws)-.25 G
+(ong or mo)-2.5 E -.15(ve)-.15 G(ment.).15 E 1.08
+(The "outer" layer is speci\214ed by four conte)69.336 575 R 1.081
+(xts: header)-.15 F 3.581(,f)-.4 G(ooter)-3.581 E 3.581(,h)-.4 G 1.081
+(eader2, and footer2. The "inner" layer is)-3.581 F .858
+(speci\214ed by four conte)69.336 587 R .858
+(xts: top, bottom, top2, and bottom2.)-.15 F .857(All of these conte)
+5.857 F .857(xts are optional.)-.15 F .857(The outer)5.857 F(conte)
+69.336 599 Q .827(xts can only be speci\214ed once per \214le.)-.15 F
+.827(The inner conte)5.827 F .827
+(xts can be speci\214ed more than once per \214le,)-.15 F .238
+(and each time a set of them occurs, a ne)69.336 611 R 2.738(wp)-.25 G
+.238(age is started.)-2.738 F .238(On output pages, all of these conte)
+5.238 F .238(xts are placed)-.15 F
+(horizontally between the left and right mar)69.336 623 Q(gins, and v)
+-.18 E(ertically the elements appear in the follo)-.15 E(wing order:)
+-.25 E(\(topmar)71.836 641 Q(gin\))-.18 E(header)69.336 653 Q(top)69.336
+665 Q(\(one or more scores of music or blocks of te)71.836 677 Q(xt\))
+-.15 E(bottom)69.336 689 Q(footer)69.336 701 Q(\(bottommar)71.836 713 Q
+(gin\))-.18 E .875(Which v)69.336 731 R .875
+(ersion is used\212the one with or without the "2" suf)-.15 F .875
+(\214x\212depends on which page is being printed.)-.25 F .031
+(The items in header and footer appear on only the v)69.336 743 R .031
+(ery \214rst page, while those in header2 and footer2 appear)-.15 F EP
+%%Page: 94 100
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-9)274.506 48 S 2.5(4-)-2.5 G .733
+(on all subsequent pages.)69.336 96 R(Some)5.733 E .733(what similarly)
+-.25 F 3.233(,t)-.65 G .733
+(he items in top and bottom will appear on the page that is)-3.233 F
+.262(started when the)69.336 108 R 2.761(ya)-.15 G .261(re encountered \
+in the input, while top2 and bottom2 will then be used on all subsequen\
+t)-2.761 F 2.508(pages. Ho)69.336 120 R(we)-.25 E -.15(ve)-.25 G .808
+-.4(r, y).15 H .008(ou can specify a ne).4 F 2.508(wt)-.25 G .008
+(op and/or bottom later)-2.508 F 2.509(,t)-.4 G .009
+(hat will then to used for one page, and you)-2.509 F .297
+(can specify a ne)69.336 132 R 2.797(wt)-.25 G .297
+(op2 and/or bottom2 later which will replace the pre)-2.797 F .296
+(vious top2/bottom2.)-.25 F .296(Note, ho)5.296 F(we)-.25 E -.15(ve)-.25
+G -.4(r,).15 G 1.054(that if you change top2 b)69.336 144 R 1.054
+(ut not top, that ne)-.2 F 3.554(wt)-.25 G 1.054
+(op2 is used immediately on the ne)-3.554 F 3.554(wp)-.25 G 1.054
+(age, whereas if you)-3.554 F .395(change both, the ne)69.336 156 R
+2.895(wt)-.25 G .395(op applies to the immediately follo)-2.895 F .395
+(wing ne)-.25 F 2.895(wp)-.25 G .395(age, and the ne)-2.895 F 2.895(wt)
+-.25 G .395(op2 isn')-2.895 F 2.895(tu)-.18 G .395(sed until)-2.895 F
+(the follo)69.336 168 Q
+(wing page. Subsequent pages will use top2 in either case.)-.25 E .282
+(Some e)69.336 186 R .282(xamples may help.)-.15 F .282
+(First a simple case: suppose you ha)5.282 F .582 -.15(ve a s)-.2 H .282
+(ingle song, and you').15 F 2.782(dl)-.5 G(ik)-2.782 E 2.782(eat)-.1 G
+.282(itle at the)-2.782 F(top of the \214rst page. This is straightforw)
+69.336 198 Q(ard:)-.1 E/F1 10/Courier@0 SF(top)105.336 216 Q
+(title "Here is the Title")129.336 228 Q F0 -.15(Fo)69.336 248 S 3.006
+(rt).15 G .506(his simple e)-3.006 F .506(xample, it w)-.15 F .506
+(ould w)-.1 F .505(ork just as well to use "header" instead of "top," s\
+o you can use either)-.1 F 1.767
+(one, although top is slightly more \215e)69.336 260 R 4.267
+(xible. Later)-.15 F(we')4.267 E 1.767(ll see some e)-.1 F 1.767
+(xamples where you might use both)-.15 F
+(header and top in the same \214le, for dif)69.336 272 Q
+(ferent kinds of titles.)-.25 E(No)69.336 290 Q 2.865(ws)-.25 G .365
+(uppose you')-2.865 F 2.865(dl)-.5 G(ik)-2.865 E 2.865(et)-.1 G 2.865
+(om)-2.865 G(ak)-2.865 E 2.865(et)-.1 G .365(he title bigger and bolder)
+-2.865 F 2.865(,a)-.4 G .365(nd w)-2.865 F .365(ould lik)-.1 F 2.865(et)
+-.1 G 2.864(oa)-2.865 G .364(dd a subtitle and composer)-2.864 F
+(information, as well as add a cop)69.336 302 Q
+(yright notice to the bottom of the page.)-.1 E F1(top)105.336 320 Q
+(title bold \(18\) "Here is the Title")123.336 332 Q
+(title ital \(14\) "Here is a subtitle")123.336 344 Q
+(title "Lyrics: Ann Author" "Composer: Me")123.336 356 Q(bottom)105.336
+368 Q(title "\\\(copyright\) Copyright 2003 by Ann Author and Me")
+123.336 380 Q F0(Ag)69.336 400 Q(ain, in this simple e)-.05 E(xample, y\
+ou could use "header" and "footer" rather than "top" and "bottom.")-.15
+E(No)69.336 418 Q 3.505(ws)-.25 G 1.006
+(uppose the song is long enough to tak)-3.505 F 3.506(es)-.1 G -2.15
+-.25(ev e)-3.506 H 1.006(ral pages, and you w).25 F 1.006(ould lik)-.1 F
+3.506(et)-.1 G 3.506(or)-3.506 G 1.006(epeat the title along)-3.506 F
+(with the page number on all pages after the \214rst. T)69.336 430 Q 2.5
+(oa)-.8 G(ccomplish this, you could add:)-2.5 E F1(top2)105.336 448 Q
+(title "Here is the Title - \\%")117.336 460 Q F0 .541
+(The \\% is a special mark)69.336 480 R .54
+(er that will get replaced on each page with the current page number)-.1
+F 3.04(.W)-.55 G .54(hile it can)-3.04 F .031(be used in an)69.336 492 R
+2.531(yt)-.15 G -.15(ex)-2.531 G 2.531(ts).15 G .031
+(tring, it is probably only lik)-2.531 F .031
+(ely to be useful in these header and footer kinds of conte)-.1 F(xts.)
+-.15 E .642(Another special mark)69.336 504 R .641(er is \\#, which wil\
+l be replaced by the page number of the \214nal page.)-.1 F .641
+(This could be)5.641 F(useful for doing something lik)69.336 516 Q 2.5
+(e")-.1 G(page \\% of \\#.")-2.5 E(As a v)69.336 534 Q
+(ariation, perhaps you')-.25 E 2.5(dp)-.5 G
+(refer the information at the bottom of the page.)-2.5 E F1(bottom2)
+105.336 552 Q(title "This is the title")123.336 564 Q("Page \\%")12 E F0
+.002(In this v)69.336 584 R .002(ariation, tw)-.25 F 2.502(os)-.1 G .002
+(eparate te)-2.502 F .002(xt strings are speci\214ed, so the \214rst st\
+ring will be left justi\214ed and the second)-.15 F
+(will be right justi\214ed.)69.336 596 Q .293(Note that if you gi)69.336
+614 R .593 -.15(ve a t)-.25 H .293(op2 or bottom2, b).15 F .292
+(ut it turns out there aren')-.2 F 2.792(ta)-.18 G .592 -.15(ny a)-2.792
+H .292(dditional pages, the).15 F 2.792(yw)-.15 G .292(ould ne)-2.892 F
+-.15(ve)-.25 G(r).15 E(actually get used.)69.336 626 Q(But it w)5 E
+(ouldn')-.1 E 2.5(th)-.18 G(urt to ha)-2.5 E .3 -.15(ve s)-.2 H
+(et them.).15 E(No)69.336 644 Q 4.026(wl)-.25 G(et')-4.026 E 4.026(sc)
+-.55 G 1.526(onsider a more complicated e)-4.026 F 1.526
+(xample, using both outer and inner conte)-.15 F 1.526
+(xts. Suppose you are)-.15 F .384
+(publishing a book of songs, entitled "My F)69.336 656 R -.2(avo)-.15 G
+.384(rite Songs," and you w).2 F .384
+(ant to put that title at the top of e)-.1 F -.15(ve)-.25 G(ry).15 E
+.852(page throughout the book, and you w)69.336 668 R .853
+(ant a page number at the bottom of each page e)-.1 F .853
+(xcept the \214rst.)-.15 F -1.1(Yo)5.853 G(u)1.1 E
+(could get that much using:)69.336 680 Q EP
+%%Page: 95 101
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-9)274.506 48 S 2.5(5-)-2.5 G/F1 10
+/Courier@0 SF(header)105.336 96 Q(title "My Favorite Songs")123.336 108
+Q(header2)105.336 120 Q(title "My Favorite Songs")123.336 132 Q(footer2)
+105.336 144 Q(title "\\%")123.336 156 Q F0 1.506
+(But suppose that in addition, you w)69.336 176 R 1.506
+(ant each song to ha)-.1 F 1.806 -.15(ve i)-.2 H 1.505
+(ts title on its \214rst page in big print, and on).15 F .911
+(subsequent pages in re)69.336 188 R .911(gular size print.)-.15 F 2.511
+-.8(To g)5.911 H .912(et this, at the be).8 F .912
+(ginning of each song, you could use top and)-.15 F(top2:)69.336 200 Q
+F1(top)105.336 218 Q(title \(18\) "This is the Song Title")123.336 230 Q
+(top2)105.336 242 Q(title "This is the Song Title")123.336 254 Q F0
+3.385(Ac)69.336 280 S .885(omposition with multiple mo)-3.385 F -.15(ve)
+-.15 G .884(ments can be handled similarly).15 F 3.384(,b)-.65 G 3.384
+(yg)-3.384 G -.25(iv)-3.384 G .884(ing header).25 F 3.384(,f)-.4 G
+(ooter)-3.384 E 3.384(,h)-.4 G .884(eader2, and)-3.384 F .458
+(footer2 \(or an)69.336 292 R 2.959(ys)-.15 G .459
+(ubset thereof\) for the composition as a whole, and then gi)-2.959 F
+.459(ving ne)-.25 F 2.959(wt)-.25 G .459(op, bottom, top2, and)-2.959 F
+(bottom2 de\214nition \(or an)69.336 304 Q 2.5(ys)-.15 G
+(ubset\) at the be)-2.5 E(ginning of each ne)-.15 E 2.5(wm)-.25 G -.15
+(ove)-2.5 G(ment.).15 E 2.208(These conte)69.336 322 R 2.208
+(xts are conceptually in a separate coordinate space, which will be o)
+-.15 F -.15(ve)-.15 G 2.208(rlaid on each page).15 F 1.457
+(coordinate space.)69.336 334 R 1.457(When in these conte)6.457 F 1.458
+(xts, the _win special tag applies to the header or footer windo)-.15 F
+(w)-.25 E(rather than the space between the header and footer as it doe\
+s in the music conte)69.336 346 Q(xt.)-.15 E .569
+(Since headers or footers will e)69.336 364 R .569(xpand as necessary)
+-.15 F 3.069(,t)-.65 G .569(he v)-3.069 F .569
+(alue of _win.s and _win.y may be changed by an)-.25 F(y)-.15 E .09
+(of the statements in the conte)69.336 376 R .09(xt. At an)-.15 F 2.59
+(yg)-.15 G -2.15 -.25(iv e)-2.59 H 2.59(nt).25 G .09(ime, the)-2.59 F
+2.591(yr)-.15 G .091
+(efer to the boundaries as de\214ned by what has been)-2.591 F .98
+(printed so f)69.336 388 R(ar)-.1 E 3.48(.T)-.55 G .98(hus, if the \214\
+rst line of a header contains an 18 point title, after that, _win.s w)
+-3.48 F .98(ould be 18)-.1 F .913(points belo)69.336 400 R 3.413(w_)-.25
+G 3.413(win.n. It)-3.413 F .914
+(the header then contained a 12 point title, after that it w)3.413 F
+.914(ould be 31 points belo)-.1 F(w)-.25 E(_win.n \(12 points for the t\
+itle string, plus 1 point of padding that is added between lines printe\
+d\).)69.336 412 Q .177
+(In addition to the "title" commands used in the e)69.336 430 R .177
+(xamples abo)-.15 F -.15(ve)-.15 G 2.677(,y).15 G .176
+(ou can also use the "print," "left," "right,")-2.677 F 1.28
+(or "center" commands.)69.336 442 R 1.28(In most cases you will w)6.28 F
+1.28(ant to use "nl" for the)-.1 F/F2 10/Times-Italic@0 SF(location)3.78
+E F0 1.28(on those commands to)3.78 F .299(place things. If you don')
+69.336 454 R 2.799(ts)-.18 G .299(pecify a)-2.799 F F2(location)2.799 E
+F0 .299(for the \214rst of these commands in a header or footer)2.799 F
+2.799(,M)-.4 G .299(up will)-2.799 F 1.123(start at the left mar)69.336
+466 R 1.123(gin, just f)-.18 F 1.123(ar enough do)-.1 F 1.123
+(wn from the top to accommodate the te)-.25 F 1.124
+(xt string to be printed.)-.15 F 1.722(These conte)69.336 478 R 1.722
+(xts can also contain settings of the font, fontf)-.15 F(amily)-.1 E
+4.221(,a)-.65 G 1.721(nd size parameters.)-4.221 F 1.721
+(These parameter)6.721 F -.25(va)69.336 490 S
+(lues will be used until the end of the conte).25 E(xt or until set ag)
+-.15 E(ain to some other v)-.05 E(alue.)-.25 E 69.336 508 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(11.3 Macr)72.836 508 R(os)-.252 E 69.336
+526 EBEGIN
+0 0 0 setrgbcolor
+EEND 69.336 543 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(11.3.1 Simple)72.586 543 R(Macr)3.25 E
+(os \(without par)-.585 E(ameter)-.195 E(s\))-.13 E 69.336 555 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .128(Macros can be de\214ned to a)71.964 555
+R -.2(vo)-.2 G .128(id retyping or to gi).2 F .429 -.15(ve m)-.25 H .129
+(nemonic names to things. A macro is de\214ned with the).15 F(follo)
+69.336 567 Q(wing syntax:)-.25 E/F1 10/Times-Bold@0 SF(de\214ne)105.336
+585 Q/F2 10/Times-Italic@0 SF(macr)8.5 E(o_name macr)-.45 E(o_te)-.45 E
+(xt)-.2 E F1(@)6 E F0(The)69.336 611 Q F2(macr)2.677 E(o_name)-.45 E F0
+.176(consists of one or more upper case letters, digits, and underscore\
+s, with the \214rst character)2.677 F .714(being a letter)69.336 623 R
+5.714(.T)-.55 G(he)-5.714 E F2(macr)3.214 E(o_te)-.45 E(xt)-.2 E F0 .714
+(can be an)3.214 F 3.214(yt)-.15 G -.15(ex)-3.214 G .714
+(t. It can be an).15 F 3.215(yl)-.15 G .715(ength from empty to man)
+-3.215 F 3.215(yp)-.15 G .715(ages. The "@")-3.215 F .9
+(terminates the macro. A literal "@" can be placed in the)69.336 635 R
+F2(macr)3.4 E(o_te)-.45 E(xt)-.2 E F0 .9
+(by preceding it with a backslash.)3.4 F(If)5.9 E(you w)69.336 647 Q
+(ant a literal backslash in the)-.1 E F2(macr)2.5 E(o_te)-.45 E(xt)-.2 E
+F0 2.5(,i)C 2.5(ta)-2.5 G(lso must be preceded by a backslash.)-2.5 E
+2.86(Am)69.336 665 S .36(acro is called by stating the)-2.86 F F2(macr)
+2.86 E(o_name)-.45 E F0 .36(in the input. The)2.86 F F2(macr)2.86 E
+(o_name)-.45 E F0 .36(is replaced by the)2.86 F F2(macr)2.86 E(o_te)-.45
+E(xt)-.2 E F0(.)A 3.425(Am)69.336 677 S .925
+(acro can be de\214ned at an)-3.425 F 3.425(yp)-.15 G .925
+(oint in the input. It can be used as often as desired an)-3.425 F 3.424
+(yt)-.15 G .924(ime after it has)-3.424 F 1.076(been de\214ned. A gi)
+69.336 689 R -.15(ve)-.25 G(n).15 E F2(macr)3.576 E(o_name)-.45 E F0
+1.076(can be rede\214ned as man)3.576 F 3.576(yt)-.15 G 1.077
+(imes as desired, with each ne)-3.576 F 3.577(wd)-.25 G(e\214nition)
+-3.577 E -.15(ove)69.336 701 S(rwriting the pre).15 E
+(vious de\214nition.)-.25 E .921(As an e)69.336 719 R .921(xample, supp\
+ose you are printing an orchestral score, and the oboe part happens to \
+be on staf)-.15 F 3.42(f5)-.25 G(.)-3.42 E(Rather than ha)69.336 731 Q
+(ving to remember which staf)-.2 E 2.5(fi)-.25 G 2.5(ti)-2.5 G
+(s, you could de\214ne a macro:)-2.5 E EP
+%%Page: 96 102
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-9)274.506 48 S 2.5(6-)-2.5 G/F1 10
+/Courier@0 SF(define OBOE 5: @)105.336 96 Q F0 .501
+(Not only is the name easier to remember than a number)69.336 116 R
+3.001(,b)-.4 G .501(ut if you later decide to mo)-3.201 F .802 -.15
+(ve t)-.15 H .502(he oboe part to a).15 F(dif)69.336 128 Q 1.357(ferent\
+ place in the score, only the macro de\214nition and perhaps a fe)-.25 F
+3.856(wo)-.25 G 1.356(ther things w)-3.856 F 1.356(ould ha)-.1 F 1.656
+-.15(ve t)-.2 H 3.856(ob).15 G(e)-3.856 E(changed.)69.336 140 Q .121
+(Another common use of macros might be if a musical motif occurs se)
+69.336 158 R -.15(ve)-.25 G .121(ral times. Y).15 F .121
+(ou could de\214ne a macro)-1.1 F(for the moti)69.336 170 Q -.15(ve)-.25
+G(:).15 E F1(define SCALE 8c;d;e;f;g;a;b;c+; @)105.336 188 Q F0
+(then do something lik)69.336 208 Q(e:)-.1 E F1(OBOE SCALE)105.336 226 Q
+F0(It is possible to remo)69.336 252 Q .3 -.15(ve t)-.15 H
+(he de\214nition of a macro using the "undef" statement:).15 E F1
+(undef OBOE)105.336 270 Q F0 .893(It is possible to ha)69.336 296 R
+1.192 -.15(ve p)-.2 H .892(arts of the input skipped o).15 F -.15(ve)
+-.15 G 3.392(rd).15 G .892
+(epending on whether certain macros are de\214ned or)-3.392 F .44
+(not. This is done using "ifdef," "else," and "endif." The k)69.336 308
+R -.15(ey)-.1 G -.1(wo).15 G .441(rd "ifdef" is follo).1 F .441
+(wed by a macro name. If a)-.25 F 1.176(macro by that name is currently\
+ de\214ned, Mup will continue reading and processing input normally)
+69.336 320 R 3.675(.I)-.65 G 3.675(fi)-3.675 G(t)-3.675 E 1.275
+(\214nds a matching "else," it will skip o)69.336 332 R -.15(ve)-.15 G
+3.775(ri).15 G 1.275(nput until the matching "endif.")-3.775 F 1.275
+(If the macro is not currently)6.275 F .677(de\214ned, Mup will skip o)
+69.336 344 R -.15(ve)-.15 G 3.177(rt).15 G .676
+(he input until it \214nds a matching "else" or "endif.")-3.177 F .676
+(There is also an "ifndef")5.676 F .444(command that uses the opposite \
+logic: it will read the input up to the "else" or "endif" only if the m\
+acro is)69.336 356 R(NO)69.336 368 Q 2.5(Td)-.4 G(e\214ned.)-2.5 E .535
+(The ifdefs can be sprinkled between other items in the input; the)
+69.336 386 R 3.035(yn)-.15 G .534(eed not be on separate lines. The)
+-3.035 F 3.034(yc)-.15 G(an)-3.034 E(be nested. Examples:)69.336 398 Q
+F1(// make last c an octave higher if macro "FRED" is defined)105.336
+416 Q(1: c;e;g;c ifdef FRED + endif;)105.336 428 Q(ifdef PIANO)105.336
+452 Q(staff 1 visible=n)129.336 464 Q(else)105.336 476 Q(ifdef VIOLIN)
+129.336 488 Q(staff 2 visible=n)153.336 500 Q(staff 3 visible=n)153.336
+512 Q(endif)129.336 524 Q(endif)105.336 536 Q F0 .547
+(Macros can also be set from the command line using the -D option.)
+69.336 562 R .548(Only ordinary macros can be de\214ned)5.547 F
+(using the -D option, not macros with parameters.)69.336 574 Q 69.336
+591 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(11.3.2 Macr)72.586 591 R(os with par)
+-.585 E(ameter)-.195 E(s)-.13 E 69.336 603 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .133
+(Macros de\214ned within Mup input can be de\214ned to ha)71.969 603 R
+.433 -.15(ve ")-.2 H 2.633(parameters." This).15 F .132
+(may be useful when you ha)2.633 F -.15(ve)-.2 G .302
+(something that is repeated with small v)69.336 615 R 2.803
+(ariations. When)-.25 F .303
+(de\214ning a macro with parameters, the macro name)2.803 F .562
+(must be follo)69.336 627 R .561(wed immediately by a \( with no space \
+between the end of the name and the parenthesis. The)-.25 F .25
+(opening parenthesis is follo)69.336 639 R .25(wed by one or more param\
+eter names, separated by commas, and ending with a)-.25 F .19
+(close parenthesis.)69.336 651 R -.15(Pa)5.19 G .19(rameter names ha).15
+F .49 -.15(ve t)-.2 H .189(he same rules as macro names: the).15 F 2.689
+(yc)-.15 G .189(onsist of upper case letters,)-2.689 F .739
+(numbers, and underscores, starting with an upper case letter)69.336 663
+R 3.239(.T)-.55 G .74(he parameter names can then appear in the)-3.239 F
+(te)69.336 675 Q(xt of the macro de\214nition where you w)-.15 E
+(ant a v)-.1 E(alue to be substituted.)-.25 E .235(As an e)69.336 693 R
+.235(xample, suppose you are doing a score with staf)-.15 F .234
+(fs 1 through 4 for v)-.25 F .234(ocal parts, and staf)-.2 F .234
+(fs 5 and 6 for)-.25 F 2.728(ap)69.336 705 S .228
+(iano accompaniment, and that you frequently w)-2.728 F .229
+(ant to mark a dymanics change at the same point in time)-.1 F(belo)
+69.336 717 Q 4.907(we)-.25 G 2.407(ach of the v)-4.907 F 2.407
+(ocal scores and between the tw)-.2 F 4.906(op)-.1 G 2.406(iano staf)
+-4.906 F 4.906(fs. Y)-.25 F 2.406(ou could typically do this with)-1.1 F
+(something lik)69.336 729 Q(e:)-.1 E EP
+%%Page: 97 103
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-9)274.506 48 S 2.5(7-)-2.5 G/F1 10
+/Courier@0 SF(boldital below 1-4: 1 "ff";)105.336 96 Q
+(boldital between 5&6: 1 "ff";)105.336 108 Q F0 -.2(bu)69.336 128 S 2.5
+(ti).2 G 2.5(fy)-2.5 G
+(ou needed to do this lots of times, it could get tedious.)-2.5 E
+(So let')5 E 2.5(sd)-.55 G(e\214ne a macro with parameters:)-2.5 E F1
+(define DYN\( COUNT, VOLUME \))105.336 146 Q
+(boldital below 1-4: COUNT VOLUME;)105.336 158 Q
+(boldital between 5&6: COUNT VOLUME;)105.336 170 Q(@)105.336 182 Q F0
+.226(This macro has tw)69.336 202 R 2.726(op)-.1 G .226
+(arameters, which ha)-2.726 F .526 -.15(ve b)-.2 H .226(een gi).15 F
+-.15(ve)-.25 G 2.726(nt).15 G .226(he names COUNT and V)-2.726 F 2.727
+(OLUME. When)-.4 F .227(you call)2.727 F(the macro, you will gi)69.336
+214 Q .3 -.15(ve t)-.25 H(hem v).15 E 2.5(alues. F)-.25 F(or e)-.15 E
+(xample,)-.15 E F1(DYN\(1,"ff"\))105.336 232 Q F0 -.1(wo)69.336 252 S
+(uld gi).1 E .3 -.15(ve a V)-.25 H(OLUME of "f)-.25 E
+(f" at COUNT 1, whereas)-.25 E F1(DYN\(3.5,"mp"\))105.336 270 Q F0 -.1
+(wo)69.336 290 S(uld gi).1 E .3 -.15(ve a V)-.25 H
+(OLUME of "mp" at COUNT 3.5.)-.25 E .406
+(When calling a macro with parameters, the v)69.336 308 R .406
+(alues to gi)-.25 F .706 -.15(ve t)-.25 H .405(he parameters are gi).15
+F -.15(ve)-.25 G 2.905(ni).15 G .405(nside parentheses. The)-2.905 F
+-.25(va)69.336 320 S .963(lues are separated by commas.).25 F .963
+(The v)5.963 F .963(alues in the parentheses are copied e)-.25 F .963
+(xactly as the)-.15 F 3.464(ya)-.15 G .964(re, including)-3.464 F(an)
+69.336 332 Q 2.6(ys)-.15 G .1(paces, ne)-2.6 F .1
+(wlines, macro names, etc.)-.25 F .1(There are only a fe)5.1 F 2.599(we)
+-.25 G .099(xceptions to this: you can include a comma,)-2.749 F 1.788
+(closing parenthesis, or backslash as part of a parameter v)69.336 344 R
+1.788(alue by preceding it with a backslash, and a)-.25 F
+(backslash follo)69.336 356 Q(wed by a ne)-.25 E(wline in a parameter v)
+-.25 E(alue will be discarded. Thus a macro call of)-.25 E F1
+(MAC\(\\\\\\,\\\)\))105.336 374 Q F0(has one parameter)69.336 394 Q 2.5
+(,t)-.4 G(he te)-2.5 E(xt of which is 3 characters long: a backslash, c\
+omma, and closing parenthesis.)-.15 E .244(If in a macro de\214nition a\
+ parameter is used inside backticks, as in \222N)69.336 412 R .243
+(AME\222, the v)-.35 F .243(alue of the parameter will)-.25 F
+(be placed inside double quotes. Thus, another w)69.336 424 Q
+(ay to do the e)-.1 E(xample abo)-.15 E .3 -.15(ve w)-.15 H(ould be:).05
+E F1(define DYN\( COUNT, VOLUME \))105.336 442 Q
+(boldital below 1-4: COUNT \222VOLUME\222;)105.336 454 Q
+(boldital between 5&6: COUNT \222VOLUME\222;)105.336 466 Q(@)105.336 478
+Q(DYN\(1,ff\))105.336 502 Q(DYN\(3.5,mp\))105.336 514 Q F0(Conceptually)
+69.336 540 Q 4.52(,w)-.65 G 2.02(hen the macro is e)-4.52 F 2.02
+(xpanded, the backticks are replaced by double quote marks, b)-.15 F
+2.02(ut in)-.2 F 1.114(addition, an)69.336 552 R 3.614(yd)-.15 G 1.114
+(ouble quote mark found in the v)-3.614 F 1.113
+(alue being passed to the parameter will ha)-.25 F 1.413 -.15(ve a b)-.2
+H(ackslash).15 E 2.387(inserted before it, and an)69.336 564 R 4.887(yb)
+-.15 G 2.388(ackslash that occurs within double quotes in the v)-4.887 F
+2.388(alue will also ha)-.25 F 2.688 -.15(ve a)-.2 H
+(backslash inserted before it. Thus, for e)69.336 576 Q(xample:)-.15 E
+F1(// If we define a macro like this:)105.336 594 Q
+(define QUOTED\(X\) \222X\222 @)105.336 606 Q(// then for input)105.336
+630 Q(value passed is)24 E(\222X\222 would be)24 E(which would print as)
+24 E(print QUOTED\(hello\))105.336 654 Q 54(hello "hello" hello)42 F
+(print QUOTED\("hello"\))105.336 666 Q 42("hello" "\\"hello\\"")30 F
+("hello")36 E(print QUOTED\(\\\\n\))105.336 678 Q 72(\\n "\\n" a)54 F
+(literal newline)6 E(print QUOTED\("\\\\n"\))105.336 690 Q 60
+("\\n" "\\"\\\\n\\"")42 F("\\n")48 E F0 .407
+(Sometimes it can be a little trick)69.336 716 R 2.907(yt)-.15 G 2.907
+(og)-2.907 G .406
+(et the number of backslashes right, or other details lik)-2.907 F 2.906
+(et)-.1 G 2.906(hat. The)-2.906 F(-E)2.906 E
+(Mup command line option sho)69.336 728 Q(ws ho)-.25 E 2.5(wm)-.25 G
+(acros will e)-2.5 E(xpand, which may help you \214gure out what to do.)
+-.15 E EP
+%%Page: 98 104
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-9)274.506 48 S 2.5(8-)-2.5 G 69.336 101
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 13/Times-Italic@0 SF 3.25(11.3.3 Gener)72.586 101 R
+(alized conditionals)-.195 E 69.336 113 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .27
+(Mup also supports more general "if" clauses. If you happen to be f)
+72.106 113 R .27(amiliar with the preprocessors for the C)-.1 F .193
+(and C++ programming languages, Mup "if" clauses are v)69.336 125 R .192
+(ery similar)-.15 F 5.192(.I)-.55 G 2.692(fy)-5.192 G(ou')-2.692 E .192
+(re not, that')-.5 F 2.692(so)-.55 G(kay)-2.692 E 2.692(,s)-.65 G .192
+(ince things)-2.692 F 1.17(are e)69.336 137 R 1.17(xplained belo)-.15 F
+4.97 -.65(w. A)-.25 H 1.17(lso, some of the operations are really v).65
+F 1.171(ery rarely needed, so if you \214nd some of)-.15 F 1.353
+(them confusing, you just can skip past this section; you')69.336 149 R
+1.353(ll lik)-.1 F 1.353(ely ne)-.1 F -.15(ve)-.25 G 3.853(rh).15 G
+-2.25 -.2(av e)-3.853 H 3.853(an)4.053 G 1.353(eed for the complicated)
+-3.853 F(operations an)69.336 161 Q(yw)-.15 E(ay)-.1 E(.)-.65 E
+(The general form is)69.336 179 Q/F1 10/Times-Bold@0 SF(if)105.336 197 Q
+/F2 10/Times-Italic@0 SF(condition)2.5 E F1(then)2.5 E F2
+(Mup statements)2.5 E F1(else)2.5 E F2(Mup statements)2.5 E F1(endif)2.5
+E F0(As with the "ifdef," the "else" and second set of Mup statements i\
+s optional.)69.336 217 Q .164(One form of "if" is really just a v)69.336
+235 R .164(ariation of ifdef. It uses the k)-.25 F -.15(ey)-.1 G -.1(wo)
+.15 G .164(rd "de\214ned" follo).1 F .164(wed by a macro name.)-.25 F
+(So)69.336 247 Q/F3 10/Courier@0 SF(ifdef DUET)117.336 265 Q F0
+(could also be written)69.336 285 Q F3(if defined DUET then)117.336 303
+Q F0 -1.1(Yo)69.336 323 S 2.5(um)1.1 G(ay put a set of parentheses arou\
+nd the macro name for clarity if you wish:)-2.5 E F3
+(if defined\(DUET\) then)117.336 341 Q F0
+(The ! is used to mean "not," so)69.336 367 Q F3(ifndef TRIO)117.336 385
+Q F0(could also be written as)69.336 405 Q F3(if ! defined\(TRIO\) then)
+117.336 423 Q F0 .652(So f)69.336 449 R(ar)-.1 E 3.151(,t)-.4 G .651
+(his just looks longer)-3.151 F 3.151(,s)-.4 G 3.151(ow)-3.151 G(hat')
+-3.151 E 3.151(st)-.55 G .651(he adv)-3.151 F 3.151(antage? The)-.25 F
+(dif)3.151 E .651(ference is that ifdef and ifndef can only be)-.25 F
+1.215(used to check if a single macro is de\214ned or not, whereas the \
+"if" condition is much more general, and)69.336 461 R .489
+(therefore much more po)69.336 473 R 2.989(werful. Decisions)-.25 F .489
+(can be based on the v)2.989 F .489
+(alues of macros, not just whether the)-.25 F 2.988(ya)-.15 G(re)-2.988
+E .379(de\214ned or not, and can also be based on more than one macro a\
+t a time, Here is an e)69.336 485 R .38(xample of a condition)-.15 F
+(based on se)69.336 497 Q -.15(ve)-.25 G(ral macros at once:).15 E F3(i\
+f defined\(FULL_SCORE\) && defined\(TRANSPOSE_UP\) && ! defined\(MIDI\)\
+ then)111.336 515 Q F0 -.1(wo)69.336 535 S .291
+(uld be true only if both FULL_SCORE and TRANSPOSE_UP were de\214ned, b)
+.1 F .291(ut MIDI w)-.2 F .291(as not de\214ned.)-.1 F
+(The && means "and.")69.336 547 Q(There is also || which means "or)5 E
+(," so)-.4 E F3(if defined\(CELLO\) || defined\(STRINGBASS\))111.336 565
+Q F0 -.1(wo)69.336 585 S
+(uld be true as long as at least one of the macros w).1 E(as de\214ned.)
+-.1 E .229
+(The condition can also include numbers and macros used as numeric v)
+69.336 603 R .229(alues in arithmetic and comparisons.)-.25 F -.15(Fo)
+69.336 615 S 2.5(re).15 G(xample,)-2.65 E EP
+%%Page: 99 105
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-9)274.506 48 S 2.5(9-)-2.5 G/F1 10
+/Courier@0 SF(define STAFFS 3 @)117.336 96 Q(define S 5 @)117.336 108 Q
+(if STAFFS > 5 then)117.336 120 Q
+(// ... this would not be executed, since 3 is not greater than 5)
+135.336 132 Q(endif)117.336 144 Q(if 2 <= STAFFS then)117.336 156 Q
+(// ... This would be executed, since 2 is less than or equal to 3)
+135.336 168 Q(endif)117.336 180 Q(if STAFFS + 1 == S - 1 then)117.336
+192 Q(// ... This would be executed, since 3+1 equals 5-1)135.336 204 Q
+(endif)117.336 216 Q F0 .148
+(Note that the symbol to test for "equals" is tw)69.336 236 R 2.648(oe)
+-.1 G .148
+(quals signs, not just one. This is to be consistent with what)-2.648 F
+(is used in the C and C++ languages.)69.336 248 Q
+(The operators for comparisons are:)5 E 20.64(<l)69.336 272 S(ess than)
+-20.64 E 20.64(>g)69.336 284 S(reater than)-20.64 E 12.5(<= less)69.336
+296 R(than or equal)2.5 E 12.5(>= greater)69.336 308 R(than or equal)2.5
+E 12.5(== equal)69.336 320 R 14.81(!= not)69.336 332 R(equal)2.5 E .17
+(Note that the v)69.336 350 R .171(alues in the conditions can only be \
+either literal numbers or macros whose v)-.25 F .171(alues e)-.25 F -.25
+(va)-.25 G .171(luate to).25 F 2.75(an)69.336 362 S(umber)-2.75 E 2.75
+(.T)-.55 G(he)-2.75 E 2.75(yc)-.15 G .25(annot be things lik)-2.75 F
+2.75(eM)-.1 G .25(up parameters.)-2.75 F 2.749(Am)5.25 G .249
+(acro which is not de\214ned is treated as ha)-2.749 F .249(ving a)-.2 F
+-.25(va)69.336 374 S 1.26(lue of zero.).25 F 1.26(Macro v)6.26 F 1.26
+(alues are substituted for macro names just as else)-.25 F 1.261
+(where in Mup, so if you use a)-.25 F 1.54(macro whose resulting v)
+69.336 386 R 1.54(alue does not e)-.25 F -.25(va)-.25 G 1.539
+(ulate to a number).25 F 4.039(,y)-.4 G 1.539
+(ou may get an error or other une)-4.039 F(xpected)-.15 E(result.)69.336
+398 Q 1.025(If you are f)69.336 416 R 1.025
+(amiliar with "octal" and "he)-.1 F 1.026(xadecimal" numbers, the)-.15 F
+3.526(yc)-.15 G 1.026(an be used, follo)-3.526 F 1.026
+(wing the C language)-.25 F(con)69.336 428 Q -.15(ve)-.4 G .976
+(ntion of a leading zero for octal or a leading 0x for he).15 F .976
+(xadecimal. \(If you')-.15 F .976(re not f)-.5 F .976
+(amiliar with these)-.1 F .771(numbers or con)69.336 440 R -.15(ve)-.4 G
+.771(ntions, don').15 F 3.271(tw)-.18 G .771(orry about it; it')-3.371 F
+3.271(sn)-.55 G -2.15 -.25(ev e)-3.271 H 3.271(rr).25 G .771
+(eally necessary to use them. Just mak)-3.271 F 3.272(es)-.1 G .772
+(ure you)-3.272 F(don')69.336 452 Q 2.5(ta)-.18 G
+(ccidentally start a number other than a zero with a zero\).)-2.5 E
+-1.11(Va)69.336 470 S .626
+(lues are limited to 32-bit signed numbers. \(If you don')1.11 F 3.126
+(tk)-.18 G(no)-3.126 E 3.126(ww)-.25 G .626
+(hat that means, all you need to kno)-3.126 F 3.125(wi)-.25 G(s)-3.125 E
+(that you can only use numbers between -2147483648 and 2147483647.)
+69.336 482 Q .504(Before we introduce the remaining operators, it w)
+69.336 500 R .505(ould be good to discuss tw)-.1 F 3.005(oc)-.1 G .505
+(oncepts, called precedence)-3.005 F 3.175(and associati)69.336 512 R
+(vity)-.25 E 5.675(.T)-.65 G 3.175(hese determine the order in which op\
+erations are done. Consider the follo)-5.675 F(wing)-.25 E -.15(ex)
+69.336 524 S(pression:).15 E F1 6(5+3*8)123.336 542 S F0 .678
+(What is its v)69.336 562 R .678
+(alue? If we just went left to right, we w)-.25 F .679
+(ould add 5 and 3, getting 8, then multiple by 8, for a)-.1 F 2.758
+(\214nal v)69.336 574 R 2.758(alue of 64. Ho)-.25 F(we)-.25 E -.15(ve)
+-.25 G 3.558 -.4(r, m).15 H 2.758
+(ultiplication is generally considered to ha).4 F 3.057 -.15(ve h)-.2 H
+2.757(igher "precedence" than).15 F 1.65(addition, meaning that multipl\
+ications should be done before additions.)69.336 586 R 1.65(In other w)
+6.65 F 1.65(ords, the e)-.1 F(xpression)-.15 E
+(should actually be treated as)69.336 598 Q F1 6(5+\()123.336 616 S 6
+(3*8)-6 G(\))-6 E F0(so we w)69.336 636 Q(ould \214rst multiply 3 by 8,\
+ getting 24, and then add 5 and 24, obtaining a \214nal answer of 29.)
+-.1 E .027(If you really intended the 64 meaning, that could be sho)
+69.336 654 R .027(wn by parentheses, indicating you w)-.25 F .027
+(ant the addition)-.1 F(to be done \214rst:)69.336 666 Q F1
+(\(5 + 3\) * 8)123.336 684 Q F0(Associati)69.336 710 Q 2.082(vity deter\
+mines whether operators of equal precedence are done left to right or r\
+ight to left.)-.25 F -.15(Pa)69.336 722 S 1.661
+(rentheses and all of the operators that ha).15 F 1.961 -.15(ve t)-.2 H
+1.861 -.1(wo o).15 H 1.66
+(perands associate left to right, while all the others).1 F
+(associate right to left. F)69.336 734 Q(or e)-.15 E
+(xample, since addition and subtraction associate left to right, the e)
+-.15 E(xpression)-.15 E EP
+%%Page: 100 106
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(00 -)-2.5 E/F1 10/Courier@0
+SF(10 - 6 - 1)117.336 96 Q F0 -.1(wo)69.336 116 S .191(uld be e).1 F
+-.25(va)-.25 G .191(luated by \214rst subtracting 6 from 10 to get 4, t\
+hen subtracting 1, yielding 3.).25 F .191(If the)5.191 F 2.692(ya)-.15 G
+(ssociated)-2.692 E .487(right to left, \214rst 1 w)69.336 128 R .487
+(ould be subtracted from 6 to get 5, which w)-.1 F .487
+(ould then be subtracted from 10, yielding)-.1 F 2.5(5. So)69.336 140 R
+(using dif)2.5 E(ferent associati)-.25 E(vity can lead to dif)-.25 E
+(ferent answers!)-.25 E(Since the "not" operator and unary minus associ\
+ate right to left, in the e)69.336 158 Q(xpression)-.15 E F1 6(!-\()
+117.336 176 S(5\))-6 E F0 .712(the unary minus w)69.336 196 R .712
+(ould be applied \214rst to get -5, then the "not" w)-.1 F .712
+(ould be applied. But what does "not -5")-.1 F .312
+(mean? The "not" operator will treat its operand as a boolean v)69.336
+208 R .312(alue, with a v)-.25 F .312(alue of zero meaning f)-.25 F .312
+(alse, and)-.1 F(an)69.336 220 Q 2.917(yn)-.15 G .417(on-zero v)-2.917 F
+.417(alue being true. Since -5 is not zero, it represents "true," and "\
+not true" w)-.25 F .418(ould be "f)-.1 F .418(alse," or)-.1 F 3.321
+(zero. By)69.336 232 R .821(the w)3.321 F(ay)-.1 E 3.321(,a)-.65 G 1.121
+-.15(ny o)-3.321 H .821
+(perator that yields a boolean result \(not, logical and, logical or).15
+F 3.32(,l)-.4 G .82(ess than, greater)-3.32 F .287(than, less than or e\
+qual, greater than or equal, equal, or not equal\) will al)69.336 244 R
+-.1(wa)-.1 G .287(ys yield 1 for true, e).1 F -.15(ve)-.25 G 2.787(nt)
+.15 G(hough)-2.787 E(an)69.336 256 Q 2.5(yn)-.15 G(on-zero v)-2.5 E
+(alue could mean true.)-.25 E .619(The operators are listed belo)69.336
+274 R 1.919 -.65(w. T)-.25 H .618(hose on the same line ha).65 F .918
+-.15(ve t)-.2 H .618(he same precedence, with those on each line).15 F
+(ha)69.336 286 Q(ving higher precedence than the lines belo)-.2 E -.65
+(w.)-.25 G .4 LW 463.366 302.5 107.306 302.5 DL/F2 10/Times-Bold@0 SF
+25.4(operators operations)112.306 312 R(associati)179.94 E(vity)-.1 E
+463.366 316.5 107.306 316.5 DL 463.366 318.5 107.306 318.5 DL F1 6(\(\))
+112.306 328 S F0 186.33(grouping left)45 F(to right)2.5 E 463.366 332.5
+107.306 332.5 DL F1 6(!~-+)112.306 342 S F0(not, one')21 E 2.5(sc)-.55 G
+(omplement, unary minus, unary plus)-2.5 E(right to left)32.45 E 463.366
+346.5 107.306 346.5 DL F1 6(*/%)112.306 356 S F0(multiply)33 E 2.5(,d)
+-.65 G -.25(iv)-2.5 G(ide, modulo).25 E(left to right)126.38 E 463.366
+360.5 107.306 360.5 DL F1 6(+-)112.306 370 S F0(add, subtract)45 E
+(left to right)173.84 E 463.366 374.5 107.306 374.5 DL F1(<< >>)112.306
+384 Q F0(left shift, right shift)39 E(left to right)147.16 E 463.366
+388.5 107.306 388.5 DL F1 6(<<)112.306 398 S 6(=>>)-6 G(=)-6 E F0
+(less than, less or equal, greater than, greater or equal)15 E
+(left to right)15 E 463.366 402.5 107.306 402.5 DL F1(== !=)112.306 412
+Q F0(equal, not equal)39 E(left to right)161.34 E 463.366 416.5 107.306
+416.5 DL F1(&)112.306 426 Q F0(bitwise AND)63 E(left to right)171.89 E
+463.366 430.5 107.306 430.5 DL F1(^)112.306 440 Q F0(bitwise XOR)63 E
+(left to right)172.44 E 463.366 444.5 107.306 444.5 DL F1(|)112.306 454
+Q F0(bitwise OR)63 E(left to right)179.66 E 463.366 458.5 107.306 458.5
+DL F1(&&)112.306 468 Q F0(logical AND)57 E(left to right)173.56 E
+463.366 472.5 107.306 472.5 DL F1(||)112.306 482 Q F0(logical OR)57 E
+(left to right)181.33 E 463.366 486.5 107.306 486.5 DL F1 6(?:)112.306
+496 S F0(interrog)45 E 170.83(ation right)-.05 F(to left)2.5 E 463.366
+500.5 107.306 500.5 DL 463.366 302.5 463.366 500.5 DL 107.306 302.5
+107.306 500.5 DL 398.746 302.5 398.746 500.5 DL 173.806 302.5 173.806
+500.5 DL 69.336 514 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(11.4 Include)72.836 514 R 69.336 532
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(The "include" statement can be used to incl\
+ude the contents of one \214le inside another)71.836 532 Q(.)-.55 E/F1
+10/Times-Bold@0 SF(include ")105.336 550 Q/F2 10/Times-Italic@0 SF
+(\214lename)A F1(")A F0 .738
+(causes input to be read from the speci\214ed)69.336 570 R F2
+(\214lename)3.238 E F0 3.238(.W)C .739
+(hen the end of that \214le is reached, reading of input)-3.238 F
+(resumes from the original \214le after the include statement.)69.336
+582 Q 2(If the)69.336 600 R F2(\214lename)4.5 E F0 1.999
+(cannot be found as is, and it is not an absolute path, and if the en)
+4.5 F 1.999(vironment v)-.4 F(ariable)-.25 E(MUPP)69.336 612 Q -1.11(AT)
+-.92 G 2.822(Hi)1.11 G 2.822(ss)-2.822 G .323
+(et, Mup will search for the \214le in each directory listed in MUPP)
+-2.822 F -1.11(AT)-.92 G .323(H. On Unix systems, the)1.11 F .444
+(directories are separated by colons. On systems with DOS-lik)69.336 624
+R 2.943<658c>-.1 G .443(le naming con)-2.943 F -.15(ve)-.4 G .443
+(ntions, the).15 F 2.943(ya)-.15 G .443(re separated)-2.943 F .067
+(by semicolons.)69.336 636 R .067(The MUPP)5.067 F -1.11(AT)-.92 G 2.567
+(Hm)1.11 G .068(ay be useful if, for e)-2.567 F .068(xample, you ha)-.15
+F .368 -.15(ve a n)-.2 H .068(umber of "boilerplate" \214les that).15 F
+1.026(you w)69.336 648 R 1.026(ant to include in lots of songs. Y)-.1 F
+1.026(ou can put them in some directory and set MUPP)-1.1 F -1.11(AT)
+-.92 G 3.526(Ht)1.11 G 3.526(ol)-3.526 G 1.026(ist that)-3.526 F
+(directory)69.336 660 Q 2.5(,t)-.65 G(hen an)-2.5 E 2.5(yM)-.15 G
+(up \214les you ha)-2.5 E .3 -.15(ve c)-.2 H(an refer to them.).15 E
+69.336 678 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(11.5 Installing)72.836 678 R(other f)3.5
+E(onts)-.35 E 69.336 696 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .501
+(The "font\214le" statement is used to o)72.337 696 R -.15(ve)-.15 G
+.501(rride a Mup font with some other font. Y).15 F .501
+(ou may place one or more)-1.1 F .34(of these an)69.336 708 R .34
+(ywhere in Mup input.)-.15 F .34(This might be used either because you')
+5.34 F 2.84(dl)-.5 G(ik)-2.84 E 2.84(ead)-.1 G(if)-2.84 E .34
+(ferent style of printing,)-.25 F 1.071(or because you need a dif)69.336
+720 R 1.071(ferent alphabet.)-.25 F 1.071
+(The "mkmupfnt" program that is distrib)6.071 F 1.072
+(uted with Mup can be)-.2 F
+(used to generate a font description \214le. Y)69.336 732 Q
+(ou can then use)-1.1 E EP
+%%Page: 101 107
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(01 -)-2.5 E/F1 10/Courier@0
+SF(fontfile "file")130.336 96 Q F0 .592
+(in your Mup program, where the gi)69.336 116 R -.15(ve)-.25 G 3.092(n")
+.15 G .592(\214le" is the name of the font description \214le. The manu\
+al page for)-3.092 F 1.099(mkmupfnt describes ho)69.336 128 R 3.599(wt)
+-.25 G 3.599(ou)-3.599 G 1.1(se that program. It also describes the for\
+mat of the font description \214le, in)-3.599 F(case you wish to genera\
+te it by some means other than the mkmupfnt program.)69.336 140 Q
+(Mup searches for font\214les via the MUPP)69.336 158 Q -1.11(AT)-.92 G
+2.5(Hm)1.11 G(echanism, just lik)-2.5 E 2.5(ef)-.1 G
+(or included \214les.)-2.5 E EP
+%%Page: 102 108
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(02 -)-2.5 E 69.336 103
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(12. P)73.086 103 R(ARAMETERS)-1.11 E
+69.336 121 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF -.15(Pa)71.937 121 S .101
+(rameters can be set in v).15 F .101(arious conte)-.25 F .101
+(xts. All parameters ha)-.15 F .4 -.15(ve d)-.2 H(ef).15 E .1(ault v)-.1
+F .1(alues, so that you need to e)-.25 F(xplicitly)-.15 E
+(set them only if you w)69.336 133 Q(ant some v)-.1 E
+(alue other than the def)-.25 E(ault v)-.1 E(alue.)-.25 E .438
+(Some parameters can be set only in the score conte)69.336 151 R .438
+(xt. Others can be set in either score or staf)-.15 F 2.938(fc)-.25 G
+(onte)-2.938 E .438(xts. A)-.15 F(fe)69.336 163 Q 2.739(wc)-.25 G .239
+(an be set in score, staf)-2.739 F .239(f, or v)-.25 F .239(oice conte)
+-.2 F .239(xt. If a gi)-.15 F -.15(ve)-.25 G 2.738(np).15 G .238
+(arameter can be set in se)-2.738 F -.15(ve)-.25 G .238(ral conte).15 F
+.238(xts, the v)-.15 F(alue)-.25 E .744
+(is that of the parameter at the most speci\214c conte)69.336 175 R .745
+(xt in which it is set. F)-.15 F .745(or e)-.15 F .745
+(xample, if Mup is w)-.15 F .745(orking on)-.1 F .642
+(musical data for v)69.336 187 R .642(oice 2 of staf)-.2 F 3.141(f5)-.25
+G 3.141(,a)-3.141 G .641(nd it needs to look up the v)-3.141 F .641
+(alue of a parameter)-.25 F 3.141(,i)-.4 G 3.141(tw)-3.141 G .641
+(ill \214rst see if that)-3.141 F .172(parameter has been set in conte)
+69.336 199 R .172(xt "v)-.15 F .172(oice 5 2".)-.2 F .172
+(If so, it will use that v)5.172 F .172
+(alue. If not, it will see if the parameter)-.25 F -.1(wa)69.336 211 S
+2.927(ss).1 G .427(et in conte)-2.927 F .427(xt "staf)-.15 F 2.927(f5)
+-.25 G .426(". If that has not been set either)-2.927 F 2.926(,i)-.4 G
+2.926(tw)-2.926 G .426(ill use the v)-2.926 F .426
+(alue from the score conte)-.25 F .426(xt. The)-.15 F 1.236(score conte)
+69.336 223 R 1.237(xt initially has all parameters set to their def)-.15
+F 1.237(ault v)-.1 F 3.737(alues. There)-.25 F 1.237(are a fe)3.737 F
+3.737(wp)-.25 G 1.237(arameters, mostly)-3.737 F(related to font and te)
+69.336 235 Q(xt size, that can also be set in header)-.15 E 2.5(,f)-.4 G
+(ooter)-2.5 E 2.5(,a)-.4 G(nd similiar conte)-2.5 E(xts.)-.15 E -.15(Pa)
+69.336 253 S(rameters are set by the follo).15 E(wing syntax:)-.25 E/F1
+10/Times-Italic@0 SF(par)105.336 271 Q(ameter_name)-.15 E/F2 10
+/Times-Bold@0 SF(=)A F1(value)A F0(Se)69.336 297 Q -.15(ve)-.25 G(ral p\
+arameters can be set on a single line by separating them with a semicol\
+on. F).15 E(or e)-.15 E(xample:)-.15 E/F3 10/Courier@0 SF
+(staffs=2 ; key=2& ; time=2/4)105.336 315 Q F0 -.15(Pa)69.336 341 S
+(rameters can be unset in staf).15 E 2.5(fo)-.25 G 2.5(rv)-2.5 G
+(oice conte)-2.7 E(xt using)-.15 E F2(unset)105.336 359 Q F1(par)2.5 E
+(ameter_name)-.15 E F0 .384(Unsetting a parameter in staf)69.336 379 R
+2.884(fc)-.25 G(onte)-2.884 E .384(xt will cause it to re)-.15 F -.15
+(ve)-.25 G .384(rt to its v).15 F .384(alue in score conte)-.25 F .383
+(xt \(unless o)-.15 F -.15(ve)-.15 G(rridden).15 E .449(in v)69.336 391
+R .449(oice conte)-.2 F 2.949(xt\). Unsetting)-.15 F 2.949(ap)2.949 G
+.449(arameter in v)-2.949 F .449(oice conte)-.2 F .45
+(xt will cause it to re)-.15 F -.15(ve)-.25 G .45(rt to its v).15 F .45
+(alue in staf)-.25 F 2.95(fc)-.25 G(onte)-2.95 E(xt)-.15 E
+(if that is set, otherwise to its v)69.336 403 Q(alue in score conte)
+-.25 E(xt.)-.15 E 1.21(The parameters are listed belo)69.336 421 R 3.71
+(wi)-.25 G 3.71(na)-3.71 G 1.21(lphabetical order)-3.71 F 3.71(.F)-.55 G
+1.21(or each, the description includes the parameter')-3.86 F(s)-.55 E
+.208(name, le)69.336 433 R -.05(ga)-.15 G 2.708(lv).05 G .208
+(alues, def)-2.958 F .208(ault v)-.1 F .208(alue, and conte)-.25 F .208
+(xts in which the parameter can be set, along with an e)-.15 F .209
+(xample of)-.15 F(its usage.)69.336 445 Q
+(If there are other related parameters, the)5 E 2.5(ya)-.15 G
+(re referenced as well.)-2.5 E F2(Name)69.336 493 Q F0
+(.............. abo)1.95 E -.15(ve)-.15 G(order).15 E F2(Description)
+69.336 505 Q F0 .51
+(..... specify in what order to stack items that are printed abo)B .81
+-.15(ve a s)-.15 H(taf).15 E 3.01(f. The)-.25 F -.25(va)3.01 G .51
+(lue is a comma-separated).25 F .395
+(list of all the types of things that can be printed abo)138.476 517 R
+.696 -.15(ve a s)-.15 H(taf).15 E .396(f. Items are stack)-.25 F .396
+(ed in the order listed,)-.1 F .134(starting from just abo)138.476 529 R
+.434 -.15(ve t)-.15 H .134(he staf).15 F 2.634(fa)-.25 G .134(nd w)
+-2.634 F .134(orking upw)-.1 F 2.634(ard. If)-.1 F .134(you w)2.634 F
+.134(ant se)-.1 F -.15(ve)-.25 G .134(ral types to be handled as a).15 F
+.177(single cate)138.476 541 R(gory)-.15 E 2.677(,w)-.65 G .177
+(ith all types in the cate)-2.677 F .177(gory ha)-.15 F .177
+(ving the same stacking priority)-.2 F 2.678(,s)-.65 G .178
+(eparate them with)-2.678 F .282(an ampersand rather than a comma. The \
+ampersand cannot be used with lyrics, ending, or reh. The)138.476 553 R
+.23(dyn cate)138.476 565 R .23(gory applies to crescendo and decrescend\
+o marks \(from "<" and ">" statements\) as well as)-.15 F(te)138.476 577
+Q .133(xt with the dyn modi\214er)-.15 F 5.133(.T)-.55 G .133
+(he chord cate)-5.133 F .132(gory applies to te)-.15 F .132
+(xt with chord, analysis, or \214gbass mod-)-.15 F .332
+(i\214ers. The otherte)138.476 589 R .333(xt cate)-.15 F .333
+(gory applies to rom, bold, ital, and boldital items that do not ha)-.15
+F .633 -.15(ve a c)-.2 H(hord,).15 E .311
+(analysis, \214gbass, or dyn modi\214er)138.476 601 R 5.311(.I)-.55 G
+2.811(fy)-5.311 G .311(ou omit an)-2.811 F 2.811(yc)-.15 G(ate)-2.811 E
+.311(gories, the)-.15 F 2.81(yw)-.15 G .31(ill be stack)-2.81 F .31
+(ed last, in their de-)-.1 F -.1(fa)138.476 613 S(ult order).1 E(.)-.55
+E F2 -.92(Va)69.336 625 S(lue).92 E F0(............... mussym, octa).36
+E -.15(ve)-.2 G 2.5(,d).15 G(yn, otherte)-2.5 E
+(xt, chord, lyrics, ending, reh)-.15 E F2(Default)69.336 637 Q F0
+(............ mussym, octa).28 E -.15(ve)-.2 G 2.5(,d).15 G
+(yn & otherte)-2.5 E(xt & chord, lyrics, ending, reh)-.15 E F2(Context)
+69.336 649 Q F0(........... score, staf).56 E(f)-.25 E F2(Example)69.336
+661 Q F0(......... abo)1.66 E -.15(ve)-.15 G
+(order = mussym, lyrics, dyn, octa).15 E -.15(ve)-.2 G 2.5(,o).15 G
+(therte)-2.5 E(xt, chord, ending, reh)-.15 E F2(See also)69.336 673 Q F0
+(........... belo).83 E -.1(wo)-.25 G(rder).1 E 2.5(,b)-.4 G
+(etweenorder)-2.5 E 2.5(,c)-.4 G(horddist, dist, dyndist)-2.5 E EP
+%%Page: 103 109
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(03 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. addtranspose)1.95 E
+F1(Description)69.336 108 Q F0(..... specify by what additional interv)A
+(al to transpose the music data.)-.25 E
+(There is another parameter called)5 E(just transpose.)138.476 120 Q -.8
+(Ty)5 G(pically you w).8 E
+(ould use the transpose parameter to change the k)-.1 E .3 -.15(ey o)-.1
+H 2.5(fi).15 G(ndi)-2.5 E(vidual)-.25 E(staf)138.476 132 Q(fs \(for tra\
+nsposing instruments\), and then use the addtranspose parameter if you \
+w)-.25 E(ant to change)-.1 E(the k)138.476 144 Q .3 -.15(ey o)-.1 H 2.5
+(ft).15 G(he entire score.)-2.5 E
+(But either of these parameters can be used either w)5 E(ay)-.1 E 5(.I)
+-.65 G 2.5(na)-5 G .3 -.15(ny c)-2.5 H(ase, for).15 E(each staf)138.476
+156 Q(f, and for the score, the v)-.25 E
+(alues of transpose and addtranspose are "added" to \214nd the trans-)
+-.25 E(position for that staf)138.476 168 Q 2.5(fo)-.25 G 2.5(rs)-2.5 G
+2.5(core. The)-2.5 F(interv)2.5 E(al can be lar)-.25 E(ger than an octa)
+-.18 E -.15(ve)-.2 G 2.5(,b).15 G(ut must be a v)-2.7 E(alid inter)-.25
+E(-)-.2 E -.25(va)138.476 180 S 2.5(l\().25 G(e.g., there is no such th\
+ing as a perfect 6th\). It is an error to specify a transposition v)-2.5
+E(alue which)-.25 E -.1(wo)138.476 192 S(uld result in a k).1 E .3 -.15
+(ey s)-.1 H(ignature with more than 7 \215ats or sharps.).15 E
+(It is also an error if transposition)5 E -.1(wo)138.476 204 S
+(uld result in a note requiring a triple sharp or triple \215at.).1 E F1
+-.92(Va)69.336 216 S(lue).92 E F0(............... the w).36 E
+(ord "up" or "do)-.1 E(wn," follo)-.25 E(wed by an interv)-.25 E
+(al and a whole number greater than 0.)-.25 E(The interv)5 E(al is)-.25
+E(one of major)138.476 228 Q 2.5(,m)-.4 G(inor)-2.5 E 2.5(,a)-.4 G
+(ugmented, diminished, or perfect.)-2.5 E(The interv)5 E
+(als can be abbre)-.25 E(viated to their)-.25 E
+(\214rst 3 letters \(maj, min, aug, dim, or per\).)138.476 240 Q
+(The section on transposition lists transposition interv)5 E(als)-.25 E
+(and gi)138.476 252 Q -.15(ve)-.25 G 2.5(sf).15 G(urther details.)-2.5 E
+(Depending on which k)5 E .3 -.15(ey s)-.1 H
+(ignature you are transposing from, some trans-).15 E(position interv)
+138.476 264 Q(als may not w)-.25 E(ork because the)-.1 E 2.5(yr)-.15 G
+(esult in more than 7 \215ats or sharps.)-2.5 E F1(Default)69.336 276 Q
+F0(............ up perfect 1 \(i.e., no transposition\)).28 E F1
+(Context)69.336 288 Q F0(........... score, staf).56 E(f)-.25 E F1
+(Examples)69.336 300 Q F0(........ addtranspose = do).27 E(wn major 3)
+-.25 E(addtranspose = up perfect 5)138.476 312 Q F1(See also)69.336 324
+Q F0(........... k).83 E -.15(ey)-.1 G 2.5(,t)-.5 G(ranspose)-2.5 E F1
+(Name)69.336 372 Q F0(.............. barstyle)1.95 E F1(Description)
+69.336 384 Q F0(..... speci\214es which staf)A(fs are to ha)-.25 E .3
+-.15(ve t)-.2 H(heir bar lines connected together).15 E 5(.W)-.55 G
+(hen dra)-5 E(wing bar lines, a con-)-.15 E(tinuous v)138.476 396 Q
+(ertical line will be dra)-.15 E(wn from the top line of the top staf)
+-.15 E 2.5(fi)-.25 G 2.5(nar)-2.5 G(ange to the bottom line of)-2.5 E
+(the bottom staf)138.476 408 Q 2.5(fo)-.25 G 2.5(ft)-2.5 G(he range.)
+-2.5 E(An)5 E 2.5(ys)-.15 G(taf)-2.5 E 2.5(fn)-.25 G
+(ot listed will be barred by itself, with the bar line span-)-2.5 E
+(ning only the height of the staf)138.476 420 Q(f.)-.25 E F1 -.92(Va)
+69.336 432 S(lue).92 E F0
+(............... a comma-separated list of staf).36 E 2.5(fn)-.25 G
+(umbers and/or ranges of staf)-2.5 E 2.5(fn)-.25 G 2.5(umbers. Staf)-2.5
+F 2.5(fn)-.25 G(umbers can be from)-2.5 E 2.5(1t)138.476 444 S 2.5(ot)
+-2.5 G(he v)-2.5 E(alue of the "staf)-.25 E(fs" parameter)-.25 E 5(.A)
+-.55 G(range is a pair of numbers separated by a dash.)-2.5 E 2.5(Ag)5 G
+-2.15 -.25(iv e)-2.5 H(n).25 E(staf)138.476 456 Q 2.5(fn)-.25 G
+(umber can be speci\214ed only once, and there can be no o)-2.5 E -.15
+(ve)-.15 G(rlapping between ranges.).15 E F1(Default)69.336 468 Q F0
+(............ each visible staf).28 E 2.5(fb)-.25 G(arred indi)-2.5 E
+(vidually)-.25 E F1(Context)69.336 480 Q F0(........... score).56 E F1
+(Example)69.336 492 Q F0(......... barstyle = 1-2, 5-8)1.66 E F1
+(See also)69.336 504 Q F0(........... staf).83 E(fs, visible)-.25 E EP
+%%Page: 104 110
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(04 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. beamslope)1.95 E F1
+(Description)69.336 108 Q F0(..... allo)A
+(ws you to control the slope of beams.)-.25 E -1 -.8(Tw o)5 H -.25(va)
+3.3 G(lues must be gi).25 E -.15(ve)-.25 G(n, separated by a comma.).15
+E(Mup)5 E
+(calculates an appropriate slope for beams by applying a linear re)
+138.476 120 Q(gression algorithm that uses the)-.15 E
+(positions of the note heads within the beam. The \214rst v)138.476 132
+Q(alue supplied for the beamslope parameter is)-.25 E 2.5(af)138.476 144
+S(actor by which to multiply the def)-2.6 E
+(ault slope that Mup calculates.)-.1 E(The minimum v)5 E(alue of 0.0)
+-.25 E -.1(wo)138.476 156 S
+(uld cause all beams to be horizontal, whereas the maximum v).1 E
+(alue of 1.0 will use the slope Mup)-.25 E 2.5(calculates. Intermediate)
+138.476 168 R -.25(va)2.5 G
+(lues will yield beams that are less slanted than the def).25 E
+(ault slope calcula-)-.1 E(tion. The second v)138.476 180 Q(alue gi)-.25
+E -.15(ve)-.25 G 2.5(nt).15 G 2.5(ot)-2.5 G
+(he beamslope parameter is the maximum angle for the beam, in)-2.5 E(de)
+138.476 192 Q 2.5(grees. If)-.15 F(the originally calculated v)2.5 E
+(alue multiplied by the f)-.25 E(actor yields an angle of greater than)
+-.1 E(this maximum angle, the maximum angle will be used.)138.476 204 Q
+(Cross-staf)5 E 2.5(fb)-.25 G(eams that are between staf)-2.5 E(fs)-.25
+E(are allo)138.476 216 Q(wed to ha)-.25 E .3 -.15(ve a s)-.2 H
+(lope up to 1.4 times the v).15 E
+(alue of the slope of the maximum angle, since the)-.25 E(y)-.15 E -.1
+(fa)138.476 228 S(ce more constraints.).1 E(The slope can be o)5 E -.15
+(ve)-.15 G(rridden on a particular beam by specifying a slope as).15 E
+(an interchord attrib)138.476 240 Q
+(ute on the \214rst chord of the beamed set.)-.2 E F1 -.92(Va)69.336 252
+S(lue).92 E F0(............... 0.0 to 1.0 for the f).36 E(actor)-.1 E
+2.5(,a)-.4 G(nd 0.0 to 45.0 for the maximum angle)-2.5 E F1(Default)
+69.336 264 Q F0(............ 1.0, 20.0).28 E F1(Context)69.336 276 Q F0
+(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E F1(Example)69.336
+288 Q F0(......... beamslope=0.8,20)1.66 E EP
+%%Page: 105 111
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(05 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. beamstyle)1.95 E F1
+(Description)69.336 108 Q F0(..... speci\214es ho)A 2.5(wt)-.25 G 2.5
+(ob)-2.5 G(eam eighth notes or shorter)-2.5 E 2.5(.I)-.55 G 2.5(ti)-2.5
+G 2.5(ss)-2.5 G(peci\214ed as a list of time v)-2.5 E(alues. An)-.25 E
+2.5(yn)-.15 G(umber of)-2.5 E(notes up to each time v)138.476 120 Q
+(alue will be beamed together)-.25 E 2.5(.F)-.55 G(or e)-2.65 E
+(xample, in 4/4 time, with beam-)-.15 E
+(style=4,4,4,4 each quarter note w)138.476 132 Q
+(orth of shorter notes w)-.1 E(ould be beamed together)-.1 E 5(.H)-.55 G
+-.25(ow)-5 G -2.15 -.25(ev e).25 H .8 -.4(r, b).25 H(eams).4 E -.1(wo)
+138.476 144 S(uld not span across beats. As another e).1 E
+(xample, for an input of 4.; 8; 8; 4.; the tw)-.15 E 2.5(oe)-.1 G
+(ighth notes)-2.5 E -.1(wo)138.476 156 S(uld not be beamed together).1 E
+2.5(,b)-.4 G(ecause the)-2.5 E 2.5(ys)-.15 G
+(pan beats. If beamstyle had been speci\214ed as 4,2,4)-2.5 E
+(then the eighth notes w)138.476 168 Q(ould be beamed.)-.1 E(Normally)5
+E 2.5(,b)-.65 G(eams also end whene)-2.5 E -.15(ve)-.25 G 2.5(rar).15 G
+(est or space is en-)-2.5 E 2.5(countered. Ho)138.476 180 R(we)-.25 E
+-.15(ve)-.25 G .8 -.4(r, i).15 H 2.5(fa).4 G 2.5(n")-2.5 G
+(r" is placed at the end of the list of time v)-2.5 E
+(alues, Mup will beams across)-.25 E
+(rests of less than quarter note duration.)138.476 192 Q(Similarly)5 E
+2.5(,i)-.65 G 2.5(fa)-2.5 G 2.5(n")-2.5 G
+(s" is placed at the end of the list, Mup will)-2.5 E
+(beam across spaces of less than quarter note duration.)138.476 204 Q
+-1.1(Yo)5 G 2.5(uc)1.1 G(an specify both r and s in either order)-2.5 E
+(.)-.55 E(It is possible to specify subbeams, or secondary groupings wi\
+thin a beam, by enclosing a list of)138.476 216 Q(time v)138.476 228 Q
+(alues in parentheses. In this case, the outer beam e)-.25 E
+(xtends for the sum of the v)-.15 E(alues in the)-.25 E
+(parentheses, while inner beams e)138.476 240 Q(xtend only for the indi)
+-.15 E(vidual v)-.25 E(alues within the parentheses.)-.25 E -.15(Fo)5 G
+(r).15 E -.15(ex)138.476 252 S
+(ample, if you set beamstyle=\(4,4\),\(4,4\) and then ha).15 E .3 -.15
+(ve a m)-.2 H(easure that consists of all 16th notes,).15 E
+(the \214rst 8 notes w)138.476 264 Q
+(ould be connected by an outer beam, as w)-.1 E
+(ould the last 8 notes, b)-.1 E(ut the second \(in-)-.2 E(ner\) beams w)
+138.476 276 Q(ould co)-.1 E -.15(ve)-.15 G 2.5(ro).15 G
+(nly 4 notes each.)-2.5 E(The parentheses cannot be nested.)5 E
+(It is possible to)5 E -.15(ove)138.476 288 S(rride this def).15 E(ault\
+ beaming style within a speci\214c measure. See the section on Custom B\
+eaming)-.1 E(for e)138.476 300 Q(xamples of ho)-.15 E 2.5(wt)-.25 G 2.5
+(oo)-2.5 G(btain v)-2.5 E(arious kinds of beaming.)-.25 E(The v)5 E
+(alue of the beamstyle parameter is)-.25 E(remembered for an)138.476 312
+Q 2.5(yl)-.15 G(ater changes back to the same time signature.)-2.5 E
+(In other w)5 E(ords, if you set the)-.1 E -.25(va)138.476 324 S(lue of\
+ the time parameter and the beamstyle parameter in the same conte).25 E
+(xt, then later set only the)-.15 E
+(time, the beamstyle that you had set earlier will be used ag)138.476
+336 Q(ain.)-.05 E F1 -.92(Va)69.336 348 S(lue).92 E F0
+(............... a comma-separated list of time v).36 E
+(alues that add up to a measure. T)-.25 E(ime v)-.35 E
+(alues are speci\214ed as 4 for a)-.25 E
+(quarter note, 2 for half note, etc, and can be dotted if necessary)
+138.476 360 Q 2.5(,o)-.65 G 2.5(ra)-2.5 G 2.5(ne)-2.5 G
+(xpression with added and/or)-2.65 E
+(subtracted times. The list can optionally be follo)138.476 372 Q
+(wed by an "r" to indicate beams should span rests.)-.25 E
+(It can optionally be follo)138.476 384 Q
+(wed by "s" to indicate beams should span spaces.)-.25 E -1 -.8(Tw o)5 H
+(or more of the time)3.3 E -.25(va)138.476 396 S(lues may be enclosed i\
+n parentheses, to indicate sub-groupings of inner \(secondary\) beams w\
+ith-).25 E(in outer \(primary\) beams.)138.476 408 Q(If the v)5 E
+(alue is empty)-.25 E 2.5(,a)-.65 G(utomatic beaming is turned of)-2.5 E
+(f.)-.25 E F1(Default)69.336 420 Q F0
+(............ no beams; each note of eighth or shorter duration is indi)
+.28 E(vidually \215agged.)-.25 E F1(Context)69.336 432 Q F0
+(........... score, staf).56 E(f, and v)-.25 E(oice)-.2 E F1(Examples)
+69.336 444 Q F0(........ beamstyle = 4,4,4,4).27 E(beamstyle = 2.)
+138.476 456 Q(beamstyle=4+16, 4+16)138.476 468 Q(beamstyle = 2, 2 rs)
+138.476 480 Q(// beam across rests and spaces)7.5 E
+(beamstyle = \(4., 4., 4.\))138.476 492 Q
+(// one outer beam per measure,)5 E(// with inner beams brok)170.976 504
+Q(en at each dotted quarter duration)-.1 E(beamstyle =)138.476 516 Q
+(// turn of)15 E 2.5(fb)-.25 G(eaming)-2.5 E EP
+%%Page: 106 112
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(06 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. belo)1.95 E -.1(wo)
+-.25 G(rder).1 E F1(Description)69.336 108 Q F0
+(..... specify in what order to stack items that are printed belo)A 2.5
+(was)-.25 G(taf)-2.5 E 2.5(f. The)-.25 F -.25(va)2.5 G
+(lue is a comma-separated).25 E
+(list of all the types of things that can be printed belo)138.476 120 Q
+2.5(was)-.25 G(taf)-2.5 E(f. Items are stack)-.25 E
+(ed in the order listed,)-.1 E(starting from just belo)138.476 132 Q 2.5
+(wt)-.25 G(he staf)-2.5 E 2.5(fa)-.25 G(nd w)-2.5 E(orking do)-.1 E(wnw)
+-.25 E 2.5(ard. If)-.1 F(you w)2.5 E(ant se)-.1 E -.15(ve)-.25 G
+(ral types to be handled).15 E(as a single cate)138.476 144 Q(gory)-.15
+E 2.5(,w)-.65 G(ith all types in the cate)-2.5 E(gory ha)-.15 E
+(ving the same stacking priority)-.2 E 2.5(,s)-.65 G(eparate them)-2.5 E
+(with an ampersand rather than a comma. The ampersand cannot be used wi\
+th lyrics or pedal. The)138.476 156 Q(dyn cate)138.476 168 Q(gory appli\
+es to crescendo and decrescendo marks \(from "<" and ">" statements\) a\
+s well as)-.15 E(te)138.476 180 Q(xt with the dyn modi\214er)-.15 E 5
+(.T)-.55 G(he chord cate)-5 E(gory applies to te)-.15 E
+(xt with chord, analysis, or \214gbass mod-)-.15 E
+(i\214ers. The otherte)138.476 192 Q(xt cate)-.15 E
+(gory applies to rom, bold, ital, and boldital items that do not ha)-.15
+E .3 -.15(ve a c)-.2 H(hord,).15 E
+(analysis, \214gbass, or dyn modi\214er)138.476 204 Q 5(.I)-.55 G 2.5
+(fy)-5 G(ou omit an)-2.5 E 2.5(yc)-.15 G(ate)-2.5 E(gories, the)-.15 E
+2.5(yw)-.15 G(ill be stack)-2.5 E(ed last, in their de-)-.1 E -.1(fa)
+138.476 216 S(ult order).1 E(.)-.55 E F1 -.92(Va)69.336 228 S(lue).92 E
+F0(............... mussym, octa).36 E -.15(ve)-.2 G 2.5(,d).15 G
+(yn, otherte)-2.5 E(xt, chord, lyrics, pedal)-.15 E F1(Default)69.336
+240 Q F0(............ mussym, octa).28 E -.15(ve)-.2 G 2.5(,d).15 G
+(yn & otherte)-2.5 E(xt & chord, lyrics, pedal)-.15 E F1(Context)69.336
+252 Q F0(........... score, staf).56 E(f)-.25 E F1(Example)69.336 264 Q
+F0(......... belo)1.66 E -.1(wo)-.25 G(rder = mussym, lyrics, dyn, octa)
+.1 E -.15(ve)-.2 G 2.5(,o).15 G(therte)-2.5 E(xt, chord, pedal)-.15 E F1
+(See also)69.336 276 Q F0(........... abo).83 E -.15(ve)-.15 G(order).15
+E 2.5(,b)-.4 G(etweenorder)-2.5 E 2.5(,c)-.4 G(horddist, dist, dyndist)
+-2.5 E F1(Name)69.336 324 Q F0(.............. betweenorder)1.95 E F1
+(Description)69.336 336 Q F0
+(..... specify in what order to stack items that are printed between tw)
+A 2.5(os)-.1 G(taf)-2.5 E 2.5(fs. The)-.25 F -.25(va)2.5 G
+(lue is a comma-sepa-).25 E
+(rated list of all the types of things that can be printed between staf)
+138.476 348 Q(fs. Items are stack)-.25 E(ed in the order)-.1 E
+(listed, starting from a baseline and w)138.476 360 Q(orking upw)-.1 E
+2.5(ard. If)-.1 F(you w)2.5 E(ant se)-.1 E -.15(ve)-.25 G
+(ral types to be handled as a).15 E(single cate)138.476 372 Q(gory)-.15
+E 2.5(,w)-.65 G(ith all types in the cate)-2.5 E(gory ha)-.15 E
+(ving the same stacking priority)-.2 E 2.5(,s)-.65 G(eparate them with)
+-2.5 E(an ampersand rather than a comma. The ampersand cannot be used w\
+ith lyrics. The dyn cate)138.476 384 Q(gory)-.15 E(applies to crescendo\
+ and decrescendo marks \(from "<" and ">" statements\) as well as te)
+138.476 396 Q(xt with the)-.15 E(dyn modi\214er)138.476 408 Q 5(.T)-.55
+G(he chord cate)-5 E(gory applies to te)-.15 E
+(xt with chord, analysis, or \214gbass modi\214ers. The)-.15 E(otherte)
+138.476 420 Q(xt cate)-.15 E
+(gory applies to rom, bold, ital, and boldital items that do not ha)-.15
+E .3 -.15(ve a c)-.2 H(hord, analysis,).15 E
+(\214gbass, or dyn modi\214er)138.476 432 Q 5(.I)-.55 G 2.5(fy)-5 G
+(ou omit an)-2.5 E 2.5(yc)-.15 G(ate)-2.5 E(gories, the)-.15 E 2.5(yw)
+-.15 G(ill be stack)-2.5 E(ed last, in their def)-.1 E(ault order)-.1 E
+(.)-.55 E F1 -.92(Va)69.336 444 S(lue).92 E F0
+(............... mussym, dyn, otherte).36 E(xt, chord, lyrics,)-.15 E F1
+(Default)69.336 456 Q F0(............ mussym, dyn & otherte).28 E
+(xt & chord, lyrics)-.15 E F1(Context)69.336 468 Q F0
+(........... score, staf).56 E(f)-.25 E F1(Example)69.336 480 Q F0
+(......... betweenorder = mussym, lyrics, dyn & otherte)1.66 E
+(xt, chord)-.15 E F1(See also)69.336 492 Q F0(........... abo).83 E -.15
+(ve)-.15 G(order).15 E 2.5(,b)-.4 G(elo)-2.5 E -.1(wo)-.25 G(rder).1 E
+2.5(,c)-.4 G(horddist, dist, dyndist)-2.5 E F1(Name)69.336 540 Q F0
+(.............. bottommar)1.95 E(gin)-.18 E F1(Description)69.336 552 Q
+F0(..... sets the amount of white space mar)A
+(gin to put at the bottom of each page.)-.18 E
+(It is speci\214ed in inches if)5 E(the units parameter is set to inche\
+s, or in centimeters if the units parameter is set to cm.)138.476 564 Q
+(This pa-)5 E(rameter can only be speci\214ed before an)138.476 576 Q
+2.5(ym)-.15 G(usic or block input.)-2.5 E(Mar)5 E(gins are unaf)-.18 E
+(fected by the)-.25 E("scale" parameter)138.476 588 Q 5(.T)-.55 G
+(he parameter name can be abbre)-5 E(viated to just "botmar)-.25 E
+(gin" if you wish.)-.18 E F1 -.92(Va)69.336 600 S(lue).92 E F0
+(............... 0.0 to pageheight minus 0.5 inches).36 E F1(Default)
+69.336 612 Q F0(............ 0.5 inches).28 E F1(Context)69.336 624 Q F0
+(........... score).56 E F1(Example)69.336 636 Q F0(......... bottommar)
+1.66 E(gin = 0.8)-.18 E F1(See also)69.336 648 Q F0(........... leftmar)
+.83 E(gin, rightmar)-.18 E(gin, topmar)-.18 E(gin pageheight units)-.18
+E EP
+%%Page: 107 113
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(07 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. brace)1.95 E F1
+(Description)69.336 108 Q F0(..... speci\214es which staf)A(fs are to b\
+e grouped together with a brace to the left of the score. If there is a)
+-.25 E(string gi)138.476 120 Q -.15(ve)-.25 G 2.5(ni).15 G 2.5(np)-2.5 G
+(arentheses, that string will be used as the label to print on the ne)
+-2.5 E(xt score, left of the)-.15 E(brack)138.476 132 Q(et at its v)-.1
+E(ertical center)-.15 E 5(.I)-.55 G 2.5(ft)-5 G
+(here is a second string, that will be used as the label for succeeding)
+-2.5 E(scores.)138.476 144 Q F1 -.92(Va)69.336 156 S(lue).92 E F0
+(............... a comma-separated list of staf).36 E(fs and/or staf)
+-.25 E 2.5(fr)-.25 G(anges, each optionally follo)-2.5 E
+(wed by one or tw)-.25 E 2.5(od)-.1 G(ouble-)-2.5 E
+(quoted strings enclosed in parentheses.)138.476 168 Q(If there are tw)5
+E 2.5(os)-.1 G(trings, the)-2.5 E 2.5(ya)-.15 G
+(re separated by a comma.)-2.5 E(Staf)138.476 180 Q 2.5(fn)-.25 G
+(umbers can range from 1 to the v)-2.5 E(alue of the "staf)-.25 E
+(fs" parameter)-.25 E 5(.A)-.55 G(gi)-2.5 E -.15(ve)-.25 G 2.5(ns).15 G
+(taf)-2.5 E 2.5(fn)-.25 G(umber can be)-2.5 E
+(speci\214ed only once, and there can be no o)138.476 192 Q -.15(ve)-.15
+G(rlapping between ranges.).15 E(Gi)5 E(ving no v)-.25 E
+(alue will result in)-.25 E(no braces on an)138.476 204 Q 2.5(ys)-.15 G
+(taf)-2.5 E(fs.)-.25 E F1(Default)69.336 216 Q F0(............ no staf)
+.28 E(fs are grouped by braces.)-.25 E F1(Context)69.336 228 Q F0
+(........... score).56 E F1(Examples)69.336 240 Q F0
+(........ brace = 3-4).27 E(brace = 1, 2-3, 4, 5-6)138.476 252 Q
+(brace = 1-2 \("piano"\), 3 \("cello"\))138.476 264 Q
+(brace = 1-2 \("Primo", "I"\))138.476 276 Q(brace =)138.476 288 Q
+(// no braces at all \(the def)20 E(ault\))-.1 E F1(See also)69.336 300
+Q F0(........... brack).83 E(et, label, label2, staf)-.1 E(fs)-.25 E F1
+(Name)69.336 348 Q F0(.............. brack)1.95 E(et)-.1 E F1
+(Description)69.336 360 Q F0(..... speci\214es which staf)A
+(fs are to be grouped together with a brack)-.25 E
+(et to the left of the score. If there is a)-.1 E(string gi)138.476 372
+Q -.15(ve)-.25 G 2.5(ni).15 G 2.5(np)-2.5 G
+(arentheses, that string will be used as the label to print on the ne)
+-2.5 E(xt score, left of the)-.15 E(brack)138.476 384 Q(et at its v)-.1
+E(ertical center)-.15 E 5(.I)-.55 G 2.5(ft)-5 G
+(here is a second string, that will be used as the label for succeeding)
+-2.5 E(scores.)138.476 396 Q F1 -.92(Va)69.336 408 S(lue).92 E F0
+(............... a comma-separated list of staf).36 E(fs and/or staf)
+-.25 E 2.5(fr)-.25 G(anges, each optionally follo)-2.5 E
+(wed by one or tw)-.25 E 2.5(od)-.1 G(ouble-)-2.5 E
+(quoted strings enclosed in parentheses.)138.476 420 Q(If there are tw)5
+E 2.5(os)-.1 G(trings, the)-2.5 E 2.5(ya)-.15 G
+(re separated by a comma.)-2.5 E(Staf)138.476 432 Q 2.5(fn)-.25 G
+(umbers can range from 1 to the v)-2.5 E(alue of the "staf)-.25 E
+(fs" parameter)-.25 E 5(.A)-.55 G(brack)-2.5 E(et range can o)-.1 E -.15
+(ve)-.15 G(rlap).15 E(another brack)138.476 444 Q
+(et range, as long as one range is a proper subset of the other)-.1 E 5
+(.G)-.55 G -.25(iv)-5 G(ing no v).25 E(alue will re-)-.25 E
+(sult in no brack)138.476 456 Q(ets on an)-.1 E 2.5(ys)-.15 G(taf)-2.5 E
+(fs.)-.25 E F1(Default)69.336 468 Q F0(............ no staf).28 E
+(fs are grouped by brack)-.25 E(ets.)-.1 E F1(Context)69.336 480 Q F0
+(........... score).56 E F1(Examples)69.336 492 Q F0(........ brack).27
+E(et = 6-7)-.1 E(brack)138.476 504 Q(et = 17, 21-23)-.1 E(brack)138.476
+516 Q(et = 8-9 \("SA)-.1 E(TB"\))-1.11 E(brack)138.476 528 Q
+(et = 10-12 \("Strings", "Str"\))-.1 E(brack)138.476 540 Q(et =)-.1 E
+(// no brack)20 E(ets at all \(the def)-.1 E(ault\))-.1 E F1(See also)
+69.336 552 Q F0(........... brace, label, label2, staf).83 E(fs)-.25 E
+F1(Name)69.336 600 Q F0(.............. cancelk)1.95 E -.15(ey)-.1 G F1
+(Description)69.336 612 Q F0(..... When set to)A F1(y)2.5 E F0 2.5(,w)C
+(hen a k)-2.5 E .3 -.15(ey c)-.1 H(hanges, an).15 E 2.5(ys)-.15 G
+(harps or \215ats in the pre)-2.5 E(vious k)-.25 E .3 -.15(ey t)-.1 H
+(hat are not part of the).15 E(ne)138.476 624 Q 2.5(wk)-.25 G .3 -.15
+(ey w)-2.6 H
+(ill be canceled by printing natural signs, before printing the ne).15 E
+2.5(wk)-.25 G .3 -.15(ey s)-2.6 H(ignature. When set).15 E(to)138.476
+636 Q F1(n)2.5 E F0 2.5(,t)C(he naturals will only be printed if the ne)
+-2.5 E 2.5(wk)-.25 G .3 -.15(ey h)-2.6 H(as no sharps or \215ats.).15 E
+F1 -.92(Va)69.336 648 S(lue).92 E F0(...............).36 E F1(y)2.5 E F0
+(or)2.5 E F1(n)2.5 E(Default)69.336 660 Q F0(............ n).28 E F1
+(Context)69.336 672 Q F0(........... score, staf).56 E(f)-.25 E F1
+(Example)69.336 684 Q F0(......... cancelk)1.66 E -.15(ey)-.1 G(=y).15 E
+F1(See also)69.336 696 Q F0(........... k).83 E -.15(ey)-.1 G EP
+%%Page: 108 114
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(08 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. chorddist)1.95 E F1
+(Description)69.336 108 Q F0(..... sets minimum distance from staf)A 2.5
+(ft)-.25 G 2.5(op)-2.5 G(lace chords. When chord marks are printed, the)
+-2.5 E 2.5(yw)-.15 G(ill be)-2.5 E(placed no closer to the staf)138.476
+120 Q 2.5(ft)-.25 G(han the v)-2.5 E(alue of this parameter)-.25 E 2.5
+(.T)-.55 G(his can be used to reduce the ragged)-2.5 E(ef)138.476 132 Q
+(fect of ha)-.25 E(ving some chord marks much higher than others, becau\
+se other things were in their w)-.2 E(ay)-.1 E(.)-.65 E
+(If a speci\214c chord mark has to be mo)138.476 144 Q -.15(ve)-.15 G
+2.5(df).15 G(arther a)-2.6 E -.1(wa)-.15 G 2.5(yt).1 G
+(han this parameter to a)-2.5 E -.2(vo)-.2 G(id running into).2 E
+(something, that will still happen, b)138.476 156 Q(ut an)-.2 E 2.5(yo)
+-.15 G(thers will come out at the le)-2.5 E -.15(ve)-.25 G 2.5(ls).15 G
+(peci\214ed by this parame-)-2.5 E(ter)138.476 168 Q 5(.T)-.55 G
+(his parameter may be o)-5 E -.15(ve)-.15 G
+(rridden on speci\214c items. The section on tempo, dynamic marks,).15 E
+(ornaments, etc.)138.476 180 Q(gi)5 E -.15(ve)-.25 G 2.5(sd).15 G
+(etails on ho)-2.5 E 2.5(wt)-.25 G 2.5(od)-2.5 G 2.5(ot)-2.5 G(his.)-2.5
+E F1 -.92(Va)69.336 192 S(lue).92 E F0
+(............... a whole number between 0 and 50 inclusi).36 E -.15(ve)
+-.25 G 2.5(,g).15 G -2.15 -.25(iv e)-2.5 H 2.5(ni).25 G 2.5(ns)-2.5 G
+(tepsizes.)-2.5 E F1(Default)69.336 204 Q F0(............ 3).28 E F1
+(Context)69.336 216 Q F0(........... score, staf).56 E(f)-.25 E F1
+(Example)69.336 228 Q F0(......... chorddist = 4)1.66 E F1(See also)
+69.336 240 Q F0(........... dyndist, dist, scorepad, scoresep).83 E F1
+(Name)69.336 288 Q F0(.............. clef)1.95 E F1(Description)69.336
+300 Q F0(..... sets the clef to use.)A
+(Changing a clef may also change the def)5 E(ault octa)-.1 E .3 -.15
+(ve \()-.2 H(see the "defoct" parameter).15 E(belo)138.476 312 Q(w\).)
+-.25 E F1 -.92(Va)69.336 324 S(lue).92 E F0(............... treble, tre\
+ble8, 8treble, frenchviolin, soprano, mezzosoprano, alto, tenor).36 E
+2.5(,b)-.4 G(aritone or bass.)-2.5 E(The tre-)5 E(ble8 clef looks lik)
+138.476 336 Q 2.5(eat)-.1 G(reble clef with an 8 belo)-2.5 E 2.5(wi)-.25
+G(t, and refers to notes that are an octa)-2.5 E .3 -.15(ve l)-.2 H -.25
+(ow).15 G(er than).25 E 2.5(an)138.476 348 S(ormal treble clef.)-2.5 E
+(The 8treble clef looks lik)5 E 2.5(eat)-.1 G(reble clef with an 8 abo)
+-2.5 E .3 -.15(ve i)-.15 H(t, and refers to notes).15 E
+(that are an octa)138.476 360 Q .3 -.15(ve h)-.2 H
+(igher than a normal treble clef.).15 E(If the staf)5 E
+(\215ines parameter includes the "drum")-.25 E -.1(ke)138.476 372 S(yw)
+-.05 E(ord, then the v)-.1 E(alue of this clef parameter is only used f\
+or determining the placement of notes)-.25 E(on the staf)138.476 384 Q
+(f, with the drum \(or "neutral"\) clef actually printed.)-.25 E
+(Clef can be changed in the middle)5 E
+(of a measure using a construct lik)138.476 396 Q 2.5(e<)-.1 G(<staf)
+-2.5 E 2.5(fc)-.25 G(lef=bass>> before a note group.)-2.5 E F1(Default)
+69.336 408 Q F0(............ treble).28 E F1(Context)69.336 420 Q F0
+(........... score, staf).56 E(f)-.25 E(It is possible to change this p\
+arameter in the middle of a measure, using << >>.)138.476 432 Q F1
+(Example)69.336 444 Q F0(......... clef = alto)1.66 E F1(See also)69.336
+456 Q F0(........... defoct, staf).83 E(\215ines)-.25 E F1(Name)69.336
+504 Q F0(.............. crescdist)1.95 E F1(Description)69.336 516 Q F0
+(..... This parameter is obsolete; it has been replaced by the dyndist \
+parameter)A(.)-.55 E F1(Name)69.336 564 Q F0(.............. defoct)1.95
+E F1(Description)69.336 576 Q F0(..... sets the def)A(ault octa)-.1 E .3
+-.15(ve f)-.2 H(or an).15 E 2.5(yn)-.15 G(ote which does not ha)-2.5 E
+.3 -.15(ve a)-.2 H 2.5(ne).15 G(xplicit octa)-2.65 E .3 -.15(ve s)-.2 H
+2.5(peci\214ed. An).15 F(octa)2.5 E .3 -.15(ve g)-.2 H(oes).15 E
+(from C up to the ne)138.476 588 Q(xt B, with octa)-.15 E .3 -.15
+(ve 4 b)-.2 H(eing the octa).15 E .3 -.15(ve b)-.2 H -.15(eg).15 G
+(inning on middle C.).15 E(If the clef is)5 E(changed on a staf)138.476
+600 Q(f, the def)-.25 E(ault octa)-.1 E .3 -.15(ve i)-.2 H 2.5(sc).15 G
+(hanged to match the ne)-2.5 E 2.5(wc)-.25 G 2.5(lef. defoct)-2.5 F
+(can be changed in)2.5 E(the middle of a measure using a construct lik)
+138.476 612 Q 2.5(e<)-.1 G(<staf)-2.5 E 2.5(fd)-.25 G
+(efoct=5>> before a note group.)-2.5 E F1 -.92(Va)69.336 624 S(lue).92 E
+F0(............... a number from 0 to 9 inclusi).36 E -.15(ve)-.25 G 2.5
+(.O).15 G(cta)-2.5 E .3 -.15(ve 4 i)-.2 H 2.5(st).15 G(he octa)-2.5 E .3
+-.15(ve b)-.2 H -.15(eg).15 G(inning at middle C.).15 E F1(Default)
+69.336 636 Q F0(............ the octa).28 E .3 -.15(ve c)-.2 H
+(ontaining the note represented by the middle line of the staf).15 E 2.5
+(fg)-.25 G -2.15 -.25(iv e)-2.5 H 2.5(nt).25 G(he current clef.)-2.5 E
+(\(Oc-)5 E(ta)138.476 648 Q .3 -.15(ve 5 f)-.2 H
+(or frenchviolin and 8treble; octa).15 E .3 -.15(ve 4 f)-.2 H
+(or treble, soprano, mezzosoprano, and alto clefs; oc-).15 E(ta)138.476
+660 Q .3 -.15(ve 3 f)-.2 H(or treble8, tenor).15 E 2.5(,b)-.4 G
+(aritone and bass clefs\).)-2.5 E F1(Context)69.336 672 Q F0
+(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E(It is possible to\
+ change this parameter in the middle of a measure, using << >>.)138.476
+684 Q F1(Example)69.336 696 Q F0(......... defoct = 3)1.66 E EP
+%%Page: 109 115
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(09 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. dist)1.95 E F1
+(Description)69.336 108 Q F0(..... sets minimum distance from staf)A 2.5
+(ft)-.25 G 2.5(op)-2.5 G
+(lace rom, bold, ital, and boldital items, and rehearsal marks.)-2.5 E
+(When these items are printed, the)138.476 120 Q 2.5(yw)-.15 G
+(ill be placed no closer to the staf)-2.5 E 2.5(ft)-.25 G(han the v)-2.5
+E(alue of this param-)-.25 E(eter)138.476 132 Q 2.5(.T)-.55 G
+(his can be used to reduce the ragged ef)-2.5 E(fect of ha)-.25 E
+(ving some items much higher than others,)-.2 E
+(because other things were in their w)138.476 144 Q(ay)-.1 E 5(.I)-.65 G
+2.5(fas)-5 G(peci\214c item has to be mo)-2.5 E -.15(ve)-.15 G 2.5(df)
+.15 G(arther a)-2.6 E -.1(wa)-.15 G 2.5(yt).1 G(han this)-2.5 E
+(parameter to a)138.476 156 Q -.2(vo)-.2 G
+(id running into something, that will still happen, b).2 E(ut an)-.2 E
+2.5(yo)-.15 G(thers will come out at)-2.5 E(the le)138.476 168 Q -.15
+(ve)-.25 G 2.5(ls).15 G(peci\214ed by this parameter)-2.5 E 5(.I)-.55 G
+2.5(fa)-5 G 2.5(ni)-2.5 G
+(tem is also a chord, the chorddist parameter will be)-2.5 E
+(used instead of dist.)138.476 180 Q(This parameter may be o)5 E -.15
+(ve)-.15 G(rridden on speci\214c items. The sections on tempo,).15 E
+(dynamic marks, ornaments, etc.)138.476 192 Q(and on rehearsal marks gi)
+5 E .3 -.15(ve d)-.25 H(etails on ho).15 E 2.5(wt)-.25 G 2.5(od)-2.5 G
+2.5(ot)-2.5 G(his.)-2.5 E F1 -.92(Va)69.336 204 S(lue).92 E F0
+(............... a whole number between 0 and 50 inclusi).36 E -.15(ve)
+-.25 G 2.5(,g).15 G -2.15 -.25(iv e)-2.5 H 2.5(ni).25 G 2.5(ns)-2.5 G
+(tepsizes.)-2.5 E F1(Default)69.336 216 Q F0(............ 2).28 E F1
+(Context)69.336 228 Q F0(........... score, staf).56 E(f)-.25 E F1
+(Example)69.336 240 Q F0(......... dist = 6)1.66 E F1(See also)69.336
+252 Q F0(........... chorddist, dyndist, scorepad, scoresep).83 E F1
+(Name)69.336 300 Q F0(.............. di)1.95 E(vision)-.25 E F1
+(Description)69.336 312 Q F0(..... sets MIDI di)A(vision \(number of cl\
+ock ticks per quarter note\). This typically has a v)-.25 E
+(alue of 192 or 384.)-.25 E
+(This parameter can only be speci\214ed before an)138.476 324 Q 2.5(ym)
+-.15 G(usic or block input.)-2.5 E F1 -.92(Va)69.336 336 S(lue).92 E F0
+(............... 1 to 1536).36 E F1(Default)69.336 348 Q F0
+(............ 192).28 E F1(Context)69.336 360 Q F0(........... score).56
+E F1(Example)69.336 372 Q F0(......... di)1.66 E(vision = 384)-.25 E F1
+(Name)69.336 420 Q F0(.............. dyndist)1.95 E F1(Description)
+69.336 432 Q F0(..... sets minimum distance from staf)A 2.5(ft)-.25 G
+2.5(op)-2.5 G(lace crescendo and decrescendo marks.)-2.5 E(and te)5 E
+(xt that is)-.15 E(mark)138.476 444 Q(ed "dyn.")-.1 E
+(When these items are printed, the)5 E 2.5(yw)-.15 G
+(ill be placed no closer to the staf)-2.5 E 2.5(ft)-.25 G(han the v)-2.5
+E(al-)-.25 E(ue of this parameter)138.476 456 Q 2.5(.T)-.55 G
+(his can be used to reduce the ragged ef)-2.5 E(fect of ha)-.25 E
+(ving some items much high-)-.2 E
+(er than others, because other things were in their w)138.476 468 Q(ay)
+-.1 E 5(.I)-.65 G 2.5(fas)-5 G(peci\214c item has to be mo)-2.5 E -.15
+(ve)-.15 G 2.5(df).15 G(arther)-2.6 E -2.3 -.15(aw a)138.476 480 T 2.5
+(yt).15 G(han this parameter to a)-2.5 E -.2(vo)-.2 G
+(id running into something, that will still happen, b).2 E(ut an)-.2 E
+2.5(yo)-.15 G(thers will)-2.5 E(come out at the le)138.476 492 Q -.15
+(ve)-.25 G 2.5(ls).15 G(peci\214ed by this parameter)-2.5 E 5(.T)-.55 G
+(his parameter may be o)-5 E -.15(ve)-.15 G(rridden on speci\214c).15 E
+(items. The section on tempo, dynamic marks, ornaments, etc.)138.476 504
+Q(gi)5 E -.15(ve)-.25 G 2.5(sd).15 G(etails on ho)-2.5 E 2.5(wt)-.25 G
+2.5(od)-2.5 G 2.5(ot)-2.5 G(his.)-2.5 E F1 -.92(Va)69.336 516 S(lue).92
+E F0(............... a whole number between 0 and 50 inclusi).36 E -.15
+(ve)-.25 G 2.5(,g).15 G -2.15 -.25(iv e)-2.5 H 2.5(ni).25 G 2.5(ns)-2.5
+G(tepsizes.)-2.5 E F1(Default)69.336 528 Q F0(............ 2).28 E F1
+(Context)69.336 540 Q F0(........... score, staf).56 E(f)-.25 E F1
+(Example)69.336 552 Q F0(......... dyndist = 4)1.66 E F1(See also)69.336
+564 Q F0(........... chorddist, dist, scorepad, scoresep).83 E EP
+%%Page: 110 116
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(10 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. endingstyle)1.95 E
+F1(Description)69.336 108 Q F0(..... controls ho)A 2.5<778c>-.25 G
+(rst and second endings are placed.)-2.5 E
+(This parameter also controls where measure num-)5 E
+(bers and rehearsal marks are placed.)138.476 120 Q 2.5(Av)5 G
+(alue of "top" means that the endings and similar marks)-2.75 E
+(will be sho)138.476 132 Q(wn only abo)-.25 E .3 -.15(ve t)-.15 H
+(he top visible staf).15 E 2.5(f. A)-.25 F -.25(va)2.5 G
+(lue of "barred" means these marks will be).25 E(sho)138.476 144 Q
+(wn abo)-.25 E .3 -.15(ve e)-.15 H(ach set of staf).15 E
+(fs that is barred together)-.25 E 2.5(.E)-.55 G(ach staf)-2.5 E 2.5(ft)
+-.25 G(hat is barred indi)-2.5 E(vidually will also)-.25 E(ha)138.476
+156 Q .3 -.15(ve t)-.2 H(he ending sho).15 E(wn abo)-.25 E .3 -.15(ve i)
+-.15 H 2.5(t. \(See).15 F(the "barstyle" parameter abo)2.5 E -.15(ve)
+-.15 G 2.5(.\) A).15 F -.25(va)2.5 G(lue of "grouped").25 E
+(means the marks will be sho)138.476 168 Q(wn abo)-.25 E .3 -.15(ve t)
+-.15 H(he top visible staf).15 E 2.5(fo)-.25 G 2.5(fe)-2.5 G
+(ach range of staf)-2.5 E(fs that are joined by)-.25 E 2.5(ab)138.476
+180 S(race or brack)-2.5 E 2.5(et. In)-.1 F
+(all cases, at least the top visible staf)2.5 E 2.5(fw)-.25 G(ill ha)
+-2.5 E .3 -.15(ve e)-.2 H(ndings sho).15 E(wn abo)-.25 E .3 -.15(ve i)
+-.15 H(t.).15 E F1 -.92(Va)69.336 192 S(lue).92 E F0
+(............... top, barred, or grouped).36 E F1(Default)69.336 204 Q
+F0(............ top).28 E F1(Context)69.336 216 Q F0(........... score)
+.56 E F1(Example)69.336 228 Q F0(......... endingstyle = grouped)1.66 E
+F1(See also)69.336 240 Q F0(........... barstyle, brace, brack).83 E
+(et, measnum, rehstyle, visible)-.1 E F1(Name)69.336 288 Q F0
+(.............. \214rstpage)1.95 E F1(Description)69.336 300 Q F0
+(..... speci\214es what to number the \214rst page.)A(This v)5 E
+(alue can be o)-.25 E -.15(ve)-.15 G(rridden by the -p command line op-)
+.15 E 2.5(tion. This)138.476 312 R(parameter can only be set before an)
+2.5 E 2.5(ym)-.15 G(usic or block input.)-2.5 E F1 -.92(Va)69.336 324 S
+(lue).92 E F0(............... 1 to 5000).36 E F1(Default)69.336 336 Q F0
+(............ 1).28 E F1(Context)69.336 348 Q F0(........... score).56 E
+F1(Example)69.336 360 Q F0(......... \214rstpage = 12)1.66 E F1(Name)
+69.336 408 Q F0(.............. font)1.95 E F1(Description)69.336 420 Q
+F0(..... speci\214es which font to use for print, left, right, center)A
+2.5(,a)-.4 G(nd title statements, and "with" lists \(i.e.,)-2.5 E
+(strings that are associated with a particular chord\).)138.476 432 Q F1
+-.92(Va)69.336 444 S(lue).92 E F0
+(............... rom, ital, bold, or boldital).36 E F1(Default)69.336
+456 Q F0(............ rom).28 E F1(Context)69.336 468 Q F0
+(........... score, staf).56 E(f, header)-.25 E 2.5(,f)-.4 G(ooter)-2.5
+E 2.5(,h)-.4 G(eader2, footer2, top, bottom, top2, bottom2, block)-2.5 E
+F1(Example)69.336 480 Q F0(......... font = boldital)1.66 E F1(See also)
+69.336 492 Q F0(........... fontf).83 E(amily)-.1 E 2.5(,l)-.65 G
+(yricsfont, lyricsfontf)-2.5 E(amily)-.1 E 2.5(,s)-.65 G(ize)-2.5 E F1
+(Name)69.336 540 Q F0(.............. fontf)1.95 E(amily)-.1 E F1
+(Description)69.336 552 Q F0(..... speci\214es what font f)A
+(amily to use for print, left, right, center)-.1 E 2.5(,a)-.4 G
+(nd title statements and "with" lists \(i.e.,)-2.5 E
+(strings that are associated with a particular chord\).)138.476 564 Q F1
+-.92(Va)69.336 576 S(lue).92 E F0(............... a).36 E -.25(va)-.2 G
+(ntg).25 E(arde, bookman, courier)-.05 E 2.5(,h)-.4 G(elv)-2.5 E
+(etica, ne)-.15 E(wcentury)-.25 E 2.5(,p)-.65 G(alatino, times)-2.5 E F1
+(Default)69.336 588 Q F0(............ times).28 E F1(Context)69.336 600
+Q F0(........... score, staf).56 E(f, header)-.25 E 2.5(,f)-.4 G(ooter)
+-2.5 E 2.5(,h)-.4 G(eader2, footer2, top, bottom, top2, bottom2, block)
+-2.5 E F1(Example)69.336 612 Q F0(......... fontf)1.66 E(amily=palatino)
+-.1 E F1(See also)69.336 624 Q F0
+(........... font, lyricsfont, lyricsfontf).83 E(amily)-.1 E EP
+%%Page: 111 117
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(11 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. gridfret)1.95 E F1
+(Description)69.336 108 Q F0
+(..... speci\214es when to print fret numbers on grids.)A(Normally)5 E
+2.5(,t)-.65 G(he top line of a grid represents the nut.)-2.5 E(Ho)
+138.476 120 Q(we)-.25 E -.15(ve)-.25 G .8 -.4(r, i).15 H 2.5(ft).4 G
+(he \214ngering for a chord is rather f)-2.5 E
+(ar up the neck, it is customary to ha)-.1 E .3 -.15(ve t)-.2 H
+(he top line of).15 E(the grid represent some other fret, and print a f\
+ret number and "fr" ne)138.476 132 Q(xt to the grid, sho)-.15 E
+(wing the ac-)-.25 E(tual fret of the rightmost fret mark. This paramet\
+er controls when Mup be)138.476 144 Q(gins using this alternate)-.15 E
+(format. Whene)138.476 156 Q -.15(ve)-.25 G 2.5(ra).15 G
+(ll the frets of a chord are greater than or equal to the v)-2.5 E
+(alue speci\214ed for this pa-)-.25 E(rameter)138.476 168 Q 2.5(,a)-.4 G
+(nd there are no strings mark)-2.5 E
+(ed "o", the "fr" notation is used. If no v)-.1 E
+(alue is set for this pa-)-.25 E(rameter)138.476 180 Q 2.5(,t)-.4 G(he \
+grid will just be made as tall as necessary to accommodate the chord')
+-2.5 E 2.5(sf)-.55 G(rets.)-2.5 E F1 -.92(Va)69.336 192 S(lue).92 E F0
+(............... 2 to 99, or not set).36 E F1(Default)69.336 204 Q F0
+(............ 4).28 E F1(Context)69.336 216 Q F0
+(........... score, staf).56 E(f)-.25 E F1(Example)69.336 228 Q F0
+(......... gridfret = 3)1.66 E(gridfret =)138.476 240 Q F1(See also)
+69.336 252 Q F0(........... gridsatend, gridscale, gridswhereused,).83 E
+F1(Name)69.336 300 Q F0(.............. gridsatend)1.95 E F1(Description)
+69.336 312 Q F0(..... speci\214es whether to print guitar grids at the \
+end of the song.)A(If set to "y" grids for all of the chords)5 E
+(used in the song will be printed.)138.476 324 Q F1 -.92(Va)69.336 336 S
+(lue).92 E F0(............... y or n).36 E F1(Default)69.336 348 Q F0
+(............ n).28 E F1(Context)69.336 360 Q F0(........... score).56 E
+F1(Example)69.336 372 Q F0(......... gridsatend = y)1.66 E F1(See also)
+69.336 384 Q F0(........... gridfret, gridscale, gridswhereused).83 E F1
+(Name)69.336 432 Q F0(.............. gridscale)1.95 E F1(Description)
+69.336 444 Q F0(..... speci\214es ho)A 2.5(wl)-.25 G(ar)-2.5 E
+(ge to mak)-.18 E 2.5(eg)-.1 G(rids, relati)-2.5 E .3 -.15(ve t)-.25 H
+2.5(ot).15 G(heir def)-2.5 E(ault size.)-.1 E -.15(Fo)5 G 2.5(re).15 G
+(xample, a v)-2.65 E(alue of 0.5 will)-.25 E(mak)138.476 456 Q 2.5(et)
+-.1 G(hem 1/2 their def)-2.5 E(ault size.)-.1 E(The def)5 E
+(ault size for grids summarized at the end of the song \(the)-.1 E
+(gridsatend parameter\) is lar)138.476 468 Q(ger than the def)-.18 E
+(ault size for those printed with the music \(the)-.1 E
+(gridswhereused parameter\).)138.476 480 Q F1 -.92(Va)69.336 492 S(lue)
+.92 E F0(............... 0.1 to 10.0).36 E F1(Default)69.336 504 Q F0
+(............ 1.0).28 E F1(Context)69.336 516 Q F0
+(........... score, staf).56 E(f)-.25 E F1(Example)69.336 528 Q F0
+(......... gridscale = 0.5)1.66 E F1(See also)69.336 540 Q F0
+(........... gridsatend, gridfret, gridswhereused, scale, staf).83 E
+(fscale)-.25 E F1(Name)69.336 588 Q F0(.............. gridswhereused)
+1.95 E F1(Description)69.336 600 Q F0(..... speci\214es whether to prin\
+t guitar grids along with chords where the)A 2.5(ya)-.15 G
+(ppear in the song. If set to "y")-2.5 E(each te)138.476 612 Q
+(xt item with the chord modi\214er will ha)-.15 E .3 -.15(ve a g)-.2 H
+(rid printed belo).15 E 2.5(wi)-.25 G(ts name.)-2.5 E F1 -.92(Va)69.336
+624 S(lue).92 E F0(............... y or n).36 E F1(Default)69.336 636 Q
+F0(............ n).28 E F1(Context)69.336 648 Q F0
+(........... score, staf).56 E(f)-.25 E F1(Example)69.336 660 Q F0
+(......... gridswhereused = y)1.66 E F1(See also)69.336 672 Q F0
+(........... gridfret, gridsatend, gridscale).83 E EP
+%%Page: 112 118
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(12 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. k)1.95 E -.15(ey)-.1
+G F1(Description)69.336 108 Q F0(..... sets the k)A .3 -.15(ey s)-.1 H
+(ignature. This can be speci\214ed either by gi).15 E
+(ving the number of sharps \(#\) or \215ats \(&\), or)-.25 E(by gi)
+138.476 120 Q(ving the name of the k)-.25 E -.15(ey)-.1 G(.)-.5 E F1
+-.92(Va)69.336 132 S(lue).92 E F0
+(............... If using the number of sharps/\215ats format, the v).36
+E(alue is a number from 0 to 7, follo)-.25 E(wed by "#" or)-.25 E
+("&," optionally follo)138.476 144 Q(wed by "major" or "minor)-.25 E
+(." 0& and 0# are equi)-.55 E -.25(va)-.25 G 2.5(lent. If).25 F
+(using the name of)2.5 E(the k)138.476 156 Q -.15(ey)-.1 G 2.5(,t)-.5 G
+(he v)-2.5 E(alue is a letter "a" through "g," optionally follo)-.25 E
+(wed by a "#" or "&," optionally fol-)-.25 E(lo)138.476 168 Q
+(wed by "major" or "minor)-.25 E 2.5(." The)-.55 F
+("major" and "minor" can be abbre)2.5 E(viated to "maj" or "min.")-.25 E
+(The)5 E("major" or "minor" is used for MIDI \214le purposes, and is op\
+tional; if omitted, it def)138.476 180 Q(aults to major)-.1 E(.)-.55 E
+(If you wish to use a mode other than major or minor)138.476 192 Q 2.5
+(,y)-.4 G(ou ha)-2.5 E .3 -.15(ve t)-.2 H 2.5(os).15 G
+(pecify the number of sharps or)-2.5 E(\215ats.)138.476 204 Q F1
+(Default)69.336 216 Q F0(............ c major).28 E F1(Context)69.336
+228 Q F0(........... score, staf).56 E(f)-.25 E F1(Example)69.336 240 Q
+F0(......... k)1.66 E .3 -.15(ey = 3)-.1 H(&).15 E -.1(ke)138.476 252 S
+2.5(y=6)-.05 G(#)-2.5 E -.1(ke)138.476 264 S 2.5(y=c)-.05 G 2.5(#m)-2.5
+G(inor)-2.5 E -.1(ke)138.476 276 S 2.5(y=dm)-.05 G(ajor)-2.5 E F1
+(See also)69.336 288 Q F0(........... staf).83 E
+(\215ines, transpose, addtranspose)-.25 E F1(Name)69.336 336 Q F0
+(.............. label)1.95 E F1(Description)69.336 348 Q F0
+(..... specify a label to be printed to the left of the staf)A 2.5(fo)
+-.25 G 2.5(nt)-2.5 G(he ne)-2.5 E
+(xt score. If there is also a brace or brack)-.15 E(et)-.1 E
+(label, that label will be to the left of this label.)138.476 360 Q
+(There is a label2 parameter that is used on subse-)5 E(quent scores.)
+138.476 372 Q(In addition to being used for the v)5 E
+(ery \214rst score of a song, this label parameter might)-.15 E
+(be used to clearly mark a change in instrumentation or v)138.476 384 Q
+(oices for a particular staf)-.2 E(f. The label2)-.25 E -.1(wo)138.476
+396 S(uld typically be changed at the same time, gi).1 E
+(ving a more abbre)-.25 E(viated label. F)-.25 E(or e)-.15 E
+(xample, you)-.15 E(might set label="T)138.476 408 Q
+(enor/Bass" and label2="TB")-.7 E F1 -.92(Va)69.336 420 S(lue).92 E F0
+(............... a te).36 E(xt string enclosed in double quotes.)-.15 E
+F1(Default)69.336 432 Q F0
+(............ enough spaces to produce an indent of 1/2 inch).28 E F1
+(Context)69.336 444 Q F0(........... score, staf).56 E(f)-.25 E F1
+(Example)69.336 456 Q F0(......... label = "oboe")1.66 E F1(See also)
+69.336 468 Q F0(........... brace, brack).83 E(et, label2)-.1 E F1(Name)
+69.336 516 Q F0(.............. label2)1.95 E F1(Description)69.336 528 Q
+F0(..... specify a label to be printed to the left of the staf)A 2.5(fo)
+-.25 G 2.5(na)-2.5 G
+(ll scores after the \214rst. If there is also a brace)-2.5 E(or brack)
+138.476 540 Q(et label, that label will be to the left of this label.)
+-.1 E(If both the label and label2 parameters)5 E
+(are set at the same time, the label v)138.476 552 Q
+(alue will be used for the immediately follo)-.25 E
+(wing score, with the)-.25 E(label2 v)138.476 564 Q
+(alue used for subsequent scores.)-.25 E(If ho)5 E(we)-.25 E -.15(ve)
+-.25 G .8 -.4(r, a).15 H(fter the \214rst score, only the label2 is).4 E
+(changed, then the label2 v)138.476 576 Q
+(alue will be used on the immediately follo)-.25 E
+(wing score as well as subse-)-.25 E(quent scores.)138.476 588 Q F1 -.92
+(Va)69.336 600 S(lue).92 E F0(............... a te).36 E
+(xt string enclosed in double quotes)-.15 E F1(Default)69.336 612 Q F0
+(............ no label).28 E F1(Context)69.336 624 Q F0
+(........... score, staf).56 E(f)-.25 E F1(Example)69.336 636 Q F0
+(......... label2 = "Solo")1.66 E F1(See also)69.336 648 Q F0
+(........... brace, brack).83 E(et, label)-.1 E EP
+%%Page: 113 119
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(13 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. leftmar)1.95 E(gin)
+-.18 E F1(Description)69.336 108 Q F0
+(..... sets the amount of white space mar)A
+(gin to put at the left side of each page.)-.18 E
+(It is speci\214ed in inches if)5 E(the units parameter is set to inche\
+s, or in centimeters if the units parameter is set to cm.)138.476 120 Q
+(This pa-)5 E(rameter can only be speci\214ed before an)138.476 132 Q
+2.5(ym)-.15 G(usic or block input.)-2.5 E(Mar)5 E(gins are unaf)-.18 E
+(fected by the)-.25 E("scale" parameter)138.476 144 Q(.)-.55 E F1 -.92
+(Va)69.336 156 S(lue).92 E F0(............... 0.0 to page).36 E
+(width minus 0.5 inches)-.25 E F1(Default)69.336 168 Q F0
+(............ 0.5 inches).28 E F1(Context)69.336 180 Q F0
+(........... score).56 E F1(Example)69.336 192 Q F0(......... leftmar)
+1.66 E(gin = 0.3)-.18 E F1(See also)69.336 204 Q F0
+(........... bottommar).83 E(gin, rightmar)-.18 E(gin, topmar)-.18 E
+(gin, page)-.18 E(width, units)-.25 E F1(Name)69.336 252 Q F0
+(.............. lyricsalign)1.95 E F1(Description)69.336 264 Q F0
+(..... speci\214es ho)A 2.5(wt)-.25 G 2.5(oa)-2.5 G
+(lign lyric syllables with chords. Its v)-2.5 E
+(alue is the proportion of each syllable to place)-.25 E
+(to the left of the syllable')138.476 276 Q 2.5(sc)-.55 G 2.5
+(hord. Thus)-2.5 F(for e)2.5 E(xample, a v)-.15 E
+(alue of 0.0 causes the left edge of syllables)-.25 E
+(to be aligned with the chords, whereas a v)138.476 288 Q
+(alue of 0.5 causes syllables to be centered with the chord,)-.25 E(and\
+ 1.0 causes the right edge of the syllables to be aligned with the chor\
+d.)138.476 300 Q F1 -.92(Va)69.336 312 S(lue).92 E F0
+(............... 0.0 to 1.0).36 E F1(Default)69.336 324 Q F0
+(............ 0.25).28 E F1(Context)69.336 336 Q F0
+(........... score, staf).56 E(f)-.25 E F1(Example)69.336 348 Q F0
+(......... lyricsalign = 0.1)1.66 E F1(See also)69.336 360 Q F0
+(........... sylposition).83 E F1(Name)69.336 408 Q F0
+(.............. lyricsfont)1.95 E F1(Description)69.336 420 Q F0
+(..... sets which font to use for lyrics.)A F1 -.92(Va)69.336 432 S(lue)
+.92 E F0(............... rom, ital, bold, boldital).36 E F1(Default)
+69.336 444 Q F0(............ rom).28 E F1(Context)69.336 456 Q F0
+(........... score, staf).56 E(f)-.25 E F1(Example)69.336 468 Q F0
+(......... lyricsfont = ital)1.66 E F1(See also)69.336 480 Q F0
+(........... font, lyricssize).83 E F1(Name)69.336 528 Q F0
+(.............. lyricsfontf)1.95 E(amily)-.1 E F1(Description)69.336 540
+Q F0(..... speci\214es what font f)A(amily to use for lyrics.)-.1 E F1
+-.92(Va)69.336 552 S(lue).92 E F0(............... a).36 E -.25(va)-.2 G
+(ntg).25 E(arde, bookman, courier)-.05 E 2.5(,h)-.4 G(elv)-2.5 E
+(etica, ne)-.15 E(wcentury)-.25 E 2.5(,p)-.65 G(alatino, times)-2.5 E F1
+(Default)69.336 564 Q F0(............ times).28 E F1(Context)69.336 576
+Q F0(........... score, staf).56 E(f)-.25 E F1(Example)69.336 588 Q F0
+(......... lyricsfontf)1.66 E(amily=helv)-.1 E(etica)-.15 E F1(See also)
+69.336 600 Q F0(........... font, fontf).83 E(amily)-.1 E 2.5(,l)-.65 G
+(yricsfont)-2.5 E F1(Name)69.336 648 Q F0(.............. lyricssize)1.95
+E F1(Description)69.336 660 Q F0
+(..... sets point size to use for lyrics.)A F1 -.92(Va)69.336 672 S(lue)
+.92 E F0(............... a number from 1 to 100).36 E F1(Default)69.336
+684 Q F0(............ 12).28 E F1(Context)69.336 696 Q F0
+(........... score, staf).56 E(f)-.25 E F1(Example)69.336 708 Q F0
+(......... lyricssize = 10)1.66 E F1(See also)69.336 720 Q F0
+(........... lyricsfont, lyricsfontf).83 E(amily)-.1 E 2.5(,s)-.65 G
+(ize)-2.5 E EP
+%%Page: 114 120
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(14 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. measnum)1.95 E F1
+(Description)69.336 108 Q F0
+(..... speci\214es whether or not to print measure numbers.)A
+(If set to "y)5 E(," the current measure number will be)-.65 E
+(printed at the be)138.476 120 Q(ginning of each score other than the \
+\214rst. The number will be printed abo)-.15 E .3 -.15(ve a)-.15 H -.15
+(ny).15 G(scores that w)138.476 132 Q(ould recei)-.1 E .3 -.15(ve e)-.25
+H(nding marks \(see "endingstyle" parameter\).).15 E
+(If set to "n," no measure)5 E(numbers will be printed.)138.476 144 Q
+(This parameter does not af)5 E
+(fect rehearsal numbers, which are equal to)-.25 E
+(measure numbers when "mnum" is used.)138.476 156 Q F1 -.92(Va)69.336
+168 S(lue).92 E F0(............... y or n).36 E F1(Default)69.336 180 Q
+F0(............ n).28 E F1(Context)69.336 192 Q F0(........... score).56
+E F1(Example)69.336 204 Q F0(......... measnum = y)1.66 E F1(See also)
+69.336 216 Q F0(........... endingstyle, measnumfont, measnumfontf).83 E
+(amily)-.1 E 2.5(,m)-.65 G(easnumsize, rehstyle)-2.5 E F1(Name)69.336
+264 Q F0(.............. measnumfont)1.95 E F1(Description)69.336 276 Q
+F0(..... This speci\214es which font type to use for the automatic meas\
+ure numbers, if the)A 2.5(ya)-.15 G(re turned on via)-2.5 E
+(the measnum parameter)138.476 288 Q(.)-.55 E F1 -.92(Va)69.336 300 S
+(lue).92 E F0(............... rom, ital, bold, or boldital).36 E F1
+(Default)69.336 312 Q F0(............ rom).28 E F1(Context)69.336 324 Q
+F0(........... score).56 E F1(Example)69.336 336 Q F0
+(......... measnumfont=boldital)1.66 E F1(See also)69.336 348 Q F0
+(........... measnum, measnumfontf).83 E(amily)-.1 E 2.5(,m)-.65 G
+(easnumsize)-2.5 E F1(Name)69.336 396 Q F0(.............. measnumfontf)
+1.95 E(amily)-.1 E F1(Description)69.336 408 Q F0
+(..... This speci\214es which font f)A
+(amily to use for the automatic measure numbers, if the)-.1 E 2.5(ya)
+-.15 G(re turned on via)-2.5 E(the measnum parameter)138.476 420 Q(.)
+-.55 E F1 -.92(Va)69.336 432 S(lue).92 E F0(............... a).36 E -.25
+(va)-.2 G(nte).25 E -.05(ga)-.15 G(rde, bookman, courier).05 E 2.5(,h)
+-.4 G(elv)-2.5 E(etica, ne)-.15 E(wcentry)-.25 E 2.5(,p)-.65 G
+(alatino, or times)-2.5 E F1(Default)69.336 444 Q F0(............ times)
+.28 E F1(Context)69.336 456 Q F0(........... score).56 E F1(Example)
+69.336 468 Q F0(......... measnumfontf)1.66 E(amily=helv)-.1 E(etica)
+-.15 E F1(See also)69.336 480 Q F0
+(........... measnum, measnumfont, measnumsize).83 E F1(Name)69.336 528
+Q F0(.............. measnumsize)1.95 E F1(Description)69.336 540 Q F0(.\
+.... This speci\214es what size to use for the automatic measure number\
+s, in points, if the)A 2.5(ya)-.15 G(re turned on)-2.5 E
+(via the measnum parameter)138.476 552 Q(.)-.55 E F1 -.92(Va)69.336 564
+S(lue).92 E F0(............... 1 to 100).36 E F1(Default)69.336 576 Q F0
+(............ 11).28 E F1(Context)69.336 588 Q F0(........... score).56
+E F1(Example)69.336 600 Q F0(......... measnumsize=15)1.66 E F1
+(See also)69.336 612 Q F0
+(........... measnum, measnumfont, measnumfontf).83 E(amily)-.1 E EP
+%%Page: 115 121
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(15 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. noteheads)1.95 E F1
+(Description)69.336 108 Q F0(..... The noteheads parameter describes wh\
+ich note head shape\(s\) to use for each pitch in the scale.)A(If)5 E
+(you w)138.476 120 Q(ant to use the same shape for all pitches, as is t\
+he case with standard notation, the v)-.1 E(alue is a)-.25 E(string con\
+taining a single shape name \(e.g., "norm" for standard notation\).)
+138.476 132 Q(If you w)5 E(ant to use dif-)-.1 E(ferent shapes for dif)
+138.476 144 Q(ferent pitches, the noteheads parameter v)-.25 E
+(alue is a string containing a list of 7)-.25 E(shape names.)138.476 156
+Q(The)5 E 2.5(ya)-.15 G
+(re listed in order starting from the "tonic" of the major k)-2.5 E .3
+-.15(ey a)-.1 H 2.5(si).15 G(ndicated by the)-2.5 E
+(number of sharps or \215ats in the k)138.476 168 Q .3 -.15(ey s)-.1 H
+2.5(ignature. There).15 F
+(are 10 pre-de\214ned head shapes: blank, diam,)2.5 E
+(isostri, norm, pie, rect, righttri, semicirc, slash, and xnote.)138.476
+180 Q(Additional head shapes can be de\214ned)5 E
+(in the headshapes conte)138.476 192 Q 2.5(xt. See)-.15 F(the e)2.5 E
+(xamples belo)-.15 E 2.5(wf)-.25 G
+(or the most common settings for this parame-)-2.5 E(ter)138.476 204 Q
+2.5(.H)-.55 G(ead shape can be o)-2.5 E -.15(ve)-.15 G
+(rridden on an indi).15 E
+(vidual chord by using [hs "shapename"] before the)-.25 E
+(chord. It can also be o)138.476 216 Q -.15(ve)-.15 G
+(rridden on an indi).15 E
+(vidual note by putting hs "shapename" after the note.)-.25 E F1 -.92
+(Va)69.336 228 S(lue).92 E F0
+(............... A string containing either 1 or 7 head shape names.).36
+E F1(Default)69.336 240 Q F0(............ "norm").28 E F1(Context)69.336
+252 Q F0(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E F1
+(Example)69.336 264 Q F0(......... // This is the setting for the most \
+common shaped note system using 4 shapes.)1.66 E
+(noteheads = "righttri norm rect righttri norm rect diam")138.476 276 Q
+(// This is the setting for a shaped notes system that uses 7 dif)
+138.476 300 Q(ferent shapes.)-.25 E
+(noteheads = "isostri semicirc diam righttri norm rect pie")138.476 312
+Q F1(Name)69.336 360 Q F0(.............. numbermrpt)1.95 E F1
+(Description)69.336 372 Q F0
+(..... If set to 'y' measure repeats are numbered; if set to 'n' the)A
+2.5(ya)-.15 G(ren')-2.5 E(t.)-.18 E F1 -.92(Va)69.336 384 S(lue).92 E F0
+(............... y or n).36 E F1(Default)69.336 396 Q F0(............ y)
+.28 E F1(Context)69.336 408 Q F0(........... score, staf).56 E(f)-.25 E
+F1(Example)69.336 420 Q F0(......... numbermrpt = n)1.66 E F1(Name)
+69.336 468 Q F0(.............. ontheline)1.95 E F1(Description)69.336
+480 Q F0(..... speci\214es whether notes for v)A
+(oices 1 and 2 on a 1-line staf)-.2 E 2.5(fa)-.25 G
+(re to be placed on the line.)-2.5 E(If this is set)5 E
+(to n, notes with stem up will be placed abo)138.476 492 Q .3 -.15(ve t)
+-.15 H(he line and notes with stem do).15 E(wn will be placed be-)-.25 E
+(lo)138.476 504 Q 2.5(wt)-.25 G
+(he line, otherwise both will be placed on the line. F)-2.5 E
+(or notes that don')-.15 E 2.5(th)-.18 G -2.25 -.2(av e)-2.5 H 2.5(as)
+2.7 G(tem, the rules)-2.5 E(are applied using the direction the stem w)
+138.476 516 Q(ould be if there were a stem.)-.1 E
+(This parameter has no ef-)5 E(fect on 5-line staf)138.476 528 Q
+(fs or tablature staf)-.25 E 2.5(fs. Notes)-.25 F(for v)2.5 E
+(oice 3 are al)-.2 E -.1(wa)-.1 G(ys placed on the line on 1-line).1 E
+(staf)138.476 540 Q(fs, re)-.25 E -.05(ga)-.15 G(rdless of the v).05 E
+(alue of this parameter)-.25 E(.)-.55 E F1 -.92(Va)69.336 552 S(lue).92
+E F0(............... y or n).36 E F1(Default)69.336 564 Q F0
+(............ y).28 E F1(Context)69.336 576 Q F0
+(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E F1(Example)69.336
+588 Q F0(......... ontheline=n)1.66 E F1(See also)69.336 600 Q F0
+(........... staf).83 E(\215ines)-.25 E EP
+%%Page: 116 122
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(16 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. pack)1.95 E -.15(ex)
+-.1 G(p).15 E F1(Description)69.336 108 Q F0(..... sets note e)A
+(xpansion f)-.15 E(actor)-.1 E 2.5(.T)-.55 G(his f)-2.5 E
+(actor controls spacing of notes relati)-.1 E .3 -.15(ve t)-.25 H 2.5
+(ot).15 G(heir time v)-2.5 E(alues. If set to)-.25 E
+(1.0, Mup will try to gi)138.476 120 Q .3 -.15(ve a h)-.25 H
+(alf note twice as much space as a quarter note, a whole note twice as)
+.15 E(much as a half note, etc. If set to 0.0, a chord')138.476 132 Q
+2.5(st)-.55 G(ime v)-2.5 E(alue will ha)-.25 E .3 -.15(ve n)-.2 H 2.5
+(oi).15 G(mpact on its placement.)-2.5 E(Intermediate v)138.476 144 Q
+(alues will cause relati)-.25 E .3 -.15(ve s)-.25 H
+(pacing between the tw).15 E 2.5(oe)-.1 G(xtremes. Note that indi)-2.65
+E(vidual)-.25 E(chords may get more space than the)138.476 156 Q 2.5(yw)
+-.15 G(ould theoretically "deserv)-2.6 E(e" if the)-.15 E 2.5(yh)-.15 G
+(appen to need e)-2.5 E(xtra)-.15 E
+(space to accommodate accidentals, dots, etc.)138.476 168 Q F1 -.92(Va)
+69.336 180 S(lue).92 E F0
+(............... a number from 0.0 to 1.0 inclusi).36 E -.15(ve)-.25 G
+F1(Default)69.336 192 Q F0(............ 0.8).28 E F1(Context)69.336 204
+Q F0(........... score).56 E F1(Example)69.336 216 Q F0(......... pack)
+1.66 E -.15(ex)-.1 G 2.5(p=0).15 G(.95)-2.5 E F1(See also)69.336 228 Q
+F0(........... packf).83 E(act, pad)-.1 E F1(Name)69.336 276 Q F0
+(.............. packf)1.95 E(act)-.1 E F1(Description)69.336 288 Q F0
+(..... speci\214es ho)A 2.5(wt)-.25 G
+(ightly to pack notes together on output. The smaller the v)-2.5 E
+(alue, the more tightly notes)-.25 E(are pack)138.476 300 Q(ed together)
+-.1 E(.)-.55 E F1 -.92(Va)69.336 312 S(lue).92 E F0
+(............... a number from 0.0 to 10.0).36 E F1(Default)69.336 324 Q
+F0(............ 1.0).28 E F1(Context)69.336 336 Q F0(........... score)
+.56 E F1(Example)69.336 348 Q F0(......... packf)1.66 E(act = 1.4)-.1 E
+F1(See also)69.336 360 Q F0(........... pack).83 E -.15(ex)-.1 G(p, pad)
+.15 E F1(Name)69.336 408 Q F0(.............. pad)1.95 E F1(Description)
+69.336 420 Q F0
+(..... speci\214es the amount of padding to be added to notes.)A
+(This can be used to control ho)5 E 2.5(wt)-.25 G(ightly things)-2.5 E
+(are pack)138.476 432 Q(ed together)-.1 E 5(.E)-.55 G(specially if pack)
+-5 E -.15(ex)-.1 G 2.5(pa).15 G(nd packf)-2.5 E(act are v)-.1 E
+(ery small, notes can get placed v)-.15 E(ery)-.15 E(close together)
+138.476 444 Q 5(.T)-.55 G(his parameter can be used to al)-5 E -.1(wa)
+-.1 G(ys force a minimum amount of space between).1 E
+(horizontally adjacent note groups.)138.476 456 Q 2.5(Av)5 G
+(alue of zero means notes will be allo)-2.75 E(wed to just touch.)-.25 E
+(More positi)138.476 468 Q .3 -.15(ve v)-.25 H
+(alues cause more space around notes.)-.1 E 2.5(An)5 G -2.25 -.15(eg a)
+-2.5 H(ti).15 E .3 -.15(ve v)-.25 H(alue will let things actually o)-.1
+E -.15(ve)-.15 G -.2(r-).15 G(lap, so most people will probably ne)
+138.476 480 Q -.15(ve)-.25 G 2.5(rw).15 G(ant to use a ne)-2.6 E -.05
+(ga)-.15 G(ti).05 E .3 -.15(ve v)-.25 H(alue, b)-.1 E
+(ut the option is there if you)-.2 E -.1(wa)138.476 492 S
+(nt to do something unusual.).1 E(This parameter w)5 E(orks some)-.1 E
+(what lik)-.25 E 2.5(et)-.1 G(he "pad" v)-2.5 E(alue that can be)-.25 E
+(speci\214ed for indi)138.476 504 Q(vidual note groups, e)-.25 E
+(xcept that it applies to all groups.)-.15 E F1 -.92(Va)69.336 516 S
+(lue).92 E F0
+(............... a \215oating point number of stepsizes, -5.0 to 50.0)
+.36 E F1(Default)69.336 528 Q F0(............ 0.3333).28 E F1(Context)
+69.336 540 Q F0(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E F1
+(Example)69.336 552 Q F0(......... pad = 1.76)1.66 E F1(See also)69.336
+564 Q F0(........... pack).83 E -.15(ex)-.1 G(p, packf).15 E(act)-.1 E
+F1(Name)69.336 612 Q F0(.............. pageheight)1.95 E F1(Description)
+69.336 624 Q F0
+(..... Set the page height. If the units parameter is inches, the v)A
+(alue of pageheight is gi)-.25 E -.15(ve)-.25 G 2.5(ni).15 G 2.5(ni)-2.5
+G(nches, or if)-2.5 E(the units parameter is cm, it is gi)138.476 636 Q
+-.15(ve)-.25 G 2.5(ni).15 G 2.5(nc)-2.5 G 2.5(entimeters. This)-2.5 F
+(parameter can only be speci\214ed before)2.5 E(an)138.476 648 Q 2.5(ym)
+-.15 G(usic or block input.)-2.5 E(If the page)5 E
+(width and pageheight parameters are set to v)-.25 E(alues that match)
+-.25 E 2.5(as)138.476 660 S(tandard paper size in landscape mode, the M\
+up output will be rotated to print properly in land-)-2.5 E(scape mode.)
+138.476 672 Q F1 -.92(Va)69.336 684 S(lue).92 E F0
+(............... 2.0 to 24.0 inches or 5.0 to 61.0 cm).36 E F1(Default)
+69.336 696 Q F0(............ 11.0 inches).28 E F1(Context)69.336 708 Q
+F0(........... score).56 E F1(Example)69.336 720 Q F0
+(......... pageheight = 9)1.66 E F1(See also)69.336 732 Q F0
+(........... page).83 E(width, bottommar)-.25 E(gin topmar)-.18 E
+(gin, units)-.18 E EP
+%%Page: 117 123
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(17 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. pagesize)1.95 E F1
+(Description)69.336 108 Q F0
+(..... Set the page size. This is just an alternate w)A
+(ay of specifying pageheight and page)-.1 E(width using the)-.25 E
+(common names for paper sizes rather than specifying in inches or cm.)
+138.476 120 Q(An orientation \(portrait or)5 E
+(landscape\) can also be speci\214ed; the def)138.476 132 Q
+(ault is portrait.)-.1 E(This parameter can only be speci\214ed be-)5 E
+(fore an)138.476 144 Q 2.5(ym)-.15 G(usic or block input.)-2.5 E F1 -.92
+(Va)69.336 156 S(lue).92 E F0(............... letter).36 E 2.5(,l)-.4 G
+-2.25 -.15(eg a)-2.5 H(l, \215sa, hal\215etter).15 E 2.5(,a)-.4 G
+(4, a5, a6; optionally follo)-2.5 E(wed by portrait or landscape.)-.25 E
+F1(Default)69.336 168 Q F0(............ letter).28 E F1(Context)69.336
+180 Q F0(........... score).56 E F1(Example)69.336 192 Q F0
+(......... pagesize = a4)1.66 E(pagesize = le)138.476 204 Q -.05(ga)-.15
+G 2.5(ll).05 G(andscape)-2.5 E F1(See also)69.336 216 Q F0
+(........... pageheight, page).83 E(width, panelsperpage)-.25 E F1(Name)
+69.336 264 Q F0(.............. page)1.95 E(width)-.25 E F1(Description)
+69.336 276 Q F0
+(..... Set the page width. If the units parameter is inches, the v)A
+(alue of page)-.25 E(width is gi)-.25 E -.15(ve)-.25 G 2.5(ni).15 G 2.5
+(ni)-2.5 G(nches, or if)-2.5 E(the units parameter is cm, it is gi)
+138.476 288 Q -.15(ve)-.25 G 2.5(ni).15 G 2.5(nc)-2.5 G 2.5
+(entimeters. This)-2.5 F(parameter can only be speci\214ed before)2.5 E
+(an)138.476 300 Q 2.5(ym)-.15 G(usic or block input.)-2.5 E(If the page)
+5 E(width and pageheight parameters are set to v)-.25 E
+(alues that match)-.25 E 2.5(as)138.476 312 S(tandard paper size in lan\
+dscape mode, the Mup output will be rotated to print properly in land-)
+-2.5 E(scape mode.)138.476 324 Q F1 -.92(Va)69.336 336 S(lue).92 E F0
+(............... 2.0 to 24.0 inches or 5.0 to 61.0 cm).36 E F1(Default)
+69.336 348 Q F0(............ 8.5 inches).28 E F1(Context)69.336 360 Q F0
+(........... score).56 E F1(Example)69.336 372 Q F0(......... page)1.66
+E(width = 6.5)-.25 E F1(See also)69.336 384 Q F0
+(........... pageheight, leftmar).83 E(gin, rightmar)-.18 E(gin, units)
+-.18 E F1(Name)69.336 432 Q F0(.............. panelsperpage)1.95 E F1
+(Description)69.336 444 Q F0(..... Speci\214es ho)A 2.5(wm)-.25 G(an)
+-2.5 E 2.5(yp)-.15 G(ages of music to print on each ph)-2.5 E
+(ysical page.)-.05 E(This parameter can only be)5 E
+(speci\214ed before an)138.476 456 Q 2.5(ym)-.15 G(usic or block input.)
+-2.5 E(Note that the pageheight and page)5 E(width parameters still)-.25
+E(apply to the ph)138.476 468 Q(ysical paper size vie)-.05 E
+(wed in portrait mode, e)-.25 E -.15(ve)-.25 G 2.5(nw).15 G
+(hen the panelsperpage v)-2.5 E(alue causes)-.25 E
+(the printing to be landscape mode, so you should continue to lea)
+138.476 480 Q .3 -.15(ve t)-.2 H(hose set as you normally).15 E -.1(wo)
+138.476 492 S 2.5(uld. The).1 F(-o command line option may be useful fo\
+r getting pages printed in desired order)2.5 E 5(.F)-.55 G(or)-5.15 E
+-.15(ex)138.476 504 S(ample, to mak).15 E 2.5(ea4)-.1 G(-page booklet f\
+rom a single sheet of paper folded in half, you can use pan-)-2.5 E
+(elsperpage=2, then use -o4,1 to print one side of the paper)138.476 516
+Q 2.5(,a)-.4 G(nd -o2,3 to print the other side.)-2.5 E F1 -.92(Va)
+69.336 528 S(lue).92 E F0(............... 1 or 2).36 E F1(Default)69.336
+540 Q F0(............ 1).28 E F1(Context)69.336 552 Q F0
+(........... score).56 E F1(Example)69.336 564 Q F0
+(......... panelsperpage=2)1.66 E F1(See also)69.336 576 Q F0
+(........... pageheight, page).83 E(width)-.25 E F1(Name)69.336 624 Q F0
+(.............. pedstyle)1.95 E F1(Description)69.336 636 Q F0(..... Sp\
+eci\214es whether to display piano pedal marks with lines or with the w)
+A(ord "Ped" and "*".)-.1 E -.4(Wi)5 G(th the).4 E
+("pedstar" style, a "bounce" of the pedal is sho)138.476 648 Q
+(wn by a "* Ped" whereas with the "alt pedstar" style,)-.25 E
+(only a "Ped" is printed.)138.476 660 Q F1 -.92(Va)69.336 672 S(lue).92
+E F0(............... line, pedstar).36 E 2.5(,o)-.4 G 2.5(ra)-2.5 G
+(lt pedstar)-2.5 E F1(Default)69.336 684 Q F0(............ line).28 E F1
+(Context)69.336 696 Q F0(........... score, staf).56 E(f)-.25 E F1
+(Example)69.336 708 Q F0(......... pedstyle = pedstar)1.66 E EP
+%%Page: 118 124
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(18 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. printmultnum)1.95 E
+F1(Description)69.336 108 Q F0(..... If set to 'y' multirests are label\
+ed with the number of measures of rest the)A 2.5(yr)-.15 G
+(epresent; if set to 'n')-2.5 E(the)138.476 120 Q 2.5(ya)-.15 G(ren')
+-2.5 E 2.5(t. This)-.18 F -.1(wo)2.5 G(uld allo).1 E 2.5(wy)-.25 G
+(ou to print some other commentary in place of the number)-2.5 E 2.5(,p)
+-.4 G(rint it)-2.5 E(in a dif)138.476 132 Q(ferent style, etc.)-.25 E F1
+-.92(Va)69.336 144 S(lue).92 E F0(............... y or n).36 E F1
+(Default)69.336 156 Q F0(............ y).28 E F1(Context)69.336 168 Q F0
+(........... score, staf).56 E(f)-.25 E F1(Example)69.336 180 Q F0
+(......... printmultnum = n)1.66 E F1(Name)69.336 228 Q F0
+(.............. rehstyle)1.95 E F1(Description)69.336 240 Q F0(..... Sp\
+eci\214es whether to enclose rehearsal marks inside box, inside a circl\
+e, or just as plain te)A(xt.)-.15 E F1 -.92(Va)69.336 252 S(lue).92 E F0
+(............... box).36 E(ed, circled, or plain)-.15 E F1(Default)
+69.336 264 Q F0(............ box).28 E(ed)-.15 E F1(Context)69.336 276 Q
+F0(........... score, staf).56 E(f)-.25 E F1(Example)69.336 288 Q F0
+(......... rehstyle = circled)1.66 E F1(See also)69.336 300 Q F0
+(........... endingstyle).83 E F1(Name)69.336 348 Q F0
+(.............. release)1.95 E F1(Description)69.336 360 Q F0
+(..... Speci\214es ho)A 2.5(ws)-.25 G
+(oon \(in milliseconds\) before the full time v)-2.5 E
+(alue of note to release the note when gen-)-.25 E(erating MIDI output.)
+138.476 372 Q(This controls ho)5 E 2.5(wl)-.25 G -2.25 -.15(eg a)-2.5 H
+(to \(smooth\) the music is.).15 E 2.5(Av)5 G(alue of 0 will mak)-2.75 E
+2.5(ei)-.1 G(t)-2.5 E -.15(ve)138.476 384 S(ry le).15 E -.05(ga)-.15 G
+(to. The lar).05 E(ger the v)-.18 E(alue, the more detached notes will \
+be. This parameter speci\214es a maxi-)-.25 E
+(mum amount to shorten notes; a note will ne)138.476 396 Q -.15(ve)-.25
+G 2.5(rb).15 G 2.5(es)-2.5 G(hortened to less than 75% of its full v)
+-2.5 E 2.5(alue. re-)-.25 F
+(lease can be changed in the middle of a measure using a construct lik)
+138.476 408 Q 2.5(e<)-.1 G(<score release=50>> be-)-2.5 E
+(fore a note group.)138.476 420 Q F1 -.92(Va)69.336 432 S(lue).92 E F0
+(............... 0 to 500).36 E F1(Default)69.336 444 Q F0
+(............ 20).28 E F1(Context)69.336 456 Q F0
+(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E(It is possible to\
+ change this parameter in the middle of a measure, using << >>.)138.476
+468 Q F1(Example)69.336 480 Q F0(......... release = 40)1.66 E F1(Name)
+69.336 528 Q F0(.............. restcombine)1.95 E F1(Description)69.336
+540 Q F0(..... If the gi)A -.15(ve)-.25 G 2.5(nn).15 G
+(umber of measures of rest occur in a ro)-2.5 E 1.3 -.65(w, t)-.25 H(he)
+.65 E 2.5(yw)-.15 G(ill be replaced by a multirest.)-2.5 E(This pa-)5 E
+(rameter can be o)138.476 552 Q -.15(ve)-.15 G
+(rridden by the -c command line option.).15 E
+(See the description of the -c option for)5 E
+(more complete information on ho)138.476 564 Q 2.5(wt)-.25 G
+(he combining is done.)-2.5 E F1 -.92(Va)69.336 576 S(lue).92 E F0
+(............... 2 to 1000 or nothing).36 E F1(Default)69.336 588 Q F0
+(............ not set).28 E F1(Context)69.336 600 Q F0
+(........... score).56 E F1(Example)69.336 612 Q F0
+(......... restcombine = 5)1.66 E(restcombine =)138.476 624 Q
+(// turn of)10 E 2.5(fc)-.25 G(ombining)-2.5 E EP
+%%Page: 119 125
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(19 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. restsymmult)1.95 E
+F1(Description)69.336 108 Q F0(..... Multi-rests are normally dra)A
+(wn as a horizontal line on the middle line of the staf)-.15 E
+(f, with tw)-.25 E 2.5(ov)-.1 G(ertical)-2.65 E(lines at the end. But t\
+here is an alternate notation style that uses rest symbols \(whole, dou\
+ble whole,)138.476 120 Q
+(and quad whole\) when the number of measures is short.)138.476 132 Q
+(If this parameter is set to y)5 E 2.5(,t)-.65 G(hat alternate)-2.5 E
+(style will be used for multirests of eight measures or less.)138.476
+144 Q F1 -.92(Va)69.336 156 S(lue).92 E F0(............... y or n).36 E
+F1(Default)69.336 168 Q F0(............ n).28 E F1(Context)69.336 180 Q
+F0(........... score, staf).56 E(f)-.25 E F1(Example)69.336 192 Q F0
+(......... restsymmult = y)1.66 E F1(See also)69.336 204 Q F0
+(........... printmultnum).83 E F1(Name)69.336 252 Q F0
+(.............. rightmar)1.95 E(gin)-.18 E F1(Description)69.336 264 Q
+F0(..... sets the amount of white space mar)A
+(gin to put at the right side of each page.)-.18 E
+(It is speci\214ed in inches)5 E(if the units parameter is set to inche\
+s, or in centimeters if the units parameter is set to cm.)138.476 276 Q
+(This pa-)5 E(rameter can only be speci\214ed before an)138.476 288 Q
+2.5(ym)-.15 G(usic or block input.)-2.5 E(Mar)5 E(gins are unaf)-.18 E
+(fected by the)-.25 E("scale" parameter)138.476 300 Q(.)-.55 E F1 -.92
+(Va)69.336 312 S(lue).92 E F0(............... 0.0 to page).36 E
+(width minus 0.5 inches)-.25 E F1(Default)69.336 324 Q F0
+(............ 0.5 inches).28 E F1(Context)69.336 336 Q F0
+(........... score).56 E F1(Example)69.336 348 Q F0(......... rightmar)
+1.66 E(gin = 0.3)-.18 E F1(See also)69.336 360 Q F0
+(........... bottommar).83 E(gin, leftmar)-.18 E(gin, topmar)-.18 E
+(gin, page)-.18 E(width, units)-.25 E F1(Name)69.336 408 Q F0
+(.............. scale)1.95 E F1(Description)69.336 420 Q F0
+(..... Scale the printed output by the speci\214ed f)A(actor)-.1 E 2.5
+(.F)-.55 G(or e)-2.65 E(xample, scale=2 prints e)-.15 E -.15(ve)-.25 G
+(rything twice as).15 E(lar)138.476 432 Q
+(ge as normal, while scale=0.5 prints e)-.18 E -.15(ve)-.25 G
+(rything at half size.).15 E(This parameter can only be speci-)5 E
+(\214ed before an)138.476 444 Q 2.5(ym)-.15 G(usic or block input.)-2.5
+E F1 -.92(Va)69.336 456 S(lue).92 E F0
+(............... A number between 0.1 and 10.0).36 E F1(Default)69.336
+468 Q F0(............ 1.0).28 E F1(Context)69.336 480 Q F0
+(........... score).56 E F1(Example)69.336 492 Q F0
+(......... scale=0.95)1.66 E F1(See also)69.336 504 Q F0
+(........... packf).83 E(act, pack)-.1 E -.15(ex)-.1 G(p, staf).15 E
+(fscale)-.25 E EP
+%%Page: 120 126
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(20 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. scorepad)1.95 E F1
+(Description)69.336 108 Q F0
+(..... sets the amount of padding \(white space\) to lea)A .3 -.15(ve b)
+-.2 H(etween scores, accounting for all the things that).15 E
+(protrude from both scores.)138.476 120 Q(Either a single number)5 E 2.5
+(,g)-.4 G -.25(iv)-2.5 G(ing a minimum amount, or tw).25 E 2.5(on)-.1 G
+(umbers,)-2.5 E(gi)138.476 132 Q
+(ving a minimum and maximum, can be speci\214ed. The)-.25 E 2.5(ya)-.15
+G(re speci\214ed in stepsizes.)-2.5 E(If only the)5 E
+(minimum is speci\214ed, and it is lar)138.476 144 Q(ger than the def)
+-.18 E(ault maximum of 2, the maximum will be adjust-)-.1 E
+(ed to equal the minimum.)138.476 156 Q
+(Depending on the setting of the scoresep parameter)5 E 2.5(,t)-.4 G
+(he maximum may)-2.5 E(be e)138.476 168 Q
+(xceeded; see the description of scoresep for ho)-.15 E 2.5(wt)-.25 G
+(hese parameters interact to determine the)-2.5 E
+(placement of the scores.)138.476 180 Q(If a ne)5 E -.05(ga)-.15 G(ti)
+.05 E .3 -.15(ve v)-.25 H(alue is speci\214ed for scorepad, some o)-.1 E
+-.15(ve)-.15 G(rlap may occur).15 E(,)-.4 E
+(\(subject to the interaction with scoresep\).)138.476 192 Q
+(Specifying a ne)5 E -.05(ga)-.15 G(ti).05 E .3 -.15(ve v)-.25 H
+(alue may be particularly useful)-.1 E(when things protrude do)138.476
+204 Q(wnw)-.25 E(ard from the top score and upw)-.1 E
+(ard from the bottom score, b)-.1 E(ut at dif-)-.2 E
+(ferent places horizontally)138.476 216 Q 2.5(,s)-.65 G(uch that it is \
+actually safe to put the scores closer together without colli-)-2.5 E
+(sion, e)138.476 228 Q -.15(ve)-.25 G 2.5(nt).15 G(hough Mup can')-2.5 E
+2.5(tt)-.18 G(ell that it is safe.)-2.5 E(Note, ho)5 E(we)-.25 E -.15
+(ve)-.25 G .8 -.4(r, t).15 H(hat this o).4 E -.15(ve)-.15 G(rrides Mup')
+.15 E 2.5(sp)-.55 G(rotection)-2.5 E(ag)138.476 240 Q
+(ainst real collisions, so this must be used with care to a)-.05 E -.2
+(vo)-.2 G(id undesired o).2 E -.15(ve)-.15 G(rlaps.).15 E F1 -.92(Va)
+69.336 252 S(lue).92 E F0(............... one or tw).36 E 2.5(ow)-.1 G
+(hole numbers, in the range from ne)-2.5 E -.05(ga)-.15 G(ti).05 E .3
+-.15(ve t)-.25 H(he height of the page and the height of a).15 E
+(page, in stepsizes.)138.476 264 Q(If there are tw)5 E 2.5(on)-.1 G
+(umbers, the)-2.5 E 2.5(ya)-.15 G
+(re separated by a comma, and the second must)-2.5 E
+(be greater than or equal to the \214rst.)138.476 276 Q F1(Default)
+69.336 288 Q F0(............ 2,2).28 E F1(Context)69.336 300 Q F0
+(........... score).56 E F1(Example)69.336 312 Q F0
+(......... scorepad = 5)1.66 E(scorepad = -1)138.476 324 Q
+(scorepad = 3,10)138.476 336 Q F1(See also)69.336 348 Q F0
+(........... scoresep, staf).83 E(fpad, staf)-.25 E(fsep)-.25 E F1(Name)
+69.336 396 Q F0(.............. scoresep)1.95 E F1(Description)69.336 408
+Q F0(..... sets ho)A 2.5(wm)-.25 G(uch space to lea)-2.5 E .3 -.15(ve b)
+-.2 H(etween scores; i.e., between the bottom line of the bottom staf)
+.15 E 2.5(fo)-.25 G(f)-2.5 E(one score and the top line of the top staf)
+138.476 420 Q 2.5(fo)-.25 G 2.5(ft)-2.5 G(he follo)-2.5 E
+(wing score. Either a single number)-.25 E 2.5(,g)-.4 G -.25(iv)-2.5 G
+(ing a).25 E(minimum amount, or tw)138.476 432 Q 2.5(on)-.1 G
+(umbers, gi)-2.5 E(ving a minimum and maximum, can be speci\214ed. The)
+-.25 E 2.5(ya)-.15 G(re)-2.5 E(speci\214ed in stepsizes.)138.476 444 Q
+(If only the minimum is speci\214ed, and it is lar)5 E(ger than the def)
+-.18 E(ault maximum)-.1 E
+(of 20, the maximum will be adjusted to equal the minimum.)138.476 456 Q
+(Depending on the setting of the)5 E(scorepad parameter)138.476 468 Q
+2.5(,t)-.4 G(he maximum may be e)-2.5 E 2.5(xceeded. The)-.15 F
+(parameters interact as follo)2.5 E(ws in deter)-.25 E(-)-.2 E
+(mining the layout of a page: As man)138.476 480 Q 2.5(ys)-.15 G
+(cores are allocated to the page as will \214t \(or until a "ne)-2.5 E
+(w-)-.25 E(page" command is encountered\).)138.476 492 Q(Initially)5 E
+2.5(,t)-.65 G(he)-2.5 E 2.5(ya)-.15 G(re pack)-2.5 E
+(ed together as tightly as the)-.1 E 2.5(yc)-.15 G(an be with-)-2.5 E
+(out violating the minimum v)138.476 504 Q
+(alues of scorepad and scoresep between an)-.25 E 2.5(yn)-.15 G
+(eighboring scores.)-2.5 E(Ne)5 E(xt,)-.15 E(if there is e)138.476 516 Q
+(xtra space a)-.15 E -.25(va)-.2 G(ilable at the bottom of the page, th\
+e scores are spread out, increasing the).25 E
+(white space between them, b)138.476 528 Q(ut not increasing an)-.2 E
+2.5(yb)-.15 G -.15(ey)-2.5 G(ond the maximum scorepad v).15 E 2.5
+(alue. \(Some)-.25 F(may ho)138.476 540 Q(we)-.25 E -.15(ve)-.25 G 2.5
+(ra).15 G(lready be be)-2.5 E(yond the maximum scorepad v)-.15 E
+(alue, because the minimum scoresep v)-.25 E(al-)-.25 E
+(ue required it.\))138.476 552 Q(This spreading is done without re)5 E
+-.05(ga)-.15 G(rd for the maximum scoresep v).05 E 2.5(alue. If)-.25 F
+(an)2.5 E 2.5(yo)-.15 G(f)-2.5 E(the inter)138.476 564 Q(-score g)-.2 E
+(aps start narro)-.05 E
+(wer than others \(because of the minimum scoresep\), the)-.25 E 2.5(ya)
+-.15 G(re in-)-2.5 E(creased \214rst, in an attempt to e)138.476 576 Q
+-.15(ve)-.25 G 2.5(no).15 G(ut the dif)-2.5 E 2.5(ferences. If)-.25 F
+(the maximum scorepad v)2.5 E(alue is reached)-.25 E(or e)138.476 588 Q
+(xceeded between all the scores, and there is still e)-.15 E
+(xtra space a)-.15 E -.25(va)-.2 G(ilable at the bottom of the page,).25
+E(then the scores are spread out some more, increasing the white space \
+between them, this time ig-)138.476 600 Q(noring the scorepad v)138.476
+612 Q(alues, b)-.25 E(ut not increasing an)-.2 E 2.5(yb)-.15 G -.15(ey)
+-2.5 G(ond the maximum scoresep v).15 E 2.5(alue. \(Some)-.25 F(may ho)
+138.476 624 Q(we)-.25 E -.15(ve)-.25 G 2.5(ra).15 G(lready be be)-2.5 E
+(yond the maximum scoresep v)-.15 E(alue, because of the pre)-.25 E
+(vious steps.\))-.25 E(If)5 E
+(still not all the space is used up, it remains as e)138.476 636 Q
+(xtra space at the bottom of the page.)-.15 E F1 -.92(Va)69.336 648 S
+(lue).92 E F0(............... one or tw).36 E 2.5(ow)-.1 G(hole numbers\
+, in the range from 6 to the height of the page in stepsizes.)-2.5 E
+(If there are)5 E(tw)138.476 660 Q 2.5(on)-.1 G(umbers, the)-2.5 E 2.5
+(ya)-.15 G(re separated by a comma, and the second must be greater than\
+ or equal to the)-2.5 E(\214rst.)138.476 672 Q F1(Default)69.336 684 Q
+F0(............ 12,20).28 E F1(Context)69.336 696 Q F0
+(........... score).56 E F1(Examples)69.336 708 Q F0
+(........ scoresep = 25).27 E(scoresep = 9,15)138.476 720 Q F1(See also)
+69.336 732 Q F0(........... scorepad, staf).83 E(fpad, staf)-.25 E(fsep)
+-.25 E EP
+%%Page: 121 127
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(21 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. size)1.95 E F1
+(Description)69.336 108 Q F0
+(..... speci\214es what point size to use for te)A
+(xt in print, title, left, right, and center statements, and "with")-.15
+E(lists \(i.e., strings that are associated with a particular chord\).)
+138.476 120 Q F1 -.92(Va)69.336 132 S(lue).92 E F0
+(............... a number from 1 to 100 inclusi).36 E -.15(ve)-.25 G F1
+(Default)69.336 144 Q F0(............ 12).28 E F1(Context)69.336 156 Q
+F0(........... score, staf).56 E(f, header)-.25 E 2.5(,f)-.4 G(ooter)
+-2.5 E 2.5(,h)-.4 G(eader2, footer2, top, bottom, top2, bottom2, block)
+-2.5 E F1(Example)69.336 168 Q F0(......... size = 9)1.66 E F1(See also)
+69.336 180 Q F0(........... font, fontf).83 E(amily)-.1 E 2.5(,l)-.65 G
+(yricssize)-2.5 E F1(Name)69.336 228 Q F0(.............. staf)1.95 E
+(\215ines)-.25 E F1(Description)69.336 240 Q F0(..... speci\214es ho)A
+2.5(wm)-.25 G(an)-2.5 E 2.5(yl)-.15 G(ines to dra)-2.5 E 2.5(wf)-.15 G
+(or the staf)-2.5 E(f. Normally)-.25 E 2.5(,t)-.65 G
+(here are 5 lines per staf)-2.5 E(f, b)-.25 E(ut a single line)-.2 E
+(staf)138.476 252 Q 2.5(fi)-.25 G 2.5(ss)-2.5 G
+(ometimes used for percussion, and tablature staf)-2.5 E(fs for v)-.25 E
+(arious instruments may ha)-.25 E .3 -.15(ve d)-.2 H(if).15 E(fer)-.25 E
+(-)-.2 E(ent numbers of lines.)138.476 264 Q
+(Setting this parameter to 1 will produce a single line staf)5 E 2.5
+(f. The)-.25 F(number of)2.5 E(lines can be follo)138.476 276 Q
+(wed by "n" to indicate that clef and k)-.25 E .3 -.15(ey s)-.1 H
+(ignature are not to be printed. The "n" al-).15 E
+(so implies that accidentals are to be ignored and that notes are ne)
+138.476 288 Q -.15(ve)-.25 G 2.5(rt).15 G 2.5(ob)-2.5 G 2.5(et)-2.5 G
+2.5(ransposed. If)-2.5 F(the num-)2.5 E
+(ber of lines is 1, the clef and k)138.476 300 Q .3 -.15(ey s)-.1 H
+(ignature are ne).15 E -.15(ve)-.25 G 2.5(rp).15 G(rinted, re)-2.5 E
+-.05(ga)-.15 G(rdless of whether or not you add).05 E(the "n," so the "\
+n" is really only meaningful when used with 5. When staf)138.476 312 Q
+(\215ines=1, you can only)-.25 E(ha)138.476 324 Q .3 -.15(ve o)-.2 H
+(ne note per chord, and the pitch of that note is irrele).15 E -.25(va)
+-.25 G(nt, e).25 E(xcept for MIDI output.)-.15 E(Alternate-)5 E(ly)
+138.476 336 Q 2.5(,r)-.65 G(ather than specifying "n" you can specify "\
+drum" which means to use the drum clef \(also some-)-2.5 E
+(times called the "neutral" clef\).)138.476 348 Q -.4(Wi)5 G
+(th the drum clef, no k).4 E .3 -.15(ey s)-.1 H
+(ignature is printed, accidentals are ig-).15 E(nored, and notes are ne)
+138.476 360 Q -.15(ve)-.25 G 2.5(rt).15 G(ransposed. The v)-2.5 E
+(alue used for the clef parameter is used to determine)-.25 E
+(the pitch for placement of notes in this case, b)138.476 372 Q
+(ut the drum clef of tw)-.2 E 2.5(ov)-.1 G(ertical lines is printed.)
+-2.65 E -.15(Fo)138.476 396 S 2.5(rat).15 G(ablature staf)-2.5 E
+(f, rather than specifying a number of staf)-.25 E 2.5(fl)-.25 G
+(ines as the v)-2.5 E(alue, the k)-.25 E -.15(ey)-.1 G -.1(wo).15 G
+(rd "tab" is).1 E(used, optionally follo)138.476 408 Q(wed by a list of\
+ strings in parentheses. The strings are listed in order from the)-.25 E
+(top line of the tablature staf)138.476 420 Q 2.5(ft)-.25 G 2.5(ot)-2.5
+G(he bottom.)-2.5 E
+(Each item in the list has at least a string pitch, which is)5 E 2.5(al)
+138.476 432 S(etter from a to g, optionally follo)-2.5 E
+(wed by # or &. If there is more than one string ha)-.25 E
+(ving the same)-.2 E(letter/accidental, the)138.476 444 Q 2.5(ya)-.15 G
+(re distinguished by adding one or more single quote marks \("ticks"\).\
+ An oc-)-2.5 E(ta)138.476 456 Q .3 -.15(ve n)-.2 H
+(umber can also be speci\214ed.).15 E
+(If the list of strings is omitted, standard guitar strings are used,)5
+E(which is tab\( e5 b4 g4 d4 a3 e'3 \).)138.476 468 Q -.8(Ta)5 G
+(blature can only be speci\214ed in staf).8 E 2.5(fc)-.25 G(onte)-2.5 E
+(xt, not score or)-.15 E -.2(vo)138.476 480 S
+(ice, and when a tablature staf).2 E 2.5(fi)-.25 G 2.5(ss)-2.5 G
+(peci\214ed, the staf)-2.5 E 2.5(fa)-.25 G(bo)-2.5 E .3 -.15(ve i)-.15 H
+2.5(tb).15 G(ecomes a "tabnote" staf)-2.5 E 2.5(fw)-.25 G(hich is a)-2.5
+E(normal 5-line staf)138.476 492 Q 2.5(fc)-.25 G(ontaining music deri)
+-2.5 E -.15(ve)-.25 G 2.5(df).15 G(rom the tablature staf)-2.5 E(f.)-.25
+E F1 -.92(Va)69.336 504 S(lue).92 E F0
+(............... 1 or 5, optionally follo).36 E
+(wed by "n" or "drum"; or for tablature staf)-.25 E(f, the k)-.25 E -.15
+(ey)-.1 G -.1(wo).15 G(rd "tab" optionally fol-).1 E(lo)138.476 516 Q
+(wed by a list of strings, in parentheses.)-.25 E(Setting the staf)5 E
+(\215ines parameter will also reinitialize other)-.25 E(parameters: k)
+138.476 528 Q -.15(ey)-.1 G 2.5(,t)-.5 G
+(ranspose, addtranspose, clef, beamstyle, and defoct.)-2.5 E F1(Default)
+69.336 540 Q F0(............ 5).28 E F1(Context)69.336 552 Q F0
+(........... score, staf).56 E(f)-.25 E F1(Examples)69.336 564 Q F0
+(........ staf).27 E(\215ines=1)-.25 E(staf)138.476 576 Q(\215ines=5n)
+-.25 E(staf)138.476 588 Q(\215ines = tab)-.25 E
+(// standard guitar tablature staf)3.22 E(f)-.25 E(staf)138.476 600 Q
+(\215ines = tab \( g3 d3 a2 e2 \))-.25 E(// standard bass guitar)5 E
+(staf)138.476 612 Q(\215ines = tab \(d# g b3 g'3\))-.25 E F1(See also)
+69.336 624 Q F0(........... clef, k).83 E -.15(ey)-.1 G 2.5(,t)-.5 G
+(ranspose, addtranspose)-2.5 E EP
+%%Page: 122 128
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(22 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. staf)1.95 E(fpad)
+-.25 E F1(Description)69.336 108 Q F0
+(..... sets the minimum amount of space to lea)A .3 -.15(ve b)-.2 H
+(etween staf).15 E(fs, accounting for all the things that protrude)-.25
+E(from both staf)138.476 120 Q 2.5(fs. If)-.25 F 2.5(an)2.5 G -2.25 -.15
+(eg a)-2.5 H(ti).15 E .3 -.15(ve v)-.25 H(alue is speci\214ed, some o)
+-.1 E -.15(ve)-.15 G(rlap may occur).15 E 2.5(,a)-.4 G
+(lthough it will still be)-2.5 E(limited by the v)138.476 132 Q
+(alue of the staf)-.25 E(fsep parameter)-.25 E 5(.S)-.55 G
+(pecifying a ne)-5 E -.05(ga)-.15 G(ti).05 E .3 -.15(ve v)-.25 H
+(alue may be particularly use-)-.1 E(ful when things protrude do)138.476
+144 Q(wnw)-.25 E(ard from the top staf)-.1 E 2.5(fa)-.25 G(nd upw)-2.5 E
+(ard from the bottom staf)-.1 E(f, b)-.25 E(ut at dif-)-.2 E
+(ferent places horizontally)138.476 156 Q 2.5(,s)-.65 G
+(uch that it is actually safe to put the staf)-2.5 E
+(fs closer together without colli-)-.25 E(sion, e)138.476 168 Q -.15(ve)
+-.25 G 2.5(nt).15 G(hough Mup can')-2.5 E 2.5(tt)-.18 G
+(ell that it is safe.)-2.5 E(Note, ho)5 E(we)-.25 E -.15(ve)-.25 G .8
+-.4(r, t).15 H(hat this o).4 E -.15(ve)-.15 G(rrides Mup').15 E 2.5(sp)
+-.55 G(rotection)-2.5 E(ag)138.476 180 Q
+(ainst real collisions, so this must be used with care to a)-.05 E -.2
+(vo)-.2 G(id undesired o).2 E -.15(ve)-.15 G(rlaps.).15 E F1 -.92(Va)
+69.336 192 S(lue).92 E F0(............... a whole number between ne).36
+E -.05(ga)-.15 G(ti).05 E .3 -.15(ve t)-.25 H
+(he height of the page and the height of a page, in stepsizes.).15 E F1
+(Default)69.336 204 Q F0(............ 0).28 E F1(Context)69.336 216 Q F0
+(........... score, staf).56 E(f)-.25 E F1(Example)69.336 228 Q F0
+(......... staf)1.66 E(fpad = -2)-.25 E F1(See also)69.336 240 Q F0
+(........... scorepad, scoresep, staf).83 E(fsep)-.25 E F1(Name)69.336
+288 Q F0(.............. staf)1.95 E(fs)-.25 E F1(Description)69.336 300
+Q F0(..... speci\214es the number of staf)A
+(fs. It is possible that not all of these staf)-.25 E
+(fs will be printed \(see the "visi-)-.25 E(ble" parameter belo)138.476
+312 Q 2.5(wa)-.25 G(nd the -s command line ar)-2.5 E 2.5
+(gument\). Changing)-.18 F(the number of staf)2.5 E(fs causes)-.25 E
+(all parameters that had been set in staf)138.476 324 Q 2.5(fa)-.25 G
+(nd v)-2.5 E(oice conte)-.2 E(xt to be set back to their def)-.15 E
+(ault v)-.1 E 2.5(alues. It)-.25 F(is)2.5 E
+(usually preferable to only set the staf)138.476 336 Q 2.5(fp)-.25 G
+(arameter once at the be)-2.5 E(ginning of a song, and use the "visi-)
+-.15 E(ble" parameter when you w)138.476 348 Q(ant to change which staf)
+-.1 E(fs are actually printed, rather than changing the)-.25 E
+(number of staf)138.476 360 Q(fs.)-.25 E F1 -.92(Va)69.336 372 S(lue).92
+E F0(............... a number between 1 and 40 inclusi).36 E -.15(ve)
+-.25 G(.).15 E F1(Default)69.336 384 Q F0(............ 1).28 E F1
+(Context)69.336 396 Q F0(........... score).56 E F1(Example)69.336 408 Q
+F0(......... staf)1.66 E(fs = 12)-.25 E F1(See also)69.336 420 Q F0
+(........... visible).83 E F1(Name)69.336 468 Q F0(.............. staf)
+1.95 E(fscale)-.25 E F1(Description)69.336 480 Q F0
+(..... Speci\214es ho)A 2.5(wt)-.25 G 2.5(os)-2.5 G
+(cale the size of a staf)-2.5 E 2.5(fr)-.25 G(elati)-2.5 E .3 -.15(ve t)
+-.25 H 2.5(ot).15 G(he size of other staf)-2.5 E(fs. A v)-.25 E
+(alue of 1.0 yields the)-.25 E(normal size, whereas 0.5 yields a staf)
+138.476 492 Q 2.5(ft)-.25 G
+(hat is half as high, and 2.0 one that is twice as high as nor)-2.5 E(-)
+-.2 E(mal, and so forth. This might be used, for e)138.476 504 Q
+(xample, for a piece written for tw)-.15 E 2.5(oi)-.1 G
+(nstruments, say pi-)-2.5 E(ano and violin, where you w)138.476 516 Q
+(ant the piano part to be written in normal size, b)-.1 E(ut w)-.2 E
+(ant to sho)-.1 E 2.5(wt)-.25 G(he vi-)-2.5 E
+(olin part in smaller size, such that while the pianist will ha)138.476
+528 Q .3 -.15(ve t)-.2 H(he violin part a).15 E -.25(va)-.2 G
+(ilable for reference,).25 E(it w)138.476 540 Q(on')-.1 E 2.5(tt)-.18 G
+(ak)-2.5 E 2.5(eu)-.1 G 2.5(pal)-2.5 G(ot of space.)-2.5 E
+(Another possible use is to set staf)5 E(fscale in score conte)-.25 E
+(xt, to mak)-.15 E 2.5(ea)-.1 G(ll)-2.5 E(staf)138.476 552 Q
+(f-related things a dif)-.25 E(ferent size, b)-.25 E(ut lea)-.2 E .3
+-.15(ve o)-.2 H(ther things, lik).15 E 2.5(eh)-.1 G
+(eaders and footers, unaf)-2.5 E(fected.)-.25 E F1 -.92(Va)69.336 564 S
+(lue).92 E F0(............... 0.1 to 10.0).36 E F1(Default)69.336 576 Q
+F0(............ 1.0).28 E F1(Context)69.336 588 Q F0
+(........... score, staf).56 E(f)-.25 E F1(Example)69.336 600 Q F0
+(......... staf)1.66 E(fscale=0.75)-.25 E F1(See also)69.336 612 Q F0
+(........... scale).83 E EP
+%%Page: 123 129
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(23 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. staf)1.95 E(fsep)
+-.25 E F1(Description)69.336 108 Q F0
+(..... speci\214es the minimum amount of space to lea)A .3 -.15(ve b)-.2
+H(etween an).15 E 2.5(yt)-.15 G .2 -.1(wo a)-2.5 H(djacent staf).1 E
+(fs within the same)-.25 E(score. It is speci\214ed in stepsizes, and i\
+s measured from the bottom line of the staf)138.476 120 Q 2.5(fa)-.25 G
+(bo)-2.5 E .3 -.15(ve t)-.15 H 2.5(ot).15 G(he top)-2.5 E
+(line of the staf)138.476 132 Q 2.5(fb)-.25 G(elo)-2.5 E 1.3 -.65(w. S)
+-.25 H(taf).65 E
+(fs will be spread wider than this minimum if necessary to pre)-.25 E
+-.15(ve)-.25 G(nt things).15 E(from colliding.)138.476 144 Q F1 -.92(Va)
+69.336 156 S(lue).92 E F0
+(............... a number from 6 to the height of the page in stepsizes)
+.36 E F1(Default)69.336 168 Q F0(............ 10).28 E F1(Context)69.336
+180 Q F0(........... score, staf).56 E(f)-.25 E F1(Example)69.336 192 Q
+F0(......... staf)1.66 E(fsep = 14)-.25 E F1(See also)69.336 204 Q F0
+(........... scorepad, scoresep, staf).83 E(fpad)-.25 E F1(Name)69.336
+252 Q F0(.............. stemlen)1.95 E F1(Description)69.336 264 Q F0
+(..... Speci\214es ho)A 2.5(wl)-.25 G
+(ong stems should be, in stepsizes.)-2.5 E
+(This is for normal-sized chords; grace or cue size)5 E
+(chords will gets stems that are 5/7 of this length.)138.476 276 Q
+(This length can be o)5 E -.15(ve)-.15 G(rridden on speci\214c chords)
+.15 E(using the len attrib)138.476 288 Q(ute in back)-.2 E
+(ets before the chord.)-.1 E F1 -.92(Va)69.336 300 S(lue).92 E F0
+(............... 0.0 to 100.0).36 E F1(Default)69.336 312 Q F0
+(............ 7.0).28 E F1(Context)69.336 324 Q F0
+(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E F1(Example)69.336
+336 Q F0(......... stemlen = 0)1.66 E(// to mak)15.19 E 2.5(ea)-.1 G
+(ll notes stemless)-2.5 E F1(Name)69.336 384 Q F0
+(.............. stemshorten)1.95 E F1(Description)69.336 396 Q F0
+(..... On beamed chords, Mup will sometimes shorten stems slightly)A 5
+(.T)-.65 G(his parameter lets you control the)-5 E
+(maximum amount of shortening that will e)138.476 408 Q -.15(ve)-.25 G
+2.5(rb).15 G 2.5(ed)-2.5 G(one. It is speci\214ed in stepsizes.)-2.5 E
+F1 -.92(Va)69.336 420 S(lue).92 E F0(............... 0.0 to 2.0).36 E F1
+(Default)69.336 432 Q F0(............ 1.0).28 E F1(Context)69.336 444 Q
+F0(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E F1(Example)
+69.336 456 Q F0(......... stemshorten = 0)1.66 E(// ne)12.5 E -.15(ve)
+-.25 G 2.5(rs).15 G(horten an)-2.5 E 2.5(ys)-.15 G(tems)-2.5 E EP
+%%Page: 124 130
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(24 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. swingunit)1.95 E F1
+(Description)69.336 108 Q F0(..... This parameter only af)A
+(fects MIDI output.)-.25 E
+(Some styles of music are often written in "swing time,")5 E
+(meaning the players are e)138.476 120 Q(xpected to play pairs of notes\
+ with the \214rst twice as long as the second,)-.15 E -2.15 -.25(ev e)
+138.476 132 T 2.5(nt).25 G(hough the)-2.5 E 2.5(ya)-.15 G
+(re written as if the)-2.5 E 2.5(yw)-.15 G
+(ere the same duration, or as if the \214rst w)-2.5 E(as three times as)
+-.1 E(long as the second.)138.476 144 Q(The most common e)5 E(xample w)
+-.15 E(ould be where the written notation sho)-.1 E(ws tw)-.25 E(o)-.1 E
+(eighth notes lik)138.476 156 Q 2.5(e8)-.1 G(;; or a dotted rh)-2.5 E
+(ythm lik)-.05 E 2.5(e8)-.1 G(.;16; b)-2.5 E(ut the musician "kno)-.2 E
+(ws" that the composer real-)-.25 E(ly intended it to be played as if i\
+t were a triplet {4;8;}3; This parameter adjusts the Mup MIDI out-)
+138.476 168 Q(put to follo)138.476 180 Q 2.5(wt)-.25 G
+(his performance con)-2.5 E -.15(ve)-.4 G 2.5(ntion. If).15 F
+(this parameter is set, each measure is di)2.5 E(vided into)-.25 E(se)
+138.476 192 Q(gments of durations of "swingunit," starting at the be)
+-.15 E(ginning. \(Usually the time signature di)-.15 E(vided)-.25 E
+(by swingunit will be an inte)138.476 204 Q(ger)-.15 E 2.5(,b)-.4 G
+(ut if not, the last piece will be shorter)-2.7 E 2.5(.\) Then)-.55 F
+(within each se)2.5 E(g-)-.15 E
+(ment, the time where one group ends and the ne)138.476 216 Q
+(xt group starts will be altered in either of these tw)-.15 E(o)-.1 E
+(circumstances: \(1\) The current boundary time is halfw)138.476 228 Q
+(ay into a swingunit, and each group is at)-.1 E(least half a swingunit\
+ long, or \(2\) The current boundary time is 3/4 of the w)138.476 240 Q
+(ay into a swingunit, and)-.1 E(the \214rst group is at least 3/4 of a \
+swingunit long, and the second group is at least 1/4 of a swingunit)
+138.476 252 Q 2.5(long. In)138.476 264 R(both of these cases, the durat\
+ions are altered so that the meeting point is 2/3 of the w)2.5 E(ay in-)
+-.1 E(to the swingunit.)138.476 276 Q F1 -.92(Va)69.336 288 S(lue).92 E
+F0(............... A time v).36 E(alue, lik)-.25 E 2.5(e2)-.1 G 2.5(,4)
+-2.5 G 2.5(,o)-2.5 G 2.5(r8)-2.5 G 2.5(,o)-2.5 G 2.5(rn)-2.5 G
+(ot set to an)-2.5 E 2.5(ything. It)-.15 F(can be a dotted v)2.5 E
+(alue lik)-.25 E 2.5(e2)-.1 G 2.5(.o)-2.5 G 2.5(r1)-2.5 G(6.. although)
+-2.5 E(dotted v)138.476 300 Q(alues are rarely lik)-.25 E
+(ely to be useful.)-.1 E(It can e)5 E -.15(ve)-.25 G 2.5(nb).15 G 2.5
+(eat)-2.5 G(ime e)-2.5 E(xpression lik)-.15 E 2.5(e2)-.1 G
+(.-32 although that)-2.5 E(is e)138.476 312 Q -.15(ve)-.25 G 2.5(nl).15
+G(ess lik)-2.5 E(ely to be useful.)-.1 E F1(Default)69.336 324 Q F0
+(............ not set).28 E F1(Context)69.336 336 Q F0
+(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E F1(Example)69.336
+348 Q F0(......... swingunit = 4)1.66 E(swingunit =)138.476 360 Q
+(// turn of)12.5 E 2.5(fs)-.25 G(wing)-2.5 E F1(See also)69.336 372 Q F0
+(........... timeunit).83 E F1(Name)69.336 420 Q F0
+(.............. sylposition)1.95 E F1(Description)69.336 432 Q F0
+(..... A | can be used in lyrics at the be)A
+(ginning of a syllable \(after an)-.15 E(ything in angle brack)-.15 E
+(ets\) to indicate)-.1 E(syllable alignment.)138.476 444 Q(This will o)5
+E -.15(ve)-.15 G(rride the lyricsalign parameter).15 E 2.5(,a)-.4 G
+(nd may be useful for aligning)-2.5 E -.15(ve)138.476 456 S
+(rse numbers or to mak).15 E 2.5(es)-.1 G(yllables at the be)-2.5 E
+(ginning of poetic lines line up.)-.15 E(If the | is not preceded)5 E
+(by a number)138.476 468 Q 2.5(,t)-.4 G
+(he sylposition parameter speci\214es the def)-2.5 E(ault alignment v)
+-.1 E(alue to use. It is the number)-.25 E(of points \(1 point is 1/72 \
+of an inch\) from the horizontal "middle" of the chord to place the lef\
+t)138.476 480 Q(edge of the syllable. Ne)138.476 492 Q -.05(ga)-.15 G
+(ti).05 E .3 -.15(ve v)-.25 H
+(alues are to the left of the middle, positi)-.1 E .3 -.15(ve t)-.25 H
+2.5(ot).15 G(he right, so this v)-2.5 E(alue)-.25 E(is usually ne)
+138.476 504 Q -.05(ga)-.15 G(ti).05 E -.15(ve)-.25 G(.).15 E F1 -.92(Va)
+69.336 516 S(lue).92 E F0(............... -100 to 100).36 E F1(Default)
+69.336 528 Q F0(............ -5).28 E F1(Context)69.336 540 Q F0
+(........... score, staf).56 E(f)-.25 E F1(Example)69.336 552 Q F0
+(......... sylposition = -4)1.66 E F1(See also)69.336 564 Q F0
+(........... lyricsalign).83 E F1(Name)69.336 612 Q F0
+(.............. tabwhitebox)1.95 E F1(Description)69.336 624 Q F0(.....\
+ says whether or not to put a small white box behind each fret number o\
+n tablature staf)A 2.5(fs. This)-.25 F(may)2.5 E(mak)138.476 636 Q 2.5
+(et)-.1 G(he music a little easier to read, since the staf)-2.5 E 2.5
+(fl)-.25 G(ines w)-2.5 E(on')-.1 E 2.5(tb)-.18 G 2.5(eg)-2.5 G
+(oing through the middle of the)-2.5 E(fret numbers.)138.476 648 Q F1
+-.92(Va)69.336 660 S(lue).92 E F0(...............).36 E F1(y)2.5 E F0
+(or)2.5 E F1(n)2.5 E(Default)69.336 672 Q F0(............ n).28 E F1
+(Context)69.336 684 Q F0(........... score, staf).56 E(f, v)-.25 E(oice)
+-.2 E F1(Examples)69.336 696 Q F0(........ tabwhitebox = y).27 E F1
+(See also)69.336 708 Q F0(........... staf).83 E(\215ines)-.25 E EP
+%%Page: 125 131
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(25 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. time)1.95 E F1
+(Description)69.336 108 Q F0
+(..... sets the time signature. Music data for each measure is check)A
+(ed to ensure that the total time in the)-.1 E(measure for each v)
+138.476 120 Q(oice and v)-.2 E(erse adds up to e)-.15 E
+(xactly the time signature. Setting the time parameter)-.15 E(will also\
+ reinitialize the timeunit parameter and the beamstyle parameter to the\
+ir most recent v)138.476 132 Q(alues)-.25 E
+(for the same time signature \(which w)138.476 144 Q(ould be their def)
+-.1 E(ault v)-.1 E(alues if the)-.25 E 2.5(yh)-.15 G(ad ne)-2.5 E -.15
+(ve)-.25 G 2.5(rb).15 G(een e)-2.5 E(xplicitly)-.15 E
+(set for this time signature\).)138.476 156 Q F1 -.92(Va)69.336 168 S
+(lue).92 E F0(............... either a ratio of the form).36 E/F2 10
+/Times-Italic@0 SF(N/D)2.5 E F0(or the w)2.5 E
+(ord "cut" or "common." If the ratio form is used,)-.1 E F2(N)2.5 E F0
+(must be)2.5 E(between 1 and 99 inclusi)138.476 180 Q -.15(ve)-.25 G 2.5
+(,a).15 G(nd)-2.5 E F2(D)2.5 E F0(must be 1, 2, 4, 8, 16, 32, or 64.)2.5
+E(The numerator of the time sig-)5 E(nature can be the sum of se)138.476
+192 Q -.15(ve)-.25 G(ral numbers, as in 3+4/4 or 2+3+2/2. Y).15 E
+(ou can also ha)-1.1 E .3 -.15(ve s)-.2 H -2.15 -.25(ev e).15 H
+(ral frac-).25 E(tions added together)138.476 204 Q 2.5(,a)-.4 G 2.5(si)
+-2.5 G 2.5(n3)-2.5 G(/4 + 4/4. It is also possible to pro)-2.5 E
+(vide "alternating" time signatures,)-.15 E(where you list tw)138.476
+216 Q 2.5(o\()-.1 G(or more, although tw)-2.5 E 2.5(oi)-.1 G 2.5(st)-2.5
+G(ypical\) time signatures separated by white space.)-2.5 E
+(Each measure then uses the ne)138.476 228 Q
+(xt time signature in the list. F)-.15 E(or e)-.15 E
+(xample, for 3/4 4/4, the \214rst mea-)-.15 E(sure w)138.476 240 Q(ould\
+ be in 3/4 time, the second measure in 4/4, the third back in 3/4, the \
+fourth in 4/4, and so)-.1 E 2.5(forth. It)138.476 252 R
+(is possible to combine all the v)2.5 E(arious comple)-.25 E
+(xities, with things lik)-.15 E 2.5(e3)-.1 G(+4/8 + 2+3/4 4+3/4)-2.5 E
+(although that w)138.476 264 Q(ould be v)-.1 E(ery uncommon.)-.15 E
+(The time signature can optionally be follo)5 E(wed by the let-)-.25 E
+(ter n to specify that the time signature is not to be printed.)138.476
+276 Q(Or it can be follo)5 E(wed by the letter y)-.25 E(,)-.65 E
+(which causes alternating time signatures to be treated dif)138.476 288
+Q(ferently)-.25 E 5(.B)-.65 G 2.5(yd)-5 G(ef)-2.5 E
+(ault, the alternating signa-)-.1 E(ture are printed just once, as a li\
+st, and the performer has to remember that each subsequent mea-)138.476
+300 Q(sure has a dif)138.476 312 Q(ferent time signature.)-.25 E
+(Using y forces Mup to print the appropriate time signature on)5 E
+(each measure.)138.476 324 Q F1(Default)69.336 336 Q F0
+(............ 4/4).28 E F1(Context)69.336 348 Q F0(........... score).56
+E F1(Examples)69.336 360 Q F0(........ time = 6/8).27 E(time = cut)
+138.476 372 Q(time = 13/16n)138.476 384 Q(time = 2+3+4 / 8)138.476 396 Q
+(// additi)10 E .3 -.15(ve n)-.25 H(umerator).15 E(time = 3/4 + 4/4)
+138.476 408 Q(// fractions added together)10 E(time = 4/4 3/4)138.476
+420 Q(// alternating)15 E(time = 3/4 6/8 y)138.476 432 Q
+(// alternating, printing time sig on e)10 E -.15(ve)-.25 G(ry measure)
+.15 E F1(See also)69.336 444 Q F0(........... timeunit).83 E F1(Name)
+69.336 492 Q F0(.............. timeunit)1.95 E F1(Description)69.336 504
+Q F0(..... sets the def)A
+(ault time unit. If the \214rst note of a measure has no time v)-.1 E
+(alue speci\214ed, the v)-.25 E(alue of the)-.25 E
+(timeunit parameter will be used.)138.476 516 Q
+(If the time signature is changed, the timeunit parameter re)5 E -.15
+(ve)-.25 G(rts).15 E(back to its pre)138.476 528 Q(vious v)-.25 E
+(alue for that time signature, which def)-.25 E(aults to the v)-.1 E
+(alue of the denominator)-.25 E(\(bottom number\) of the ne)138.476 540
+Q 2.5(wt)-.25 G(ime signature.)-2.5 E F1 -.92(Va)69.336 552 S(lue).92 E
+F0(............... 1/4, 1/2, 1, 2, 4, 8, 16, 32, 64, 128, or 256 repres\
+enting quadruple whole, double whole, whole, half,).36 E(quarter)138.476
+564 Q 2.5(,e)-.4 G
+(ighth, sixteenth, thirty-second, sixty-fourth, 128th, or 256th, follo)
+-2.5 E(wed by zero or more)-.25 E(dots. Each dot adds 50% of the pre)
+138.476 576 Q(vious note or dot to the time.)-.25 E
+(It can also be a time e)5 E(xpression,)-.15 E(lik)138.476 588 Q 2.5(e2)
+-.1 G(+8 or 1-4+16.)-2.5 E(The time v)5 E
+(alue must be less than or equal to the time signature.)-.25 E
+(The timeunit)5 E -.25(va)138.476 600 S
+(lue can be reinitialized indirectly by setting the time parameter).25 E
+5(.S)-.55 G(etting the time parameter will)-5 E
+(set the timeunit to the v)138.476 612 Q
+(alue used most recently for that time signature.)-.25 E F1(Default)
+69.336 624 Q F0
+(............ The denominator \(bottom number\) of the time signature)
+.28 E F1(Context)69.336 636 Q F0(........... score, staf).56 E(f, v)-.25
+E(oice)-.2 E F1(Examples)69.336 648 Q F0(........ timeunit = 2).27 E
+(timeunit = 4.)138.476 660 Q(timeunit = 2 + 8)138.476 672 Q F1(See also)
+69.336 684 Q F0(........... swingunit, time).83 E EP
+%%Page: 126 132
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(26 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. topmar)1.95 E(gin)
+-.18 E F1(Description)69.336 108 Q F0
+(..... sets the amount of white space mar)A
+(gin to put at the top of each page.)-.18 E
+(It is speci\214ed in inches if the)5 E(units parameter is set to inche\
+s, or in centimeters if the units parameter is set to cm.)138.476 120 Q
+(This parameter)5 E(can only be speci\214ed before an)138.476 132 Q 2.5
+(ym)-.15 G(usic or block input.)-2.5 E(Mar)5 E(gins are unaf)-.18 E
+(fected by the "scale" pa-)-.25 E(rameter)138.476 144 Q(.)-.55 E F1 -.92
+(Va)69.336 156 S(lue).92 E F0
+(............... 0.0 to pageheight minus 0.5 inches).36 E F1(Default)
+69.336 168 Q F0(............ 0.5 inches).28 E F1(Context)69.336 180 Q F0
+(........... score).56 E F1(Example)69.336 192 Q F0(......... topmar)
+1.66 E(gin = 0.8)-.18 E F1(See also)69.336 204 Q F0
+(........... bottommar).83 E(gin, leftmar)-.18 E(gin, rightmar)-.18 E
+(gin, pageheight, units)-.18 E F1(Name)69.336 252 Q F0
+(.............. transpose)1.95 E F1(Description)69.336 264 Q F0
+(..... specify by what interv)A(al to transpose the music data.)-.25 E
+(The interv)5 E(al can be lar)-.25 E(ger than an octa)-.18 E -.15(ve)-.2
+G 2.5(,b).15 G(ut)-2.7 E(must be a v)138.476 276 Q(alid interv)-.25 E(a\
+l \(e.g., there is no such thing as a perfect 6th\). It is an error to \
+specify a trans-)-.25 E(position v)138.476 288 Q(alue which w)-.25 E
+(ould result in a k)-.1 E .3 -.15(ey s)-.1 H
+(ignature with more than 7 \215ats or sharps.).15 E(It is also an)5 E
+(error if transposition w)138.476 300 Q
+(ould result in a note requiring a triple sharp or triple \215at.)-.1 E
+F1 -.92(Va)69.336 312 S(lue).92 E F0(............... the w).36 E
+(ord "up" or "do)-.1 E(wn," follo)-.25 E(wed by an interv)-.25 E
+(al and a whole number greater than 0.)-.25 E(The interv)5 E(al is)-.25
+E(one of major)138.476 324 Q 2.5(,m)-.4 G(inor)-2.5 E 2.5(,a)-.4 G
+(ugmented, diminished, or perfect.)-2.5 E(The interv)5 E
+(als can be abbre)-.25 E(viated to their)-.25 E
+(\214rst 3 letters \(maj, min, aug, dim, or per\).)138.476 336 Q
+(The section on transposition lists transposition interv)5 E(als)-.25 E
+(and gi)138.476 348 Q -.15(ve)-.25 G 2.5(sf).15 G(urther details.)-2.5 E
+(Depending on which k)5 E .3 -.15(ey s)-.1 H
+(ignature you are transposing from, some trans-).15 E(position interv)
+138.476 360 Q(als may not w)-.25 E(ork because the)-.1 E 2.5(yr)-.15 G
+(esult in more than 7 \215ats or sharps.)-2.5 E(There is also an-)5 E
+(other parameter called addtranspose.)138.476 372 Q -.8(Ty)5 G
+(pically you w).8 E(ould use the transpose parameter to change)-.1 E
+(the k)138.476 384 Q .3 -.15(ey o)-.1 H 2.5(fi).15 G(ndi)-2.5 E
+(vidual staf)-.25 E(fs \(for transposing instruments\), and then use th\
+e addtranspose parameter)-.25 E(if you w)138.476 396 Q
+(ant to change the k)-.1 E .3 -.15(ey o)-.1 H 2.5(ft).15 G
+(he entire score.)-2.5 E
+(But either of these parameters can be used either)5 E -.1(wa)138.476
+408 S 3.8 -.65(y. I).1 H 2.5(na).65 G .3 -.15(ny c)-2.5 H
+(ase, for each staf).15 E(f, and for the score, the v)-.25 E
+(alues of transpose and addtranspose are)-.25 E
+("added" to \214nd the transposition for that staf)138.476 420 Q 2.5(fo)
+-.25 G 2.5(rs)-2.5 G(core.)-2.5 E F1(Default)69.336 432 Q F0
+(............ up perfect 1 \(i.e., no transposition\)).28 E F1(Context)
+69.336 444 Q F0(........... score, staf).56 E(f)-.25 E F1(Examples)
+69.336 456 Q F0(........ transpose = up minor 3).27 E(transpose = do)
+138.476 468 Q(wn perfect 4)-.25 E F1(See also)69.336 480 Q F0
+(........... addtranspose, k).83 E -.15(ey)-.1 G F1(Name)69.336 528 Q F0
+(.............. units)1.95 E F1(Description)69.336 540 Q F0
+(..... Speci\214es whether mar)A(gin and page size parameters are speci\
+\214ed in inches or in centimeters.)-.18 E F1 -.92(Va)69.336 552 S(lue)
+.92 E F0(............... inches or cm).36 E F1(Default)69.336 564 Q F0
+(............ inches).28 E F1(Context)69.336 576 Q F0(........... score)
+.56 E F1(Example)69.336 588 Q F0(......... units = cm)1.66 E F1
+(See also)69.336 600 Q F0(........... topmar).83 E(gin, bottommar)-.18 E
+(gin leftmar)-.18 E(gin, rightmar)-.18 E(gin, pageheight, page)-.18 E
+(width)-.25 E EP
+%%Page: 127 133
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(27 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. vcombine)1.95 E F1
+(Description)69.336 108 Q F0
+(..... This parameter tells Mup to combine the speci\214ed v)A
+(oices onto a single stem whene)-.2 E -.15(ve)-.25 G 2.5(rp).15 G
+(ossible.)-2.5 E(One common use w)138.476 120 Q(ould be if you w)-.1 E
+(ant multiple v)-.1 E(oices for MIDI purposes, b)-.2 E(ut w)-.2 E
+(ant them printed)-.1 E(on the same stems.)138.476 132 Q
+(Another typical use w)5 E
+(ould be to obtain a printing style common for h)-.1 E(ymns and)-.05 E
+(certain other styles of music, where the tw)138.476 144 Q 2.5(ov)-.1 G
+(oices on each staf)-2.7 E 2.5(fa)-.25 G(re printed on one common stem)
+-2.5 E(whene)138.476 156 Q -.15(ve)-.25 G 2.5(rp).15 G(ossible, b)-2.5 E
+(ut when a note is shared between tw)-.2 E 2.5(ov)-.1 G(oices, tw)-2.7 E
+2.5(oo)-.1 G(pposing stems are used to)-2.5 E(mak)138.476 168 Q 2.5(ei)
+-.1 G 2.5(tc)-2.5 G(lear the note is indeed shared.)-2.5 E(The v)5 E
+(alue of this parameter is a list of v)-.25 E(oices plus an op-)-.2 E
+(tional quali\214er)138.476 180 Q 5(.T)-.55 G(he list format is lik)-5 E
+2.5(ee)-.1 G(lse)-2.5 E(where for v)-.25 E(oices; common e)-.2 E
+(xamples w)-.15 E(ould be)-.1 E/F2 10/Courier@0 SF(1,2)2.5 E F0(or)2.5 E
+F2(1-3)138.476 192 Q F0(or)2.5 E F2(2-3)2.5 E F0 5(.O)C(rder of v)-5 E
+(oices is signi\214cant: sometimes Mup may ha)-.2 E .3 -.15(ve t)-.2 H
+2.5(oc).15 G(hoose between tw)-2.5 E 2.5(op)-.1 G(os-)-2.5 E
+(sible combinations, so v)138.476 204 Q
+(oices listed \214rst get priority)-.2 E 5(.T)-.65 G(he list of v)-5 E
+(oices can be follo)-.2 E(wed by a quali-)-.25 E
+(\214er to specify what happens when v)138.476 216 Q(oices o)-.2 E -.15
+(ve)-.15 G(rlap. If the quali\214er is "noo).15 E -.15(ve)-.15 G
+(rlap," v).15 E(oices will only be)-.2 E
+(combined if the bottom note of the higher v)138.476 228 Q
+(oice is higher than the top note of the lo)-.2 E(wer v)-.25 E(oice.)-.2
+E(\(That is the typical v)138.476 240 Q(alue for getting the h)-.25 E
+(ymn style described abo)-.05 E -.15(ve)-.15 G 2.5(.\) If).15 F
+(the quali\214er is "shareone")2.5 E(the bottom note of the top v)
+138.476 252 Q(oice must be no lo)-.2 E(wer than than top note of the lo)
+-.25 E(wer v)-.25 E(oice for combin-)-.2 E(ing to occur)138.476 264 Q 5
+(.I)-.55 G 2.5(ft)-5 G(he quali\214er is "o)-2.5 E -.15(ve)-.15 G
+(rlap," combining will occur without re).15 E -.05(ga)-.15 G(rd for ho)
+.05 E 2.5(wt)-.25 G(he v)-2.5 E(oices)-.2 E -.15(ove)138.476 276 S
+(rlap. F).15 E(or the purpose of the quali\214er)-.15 E 2.5(,v)-.4 G
+(oice 1 is assumed to be the highest v)-2.7 E(oice, v)-.2 E(oice 3 the)
+-.2 E(middle v)138.476 288 Q(oice, and v)-.2 E(oice 2 the lo)-.2 E 2.5
+(west. If)-.25 F(no quali\214er is speci\214ed, the def)2.5 E
+(ault is noo)-.1 E -.15(ve)-.15 G(rlap. While the).15 E
+(vcombine parameter is allo)138.476 300 Q(wed to be used with an)-.25 E
+2.5(yv)-.15 G(scheme parameter v)-2.5 E(alue, using it with)-.25 E
+(vscheme=1 is pointless, and only vscheme v)138.476 312 Q
+(alues of 2f and 3f are really appropriate.)-.25 E(This parame-)5 E
+(ters can be used with both v)138.476 324 Q
+(oice-at-a-time and chord-at-a-time input styles. It has no ef)-.2 E
+(fect on tab-)-.25 E(lature or 1-line staf)138.476 336 Q 2.5(fs. Note)
+-.25 F(that there are v)2.5 E
+(arious cases where combining will not be done, such as)-.25 E
+(when time v)138.476 348 Q(alues or beamings are dif)-.25 E
+(ferent in dif)-.25 E(ferent v)-.25 E
+(oices, and cases where combining w)-.2 E(ould)-.1 E
+(cause information loss, such as when a shared note is tied in one v)
+138.476 360 Q(oice b)-.2 E(ut not another)-.2 E 2.5(.I)-.55 G 2.5(ns)
+-2.5 G(uch cas-)-2.5 E(es, the usual non-combined format will be used.)
+138.476 372 Q F1 -.92(Va)69.336 384 S(lue).92 E F0
+(............... comma-separated list of v).36 E(oices or v)-.2 E
+(oice ranges, or nothing, optionally follo)-.2 E(wed by noo)-.25 E -.15
+(ve)-.15 G(rlap, share-).15 E(one, or o)138.476 396 Q -.15(ve)-.15 G
+(rlap.).15 E F1(Default)69.336 408 Q F0(............ not set).28 E F1
+(Context)69.336 420 Q F0(........... score, staf).56 E(f)-.25 E F1
+(Example)69.336 432 Q F0(......... vcombine=3,1-2 shareone)1.66 E 5
+(vcombine= //)138.476 444 R(turn of)2.5 E 2.5(fc)-.25 G(ombining)-2.5 E
+F1(See also)69.336 456 Q F0(........... vscheme).83 E F1(Name)69.336 504
+Q F0(.............. visible)1.95 E F1(Description)69.336 516 Q F0
+(..... speci\214es whether a staf)A 2.5(fo)-.25 G 2.5(rv)-2.5 G
+(oice is actually to be printed.)-2.7 E
+(This can be useful for printing a subset of)5 E 2.5(af)138.476 528 S
+(ull score. The v)-2.5 E(alue is either y or n, for yes or no, or where\
+used. When whereused is speci\214ed, if)-.25 E 2.5(as)138.476 540 S(taf)
+-2.5 E 2.5(fh)-.25 G(as no notes or lyrics or other associated things o\
+n an entire score, that staf)-2.5 E 2.5(fi)-.25 G 2.5(sn)-2.5 G
+(ot printed.)-2.5 E(This might be used, for e)138.476 552 Q
+(xample, to sa)-.15 E .3 -.15(ve p)-.2 H
+(aper on an orchestral score by only printing staf).15 E(fs for in-)-.25
+E(struments when the)138.476 564 Q 2.5(ya)-.15 G(re actually playing.)
+-2.5 E(At least one staf)5 E 2.5(fm)-.25 G(ust be visible at all times.)
+-2.5 E(When an)5 E(indi)138.476 576 Q(vidual v)-.25 E(oice is made in)
+-.2 E(visible, b)-.4 E(ut the other v)-.2 E(oice\(s\) on that staf)-.2 E
+2.5(fr)-.25 G(emain visible, all the tempo,)-2.5 E
+(dynamics, and similar marks associated with the staf)138.476 588 Q 2.5
+(fw)-.25 G(ill still be printed, since Mup cannot kno)-2.5 E(w)-.25 E
+(for sure whether you meant them to be associated with a particular v)
+138.476 600 Q(oice or with the staf)-.2 E 2.5(fa)-.25 G 2.5(sa)-2.5 G
+2.5(whole. When)138.476 612 R
+(MIDI output is generated, this parameter controls whether the staf)2.5
+E 2.5(fo)-.25 G 2.5(rv)-2.5 G(oice is audi-)-2.7 E
+(ble, so you can control which v)138.476 624 Q(oices are played.)-.2 E
+(The -s command line ar)5 E(gument can also be used)-.18 E
+(to control which staf)138.476 636 Q(fs are printed or played.)-.25 E F1
+-.92(Va)69.336 648 S(lue).92 E F0(............... y).36 E 2.5(,n)-.65 G
+2.5(,o)-2.5 G 2.5(rw)-2.5 G(hereused)-2.5 E F1(Default)69.336 660 Q F0
+(............ y).28 E F1(Context)69.336 672 Q F0
+(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E F1(Example)69.336
+684 Q F0(......... visible = n)1.66 E F1(See also)69.336 696 Q F0
+(........... brace, brack).83 E(et, endingstyle, staf)-.1 E(fs)-.25 E EP
+%%Page: 128 134
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(28 -)-2.5 E/F1 10
+/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. vscheme)1.95 E F1
+(Description)69.336 108 Q F0(..... sets v)A(oice scheme. A v)-.2 E
+(alue of 1 means there is only a single v)-.25 E(oice on a staf)-.2 E
+(f. The direction of note)-.25 E(stems will be determined based on ho)
+138.476 120 Q 2.5(wh)-.25 G(igh or lo)-2.5 E 2.5(wt)-.25 G
+(he notes are on the staf)-2.5 E(f. A v)-.25 E(alue of 2o means)-.25 E
+(there are tw)138.476 132 Q 2.5(ov)-.1 G
+(oices with "opposing" stems. In other w)-2.7 E(ords, the stems of v)-.1
+E(oice 1 will al)-.2 E -.1(wa)-.1 G(ys point).1 E(upw)138.476 144 Q
+(ard, and the stems of v)-.1 E(oice 2 will al)-.2 E -.1(wa)-.1 G
+(ys point do).1 E(wnw)-.25 E(ard, unless the)-.1 E 2.5(ya)-.15 G(re e)
+-2.5 E(xplicitly forced the)-.15 E(other w)138.476 156 Q(ay)-.1 E 2.5
+(.Av)-.65 G(alue of 2f means there are tw)-2.75 E 2.5(ov)-.1 G
+(oices with "free" or "\215oating" stems.)-2.7 E(That means in)5 E
+(places where there are notes or rests in both v)138.476 168 Q
+(oices, stem directions will be as if 2o were set. Ho)-.2 E(w-)-.25 E
+-2.15 -.25(ev e)138.476 180 T .8 -.4(r, i).25 H 2.5(fo).4 G(ne of the v)
+-2.5 E(oices has "space" where there are no notes or rests, the stem di\
+rections of the)-.2 E(other v)138.476 192 Q
+(oice will be determined as if there were only a single v)-.2 E 2.5
+(oice. 2o)-.2 F(is useful if you w)2.5 E(ant to force)-.1 E
+(stem directions a certain w)138.476 204 Q(ay)-.1 E 2.5(.2)-.65 G 2.5
+(fi)-2.5 G 2.5(sg)-2.5 G(enerally preferable when there are tw)-2.5 E
+2.5(ov)-.1 G(oices only part of the)-2.7 E 2.5(time. The)138.476 216 R
+-.25(va)2.5 G(lues 3o and 3f are lik).25 E 2.5(e2)-.1 G 2.5(oa)-2.5 G
+(nd 2f e)-2.5 E(xcept that a third v)-.15 E(oice is allo)-.2 E
+(wed. The third v)-.25 E(oice')-.2 E(s)-.55 E(stem def)138.476 228 Q
+(aults to up, b)-.1 E(ut the direction can be changed at an)-.2 E 2.5
+(yc)-.15 G(hord. The stem direction remains in)-2.5 E(ef)138.476 240 Q
+(fect on subsequent chords of v)-.25 E(oice 3 until e)-.2 E
+(xplicitly changed.)-.15 E(While there can be v)5 E(oice cross-)-.2 E
+(ings, in general v)138.476 252 Q(oice 1 should be the "top" v)-.2 E
+(oice, v)-.2 E(oice 2 the "bottom" v)-.2 E(oice, and v)-.2 E
+(oice 3 the "mid-)-.2 E(dle" or "e)138.476 264 Q(xtra" v)-.15 E 2.5
+(oice. Mup)-.2 F(does not use v)2.5 E
+(oice 3 when associating things lik)-.2 E 2.5(ep)-.1 G(hrase marks and)
+-2.5 E(lyrics with chords.)138.476 276 Q(Setting vscheme to a dif)5 E
+(ferent number of v)-.25 E(oices will reinitialize all v)-.2 E(oice le)
+-.2 E -.15(ve)-.25 G(l).15 E(parameters for the af)138.476 288 Q
+(fected staf)-.25 E(fs.)-.25 E F1 -.92(Va)69.336 300 S(lue).92 E F0
+(............... 1, 2o, 2f, 3o, or 3f).36 E F1(Default)69.336 312 Q F0
+(............ 1).28 E F1(Context)69.336 324 Q F0
+(........... score, staf).56 E(f)-.25 E F1(Example)69.336 336 Q F0
+(......... vscheme = 2f)1.66 E F1(See also)69.336 348 Q F0
+(........... vcombine).83 E F1(Name)69.336 396 Q F0(.............. w)
+1.95 E(arn)-.1 E F1(Description)69.336 408 Q F0
+(..... speci\214es whether to print w)A(arning messages or not.)-.1 E
+(Normally)5 E 2.5(,M)-.65 G(up will print w)-2.5 E(arnings when it en-)
+-.1 E(counters input that it considers some)138.476 420 Q
+(what dubious. Sometimes, ho)-.25 E(we)-.25 E -.15(ve)-.25 G .8 -.4
+(r, t).15 H(hat input will really be).4 E(what you w)138.476 432 Q
+(ant, so this parameter allo)-.1 E(ws you to turn of)-.25 E 2.5(fw)-.25
+G(arning messages.)-2.6 E F1 -.92(Va)69.336 444 S(lue).92 E F0
+(............... y or n).36 E F1(Default)69.336 456 Q F0(............ y)
+.28 E F1(Context)69.336 468 Q F0(........... score).56 E F1(Example)
+69.336 480 Q F0(......... w)1.66 E(arn = n)-.1 E EP
+%%Page: 129 135
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(29 -)-2.5 E 69.336 103
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(13. HINTS)73.086 103 R 69.336 121 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.549(This section contains hints on ho)
+73.385 121 R 4.049(wy)-.25 G 1.549(ou can use Mup to accomplish v)-4.049
+F 1.549(arious things that ha)-.25 F 1.848 -.15(ve n)-.2 H 1.548
+(ot been).15 F(co)69.336 133 Q -.15(ve)-.15 G 1.358
+(red up to this point.).15 F 1.358(It doesn')6.358 F 3.858(ti)-.18 G
+1.358(ntroduce an)-3.858 F 3.858(yn)-.15 G 1.858 -.25(ew l)-3.858 H
+1.358(anguage features, b).25 F 1.358(ut describes some additional)-.2 F
+-.1(wa)69.336 145 S(ys to apply what you ha).1 E .3 -.15(ve a)-.2 H
+(lready learned, and mentions some other tools you may \214nd useful.)
+.15 E 69.336 163 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.1 Deb)72.836 163 R(ugging)-.28 E
+69.336 181 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.823(Since Mup requires its input in a f)
+73.659 181 R 1.823
+(airly strict format, when a song is put in, it may contain "typos.")-.1
+F(Generally)69.336 193 Q 2.81(,t)-.65 G .31
+(he error messages that Mup prints will gi)-2.81 F .611 -.15(ve y)-.25 H
+.311(ou an idea of what is wrong. Ho).15 F(we)-.25 E -.15(ve)-.25 G
+1.111 -.4(r, s).15 H(ometimes).4 E .878(Mup is not able to recognize th\
+at something is wrong until some distance be)69.336 205 R .878
+(yond the actual error)-.15 F 3.378(.I)-.55 G 3.378(fy)-3.378 G(ou)
+-3.378 E(can')69.336 217 Q 4.263<748c>-.18 G 1.763(nd an)-4.263 F 1.763
+(ything wrong with the line that Mup lists as being in error)-.15 F
+4.263(,t)-.4 G 1.763(ry looking at the end of the)-4.263 F(pre)69.336
+229 Q 2.087(vious line, or e)-.25 F -.15(ve)-.25 G 4.587(ne).15 G 2.087
+(arlier lines. Some of the most common problems are missing semicolons \
+and)-4.587 F .936(missing quotes. Missing quote marks tend to be especi\
+ally confusing to Mup, and may cause man)69.336 241 R 3.436(ye)-.15 G
+(rror)-3.436 E .679(messages, e)69.336 253 R -.15(ve)-.25 G 3.179(nt).15
+G .679(hough there is only one problem.)-3.179 F .679
+(Another common problem that may cause a v)5.679 F .678(ery lar)-.15 F
+(ge)-.18 E(number of error messages is for)69.336 265 Q
+(getting to state "music" to enter music conte)-.18 E(xt.)-.15 E 1.492
+(Often listening to MIDI output is much more ef)69.336 283 R(fecti)-.25
+E 1.793 -.15(ve a)-.25 H 3.993(ts).15 G 1.493(potting things lik)-3.993
+F 3.993(ew)-.1 G 1.493(rong notes and missing)-3.993 F
+(accidentals than trying to \214nd them by e)69.336 295 Q(ye.)-.15 E
+69.336 313 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.2 Adjusting)72.836 313 R(Output)3.5 E
+69.336 331 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .42
+(Mup does its best to lay out the music in an aesthetically pleasing w)
+72.256 331 R(ay)-.1 E 5.419(.O)-.65 G .419(ften, ho)-5.419 F(we)-.25 E
+-.15(ve)-.25 G 1.219 -.4(r, y).15 H .419(ou may w).4 F .419(ant to)-.1 F
+(mak)69.336 343 Q 2.584(ea)-.1 G .084
+(djustments. Perhaps the last part of a piece spilled o)-2.584 F -.15
+(ve)-.15 G 2.584(ro).15 G .084(nto a third page and you')-2.584 F 2.584
+(dl)-.5 G(ik)-2.584 E 2.584(et)-.1 G 2.584(os)-2.584 G .084(queeze it)
+-2.584 F 1.64(all on tw)69.336 355 R 4.14(op)-.1 G 1.64
+(ages, or a page turn f)-4.14 F 1.64(alls at an a)-.1 F(wkw)-.15 E 1.64
+(ard spot. There are se)-.1 F -.15(ve)-.25 G 1.64(ral mechanisms a).15 F
+-.25(va)-.2 G 1.64(ilable for).25 F .896(making adjustments. The)69.336
+367 R 3.396(yh)-.15 G -2.25 -.2(av e)-3.396 H .896
+(already been discussed indi)3.596 F .896(vidually in v)-.25 F .896
+(arious sections of this document,)-.25 F -.2(bu)69.336 379 S 2.5(tt).2
+G(his section tries to pull things together)-2.5 E(.)-.55 E .322
+(The "ne)69.336 397 R .322(wscore" or "ne)-.25 F .322
+(wpage" commands can be used to force where breaks occur)-.25 F 5.322
+(.T)-.55 G .321(his may be useful for)-5.322 F
+(ensuring a section ends at the end of a score or page.)69.336 409 Q
+1.284(If you w)69.336 427 R 1.285(ant to get a little more or less on e\
+ach page, it is usually best to start with changing the scale,)-.1 F
+(staf)69.336 439 Q 3.162(fscale, packf)-.25 F 3.162(act, and/or pack)-.1
+F -.15(ex)-.1 G 5.662(pp).15 G 5.662(arameters. Y)-5.662 F 3.162
+(ou may w)-1.1 F 3.162(ant to e)-.1 F 3.161
+(xperiment with changing these)-.15 F(indi)69.336 451 Q 1.469
+(vidually \214rst, to get a feel for ho)-.25 F 3.969(wt)-.25 G(he)-3.969
+E 3.969(yw)-.15 G 1.47
+(ork, as trying to change all of them at once may lead to)-4.069 F .425
+(interactions that change things more radically than you might e)69.336
+463 R 2.925(xpect. Changing)-.15 F(staf)2.925 E .425
+(fscale in score conte)-.25 F(xt)-.15 E .29
+(lets you adjust the size of the music without af)69.336 475 R .29
+(fecting the size of the te)-.25 F .29(xt in headers and footers.)-.15 F
+(Adjusting)5.29 E .712(the mar)69.336 487 R .712(gins is sometimes help\
+ful as well. Other parameters which might be useful in some situations \
+are:)-.18 F(scorepad, scoresep, staf)69.336 499 Q(fpad, and staf)-.25 E
+(fsep.)-.25 E 1.196
+(The dist, dyndist, and chorddist parameters are useful if you w)69.336
+517 R 1.197(ant items to line up v)-.1 F(ertically)-.15 E 3.697(.T)-.65
+G 1.197(he "dist")-3.697 F .198
+(option can be used on rom, bold, ital, boldital, octa)69.336 529 R -.15
+(ve)-.2 G 2.698(,m).15 G .198
+(ussym, crescendo and decrescendo statements, and)-2.698 F
+(on rehearsal marks, to force something where you w)69.336 541 Q
+(ant it.)-.1 E 1.072(The appearance of lyrics can be adjusted using the\
+ lyricsfont, lyricsfontf)69.336 559 R(amily)-.1 E 3.573(,l)-.65 G 1.073
+(yricssize, and lyricsalign)-3.573 F(parameters.)69.336 571 Q 69.336 589
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.3 Special)72.836 589 R(uses of in)3.5
+E(visbar)-.56 E 69.336 607 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .01(The "in)71.846 607 R .01(visbar" can be\
+ used to force Mup into doing something in the middle of a bar that it \
+normally w)-.4 F(ould)-.1 E(allo)69.336 619 Q 2.762(wt)-.25 G 2.762(oh)
+-2.762 G .262(appen only at a bar line.)-2.762 F .262(Suppose, for e)
+5.262 F .263(xample, you wish to place a rehearsal letter in the middle)
+-.15 F(of a measure. This could be accomplished as follo)69.336 631 Q
+(ws:)-.25 E EP
+%%Page: 130 136
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(30 -)-2.5 E/F1 10/Courier@0
+SF(// assume we are in 4/4 time, but want)105.336 96 Q
+(// a rehearsal letter by count 3)105.336 108 Q(// of the measure)
+105.336 120 Q(// do first part of measure and use "space")105.336 144 Q
+(// for last part so time values will add up)105.336 156 Q
+(// properly to a full measure)105.336 168 Q(1: 4c;d;2s;)105.336 180 Q
+(// put in invisible bar with rehearsal letter)105.336 204 Q
+(invisbar rehearsal let)105.336 216 Q
+(// now do the last half of the measure,)105.336 240 Q
+(// this time with space at the beginning)105.336 252 Q(1: 2s;4e;c;)
+105.336 264 Q(bar)105.336 276 Q 127.836 285.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 69 rlineto 320 0 rlineto 0 69 neg rlineto closepath stroke grestore
+EEND 160 693 320 320 -69 69 126.836 354.6 PBEGIN
+%%BeginDocument: mugex87.ps
+%%BoundingBox: 160 693 480 762
+save
+1216322504 1216321786 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+324.29 1225.78 468.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 715.78 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+226.28 703.78 1.000000 4n
+0.70 setlinewidth
+220.05 703.78 moveto
+232.51 703.78 lineto stroke
+229.96 704.53 moveto
+229.96 724.78 lineto stroke
+287.42 706.78 1.000000 4n
+291.10 707.53 moveto
+291.10 727.78 lineto stroke
+restore
+%  S_BAR
+13 linenum
+0.70 setlinewidth
+/Times-Bold findfont
+12 scalefont
+setfont
+newpath
+332.19 742.78 moveto
+332.19 754.00 lineto
+345.33 754.00 lineto
+345.33 742.78 lineto
+closepath
+stroke
+334.19 744.28 moveto
+(A) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+351.92 709.78 1.000000 4n
+355.60 710.53 moveto
+355.60 730.78 lineto stroke
+413.06 703.78 1.000000 4n
+406.83 703.78 moveto
+419.29 703.78 lineto stroke
+416.74 704.53 moveto
+416.74 724.78 lineto stroke
+restore
+%  S_BAR
+19 linenum
+0.70 setlinewidth
+467.65 733.78 moveto
+467.65 709.78 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF 1.102(As another e)69.336 374.6 R 1.102
+(xample of in)-.15 F 1.102(visbar use, suppose you w)-.4 F 1.102
+(ant to add a "courtesy" k)-.1 F 1.401 -.15(ey s)-.1 H 1.101
+(ignature at the end of a).15 F .82
+(repeated section to remind the player that the be)69.336 386.6 R .821
+(ginning of the repeated section is in a dif)-.15 F .821(ferent k)-.25 F
+-.15(ey)-.1 G 3.321(.T)-.5 G(his)-3.321 E(can be done by adding an empt\
+y measure whose sole purpose is to produce this k)69.336 398.6 Q .3 -.15
+(ey s)-.1 H(ignature.).15 E/F1 10/Courier@0 SF(score key=3&)105.336
+416.6 Q(music)105.336 428.6 Q(1: g;f;e;d;)105.336 440.6 Q(repeatstart)
+105.336 452.6 Q(1: c;e;f;g;)105.336 464.6 Q(dblbar)105.336 476.6 Q
+(score key=0&)105.336 488.6 Q(music)105.336 500.6 Q(1: g;f;e;d;)105.336
+512.6 Q(bar ending "1.")105.336 524.6 Q(1: f;e;2c;)105.336 536.6 Q
+(// add a courtesy key signature,)105.336 548.6 Q
+(// to remind player the beginning)105.336 560.6 Q
+(// of the repeated section is in)105.336 572.6 Q(// a different key)
+105.336 584.6 Q(invisbar)105.336 596.6 Q(score key=3&)105.336 608.6 Q
+(music)105.336 620.6 Q(1: ms;)105.336 632.6 Q(repeatend ending "2.")
+105.336 644.6 Q(1: e;d;2c;)105.336 656.6 Q(endbar)105.336 668.6 Q EP
+%%Page: 131 137
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(31 -)-2.5 E 111.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 145 rlineto 352 0 rlineto 0 145 neg rlineto closepath stroke grestore
+EEND 128 618 352 352 -145 145 110.836 241 PBEGIN
+%%BeginDocument: mugex88.ps
+%%BoundingBox: 128 618 480 763
+save
+1216322504 1216321786 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+324.29 1235.00 468.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+205.62 731.00 1.000000 flat
+211.10 740.00 1.000000 flat
+216.59 728.00 1.000000 flat
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+238.42 725.00 1.000000 4n
+0.70 setlinewidth
+242.10 725.75 moveto
+242.10 746.00 lineto stroke
+260.81 722.00 1.000000 4n
+264.49 722.75 moveto
+264.49 743.00 lineto stroke
+283.19 719.00 1.000000 4n
+286.87 719.75 moveto
+286.87 740.00 lineto stroke
+306.42 716.00 1.000000 4n
+310.10 716.75 moveto
+310.10 737.00 lineto stroke
+restore
+%  S_BAR
+6 linenum
+337.91 734.00 1.000000 dot
+337.91 728.00 1.000000 dot
+0.70 setlinewidth
+334.91 743.00 moveto
+334.91 719.00 lineto stroke
+3.00 setlinewidth
+330.91 743.00 moveto
+330.91 719.00 lineto stroke
+0.70 setlinewidth
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+348.99 713.00 1.000000 4n
+342.76 713.00 moveto
+355.23 713.00 lineto stroke
+352.68 713.75 moveto
+352.68 734.00 lineto stroke
+371.38 719.00 1.000000 4n
+375.06 719.75 moveto
+375.06 740.00 lineto stroke
+393.76 722.00 1.000000 4n
+397.45 722.75 moveto
+397.45 743.00 lineto stroke
+416.99 725.00 1.000000 4n
+420.67 725.75 moveto
+420.67 746.00 lineto stroke
+restore
+%  S_BAR
+8 linenum
+0.70 setlinewidth
+438.98 743.00 moveto
+438.98 719.00 lineto stroke
+441.98 743.00 moveto
+441.98 719.00 lineto stroke
+%  S_SSV
+9 linenum
+%  S_CLEFSIG
+447.90 731.00 1.000000 nat
+453.74 740.00 1.000000 nat
+459.58 728.00 1.000000 nat
+%  S_FEED
+288.00 1151.00 468.00 5 1.000000 1.000000 stf
+264.93 661.00 moveto
+264.93 672.00 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+267.93 662.00 moveto
+(1.) show
+264.93 672.00 moveto
+370.69 672.00 lineto stroke
+370.69 672.00 moveto
+370.69 661.00 lineto stroke
+374.69 661.00 moveto
+374.69 672.00 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+377.69 662.00 moveto
+(2.) show
+374.69 672.00 moveto
+462.50 672.00 lineto stroke
+462.50 672.00 moveto
+462.50 661.00 lineto stroke
+%  S_CLEFSIG
+155.79 641.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+183.18 641.00 1.000000 4n
+186.86 641.75 moveto
+186.86 662.00 lineto stroke
+202.63 638.00 1.000000 4n
+206.32 638.75 moveto
+206.32 659.00 lineto stroke
+222.09 635.00 1.000000 4n
+225.77 635.75 moveto
+225.77 656.00 lineto stroke
+242.38 632.00 1.000000 4n
+246.06 632.75 moveto
+246.06 653.00 lineto stroke
+restore
+%  S_BAR
+12 linenum
+0.70 setlinewidth
+262.93 659.00 moveto
+262.93 635.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+273.02 638.00 1.000000 4n
+276.70 638.75 moveto
+276.70 659.00 lineto stroke
+292.44 635.00 1.000000 4n
+296.12 635.75 moveto
+296.12 656.00 lineto stroke
+315.13 629.00 1.000000 2n
+308.68 629.00 moveto
+321.58 629.00 lineto stroke
+319.03 629.75 moveto
+319.03 650.00 lineto stroke
+restore
+%  S_BAR
+18 linenum
+0.70 setlinewidth
+%  S_SSV
+19 linenum
+%  S_CLEFSIG
+345.97 647.00 1.000000 flat
+351.46 656.00 1.000000 flat
+356.95 644.00 1.000000 flat
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+restore
+%  S_BAR
+22 linenum
+368.69 650.00 1.000000 dot
+368.69 644.00 1.000000 dot
+0.70 setlinewidth
+372.69 659.00 moveto
+372.69 635.00 lineto stroke
+3.00 setlinewidth
+376.69 659.00 moveto
+376.69 635.00 lineto stroke
+0.70 setlinewidth
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+387.29 635.00 1.000000 4n
+390.97 635.75 moveto
+390.97 656.00 lineto stroke
+406.71 632.00 1.000000 4n
+410.39 632.75 moveto
+410.39 653.00 lineto stroke
+429.40 629.00 1.000000 2n
+422.95 629.00 moveto
+435.85 629.00 lineto stroke
+433.30 629.75 moveto
+433.30 650.00 lineto stroke
+restore
+%  S_BAR
+24 linenum
+0.70 setlinewidth
+462.50 659.00 moveto
+462.50 635.00 lineto stroke
+3.00 setlinewidth
+466.50 659.00 moveto
+466.50 635.00 lineto stroke
+0.70 setlinewidth
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF -1.1(Yo)69.336 261 S 2.5(uc)1.1 G
+(an use a similar technique to insert time signatures, clefs, etc.)-2.5
+E(at unusual places.)5 E 69.336 279 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.4 Chant)72.836 279 R 69.336 297 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(Here is an e)71.836 297 Q(xample that sho)
+-.15 E(ws some techniques you might use when writing chant.)-.25 E EP
+%%Page: 132 138
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(32 -)-2.5 E/F1 10/Courier@0
+SF(1: 1a;)105.336 96 Q(lyrics 1: "This<^ is an example of one way>";)
+105.336 108 Q(bar)105.336 120 Q(1: d;e;2f;)105.336 144 Q
+(lyrics 1: "to do chant.";)105.336 156 Q(bar)105.336 168 Q(1: 1f;)
+105.336 192 Q(lyrics 1: "when<^ there are many words for a>";)105.336
+204 Q(bar)105.336 216 Q(1: d;f;2;)105.336 240 Q
+(lyrics 1: "sin-gle note.";)105.336 252 Q(dblbar)105.336 264 Q(newscore)
+105.336 288 Q(// Note use of 'n' to not print the time signature)105.336
+300 Q(score time=7/4n)105.336 312 Q(music)105.336 324 Q(1: a;;;b;g;2a;)
+105.336 336 Q(lyrics 1: "When there are man-y notes,";)105.336 348 Q
+(bar)105.336 360 Q(score time=8/4n)105.336 384 Q(music)105.336 396 Q
+(1: d;e;f;e;f;8e;;2;)105.336 408 Q
+(lyrics 1: "You might change the time sig-na-ture";)105.336 420 Q(bar)
+105.336 432 Q(score time=5/4n)105.336 456 Q(music)105.336 468 Q
+(1: a;e;;2d;)105.336 480 Q(lyrics 1: "on ev-ery bar,";)105.336 492 Q
+(bar)105.336 504 Q(score time=7/4n)105.336 528 Q(music)105.336 540 Q
+(1: e;f;e;d;c;2d;)105.336 552 Q(lyrics 1: "to match the syl-la-bles.";)
+105.336 564 Q(dblbar)105.336 576 Q(newscore)105.336 600 Q
+(score time=8/4n)105.336 624 Q(music)105.336 636 Q
+(// Note use of 'n' to not print tuplet number/bracket)105.336 648 Q
+(1: {d;e;f;g;e;2d;;}10n,1/2;)105.336 660 Q
+(lyrics 1: "You can al-so use tup-lets,";)105.336 672 Q(invisbar)105.336
+684 Q(1: {f;g;e;2d;e;2.d;}9n,1/2;)105.336 708 Q
+(lyrics 1: "A-long with in-vis-bars.";)105.336 720 Q(dblbar)105.336 732
+Q EP
+%%Page: 133 139
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(33 -)-2.5 E/F1 10/Courier@0
+SF(newscore)105.336 96 Q(score stemlen=0)105.336 120 Q(music)105.336 132
+Q(1: d+;c+;b;g;2a;;)105.336 156 Q(lyrics 1: "Set stem-len to ze-ro,";)
+105.336 168 Q(invisbar)105.336 180 Q(1: {f;2e;4d;c;1d;}9n,1/2;)105.336
+204 Q(lyrics 1: "to get stem-less notes.";)105.336 216 Q(endbar)105.336
+228 Q EP
+%%Page: 134 140
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(34 -)-2.5 E 87.836 96 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 578 rlineto 400 0 rlineto 0 578 neg rlineto closepath stroke grestore
+EEND 104 185 400 400 -578 578 86.836 674 PBEGIN
+%%BeginDocument: mugex89.ps
+%%BoundingBox: 104 185 504 763
+save
+1039846316 1039845534 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+590.69 803.00 489.60 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+170.48 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+5 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+192.16 702.00 moveto
+(This is an example of one way) show
+197.49 728.00 1.000000 1n
+restore
+%  S_BAR
+8 linenum
+0.70 setlinewidth
+342.18 743.00 moveto
+342.18 719.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+9 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+351.91 702.00 moveto
+(to) show
+/Times-Roman findfont
+12 scalefont
+setfont
+386.63 702.00 moveto
+(do) show
+/Times-Roman findfont
+12 scalefont
+setfont
+422.53 702.00 moveto
+(chant.) show
+354.23 716.00 1.000000 4n
+357.91 716.75 moveto
+357.91 737.00 lineto stroke
+389.62 719.00 1.000000 4n
+393.30 719.75 moveto
+393.30 740.00 lineto stroke
+429.76 722.00 1.000000 2n
+433.66 722.75 moveto
+433.66 743.00 lineto stroke
+restore
+%  S_BAR
+12 linenum
+0.70 setlinewidth
+489.25 743.00 moveto
+489.25 719.00 lineto stroke
+%  S_FEED
+554.40 719.00 489.60 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+134.19 641.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+13 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+154.98 618.00 moveto
+(when there are many words for a) show
+161.46 638.00 1.000000 1n
+restore
+%  S_BAR
+16 linenum
+0.70 setlinewidth
+316.16 659.00 moveto
+316.16 635.00 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+17 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+350.70 618.00 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+324.08 618.00 moveto
+(sin) show
+/Times-Roman findfont
+12 scalefont
+setfont
+366.35 618.00 moveto
+(gle) show
+/Times-Roman findfont
+12 scalefont
+setfont
+411.28 618.00 moveto
+(note.) show
+328.56 632.00 1.000000 4n
+332.24 632.75 moveto
+332.24 653.00 lineto stroke
+370.00 638.00 1.000000 4n
+373.68 638.75 moveto
+373.68 659.00 lineto stroke
+417.18 638.00 1.000000 2n
+421.08 638.75 moveto
+421.08 659.00 lineto stroke
+restore
+%  S_BAR
+19 linenum
+0.70 setlinewidth
+486.25 659.00 moveto
+486.25 635.00 lineto stroke
+489.25 659.00 moveto
+489.25 635.00 lineto stroke
+%  S_SSV
+23 linenum
+%  S_CLEFSIG
+%  S_FEED
+21 linenum
+554.40 635.00 489.60 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+134.19 557.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+25 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+157.83 531.28 moveto
+(When) show
+/Times-Roman findfont
+12 scalefont
+setfont
+207.29 531.28 moveto
+(there) show
+/Times-Roman findfont
+12 scalefont
+setfont
+258.12 531.28 moveto
+(are) show
+/Times-Roman findfont
+12 scalefont
+setfont
+338.28 531.28 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+302.60 531.28 moveto
+(man) show
+/Times-Roman findfont
+12 scalefont
+setfont
+356.29 531.28 moveto
+(y) show
+/Times-Roman findfont
+12 scalefont
+setfont
+403.01 531.28 moveto
+(notes,) show
+164.98 560.00 1.000000 4n
+168.66 560.75 moveto
+168.66 581.00 lineto stroke
+213.26 560.00 1.000000 4n
+216.94 560.75 moveto
+216.94 581.00 lineto stroke
+261.78 560.00 1.000000 4n
+265.46 560.75 moveto
+265.46 581.00 lineto stroke
+308.76 563.00 1.000000 4n
+305.07 562.25 moveto
+305.07 542.00 lineto stroke
+357.78 557.00 1.000000 4n
+361.46 557.75 moveto
+361.46 578.00 lineto stroke
+410.09 560.00 1.000000 2n
+413.98 560.75 moveto
+413.98 581.00 lineto stroke
+restore
+%  S_BAR
+28 linenum
+0.70 setlinewidth
+489.25 575.00 moveto
+489.25 551.00 lineto stroke
+%  S_SSV
+29 linenum
+%  S_CLEFSIG
+%  S_FEED
+554.40 551.00 489.60 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+134.19 473.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+31 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+157.55 450.00 moveto
+(You) show
+/Times-Roman findfont
+12 scalefont
+setfont
+195.42 450.00 moveto
+(might) show
+/Times-Roman findfont
+12 scalefont
+setfont
+234.63 450.00 moveto
+(change) show
+/Times-Roman findfont
+12 scalefont
+setfont
+282.69 450.00 moveto
+(the) show
+/Times-Roman findfont
+12 scalefont
+setfont
+321.10 450.00 moveto
+(time) show
+/Times-Roman findfont
+12 scalefont
+setfont
+378.54 450.00 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+360.84 450.00 moveto
+(sig) show
+/Times-Roman findfont
+12 scalefont
+setfont
+404.96 450.00 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+385.28 450.00 moveto
+(na) show
+/Times-Roman findfont
+12 scalefont
+setfont
+416.33 450.00 moveto
+(ture) show
+162.70 464.00 1.000000 4n
+166.38 464.75 moveto
+166.38 485.00 lineto stroke
+202.41 467.00 1.000000 4n
+206.09 467.75 moveto
+206.09 488.00 lineto stroke
+243.11 470.00 1.000000 4n
+246.79 470.75 moveto
+246.79 491.00 lineto stroke
+286.34 467.00 1.000000 4n
+290.02 467.75 moveto
+290.02 488.00 lineto stroke
+326.42 470.00 1.000000 4n
+330.11 470.75 moveto
+330.11 491.00 lineto stroke
+365.32 467.00 1.000000 4n
+369.00 467.75 moveto
+369.00 488.00 lineto stroke
+372.03 488.00 1.000000 dnflag
+389.09 467.00 1.000000 4n
+392.78 467.75 moveto
+392.78 488.00 lineto stroke
+395.80 488.00 1.000000 dnflag
+420.98 467.00 1.000000 2n
+424.87 467.75 moveto
+424.87 488.00 lineto stroke
+restore
+%  S_BAR
+34 linenum
+0.70 setlinewidth
+489.25 491.00 moveto
+489.25 467.00 lineto stroke
+%  S_SSV
+35 linenum
+%  S_CLEFSIG
+%  S_FEED
+554.40 467.00 489.60 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+134.19 389.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+37 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+158.59 363.00 moveto
+(on) show
+/Times-Roman findfont
+12 scalefont
+setfont
+201.30 363.00 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+184.23 363.00 moveto
+(ev) show
+/Times-Roman findfont
+12 scalefont
+setfont
+210.07 363.00 moveto
+(ery) show
+/Times-Roman findfont
+12 scalefont
+setfont
+239.95 363.00 moveto
+(bar,) show
+161.58 392.00 1.000000 4n
+165.26 392.75 moveto
+165.26 413.00 lineto stroke
+188.05 383.00 1.000000 4n
+191.73 383.75 moveto
+191.73 404.00 lineto stroke
+213.89 383.00 1.000000 4n
+217.57 383.75 moveto
+217.57 404.00 lineto stroke
+244.52 380.00 1.000000 2n
+248.42 380.75 moveto
+248.42 401.00 lineto stroke
+restore
+%  S_BAR
+40 linenum
+0.70 setlinewidth
+288.59 407.00 moveto
+288.59 383.00 lineto stroke
+%  S_SSV
+41 linenum
+%  S_CLEFSIG
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+43 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+298.31 363.00 moveto
+(to) show
+/Times-Roman findfont
+12 scalefont
+setfont
+318.17 363.00 moveto
+(match) show
+/Times-Roman findfont
+12 scalefont
+setfont
+353.10 363.00 moveto
+(the) show
+/Times-Roman findfont
+12 scalefont
+setfont
+398.37 363.00 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+378.75 363.00 moveto
+(syl) show
+/Times-Roman findfont
+12 scalefont
+setfont
+423.31 363.00 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+407.03 363.00 moveto
+(la) show
+/Times-Roman findfont
+12 scalefont
+setfont
+433.96 363.00 moveto
+(bles.) show
+300.63 383.00 1.000000 4n
+304.31 383.75 moveto
+304.31 404.00 lineto stroke
+325.50 386.00 1.000000 4n
+329.18 386.75 moveto
+329.18 407.00 lineto stroke
+356.76 383.00 1.000000 4n
+360.44 383.75 moveto
+360.44 404.00 lineto stroke
+383.23 380.00 1.000000 4n
+386.91 380.75 moveto
+386.91 401.00 lineto stroke
+410.18 377.00 1.000000 4n
+403.95 377.00 moveto
+416.41 377.00 lineto stroke
+413.86 377.75 moveto
+413.86 398.00 lineto stroke
+439.54 380.00 1.000000 2n
+443.43 380.75 moveto
+443.43 401.00 lineto stroke
+restore
+%  S_BAR
+45 linenum
+0.70 setlinewidth
+486.25 407.00 moveto
+486.25 383.00 lineto stroke
+489.25 407.00 moveto
+489.25 383.00 lineto stroke
+%  S_SSV
+49 linenum
+%  S_CLEFSIG
+%  S_FEED
+47 linenum
+554.40 383.00 489.60 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+134.19 305.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+52 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+154.98 281.90 moveto
+(You) show
+/Times-Roman findfont
+12 scalefont
+setfont
+179.47 281.90 moveto
+(can) show
+/Times-Roman findfont
+12 scalefont
+setfont
+213.14 281.90 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+201.50 281.90 moveto
+(al) show
+/Times-Roman findfont
+12 scalefont
+setfont
+219.15 281.90 moveto
+(so) show
+/Times-Roman findfont
+12 scalefont
+setfont
+235.01 281.90 moveto
+(use) show
+/Times-Roman findfont
+12 scalefont
+setfont
+277.89 281.90 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+256.23 281.90 moveto
+(tup) show
+/Times-Roman findfont
+12 scalefont
+setfont
+287.28 281.90 moveto
+(lets,) show
+160.13 296.00 1.000000 4n
+163.81 296.75 moveto
+163.81 317.00 lineto stroke
+183.63 299.00 1.000000 4n
+187.31 299.75 moveto
+187.31 320.00 lineto stroke
+204.65 302.00 1.000000 4n
+208.33 302.75 moveto
+208.33 323.00 lineto stroke
+221.81 305.00 1.000000 4n
+225.49 305.75 moveto
+225.49 326.00 lineto stroke
+239.00 299.00 1.000000 4n
+242.68 299.75 moveto
+242.68 320.00 lineto stroke
+261.04 296.00 1.000000 2n
+264.94 296.75 moveto
+264.94 317.00 lineto stroke
+292.19 296.00 1.000000 2n
+296.09 296.75 moveto
+296.09 317.00 lineto stroke
+restore
+%  S_BAR
+54 linenum
+0.70 setlinewidth
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+56 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+331.65 281.90 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+322.01 281.90 moveto
+(A) show
+/Times-Roman findfont
+12 scalefont
+setfont
+335.66 281.90 moveto
+(long) show
+/Times-Roman findfont
+12 scalefont
+setfont
+359.92 281.90 moveto
+(with) show
+/Times-Roman findfont
+12 scalefont
+setfont
+404.40 281.90 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+388.24 281.90 moveto
+(in) show
+/Times-Roman findfont
+12 scalefont
+setfont
+434.12 281.90 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+414.28 281.90 moveto
+(vis) show
+/Times-Roman findfont
+12 scalefont
+setfont
+443.00 281.90 moveto
+(bars.) show
+325.16 302.00 1.000000 4n
+328.85 302.75 moveto
+328.85 323.00 lineto stroke
+340.97 305.00 1.000000 4n
+344.65 305.75 moveto
+344.65 326.00 lineto stroke
+365.23 299.00 1.000000 4n
+368.91 299.75 moveto
+368.91 320.00 lineto stroke
+391.55 296.00 1.000000 2n
+395.45 296.75 moveto
+395.45 317.00 lineto stroke
+418.76 299.00 1.000000 2n
+422.66 299.75 moveto
+422.66 320.00 lineto stroke
+448.75 296.00 1.000000 2n
+458.23 296.00 1.000000 dot
+452.64 296.75 moveto
+452.64 317.00 lineto stroke
+restore
+%  S_BAR
+58 linenum
+0.70 setlinewidth
+486.25 323.00 moveto
+486.25 299.00 lineto stroke
+489.25 323.00 moveto
+489.25 299.00 lineto stroke
+%  S_SSV
+62 linenum
+%  S_FEED
+60 linenum
+554.40 299.00 489.60 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+134.19 221.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+65 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+156.18 195.00 moveto
+(Set) show
+/Times-Roman findfont
+12 scalefont
+setfont
+198.52 195.00 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+174.54 195.00 moveto
+(stem) show
+/Times-Roman findfont
+12 scalefont
+setfont
+202.81 195.00 moveto
+(len) show
+/Times-Roman findfont
+12 scalefont
+setfont
+225.29 195.00 moveto
+(to) show
+/Times-Roman findfont
+12 scalefont
+setfont
+269.28 195.00 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+246.84 195.00 moveto
+(ze) show
+/Times-Roman findfont
+12 scalefont
+setfont
+284.06 195.00 moveto
+(ro,) show
+160.02 233.00 1.000000 4n
+181.20 230.00 1.000000 4n
+206.46 227.00 1.000000 4n
+227.61 221.00 1.000000 4n
+250.50 224.00 1.000000 2n
+287.30 224.00 1.000000 2n
+restore
+%  S_BAR
+67 linenum
+0.70 setlinewidth
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+69 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+321.96 195.00 moveto
+(to) show
+/Times-Roman findfont
+12 scalefont
+setfont
+340.71 195.00 moveto
+(get) show
+/Times-Roman findfont
+12 scalefont
+setfont
+391.66 195.00 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+368.23 195.00 moveto
+(stem) show
+/Times-Roman findfont
+12 scalefont
+setfont
+395.40 195.00 moveto
+(less) show
+/Times-Roman findfont
+12 scalefont
+setfont
+422.32 195.00 moveto
+(notes.) show
+324.29 218.00 1.000000 4n
+344.36 215.00 1.000000 2n
+374.89 212.00 1.000000 4n
+399.90 209.00 1.000000 4n
+393.67 209.00 moveto
+406.14 209.00 lineto stroke
+429.40 212.00 1.000000 1n
+restore
+%  S_BAR
+71 linenum
+0.70 setlinewidth
+484.10 239.00 moveto
+484.10 215.00 lineto stroke
+3.00 setlinewidth
+488.10 239.00 moveto
+488.10 215.00 lineto stroke
+0.70 setlinewidth
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 694 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.5 F)72.836 694 R(or)-.35 E(cing shar)
+-.252 E(ed noteheads)-.252 E 69.336 712 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .933(Mup will automatically share note head\
+s when it can \214gure out it is safe and proper to do so. Ho)72.77 712
+R(we)-.25 E -.15(ve)-.25 G -.4(r,).15 G .94
+(there may be some unusual cases where you w)69.336 724 R .94(ould lik)
+-.1 F 3.44(et)-.1 G 3.44(of)-3.44 G .94(orce the notes from tw)-3.44 F
+3.44(ov)-.1 G .94(oices to share note)-3.64 F .764(heads e)69.336 736 R
+-.15(ve)-.25 G 3.264(nw).15 G .764(hen Mup w)-3.264 F .763
+(ould not do that. That can be done by specifying a horizontal of)-.1 F
+.763(fset of zero, i.e.,)-.25 F EP
+%%Page: 135 141
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(35 -)-2.5 E
+([ho 0], on one or both of the v)69.336 96 Q(oices.)-.2 E 69.336 114
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.6 Manually)72.836 114 R
+(placed tuplet numbers)3.5 E 69.336 132 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(Generally)72.168 132 Q 2.832(,M)-.65 G .333
+(up will place tuplet numbers for you.)-2.832 F(Ho)5.333 E(we)-.25 E
+-.15(ve)-.25 G 1.133 -.4(r, y).15 H .333
+(ou do need to print them yourself on cross-).4 F(staf)69.336 144 Q
+3.089(fb)-.25 G 3.089(eams. And)-3.089 F .589
+(there may be cases where you choose to use 'n' to turn of)3.089 F 3.089
+(fM)-.25 G(up')-3.089 E 3.089(sa)-.55 G .589(utomatic printing of)-3.089
+F .663(tuplet numbers, in order to print them manually in a dif)69.336
+156 R .664(ferent place than Mup w)-.25 F 3.164(ould. Mup)-.1 F .664
+(normally uses)3.164 F(ne)69.336 168 Q .08
+(wcentury boldital font for tuplet numbers, in 11-point size for re)-.25
+F .079(gular notes and 9-point for cue notes.)-.15 F(So)5.079 E 1.237
+(to mak)69.336 180 R 3.737(ey)-.1 G 1.238(our manually placed tuplet nu\
+mbers look the same as automatic ones, you might use a macro)-3.737 F
+(something lik)69.336 192 Q 2.5(et)-.1 G(his:)-2.5 E/F1 10/Courier@0 SF
+(define TUPNUM\(NUM\) "\\f\(NX\)\\s\(11\)" +`NUM` @)105.336 210 Q
+(1: { 8c; d; e; } 3n; 2.us;)105.336 222 Q
+(rom above 1 dist0: 1.34 TUPNUM\(3\);)105.336 234 Q(bar)105.336 246 Q F0
+(Or another approach w)69.336 266 Q(ould be something lik)-.1 E 2.5(et)
+-.1 G(his:)-2.5 E F1
+(define TN\(NUM,WHERE,D,N\) newcentury boldital WHERE dist D: N `NUM`;@)
+105.336 284 Q(1: { 8c; d; e; } 3n; 2.us;)105.336 296 Q
+(TN\(3,above 1,0,1.34\))105.336 308 Q(bar)105.336 320 Q 69.336 346
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.7 Manual)72.836 346 R
+(placement of notes)3.5 E 69.336 364 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .86(Mup supports up to three v)72.696 364 R
+.86(oices per staf)-.2 F .86
+(f. If you need more than that, such as when 4 notes of dif)-.25 F
+(ferent)-.25 E .645
+(lengths occur on the same beat, it is possible to position e)69.336 376
+R .645(xtra notes manually)-.15 F 5.645(.M)-.65 G .645
+(anually positioned notes)-5.645 F(will not be included in MIDI output.)
+69.336 388 Q .092(First of all, unless the fourth v)69.336 406 R .092
+(oice is v)-.2 F .092(ertically f)-.15 F .092(ar a)-.1 F -.1(wa)-.15 G
+2.592(yf).1 G .091(rom the other tw)-2.592 F .091(o, you')-.1 F .091
+(ll probably need to reserv)-.1 F(e)-.15 E .313(some e)69.336 418 R .314
+(xtra space to the left or right of the other chords. This can be done \
+by adding a bit of padding to the)-.15 F 2.975(chord. If)69.336 430 R
+.475(you w)2.975 F .475(ant the e)-.1 F .474
+(xtra note on the left of the re)-.15 F .474(gular v)-.15 F .474
+(oices, add padding to whiche)-.2 F -.15(ve)-.25 G 2.974(rr).15 G -.15
+(eg)-2.974 G .474(ular v).15 F(oice)-.2 E .311(is leftmost. If you w)
+69.336 442 R .312(ant it on the right, the padding will ha)-.1 F .612
+-.15(ve t)-.2 H 2.812(og).15 G 2.812(oo)-2.812 G 2.812(nt)-2.812 G .312
+(he follo)-2.812 F .312(wing note, or on the bar line)-.25 F .174(if yo\
+u are on the last chord of a measure. The amount of padding to add may \
+ha)69.336 454 R .473 -.15(ve t)-.2 H 2.673(ob).15 G 2.673(ed)-2.673 G
+.173(etermined by trial)-2.673 F .308
+(and error; 5 stepsizes is a good \214rst guess. Ne)69.336 466 R .308
+(xt, set a location tag on one of the notes in one of the re)-.15 F
+(gular)-.15 E 2.676(groups. The)69.336 478 R .176
+(manually-positioned note will be placed relati)2.676 F .476 -.15(ve t)
+-.25 H 2.676(ot).15 G .176
+(hat location tag. The x will be slightly left)-2.676 F .055
+(or right of the west or east of the e)69.336 490 R .056
+(xisting group; something lik)-.15 F 2.556(e3s)-.1 G .056
+(tepsizes might be a good \214rst guess. The)-2.556 F 2.935(yc)69.336
+502 S .435(an be speci\214ed in terms of stepsizes up from the note you\
+ used for the location tag. Y)-2.935 F .434(ou can use a print)-1.1 F
+.143(statement using one of the special music characters, such as: dbl)
+69.336 514 R .144(whole, 1n, up2n, dn2n, up4n, up32n, etc. If)-.1 F .629
+(the note needs ledger lines, dots, or accidentals, these too ha)69.336
+526 R .928 -.15(ve t)-.2 H 3.128(ob).15 G 3.128(em)-3.128 G .628
+(anually positioned, which can be a)-3.128 F(bit trick)69.336 538 Q 1.3
+-.65(y. H)-.15 H(ere is a simple e).65 E(xample:)-.15 E/F1 10/Courier@0
+SF(score)105.336 556 Q(vscheme=3o)105.336 568 Q(beamstyle=4,4,4,4)
+105.336 580 Q(music)105.336 604 Q 6(11)105.336 616 S 6(:[)-6 G
+(pad 4] 4g =h; a; b; a;)-6 E 6(12)105.336 628 S 6(:4)-6 G(.c;8;2;)-6 E 6
+(13)105.336 640 S 6(:[)-6 G(down] 8e;; [ho 0] 2.f;)-6 E
+(print \(h.w - 2.3, h.y + 3\) "\\\(up2n\)")105.336 652 Q(bar)105.336 664
+Q EP
+%%Page: 136 142
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(36 -)-2.5 E 95.836 96 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 79 rlineto 384 0 rlineto 0 79 neg rlineto closepath stroke grestore
+EEND 128 684 384 384 -79 79 94.836 175 PBEGIN
+%%BeginDocument: mugex90.ps
+%%BoundingBox: 128 684 512 763
+save
+1039846316 1039845534 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+583.49 803.00 496.80 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+163.28 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+202.88 725.00 1.000000 4n
+0.70 setlinewidth
+206.56 725.75 moveto
+206.56 746.00 lineto stroke
+282.53 728.00 1.000000 4n
+286.21 728.75 moveto
+286.21 749.00 lineto stroke
+366.77 731.00 1.000000 4n
+370.45 731.75 moveto
+370.45 752.00 lineto stroke
+435.52 728.00 1.000000 4n
+439.20 728.75 moveto
+439.20 749.00 lineto stroke
+202.88 713.00 1.000000 4n
+212.14 710.00 1.000000 dot
+196.65 713.00 moveto
+209.11 713.00 lineto stroke
+199.20 712.25 moveto
+199.20 692.00 lineto stroke
+322.91 713.00 1.000000 4n
+316.68 713.00 moveto
+329.14 713.00 lineto stroke
+319.23 712.25 moveto
+319.23 692.00 lineto stroke
+322.25 692.00 1.000000 upflag
+366.77 713.00 1.000000 2n
+360.32 713.00 moveto
+373.21 713.00 lineto stroke
+362.87 712.25 moveto
+362.87 692.00 lineto stroke
+221.17 719.00 1.000000 4n
+217.49 718.25 moveto
+217.49 699.50 lineto stroke
+244.90 719.00 1.000000 4n
+241.21 718.25 moveto
+241.21 699.50 lineto stroke
+282.53 722.00 1.000000 2n
+292.01 722.00 1.000000 dot
+278.63 721.25 moveto
+278.63 701.00 lineto stroke
+newpath
+217.14 701.00 moveto
+241.56 701.00 lineto
+241.56 698.00 lineto
+217.14 698.00 lineto
+closepath
+fill
+restore
+%  S_PRHEAD
+11 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+191.95 734.00 moveto
+197.17 734.00 1.000000 up2n
+202.39 734.00 moveto
+%  S_BAR
+12 linenum
+0.70 setlinewidth
+496.45 743.00 moveto
+496.45 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .252(In this e)69.336 189 R .252
+(xample, 4 stepsizes of padding w)-.15 F .252
+(as added to the quarter note g of v)-.1 F .253(oice 1 on staf)-.2 F
+2.753(f1)-.25 G 2.753(.Al)-2.753 G .253(ocation tag)-2.753 F .561("h" w)
+69.336 201 R .561
+(as set to this note. After the information about the second v)-.1 F
+.561(oice on staf)-.2 F 3.061(f1)-.25 G 3.061(,ah)-3.061 G .561
+(alf note w)-3.061 F .561(as manually)-.1 F
+(placed 2.3 stepsizes left of the \214rst v)69.336 213 Q
+(oice and at pitch c+ \(3 steps up from the g\).)-.2 E .367(If you also\
+ need to place an accidental and/or dots, more padding should be reques\
+ted, and additional print)69.336 231 R(statements used for each item. F)
+69.336 243 Q(or e)-.15 E
+(xample, you could specify perhaps 5 stepsizes of padding, then add:)
+-.15 E/F1 10/Courier@0 SF(print \(h.w - 5, h.y + 3\) "\\\(flat\)")
+105.336 261 Q 95.836 270.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 79 rlineto 384 0 rlineto 0 79 neg rlineto closepath stroke grestore
+EEND 128 684 384 384 -79 79 94.836 349.6 PBEGIN
+%%BeginDocument: mugex91.ps
+%%BoundingBox: 128 684 512 763
+save
+1039846316 1039845534 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+583.49 803.00 496.80 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+163.28 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+205.81 725.00 1.000000 4n
+0.70 setlinewidth
+209.49 725.75 moveto
+209.49 746.00 lineto stroke
+284.66 728.00 1.000000 4n
+288.34 728.75 moveto
+288.34 749.00 lineto stroke
+368.05 731.00 1.000000 4n
+371.73 731.75 moveto
+371.73 752.00 lineto stroke
+436.10 728.00 1.000000 4n
+439.78 728.75 moveto
+439.78 749.00 lineto stroke
+205.81 713.00 1.000000 4n
+215.08 710.00 1.000000 dot
+199.58 713.00 moveto
+212.04 713.00 lineto stroke
+202.13 712.25 moveto
+202.13 692.00 lineto stroke
+324.64 713.00 1.000000 4n
+318.41 713.00 moveto
+330.87 713.00 lineto stroke
+320.96 712.25 moveto
+320.96 692.00 lineto stroke
+323.98 692.00 1.000000 upflag
+368.05 713.00 1.000000 2n
+361.60 713.00 moveto
+374.49 713.00 lineto stroke
+364.15 712.25 moveto
+364.15 692.00 lineto stroke
+224.11 719.00 1.000000 4n
+220.43 718.25 moveto
+220.43 699.50 lineto stroke
+247.43 719.00 1.000000 4n
+243.75 718.25 moveto
+243.75 699.50 lineto stroke
+284.66 722.00 1.000000 2n
+294.14 722.00 1.000000 dot
+280.76 721.25 moveto
+280.76 701.00 lineto stroke
+newpath
+220.08 701.00 moveto
+244.10 701.00 lineto
+244.10 698.00 lineto
+220.08 698.00 lineto
+closepath
+fill
+restore
+%  S_PRHEAD
+10 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+194.88 734.00 moveto
+200.10 734.00 1.000000 up2n
+205.32 734.00 moveto
+%  S_PRHEAD
+11 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+186.78 734.00 moveto
+190.52 734.00 1.000000 flat
+194.27 734.00 moveto
+%  S_BAR
+12 linenum
+0.70 setlinewidth
+496.45 743.00 moveto
+496.45 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF
+(to place a \215at sign in front of the c.)69.336 363.6 Q .361
+(Ledger lines needed by the notes also ha)69.336 381.6 R .661 -.15(ve t)
+-.2 H 2.861(ob).15 G 2.861(ep)-2.861 G .36(laced manually)-2.861 F 2.86
+(,u)-.65 G .36(sing the "line" command. If the note is)-2.86 F .177
+(more than three steps abo)69.336 393.6 R .478 -.15(ve o)-.15 H 2.678
+(rb).15 G(elo)-2.678 E 2.678(wt)-.25 G .178(he staf)-2.678 F .178
+(f, more than one ledger line w)-.25 F .178(ould be needed, and each w)
+-.1 F(ould)-.1 E 1.905(need to be speci\214ed separately)69.336 405.6 R
+4.404(.T)-.65 G 1.904(he y coordinate of the each ledger line w)-4.404 F
+1.904(ould be the same as the y)-.1 F .186(coordinate of the note, plus\
+ or minus some number of step sizes. The length of the line depends on \
+the note)69.336 417.6 R .051
+(head. About 4.5 stepsizes is a good estimate for most notes, b)69.336
+429.6 R .05(ut a double whole needs more lik)-.2 F 2.55(e6s)-.1 G
+(tepsizes.)-2.55 E 69.336 447.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.8 Brack)72.836 447.6 R
+(eting notes acr)-.14 E(oss staffs)-.252 E 69.336 465.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .914(In k)72.75 465.6 R -.15(ey)-.1 G .914
+(board music, sometimes a brack).15 F .914(et is dra)-.1 F .914
+(wn to indicate that notes from tw)-.15 F 3.414(os)-.1 G(taf)-3.414 E
+.915(fs are to be played)-.25 F .56(with the same hand. The brack)69.336
+477.6 R .56(et is really just a v)-.1 F .56
+(ertical line with short horizontal lines at each end. But if)-.15 F
+(you need to mak)69.336 489.6 Q 2.5(el)-.1 G(ots of brack)-2.5 E
+(ets, a macro with parameters can be v)-.1 E(ery helpful.)-.15 E EP
+%%Page: 137 143
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(37 -)-2.5 E/F1 10/Courier@0
+SF(score)105.336 96 Q(staffs=2)117.336 108 Q(staff 2)105.336 132 Q
+(clef=bass)117.336 144 Q(vscheme=2f)117.336 156 Q
+(// Define a macro to draw a bracket to show that notes on two)105.336
+180 Q(// different staffs are to be played with the same hand.)105.336
+192 Q(// The parameters are location tags for the top and bottom notes)
+105.336 204 Q(// to be included in the bracket.)105.336 216 Q
+(define BRACK\(TOP, BOT\))105.336 228 Q
+(// Draw a short horizontal line 0.5 stepsizes above the top note)
+105.336 240 Q
+(line \(TOP.w - 2, TOP.n + 0.5\) to \(TOP.w - 1, TOP.n + 0.5\))105.336
+252 Q(// Draw a vertical line from 0.5 stepsizes above the top note)
+105.336 264 Q(// to 0.5 stepsizes below the bottom note.)105.336 276 Q
+(// Do all the 'x' coordinates relative to the same note \(in)105.336
+288 Q
+(// this case the top\), so that if the top and bottom chord happen)
+105.336 300 Q
+(// to be different widths, the line will still be vertical.)105.336 312
+Q(line \(TOP.w - 2, TOP.n + 0.5\) to \(TOP.w - 2, BOT.s - 0.5\))105.336
+324 Q
+(// Draw short horizontal line just below and left of the bottom note.)
+105.336 336 Q
+(line \(TOP.w - 2, BOT.s - 0.5\) to \(TOP.w - 1, BOT.s - 0.5\))105.336
+348 Q(@)105.336 360 Q(music)105.336 384 Q
+(// For each chord that is to get a bracket, add some padding to)105.336
+408 Q(// make sure there is enough room, and set a location tag)105.336
+420 Q(// on the top and bottom notes.)105.336 432 Q
+(1: [pad 2] ce =a;[] df =b; [] d =c; [] ce =d;)105.336 444 Q
+(2: [pad 2] g =e; [] a =f; [] af =g; [] g =h;)105.336 456 Q 6(22)105.336
+468 S 6(:2)-6 G(cc-; 4g-; cc-;)-6 E
+(// Now draw the brackets, using the tags as parameters)105.336 480 Q
+(BRACK \(a, e\))105.336 492 Q(BRACK \(b, f\))105.336 504 Q
+(BRACK \(c, g\))105.336 516 Q(BRACK \(d, h\))105.336 528 Q(bar)105.336
+540 Q 127.836 549.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 141 rlineto 320 0 rlineto 0 141 neg rlineto closepath stroke grestore
+EEND 160 622 320 320 -141 141 126.836 690.6 PBEGIN
+%%BeginDocument: mugex92.ps
+%%BoundingBox: 160 622 480 763
+save
+1039846316 1039845534 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_SSV
+7 linenum
+%  S_FEED
+612.29 803.00 468.00 5 1.000000 1.000000 stf
+612.29 746.72 468.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+180.29 743.00 moveto
+180.29 662.72 lineto stroke
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+192.33 680.72 1.000000 fclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+231.72 719.00 1.000000 4n
+231.72 713.00 1.000000 4n
+225.49 713.00 moveto
+237.95 713.00 lineto stroke
+235.40 713.75 moveto
+235.40 740.00 lineto stroke
+291.66 722.00 1.000000 4n
+291.66 716.00 1.000000 4n
+295.34 716.75 moveto
+295.34 743.00 lineto stroke
+351.59 716.00 1.000000 4n
+355.27 716.75 moveto
+355.27 737.00 lineto stroke
+413.37 719.00 1.000000 4n
+413.37 713.00 1.000000 4n
+407.13 713.00 moveto
+419.60 713.00 lineto stroke
+417.05 713.75 moveto
+417.05 740.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+231.72 683.72 1.000000 4n
+0.70 setlinewidth
+235.40 684.47 moveto
+235.40 704.72 lineto stroke
+291.66 686.72 1.000000 4n
+295.34 687.47 moveto
+295.34 707.72 lineto stroke
+351.59 686.72 1.000000 4n
+351.59 680.72 1.000000 4n
+355.27 681.47 moveto
+355.27 707.72 lineto stroke
+413.37 683.72 1.000000 4n
+417.05 684.47 moveto
+417.05 704.72 lineto stroke
+231.72 671.72 1.000000 2n
+231.72 650.72 1.000000 2n
+225.27 650.72 moveto
+238.17 650.72 lineto stroke
+225.27 656.72 moveto
+238.17 656.72 lineto stroke
+227.82 670.97 moveto
+227.82 629.72 lineto stroke
+351.59 662.72 1.000000 4n
+347.91 661.97 moveto
+347.91 641.72 lineto stroke
+413.37 671.72 1.000000 4n
+413.37 650.72 1.000000 4n
+407.13 650.72 moveto
+419.60 650.72 lineto stroke
+407.13 656.72 moveto
+419.60 656.72 lineto stroke
+409.68 670.97 moveto
+409.68 629.72 lineto stroke
+restore
+%  S_LINE
+36 linenum
+0.70 setlinewidth
+221.69 723.78 moveto
+224.69 723.78 lineto stroke
+%  S_LINE
+36 linenum
+221.69 723.78 moveto
+221.69 678.95 lineto stroke
+%  S_LINE
+36 linenum
+221.69 678.95 moveto
+224.69 678.95 lineto stroke
+%  S_LINE
+37 linenum
+281.62 726.78 moveto
+284.62 726.78 lineto stroke
+%  S_LINE
+37 linenum
+281.62 726.78 moveto
+281.62 681.95 lineto stroke
+%  S_LINE
+37 linenum
+281.62 681.95 moveto
+284.62 681.95 lineto stroke
+%  S_LINE
+38 linenum
+341.56 720.78 moveto
+344.56 720.78 lineto stroke
+%  S_LINE
+38 linenum
+341.56 720.78 moveto
+341.56 675.95 lineto stroke
+%  S_LINE
+38 linenum
+341.56 675.95 moveto
+344.56 675.95 lineto stroke
+%  S_LINE
+39 linenum
+403.33 723.78 moveto
+406.33 723.78 lineto stroke
+%  S_LINE
+39 linenum
+403.33 723.78 moveto
+403.33 678.95 lineto stroke
+%  S_LINE
+39 linenum
+403.33 678.95 moveto
+406.33 678.95 lineto stroke
+%  S_BAR
+41 linenum
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+467.65 686.72 moveto
+467.65 662.72 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .956(Note that Mup supports cross-staf)
+69.336 710.6 R 3.456(fs)-.25 G .957(tems, which is another w)-3.456 F
+.957(ay to notate a chord that is split across tw)-.1 F(o)-.1 E(staf)
+69.336 722.6 Q(fs, and may often be a better choice.)-.25 E EP
+%%Page: 138 144
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(38 -)-2.5 E 69.336 102
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.9 Cr)72.836 102 R(oss-bar beaming)
+-.252 E 69.336 120 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF(Generally)71.945 120 Q 2.609(,b)-.65 G .109
+(eams do not cross bar lines, and Mup follo)-2.609 F .109(ws that rule.)
+-.25 F(Ho)5.109 E(we)-.25 E -.15(ve)-.25 G .909 -.4(r, i).15 H 2.609(fy)
+.4 G .109(ou w)-2.609 F .109(ant beams to cross a)-.1 F 1.192
+(bar line, there are at least tw)69.336 132 R 3.692(op)-.1 G 1.192
+(ossible approaches to getting the desired ef)-3.692 F 1.193
+(fect. The \214rst is to e)-.25 F(xplicitly)-.15 E .115
+(specify stem lengths such that all the beams in the v)69.336 144 R .114
+(arious measures will lie on the same line.)-.25 F -1.1(Yo)5.114 G 2.614
+(uc)1.1 G .114(an then)-2.614 F(use the line command to \214ll in the g)
+69.336 156 Q(aps in the beams across the bar lines.)-.05 E .32
+(The other approach is to dra)69.336 174 R 2.82(wi)-.15 G 2.82(nt)-2.82
+G .32(he bar line using the "line" construct.)-2.82 F 1.921 -.8(To d)
+5.321 H 2.821(ot).8 G .321(his you \214rst tell Mup that a)-2.821 F .136
+(measure is twice as long as is really is, so that you can put tw)69.336
+186 R 2.635(oa)-.1 G .135(ctual measures inside what Mup thinks is a)
+-2.635 F(single measure. Here is an e)69.336 198 Q(xample.)-.15 E/F1 10
+/Courier@0 SF(// First make an empty measure ending with an)105.336 216
+Q(// invisible bar. This is for the sole purpose)105.336 228 Q
+(// of allowing the real time signature to be)105.336 240 Q
+(// printed and would not be necessary if we)105.336 252 Q
+(// wanted to cross a bar line other than)105.336 264 Q
+(// the very first bar line of the piece.)105.336 276 Q(1: ms;)105.336
+288 Q(invisbar)105.336 300 Q
+(// Now, make the effective time signature twice)105.336 324 Q
+(// as long as the real time signature, but use 'n' so this fake)105.336
+336 Q(// time signature is not actually printed.)105.336 348 Q
+(// Set up for beaming across the entire double-length measure.)105.336
+360 Q(// \(You could could use other beamstyles if you wish, or custom \
+beaming.\))105.336 372 Q(score time=8/4n)105.336 384 Q(beamstyle=1/2)
+105.336 396 Q(music)105.336 408 Q
+(// Now do the double-length measure. On the chord)105.336 432 Q
+(// just after where we want a bar line, add some extra)105.336 444 Q
+(// padding and set a location tag so that we can draw)105.336 456 Q
+(// a bar line relative to the tag.)105.336 468 Q
+(1: 8c;e;f;d;g;e;f;a; [pad 3; =a]g;e;f;a;g;d+;4c+;)105.336 480 Q
+(// Also set a location tag on the next bar line,)105.336 492 Q
+(// so that we can get the vertical endpoints of the)105.336 504 Q
+(// bar line that we draw from the endpoints of the)105.336 516 Q
+(// normal Mup-supplied bar line.)105.336 528 Q(bar =b)105.336 540 Q
+(// Now draw the bar line that goes through the beam.)105.336 564 Q
+(// Use the horizontal position relative to the "a")105.336 576 Q
+(// location tag on the chord in the second actual measure,)105.336 588
+Q(// and get the vertical endpoints from the "b" tag)105.336 600 Q
+(// associated with the next bar line.)105.336 612 Q
+(line \(a.w + 1, b.y + 4\) to \(a.w + 1, b.y - 4\))105.336 624 Q 91.836
+633.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 392 0 rlineto 0 61 neg rlineto closepath stroke grestore
+EEND 128 702 392 392 -61 61 90.836 694.6 PBEGIN
+%%BeginDocument: mugex93.ps
+%%BoundingBox: 128 702 520 763
+save
+1039846316 1039845534 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+576.29 802.79 504.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+156.08 724.79 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+restore
+%  S_BAR
+10 linenum
+0.70 setlinewidth
+%  S_SSV
+17 linenum
+%  S_CLEFSIG
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+185.58 712.79 1.000000 4n
+179.34 712.79 moveto
+191.81 712.79 lineto stroke
+189.26 713.54 moveto
+189.26 740.15 lineto stroke
+205.67 718.79 1.000000 4n
+209.35 719.54 moveto
+209.35 741.17 lineto stroke
+225.76 721.79 1.000000 4n
+229.44 722.54 moveto
+229.44 742.20 lineto stroke
+245.85 715.79 1.000000 4n
+249.53 716.54 moveto
+249.53 743.23 lineto stroke
+265.94 724.79 1.000000 4n
+269.62 725.54 moveto
+269.62 744.26 lineto stroke
+286.03 718.79 1.000000 4n
+289.71 719.54 moveto
+289.71 745.28 lineto stroke
+306.12 721.79 1.000000 4n
+309.80 722.54 moveto
+309.80 746.31 lineto stroke
+324.71 727.79 1.000000 4n
+328.39 728.54 moveto
+328.39 747.26 lineto stroke
+346.30 724.79 1.000000 4n
+349.98 725.54 moveto
+349.98 748.36 lineto stroke
+366.39 718.79 1.000000 4n
+370.07 719.54 moveto
+370.07 749.39 lineto stroke
+386.48 721.79 1.000000 4n
+390.16 722.54 moveto
+390.16 750.42 lineto stroke
+406.57 727.79 1.000000 4n
+410.25 728.54 moveto
+410.25 751.45 lineto stroke
+426.66 724.79 1.000000 4n
+430.34 725.54 moveto
+430.34 752.47 lineto stroke
+446.75 736.79 1.000000 4n
+450.43 737.54 moveto
+450.43 753.50 lineto stroke
+470.16 733.79 1.000000 4n
+466.48 733.04 moveto
+466.48 712.79 lineto stroke
+newpath
+188.91 741.65 moveto
+450.78 755.00 lineto
+450.78 752.00 lineto
+188.91 738.65 lineto
+closepath
+fill
+restore
+%  S_BAR
+30 linenum
+0.70 setlinewidth
+503.65 742.79 moveto
+503.65 718.79 lineto stroke
+%  S_LINE
+37 linenum
+335.27 742.79 moveto
+335.27 718.79 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 714.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.10 Mixed)72.836 714.6 R(time signatur)
+3.5 E(es)-.252 E 69.336 732.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .649
+(Once in a while, music is written with dif)72.485 732.6 R .65
+(ferent time signatures on dif)-.25 F .65(ferent staf)-.25 F .65
+(fs. Mup does not support)-.25 F EP
+%%Page: 139 145
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(39 -)-2.5 E .158
+(this directly)69.336 96 R 2.658(,b)-.65 G .157(ut it is possible to si\
+mulate it for the case where the time signatures reduce to the same v)
+-2.858 F(alue,)-.25 E .85(for e)69.336 108 R .85
+(xample, 3/4 and 6/8 time \(since 6/8 tak)-.15 F .851
+(en as a fraction and reduced to lo)-.1 F .851(west terms is 3/4\). Y)
+-.25 F .851(ou can)-1.1 F(mak)69.336 120 Q 4.815(et)-.1 G 2.314(he outp\
+ut use both 3/4 and 6/8 by using a non-printing time signature, then pl\
+acing the time)-4.815 F(signatures manually)69.336 132 Q 5(.H)-.65 G
+(ere is an e)-5 E(xample of ho)-.15 E 2.5(wt)-.25 G 2.5(od)-2.5 G 2.5
+(ot)-2.5 G(hat:)-2.5 E/F1 10/Courier@0 SF(score)105.336 150 Q
+(// set time signature to 3/4 but don't print it)130.336 162 Q
+(time=3/4n)130.336 174 Q(staffs=2)130.336 186 Q(staff 1)105.336 210 Q
+(// We want this staff to be in 3/4 time,)130.336 222 Q
+(// so beam things in groups of)130.336 234 Q(// quarter note times.)
+130.336 246 Q(beamstyle=4,4,4)130.336 258 Q(staff 2)105.336 282 Q
+(// We want this staff to effectively be)130.336 294 Q
+(// in 6/8 time, so we'll beam things)130.336 306 Q
+(// in groups of dotted quarters.)130.336 318 Q(beamstyle=4., 4.)130.336
+330 Q(// In real 6/8 time, the time unit would)130.336 342 Q
+(// be eighth note, so make that the default)130.336 354 Q(timeunit=8)
+130.336 366 Q(music)105.336 390 Q
+(// Add padding to the first chord on at least one)105.336 414 Q
+(// of the staffs, to make room for the manually placed)105.336 426 Q
+(// time signatures, and set location tags)105.336 438 Q
+(1: [pad 5; =t] c; 8d; e; f; g;)105.336 450 Q(2: [=s] g; f; g; 4.c;)
+105.336 462 Q(// Manually place the time signatures)105.336 486 Q
+(// They are printed in 16-point newcentury bold font,)105.336 498 Q
+(// relative to the location tags that were set.)105.336 510 Q
+(// First print the 3/4)105.336 522 Q
+(print \(t.w - 4, t.y\) "\\f\(newcentury bold\)\\s\(16\)3";)105.336 534
+Q(print \(t.w - 4, t.y - 4\) "\\f\(newcentury bold\)\\s\(16\)4";)105.336
+546 Q(// Then print the 6/8)105.336 570 Q
+(print \(t.w - 4, s.y\) "\\f\(newcentury bold\)\\s\(16\)6";)105.336 582
+Q(print \(t.w - 4, s.y - 4\) "\\f\(newcentury bold\)\\s\(16\)8";)105.336
+594 Q(bar)105.336 606 Q 127.836 615.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 115 rlineto 320 0 rlineto 0 115 neg rlineto closepath stroke grestore
+EEND 160 648 320 320 -115 115 126.836 730.6 PBEGIN
+%%BeginDocument: mugex94.ps
+%%BoundingBox: 160 648 480 763
+save
+1039846316 1039845534 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_SSV
+9 linenum
+%  S_SSV
+15 linenum
+%  S_FEED
+612.29 803.00 468.00 5 1.000000 1.000000 stf
+612.29 749.00 468.00 5 1.000000 1.000000 stf
+0.70 setlinewidth
+180.29 743.00 moveto
+180.29 665.00 lineto stroke
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+192.08 671.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+237.65 713.00 1.000000 4n
+231.42 713.00 moveto
+243.88 713.00 lineto stroke
+241.33 713.75 moveto
+241.33 734.00 lineto stroke
+314.73 716.00 1.000000 4n
+318.41 716.75 moveto
+318.41 735.81 lineto stroke
+353.27 719.00 1.000000 4n
+356.96 719.75 moveto
+356.96 738.81 lineto stroke
+391.81 722.00 1.000000 4n
+395.50 722.75 moveto
+395.50 741.81 lineto stroke
+431.19 725.00 1.000000 4n
+434.88 725.75 moveto
+434.88 744.81 lineto stroke
+newpath
+318.06 737.31 moveto
+357.31 740.31 lineto
+357.31 737.31 lineto
+318.06 734.31 lineto
+closepath
+fill
+newpath
+395.15 743.31 moveto
+435.23 746.31 lineto
+435.23 743.31 lineto
+395.15 740.31 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+237.65 671.00 1.000000 4n
+0.70 setlinewidth
+241.33 671.75 moveto
+241.33 690.50 lineto stroke
+276.19 668.00 1.000000 4n
+279.87 668.75 moveto
+279.87 690.50 lineto stroke
+314.73 671.00 1.000000 4n
+318.41 671.75 moveto
+318.41 690.50 lineto stroke
+353.27 659.00 1.000000 4n
+362.54 662.00 1.000000 dot
+347.04 659.00 moveto
+359.51 659.00 lineto stroke
+356.96 659.75 moveto
+356.96 680.00 lineto stroke
+newpath
+240.98 692.00 moveto
+318.76 692.00 lineto
+318.76 689.00 lineto
+240.98 689.00 lineto
+closepath
+fill
+restore
+%  S_PRHEAD
+35 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+205.62 731.00 moveto
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+(3) show
+%  S_PRHEAD
+36 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+205.62 719.00 moveto
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+(4) show
+%  S_PRHEAD
+39 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+205.62 677.00 moveto
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+(6) show
+%  S_PRHEAD
+40 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+205.62 665.00 moveto
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+(8) show
+%  S_BAR
+42 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+467.65 689.00 moveto
+467.65 665.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND EP
+%%Page: 140 146
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(40 -)-2.5 E 69.336 102
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.11 Differ)72.836 102 R(ent mar)-.252 E
+(gins f)-.14 E(or odd/e)-.35 E -.14(ve)-.21 G 3.5(np).14 G(ages)-3.5 E
+69.336 120 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .629(Sometimes you may w)72.465 120 R .629
+(ant to mak)-.1 F 3.129(em)-.1 G(ar)-3.129 E .629(gins dif)-.18 F .629
+(ferent for odd and e)-.25 F -.15(ve)-.25 G 3.13(np).15 G .63
+(ages, for e)-3.13 F .63(xample, if you w)-.15 F .63(ant to)-.1 F 1.184
+(put music in a ringed binder)69.336 132 R 3.684(,a)-.4 G 1.184
+(nd thus w)-3.684 F 1.183(ant to of)-.1 F 1.183
+(fset the printing on the pages to a)-.25 F -.2(vo)-.2 G 1.183
+(id the holes in the).2 F(paper)69.336 144 Q 6.117(.W)-.55 G 1.117
+(hile you can')-6.117 F 3.617(td)-.18 G 3.617(ot)-3.617 G 1.117
+(his directly)-3.617 F 3.618(,y)-.65 G 1.118(ou can get the desired ef)
+-3.618 F 1.118(fect by using appropriate macros, and)-.25 F
+(then printing the odd and e)69.336 156 Q -.15(ve)-.25 G 2.5(np).15 G
+(ages in tw)-2.5 E 2.5(op)-.1 G(asses.)-2.5 E
+(In the Mup input \214le, put something lik)69.336 174 Q 2.5(et)-.1 G
+(his:)-2.5 E/F1 10/Courier@0 SF(score)105.336 192 Q
+(// if the WIDELEFT macro is set,)130.336 204 Q
+(// make the left margin extra wide,)130.336 216 Q
+(// otherwise if WIDERIGHT is set,)130.336 228 Q
+(// make the right margin extra wide,)130.336 240 Q
+(// otherwise make them equal.)130.336 252 Q(ifdef WIDELEFT)130.336 264
+Q(leftmargin=1)155.336 276 Q(rightmargin=0.5)155.336 288 Q
+(else ifdef WIDERIGHT)130.336 300 Q(leftmargin=0.5)155.336 312 Q
+(rightmargin=1)155.336 324 Q(else)130.336 336 Q(leftmargin=0.75)155.336
+348 Q(rightmargin=0.75)155.336 360 Q(endif endif)130.336 372 Q F0
+(Then when printing, print in tw)69.336 398 Q 2.5(op)-.1 G
+(asses. First print the odd pages:)-2.5 E F1
+(mupprnt -oodd -DWIDELEFT file.mup)105.336 416 Q F0
+(Then turn the paper o)69.336 436 Q -.15(ve)-.15 G 2.5(ra).15 G
+(nd print the e)-2.5 E -.15(ve)-.25 G 2.5(np).15 G(ages:)-2.5 E F1
+(mupprnt -oeven -DWIDERIGHT file.mup)105.336 454 Q F0 .577
+(This idea should w)69.336 480 R .577
+(ork as long as the sum of the left and right mar)-.1 F .576
+(gins are equal between the WIDELEFT)-.18 F 1.073
+(and WIDERIGHT parts. Otherwise you may get dif)69.336 492 R 1.073
+(ferent numbers of measures on each page in the tw)-.25 F(o)-.1 E
+(runs, and you')69.336 504 Q(ll end up missing or repeating measures.)
+-.1 E 69.336 522 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.12 Marking)72.836 522 R
+(complicated tempo changes)3.5 E 69.336 540 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .049
+(Sometimes you may wish to indicate tempo changes by sho)71.885 540 R
+.048(wing 2 note v)-.25 F .048(alues with an equals sign between)-.25 F
+.273(them. F)69.336 552 R .273(or simple cases, this is f)-.15 F .274
+(airly straightforw)-.1 F .274(ard, b)-.1 F .274(ut if you w)-.2 F .274
+(ant to include beamed notes or a triplet, a)-.1 F .157(little more w)
+69.336 564 R .157
+(ork is required. Another use of this notation is to sho)-.1 F 2.657(wt)
+-.25 G .156(hat the music is to be played in "swing)-2.657 F .73
+(time," as in this e)69.336 576 R .73(xample, which has tw)-.15 F 3.23
+(oo)-.1 G .73
+(rdinary eight notes on one side of the equals sign, and a triplet)-3.23
+F(made up of a quarter and eighth note on the other:)69.336 588 Q EP
+%%Page: 141 147
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(41 -)-2.5 E/F1 10/Courier@0
+SF(score)105.336 96 Q(// This example assumes "size" is set to 15)
+130.336 108 Q(size=15)130.336 120 Q(beamstyle=4,4)130.336 132 Q(music)
+105.336 156 Q(// set a location tag)105.336 180 Q(1: [=c] 8c+;a;g;f;)
+105.336 192 Q(// set X and Y to where the first note will be placed)
+105.336 216 Q(define X c.x - 3 @)105.336 228 Q(define Y c.y + 5 @)
+105.336 240 Q(// print "straight 8ths = triplet quarter plus 8th")
+105.336 264 Q(// print the basic notes and equal sign)105.336 288 Q
+(print \(X, Y\) "\\\(smup4n\))105.336 300 Q 6(\\\(smup4n\) =)12 F 6
+(\\\(smup4n\) \\\(smup8n\)")6 F
+(// print the beam between the straight 8th notes)105.336 324 Q
+(wide line \(X + 2.1, Y + 5.5\) to \(X + 7.2, Y + 5.5\))105.336 336 Q
+(// now do the triplet bracket)105.336 360 Q(line \(X + 14.7, Y + 7.0\))
+105.336 372 Q(to \(X + 17.6, Y + 7.0\) // horz left top segment)12 E
+(line \(X + 19.4, Y + 7.0\))105.336 384 Q
+(to \(X + 22.5, Y + 7.0\) // horz right top segment)12 E(line \(X + 14.\
+7, Y + 7.05\) to \(X + 14.7, Y + 5.3\) // vert left side segment)105.336
+396 Q(line \(X + 22.5, Y + 7.05\) to \(X + 22.5, Y + 5.3\) // vert righ\
+t side segment)105.336 408 Q
+(// print the 3 in the middle of the bracket)105.336 432 Q
+(print \(X + 17.9, Y + 6.1\) "\\s\(8\)\\f\(TI\)3")105.336 444 Q
+(// the 3 for the triplet)10 E(bar)105.336 468 Q 151.836 477.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 77 rlineto 272 0 rlineto 0 77 neg rlineto closepath stroke grestore
+EEND 184 701 272 272 -77 77 150.836 554.6 PBEGIN
+%%BeginDocument: mugex95.ps
+%%BoundingBox: 184 701 456 778
+save
+1039846316 1039845534 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+633.89 803.00 446.40 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+213.68 725.00 1.000000 gclef
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+225.47 731.00 moveto
+(2) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+225.47 718.98 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+257.04 734.00 1.000000 4n
+0.70 setlinewidth
+253.35 733.25 moveto
+253.35 715.00 lineto stroke
+304.99 728.00 1.000000 4n
+301.31 727.25 moveto
+301.31 709.00 lineto stroke
+352.95 725.00 1.000000 4n
+356.63 725.75 moveto
+356.63 744.25 lineto stroke
+401.75 722.00 1.000000 4n
+405.43 722.75 moveto
+405.43 741.25 lineto stroke
+newpath
+253.00 716.50 moveto
+301.66 710.50 lineto
+301.66 707.50 lineto
+253.00 713.50 lineto
+closepath
+fill
+newpath
+356.28 745.75 moveto
+405.78 742.75 lineto
+405.78 739.75 lineto
+356.28 742.75 lineto
+closepath
+fill
+restore
+%  S_PRHEAD
+22 linenum
+/Times-Roman findfont
+15 scalefont
+setfont
+248.04 746.00 moveto
+251.84 748.24 0.750000 up4n
+255.65 746.00 moveto
+(  ) show
+267.02 748.24 0.750000 up4n
+270.82 746.00 moveto
+(  = ) show
+294.43 748.24 0.750000 up4n
+298.24 746.00 moveto
+(  ) show
+311.63 748.24 0.750000 up8n
+317.46 746.00 moveto
+%  S_LINE
+24 linenum
+3.00 setlinewidth
+254.34 762.50 moveto
+269.64 762.50 lineto stroke
+%  S_LINE
+27 linenum
+0.70 setlinewidth
+292.14 767.00 moveto
+300.84 767.00 lineto stroke
+%  S_LINE
+28 linenum
+306.24 767.00 moveto
+315.54 767.00 lineto stroke
+%  S_LINE
+29 linenum
+292.14 767.15 moveto
+292.14 761.90 lineto stroke
+%  S_LINE
+30 linenum
+315.54 767.15 moveto
+315.54 761.90 lineto stroke
+%  S_PRHEAD
+34 linenum
+/Times-Roman findfont
+15 scalefont
+setfont
+301.74 764.30 moveto
+/Times-Italic findfont
+8 scalefont
+setfont
+(3) show
+%  S_BAR
+36 linenum
+446.05 743.00 moveto
+446.05 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /Times-Italic /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF .14(Note that if you w)69.336 574.6 R
+.14(ant a piece to be played in swing time, you may also w)-.1 F .139
+(ant to set the swingunit parameter)-.1 F(,)-.4 E(which will mak)69.336
+586.6 Q 2.5(et)-.1 G(he MIDI output use swing time.)-2.5 E 69.336 604.6
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.13 Placing)72.836 604.6 R(se)3.5 E
+-.14(ve)-.21 G(ral songs on one page).14 E 69.336 622.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .657
+(Sometimes you may wish to print more than one song on the same page.)
+72.493 622.6 R .657(While Mup considers all of its)5.657 F .188
+(input to be a single song, it is possible to get the ef)69.336 634.6 R
+.188(fect of separate songs.)-.25 F .188
+(First of all, on the last bar line of)5.188 F 1.135
+(\214rst song, use "hidechanges.")69.336 646.6 R 1.135(That w)6.135 F
+(ay)-.1 E 3.635(,i)-.65 G 3.635(ft)-3.635 G 1.135(he k)-3.635 F 1.436
+-.15(ey o)-.1 H 3.636(ra).15 G -.15(ny)-3.636 G 1.136(thing is dif).15 F
+1.136(ferent in the ne)-.25 F 1.136(xt song, Mup w)-.15 F(on')-.1 E(t)
+-.18 E .384(print the changes at the end of the \214rst song. Then use \
+a "block" for printing the titles for the second song.)69.336 658.6 R
+(Here is an e)69.336 670.6 Q(xample:)-.15 E EP
+%%Page: 142 148
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(42 -)-2.5 E/F1 10/Courier@0
+SF(score)105.336 96 Q(scoresep=10,14)130.336 108 Q(label="")130.336 120
+Q(header)105.336 132 Q(title \(18\) "Title for first song")130.336 144 Q
+(music)105.336 156 Q(1: c;d;e;f;)105.336 168 Q(bar)105.336 180 Q
+(1: f;e;d;c;)105.336 192 Q(bar)105.336 204 Q(1: c;d;e;f;)105.336 216 Q
+(bar)105.336 228 Q(1: f;d;2c;)105.336 240 Q(endbar)105.336 252 Q
+(// force time signature to be printed on next score)105.336 276 Q
+(// by changing the time, but only for an invisible measure)105.336 288
+Q(score time=5/4n)105.336 300 Q(music)105.336 312 Q(1: ms;)105.336 324 Q
+(invisbar hidechanges)105.336 336 Q
+(// Force the block closer to next score,)105.336 360 Q
+(// so it will better match the spacing of)105.336 372 Q
+(// the title of the first song.)105.336 384 Q(score scoresep=6,6)
+105.336 396 Q(// print title for second song)105.336 408 Q(block)105.336
+420 Q(title \(30\) " ")105.336 432 Q
+(// Allow some extra room above title)18 E
+(title \(18\) "Title for second song")105.336 444 Q(score)105.336 468 Q
+(// Set up for second song)130.336 480 Q(time=4/4)130.336 492 Q(key=1&)
+130.336 504 Q(music)105.336 528 Q(1: d;e;2f;)105.336 540 Q(bar)105.336
+552 Q(// Put score spacing back to original)105.336 564 Q
+(score scoresep=10,14)105.336 576 Q(music)105.336 588 Q(1: a;2g;4f;)
+105.336 600 Q(bar)105.336 612 Q(1: 2e;4c;d;)105.336 624 Q(bar)105.336
+636 Q(1: 2g;f;)105.336 648 Q(endbar)105.336 660 Q EP
+%%Page: 143 149
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(43 -)-2.5 E 111.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 327 rlineto 352 0 rlineto 0 327 neg rlineto closepath stroke grestore
+EEND 128 435 352 352 -327 327 110.836 423 PBEGIN
+%%BeginDocument: mugex96.ps
+%%BoundingBox: 128 435 480 762
+save
+1039846316 1039845534 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+579.00 777.13 468.00 5 1.000000 1.000000 stf
+/Times-Roman findfont
+12 scalefont
+setfont
+144.00 705.13 moveto
+%  S_CLEFSIG
+158.79 699.13 1.000000 gclef
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+170.58 705.13 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+170.58 693.11 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+188.51 687.13 1.000000 4n
+0.70 setlinewidth
+182.28 687.13 moveto
+194.74 687.13 lineto stroke
+192.19 687.88 moveto
+192.19 708.13 lineto stroke
+221.95 690.13 1.000000 4n
+225.63 690.88 moveto
+225.63 711.13 lineto stroke
+255.39 693.13 1.000000 4n
+259.07 693.88 moveto
+259.07 714.13 lineto stroke
+289.66 696.13 1.000000 4n
+293.35 696.88 moveto
+293.35 717.13 lineto stroke
+restore
+%  S_BAR
+12 linenum
+0.70 setlinewidth
+321.87 717.13 moveto
+321.87 693.13 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+334.29 696.13 1.000000 4n
+337.98 696.88 moveto
+337.98 717.13 lineto stroke
+367.73 693.13 1.000000 4n
+371.41 693.88 moveto
+371.41 714.13 lineto stroke
+401.17 690.13 1.000000 4n
+404.85 690.88 moveto
+404.85 711.13 lineto stroke
+435.45 687.13 1.000000 4n
+429.21 687.13 moveto
+441.68 687.13 lineto stroke
+439.13 687.88 moveto
+439.13 708.13 lineto stroke
+restore
+%  S_BAR
+14 linenum
+0.70 setlinewidth
+467.65 717.13 moveto
+467.65 693.13 lineto stroke
+%  S_FEED
+576.00 711.13 468.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+155.79 633.13 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+185.54 621.13 1.000000 4n
+179.31 621.13 moveto
+191.78 621.13 lineto stroke
+189.23 621.88 moveto
+189.23 642.13 lineto stroke
+219.18 624.13 1.000000 4n
+222.86 624.88 moveto
+222.86 645.13 lineto stroke
+252.81 627.13 1.000000 4n
+256.49 627.88 moveto
+256.49 648.13 lineto stroke
+287.28 630.13 1.000000 4n
+290.96 630.88 moveto
+290.96 651.13 lineto stroke
+restore
+%  S_BAR
+16 linenum
+0.70 setlinewidth
+319.65 651.13 moveto
+319.65 627.13 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+332.11 630.13 1.000000 4n
+335.79 630.88 moveto
+335.79 651.13 lineto stroke
+365.70 624.13 1.000000 4n
+369.38 624.88 moveto
+369.38 645.13 lineto stroke
+404.33 621.13 1.000000 2n
+397.88 621.13 moveto
+410.78 621.13 lineto stroke
+408.23 621.88 moveto
+408.23 642.13 lineto stroke
+restore
+%  S_BAR
+17 linenum
+0.70 setlinewidth
+462.50 651.13 moveto
+462.50 627.13 lineto stroke
+3.00 setlinewidth
+466.50 651.13 moveto
+466.50 627.13 lineto stroke
+0.70 setlinewidth
+%  S_SSV
+21 linenum
+%  S_CLEFSIG
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+restore
+%  S_BAR
+24 linenum
+0.70 setlinewidth
+%  S_SSV
+29 linenum
+%  S_CLEFSIG
+%  S_FEED
+31 linenum
+%  S_BLOCKHEAD
+31 linenum
+/Times-Roman findfont
+30 scalefont
+setfont
+302.22 584.83 moveto
+( ) show
+/Times-Roman findfont
+18 scalefont
+setfont
+229.91 565.60 moveto
+(Title for second song) show
+%  S_SSV
+36 linenum
+%  S_FEED
+576.00 601.95 468.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+155.79 523.95 1.000000 gclef
+169.33 529.95 1.000000 flat
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+175.07 529.95 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+175.07 517.94 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+204.25 514.95 1.000000 4n
+207.93 515.70 moveto
+207.93 535.95 lineto stroke
+237.87 517.95 1.000000 4n
+241.55 518.70 moveto
+241.55 538.95 lineto stroke
+276.52 520.95 1.000000 2n
+280.41 521.70 moveto
+280.41 541.95 lineto stroke
+restore
+%  S_BAR
+43 linenum
+0.70 setlinewidth
+329.72 541.95 moveto
+329.72 517.95 lineto stroke
+%  S_SSV
+44 linenum
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+342.15 526.95 1.000000 4n
+345.83 527.70 moveto
+345.83 547.95 lineto stroke
+379.96 523.95 1.000000 2n
+383.85 524.70 moveto
+383.85 544.95 lineto stroke
+435.27 520.95 1.000000 4n
+438.95 521.70 moveto
+438.95 541.95 lineto stroke
+restore
+%  S_BAR
+48 linenum
+0.70 setlinewidth
+467.65 541.95 moveto
+467.65 517.95 lineto stroke
+%  S_FEED
+576.00 535.95 468.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+155.79 457.95 1.000000 gclef
+169.33 463.95 1.000000 flat
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+197.93 451.95 1.000000 2n
+201.83 452.70 moveto
+201.83 472.95 lineto stroke
+255.50 445.95 1.000000 4n
+249.27 445.95 moveto
+261.73 445.95 lineto stroke
+259.18 446.70 moveto
+259.18 466.95 lineto stroke
+291.91 448.95 1.000000 4n
+295.59 449.70 moveto
+295.59 469.95 lineto stroke
+restore
+%  S_BAR
+50 linenum
+0.70 setlinewidth
+325.89 475.95 moveto
+325.89 451.95 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+343.21 457.95 1.000000 2n
+347.11 458.70 moveto
+347.11 478.95 lineto stroke
+406.02 454.95 1.000000 2n
+409.91 455.70 moveto
+409.91 475.95 lineto stroke
+restore
+%  S_BAR
+51 linenum
+0.70 setlinewidth
+462.50 475.95 moveto
+462.50 451.95 lineto stroke
+3.00 setlinewidth
+466.50 475.95 moveto
+466.50 451.95 lineto stroke
+0.70 setlinewidth
+%  Printing header/footer
+/Times-Roman findfont
+18 scalefont
+setfont
+240.44 741.42 moveto
+(Title for first song) show
+showpage
+restore
+%%DocumentFonts: /Times-Roman /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 443 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.14 Cadenzas)72.836 443 R 69.336 461
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .59(Cadenzas or cadenza-lik)72.426 461 R
+3.09(ep)-.1 G .591(assages are often written with an arbitrary number o\
+f notes per measure.)-3.09 F(One)5.591 E -.1(wa)69.336 473 S 2.5(yt).1 G
+2.5(oa)-2.5 G(ccomplish this is to use a tuplet with the appropriate nu\
+mber of notes.)-2.5 E/F1 10/Courier@0 SF(score)105.336 491 Q(time = 3/4)
+130.336 503 Q(music)105.336 527 Q
+(1: { [cue]... 16g- bm;b-;c;d;e;f;g;a;b;a;g;f;e;d;c;b-;g- ebm;} 17n,2.;)
+105.336 551 Q(bar)105.336 563 Q 127.836 572.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 68 rlineto 320 0 rlineto 0 68 neg rlineto closepath stroke grestore
+EEND 160 695 320 320 -68 68 126.836 640.6 PBEGIN
+%%BeginDocument: mugex97.ps
+%%BoundingBox: 160 695 480 763
+save
+1039846316 1039845534 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+612.29 803.00 468.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+203.87 731.00 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+203.87 718.98 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+228.64 704.00 0.583333 4n
+0.70 setlinewidth
+224.09 707.00 moveto
+233.20 707.00 lineto stroke
+224.09 713.00 moveto
+233.20 713.00 lineto stroke
+230.65 704.49 moveto
+230.65 742.02 lineto stroke
+242.57 710.00 0.583333 4n
+238.02 713.00 moveto
+247.12 713.00 lineto stroke
+244.57 710.49 moveto
+244.57 742.02 lineto stroke
+256.49 713.00 0.583333 4n
+251.94 713.00 moveto
+261.04 713.00 lineto stroke
+258.49 713.49 moveto
+258.49 742.02 lineto stroke
+270.42 716.00 0.583333 4n
+272.42 716.49 moveto
+272.42 742.03 lineto stroke
+284.34 719.00 0.583333 4n
+286.34 719.49 moveto
+286.34 742.02 lineto stroke
+298.26 722.00 0.583333 4n
+300.27 722.49 moveto
+300.27 742.02 lineto stroke
+312.19 725.00 0.583333 4n
+314.19 725.49 moveto
+314.19 742.03 lineto stroke
+326.11 728.00 0.583333 4n
+328.11 728.49 moveto
+328.11 742.02 lineto stroke
+340.04 731.00 0.583333 4n
+342.04 731.49 moveto
+342.04 742.02 lineto stroke
+353.96 728.00 0.583333 4n
+355.96 728.49 moveto
+355.96 742.02 lineto stroke
+367.88 725.00 0.583333 4n
+369.89 725.49 moveto
+369.89 742.03 lineto stroke
+381.81 722.00 0.583333 4n
+383.81 722.49 moveto
+383.81 742.02 lineto stroke
+395.73 719.00 0.583333 4n
+397.73 719.49 moveto
+397.73 742.02 lineto stroke
+409.66 716.00 0.583333 4n
+411.66 716.49 moveto
+411.66 742.03 lineto stroke
+423.58 713.00 0.583333 4n
+419.03 713.00 moveto
+428.13 713.00 lineto stroke
+425.58 713.49 moveto
+425.58 742.02 lineto stroke
+437.51 710.00 0.583333 4n
+432.95 713.00 moveto
+442.06 713.00 lineto stroke
+439.51 710.49 moveto
+439.51 742.02 lineto stroke
+451.99 704.00 0.583333 4n
+447.44 707.00 moveto
+456.54 707.00 lineto stroke
+447.44 713.00 moveto
+456.54 713.00 lineto stroke
+453.99 704.49 moveto
+453.99 742.02 lineto stroke
+newpath
+230.42 743.00 moveto
+454.22 743.00 lineto
+454.22 741.05 lineto
+230.42 741.05 lineto
+closepath
+fill
+newpath
+230.42 739.00 moveto
+454.22 739.00 lineto
+454.22 737.05 lineto
+230.42 737.05 lineto
+closepath
+fill
+restore
+%  S_BAR
+10 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 660.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.15 T)72.836 660.6 R(ransposition)
+-1.036 E 69.336 678.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .933(The transpose and addtranspose paramet\
+ers can be used to transpose the pitches for a staf)72.77 678.6 R 3.433
+(fo)-.25 G 3.433(rt)-3.433 G .933(he whole)-3.433 F 2.5(score. The)
+69.336 690.6 R(follo)2.5 E(wing table sho)-.25 E
+(ws what transposition v)-.25 E(alues to use for dif)-.25 E
+(ferent interv)-.25 E(als.)-.25 E EP
+%%Page: 144 150
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(44 -)-2.5 E .4 LW 398.736
+88.5 171.936 88.5 DL/F1 10/Times-Bold@0 SF 12.5
+(halfsteps tranposition alter)176.936 98 R(nate transposition)-.15 E
+398.736 102.5 171.936 102.5 DL F0 47.78(0p)176.936 112 S(erfect 1)-47.78
+E(diminished 2)31.97 E 47.78(1a)176.936 124 S(ugmented 1)-47.78 E
+(minor 2)15.85 E 47.78(2m)176.936 136 S(ajor 2)-47.78 E(diminished 3)
+36.4 E 47.78(3a)176.936 148 S(ugmented 2)-47.78 E(minor 3)15.85 E 47.78
+(4m)176.936 160 S(ajor 3)-47.78 E(diminished 4)36.4 E 47.78(5a)176.936
+172 S(ugmented 3)-47.78 E(perfect 4)15.85 E 47.78(6a)176.936 184 S
+(ugmented 4)-47.78 E(diminished 5)15.85 E 47.78(7p)176.936 196 S
+(erfect 5)-47.78 E(diminished 6)31.97 E 47.78(8a)176.936 208 S
+(ugmented 5)-47.78 E(minor 6)15.85 E 47.78(9m)176.936 220 S(ajor 6)
+-47.78 E(diminished 7)36.4 E 40.28(10 augmented)176.936 232 R 15.85(6m)
+2.5 G(inor 7)-15.85 E 40.28(11 major)176.936 244 R 36.4(7d)2.5 G
+(iminished 8)-36.4 E 398.736 248.5 171.936 248.5 DL 289.446 88.5 289.446
+248.5 DL 222.216 88.5 222.216 248.5 DL 398.736 88.5 398.736 248.5 DL
+171.936 88.5 171.936 248.5 DL 1.21(This table continues in a similar w)
+69.336 262 R 1.21(ay for interv)-.1 F 1.21(als be)-.25 F 1.21
+(yond an octa)-.15 F -.15(ve)-.2 G 6.21(.F).15 G 1.21
+(or each number of halfsteps you)-6.36 F -.1(wa)69.336 274 S .457
+(nt to transpose, there is more than one w).1 F .456
+(ay the transpose and addtranspose parameters can be speci\214ed,)-.1 F
+.579(as sho)69.336 286 R .579(wn by this table.)-.25 F .579(This allo)
+5.579 F .579(ws to you control whether a sharp k)-.25 F .88 -.15(ey o)
+-.1 H 3.08(ra\215).15 G .58(at k)-3.08 F .88 -.15(ey i)-.1 H 3.08(st).15
+G 3.08(ob)-3.08 G 3.08(eu)-3.08 G .58(sed in cases)-3.08 F .686
+(where there is a choice.)69.336 298 R -.15(Fo)5.686 G 3.185(re).15 G
+.685(xample, if the k)-3.335 F .985 -.15(ey s)-.1 H .685
+(ignature has three sharps, and you w).15 F .685(ant to transpose up)-.1
+F(tw)69.336 310 Q 2.5(oh)-.1 G(alfsteps, you could say either)-2.5 E/F2
+10/Courier@0 SF(transpose = up maj 2)130.336 328 Q F0(or)69.336 348 Q F2
+(transpose = up dim 3)130.336 366 Q F0 .709
+(The \214rst will result in a k)69.336 386 R 1.009 -.15(ey o)-.1 H 3.209
+<668c>.15 G 1.009 -.15(ve s)-3.209 H .71
+(harps, and the second will result in se).15 F -.15(ve)-.25 G 3.21<6e8d>
+.15 G 3.21(ats. These)-3.21 F .71(are equi)3.21 F -.25(va)-.25 G(lent)
+.25 E -.1(ke)69.336 398 S .754(ys; in major for e)-.05 F .754
+(xample, the)-.15 F 3.254(ya)-.15 G .754
+(re B and C \215at, which are the same note.)-3.254 F .753
+(It is up to you to choose the)5.753 F -.1(wa)69.336 410 S 3.256(yy).1 G
+.756(ou w)-3.256 F .756(ould lik)-.1 F 3.256(ei)-.1 G 3.256(tt)-3.256 G
+3.256(ob)-3.256 G 3.256(ep)-3.256 G 3.256(rinted. But)-3.256 F .756
+(no k)3.256 F 1.056 -.15(ey i)-.1 H 3.256(sa).15 G(llo)-3.256 E .756
+(wed to ha)-.25 F 1.057 -.15(ve m)-.2 H .757(ore than se).15 F -.15(ve)
+-.25 G 3.257(ns).15 G .757(harps or \215ats, so in)-3.257 F .13
+(most cases only one of the w)69.336 422 R .13(ays will result in a v)
+-.1 F .13(alid k)-.25 F -.15(ey)-.1 G 2.63(,a)-.5 G .13(nd the other w)
+-2.63 F .13(ay will result in an error message.)-.1 F 1.02
+(The transpose and addtranspose parameters are allo)69.336 440 R 1.021
+(wed in score and staf)-.25 F 3.521(fc)-.25 G(onte)-3.521 E 1.021
+(xts, so the)-.15 F 3.521(yc)-.15 G 1.021(an be set to)-3.521 F(dif)
+69.336 452 Q .99(ferent v)-.25 F .99(alues on dif)-.25 F .99
+(ferent staf)-.25 F .99(fs, and on the score as a whole.)-.25 F .99
+(This is useful for printing scores where)5.99 F 2.375
+(some of the instruments are transposing instruments \(lik)69.336 464 R
+4.875(eB)-.1 G 2.375(-\215at clarinet\).)-4.875 F -1.1(Yo)7.375 G 4.875
+(uc)1.1 G 2.375(an set the transpose)-4.875 F .802
+(parameter on speci\214c staf)69.336 476 R .802(fs to appropriate v)-.25
+F .801(alues for the transposing instruments. Then if you decide you)
+-.25 F -.1(wa)69.336 488 S .579(nt to mo).1 F .879 -.15(ve t)-.15 H .579
+(he entire score to a ne).15 F 3.079(wk)-.25 G -.15(ey)-3.179 G 3.079
+(,y)-.5 G .58(ou can set the addtranspose parameter in score conte)
+-3.079 F 3.08(xt. Y)-.15 F(ou)-1.1 E 2.316
+(can enter all the music at true pitch, b)69.336 500 R 2.315
+(ut print the score and/or the indi)-.2 F 2.315
+(vidual parts with the correct)-.25 F(transposition.)69.336 512 Q 1.964
+(Another use for setting dif)69.336 530 R 1.964(ferent transposition v)
+-.25 F 1.964(alues is the follo)-.25 F 1.964
+(wing trick, useful in guitar music for)-.25 F .665
+(printing both the real chords and chords for capo.)69.336 542 R(Say)
+5.665 E 3.165(,f)-.65 G .665(or e)-3.165 F .665(xample, you ha)-.15 F
+.965 -.15(ve a s)-.2 H .664(ong that is in B \215at, b).15 F(ut)-.2 E
+.232(the guitar is to use a capo on the third fret, and play in the k)
+69.336 554 R .532 -.15(ey o)-.1 H 2.732(fG).15 G 5.232(.Y)-2.732 G .232
+(ou could de\214ne the follo)-6.332 F .232(wing macro)-.25 F
+(to print both v)69.336 566 Q(ersions of a chord, the capo v)-.15 E
+(ersion abo)-.15 E .3 -.15(ve t)-.15 H(he real v).15 E(ersion:)-.15 E F2
+(define CHORD\(COUNT, NAME\))105.336 584 Q
+(bold chord all: COUNT \222NAME\222;)130.336 608 Q(// chord for capo)30
+E(ital\(8\) chord 1: COUNT \222NAME\222;)130.336 620 Q(// real chord)24
+E(@)105.336 632 Q F0(Then, set these transpositions:)69.336 652 Q F2 12
+(score transpose)105.336 670 R 6(=d)6 G(own minor 3)-6 E
+(// transpose score for capo)8 E(staff 1 transpose = up perfect 1)
+105.336 682 Q(// override score transposition)8 E F0
+(and similarly for an)69.336 702 Q 2.5(yo)-.15 G(ther staf)-2.5 E 2.5
+(fs. Then,)-.25 F(where)2.5 E -.15(ve)-.25 G 2.5(ry).15 G(ou w)-2.5 E
+(ant to print a chord, say \(for e)-.1 E(xample\))-.15 E F2
+(CHORD\(3,Dm\))105.336 720 Q EP
+%%Page: 145 151
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(45 -)-2.5 E .271
+(This will print both v)69.336 96 R .271(ersions of the chord abo)-.15 F
+.571 -.15(ve c)-.15 H .271(ount 3 of the measure.).15 F -.15(Fo)5.271 G
+2.771(rt).15 G .271(he top chord it will transpose)-2.771 F
+(this to Bm, the capo chord.)69.336 108 Q -.15(Fo)5 G 2.5(rt).15 G
+(he bottom chord it will lea)-2.5 E .3 -.15(ve i)-.2 H 2.5(ta).15 G 2.5
+(sD)-2.5 G(m, the real chord.)-2.5 E 69.336 126 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.16 Placing)72.836 126 R -.14(ve)3.5 G
+(rses belo).14 E 3.5(wt)-.14 G(he scor)-3.5 E(es)-.252 E 69.336 144
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .362
+(Sometimes, particularly with songs that ha)72.198 144 R .662 -.15
+(ve a l)-.2 H .362(ot of v).15 F .362(erses, you may w)-.15 F .362
+(ant to put some v)-.1 F .362(erses of lyrics as)-.15 F 2.458
+(blocks of te)69.336 156 R 2.457(xt belo)-.15 F 4.957(wt)-.25 G 2.457
+(he music. Probably the easiest w)-4.957 F 2.457
+(ay to do this is using "print" or "paragraph")-.1 F
+(statements inside a "block.")69.336 168 Q/F1 10/Courier@0 SF(block)
+105.336 186 Q(print \(_win.w + 30, _win.n - 15\) "2.)105.336 198 Q(")18
+E(print "\\)105.336 210 Q(Here is the first line)105.336 222 Q
+(and the second line)105.336 234 Q(and the third line.)105.336 246 Q(")
+105.336 258 Q(print \(_win.w + 90, _win.n - 15\) "3.)105.336 270 Q(")18
+E(print "\\)105.336 282 Q(Here is another verse's first line)105.336 294
+Q(and its second line)105.336 306 Q(and its third line.)105.336 318 Q(")
+105.336 330 Q F0 -1.1(Yo)69.336 356 S 2.98(um)1.1 G .48(ay need to use \
+a little trial-and-error to determine the coordinates to use on the pri\
+nt statements, b)-2.98 F(ut)-.2 E .044(you only ha)69.336 368 R .344
+-.15(ve t)-.2 H 2.544(od).15 G .044(etermine one coordinate per v)-2.544
+F .043
+(erse, and with a bit of practice it gets easier to \214nd the right)
+-.15 F -.25(va)69.336 380 S 2.561(lues. Since).25 F .061(the "print" st\
+atement is being used, the font and size will be determined by the size\
+ parameter)2.561 F(and font parameter)69.336 392 Q 2.5(,r)-.4 G
+(ather than by lyricssize and lyricsfont.)-2.5 E .216(If you also w)
+69.336 410 R .215(ant chords symbols with these v)-.1 F .215
+(erses, you can do that too. It is easiest if you use Courier font,)-.15
+F .05(as sho)69.336 422 R .05(wn in the e)-.25 F .05(xample belo)-.15 F
+1.35 -.65(w, s)-.25 H .05(ince its constant-width characters mak).65 F
+2.551(ei)-.1 G 2.551(te)-2.551 G .051(asy to line things up. If you use)
+-2.551 F 2.5(ap)69.336 434 S(roportional-width font, you will ha)-2.5 E
+.3 -.15(ve t)-.2 H 2.5(od).15 G(etermine ho)-2.5 E 2.5(wt)-.25 G 2.5(op)
+-2.5 G(lace the chords by trial and error)-2.5 E(.)-.55 E F1
+(print \(_win.w + 50, _win.n - 35\) "3.)105.336 452 Q(")18 E
+(print "\\f\(CR\)\\)105.336 464 Q 72(CD)105.336 476 S 24(7G)-72 G(7)-24
+E(This is the first line)105.336 488 Q 42(CF)105.336 500 S
+(of the next verse)105.336 512 Q(B\\\(smflat\))105.336 524 Q
+(of the song.)105.336 536 Q(")105.336 548 Q 69.336 574 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.17 A)72.836 574 R(utomatic piano r)-.7
+E(eduction)-.252 E 69.336 592 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .926(Perhaps you')72.762 592 R 3.426(dl)-.5
+G(ik)-3.426 E 3.426(ea4)-.1 G .926(-part v)-3.426 F .926
+(ocal piece written on 4 separate staf)-.2 F .926
+(fs, as well as a piano reduction on tw)-.25 F(o)-.1 E(staf)69.336 604 Q
+(fs with 2 v)-.25 E 2.5(oices. This)-.2 F(could be done using:)2.5 E EP
+%%Page: 146 152
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(46 -)-2.5 E/F1 10/Courier@0
+SF(score)105.336 96 Q(staffs=6)123.336 108 Q(bracket=1-4)123.336 120 Q
+(brace=5-6)123.336 132 Q(staff 3)105.336 144 Q(clef=treble8)123.336 156
+Q(staff 4)105.336 168 Q(clef=bass)123.336 180 Q(staff 5)105.336 192 Q
+(vscheme=2o)123.336 204 Q 12(staffscale=0.75 //)123.336 216 R
+(make piano staffs a little smaller)6 E(staff 6)105.336 228 Q(clef=bass)
+123.336 240 Q(vscheme=2o)123.336 252 Q(staffscale=0.75)123.336 264 Q
+(// Define macros to put each voice on its own staff)105.336 288 Q
+(// plus the appropriate staff/voice of the piano staffs.)105.336 300 Q
+(define S 1 1 & 5 1: @)105.336 312 Q(// soprano)12 E
+(define A 2 1 & 5 2: @)105.336 324 Q(// alto)12 E(define T 3 1 & 6 1: @)
+105.336 336 Q(// tenor)12 E(define B 4 1 & 6 2: @)105.336 348 Q(// bass)
+18 E(music)105.336 372 Q 6(S2)105.336 384 S(c+;;)-6 E 6(A2)105.336 396 S
+(f;e;)-6 E 6(T2)105.336 408 S(a;g;)-6 E 6(B2)105.336 420 S(c;;)-6 E(bar)
+105.336 432 Q EP
+%%Page: 147 153
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(47 -)-2.5 E 127.836 96
+EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 322 rlineto 320 0 rlineto 0 322 neg rlineto closepath stroke grestore
+EEND 160 441 320 320 -322 322 126.836 418 PBEGIN
+%%BeginDocument: mugex98.ps
+%%BoundingBox: 160 441 480 763
+save
+1039846316 1039845534 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_SSV
+8 linenum
+%  S_SSV
+10 linenum
+%  S_SSV
+12 linenum
+%  S_SSV
+15 linenum
+%  S_FEED
+622.29 803.00 468.00 5 1.000000 1.000000 stf
+622.29 749.00 468.00 5 1.000000 1.000000 stf
+622.29 695.00 468.00 5 1.000000 1.000000 stf
+622.29 641.00 468.00 5 1.000000 1.000000 stf
+622.29 590.00 468.00 5 1.000000 0.750000 stf
+622.29 539.00 468.00 5 1.000000 0.750000 stf
+188.29 746.00 554.00 bracket
+189.79 527.00 458.00 brace
+0.52 setlinewidth
+190.29 743.00 moveto
+190.29 458.00 lineto stroke
+%  S_CLEFSIG
+202.08 725.00 1.000000 gclef
+202.08 671.00 1.000000 gclef
+202.08 595.26 moveto
+/Times-Italic findfont
+9 scalefont
+setfont
+(8) show
+202.08 617.00 1.000000 gclef
+202.33 575.00 1.000000 fclef
+199.13 513.50 0.750000 gclef
+199.32 471.50 0.750000 fclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+243.02 734.00 1.000000 2n
+0.70 setlinewidth
+239.13 733.25 moveto
+239.13 713.00 lineto stroke
+360.79 734.00 1.000000 2n
+356.89 733.25 moveto
+356.89 713.00 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+243.02 668.00 1.000000 2n
+0.70 setlinewidth
+246.92 668.75 moveto
+246.92 689.00 lineto stroke
+360.79 665.00 1.000000 2n
+364.68 665.75 moveto
+364.68 686.00 lineto stroke
+restore
+%  S_STAFF
+% staff 3
+save
+243.02 620.00 1.000000 2n
+0.70 setlinewidth
+246.92 620.75 moveto
+246.92 641.00 lineto stroke
+360.79 617.00 1.000000 2n
+364.68 617.75 moveto
+364.68 638.00 lineto stroke
+restore
+%  S_STAFF
+% staff 4
+save
+243.02 566.00 1.000000 2n
+0.70 setlinewidth
+246.92 566.75 moveto
+246.92 587.00 lineto stroke
+360.79 566.00 1.000000 2n
+364.68 566.75 moveto
+364.68 587.00 lineto stroke
+restore
+%  S_STAFF
+% staff 5
+save
+243.02 520.25 0.750000 2n
+0.52 setlinewidth
+245.95 520.81 moveto
+245.95 536.00 lineto stroke
+360.79 520.25 0.750000 2n
+363.71 520.81 moveto
+363.71 536.00 lineto stroke
+243.02 511.25 0.750000 2n
+240.10 510.69 moveto
+240.10 495.50 lineto stroke
+360.79 509.00 0.750000 2n
+357.86 508.44 moveto
+357.86 493.25 lineto stroke
+restore
+%  S_STAFF
+% staff 6
+save
+243.02 476.00 0.750000 2n
+0.52 setlinewidth
+245.95 476.56 moveto
+245.95 491.75 lineto stroke
+360.79 473.75 0.750000 2n
+363.71 474.31 moveto
+363.71 489.50 lineto stroke
+243.02 464.75 0.750000 2n
+240.10 464.19 moveto
+240.10 449.00 lineto stroke
+360.79 464.75 0.750000 2n
+357.86 464.19 moveto
+357.86 449.00 lineto stroke
+restore
+%  S_BAR
+32 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+467.65 689.00 moveto
+467.65 665.00 lineto stroke
+467.65 635.00 moveto
+467.65 611.00 lineto stroke
+467.65 581.00 moveto
+467.65 557.00 lineto stroke
+467.65 527.00 moveto
+467.65 509.00 lineto stroke
+467.65 476.00 moveto
+467.65 458.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Italic 
+%%Pages: 2
+%%EndDocument
+end PEND/F0 10/Times-Roman@0 SF
+(This can also be done using chord-at-a-time input style:)69.336 438 Q
+/F1 10/Courier@0 SF
+(// Define a macro to put each voice on its own staff)105.336 456 Q
+(// plus the appropriate staff/voice of the piano staffs.)105.336 468 Q
+(// This example assumes inputting notes from bottom to top.)105.336 480
+Q(define M [ 4 1 & 6 2; \\)105.336 492 Q 6(31&61)171.336 504 S 6(;\\)-6
+G 6(21&52)171.336 516 S 6(;\\)-6 G 6(11&51]: @)171.336 528 S(music)
+105.336 552 Q 6(M2)105.336 576 S(cafc+;cgec+;)-6 E(bar)105.336 588 Q
+69.336 614 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.18 Diagonal)72.836 614 R(slash marks)
+3.5 E 69.336 632 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .346(Sometimes, instead of a note or notes,\
+ a diagonal slash mark is printed on a staf)72.182 632 R 2.846(f. This)
+-.25 F .347(is used for v)2.847 F(arious)-.25 E .166(purposes, such as \
+strumming a chord \(in a guitar part\), or to mean that the pre)69.336
+644 R .166(vious beat should be repeated)-.25 F 2.096
+(or that a note should be impro)69.336 656 R 4.597(vised. Y)-.15 F 2.097
+(ou can get slash marks for all notes by setting the noteheads)-1.1 F
+(parameter)69.336 668 Q(.)-.55 E/F1 10/Courier@0 SF
+(noteheads = "allslash")105.336 686 Q F0(or if you w)69.336 706 Q
+(ant to use hollo)-.1 E 2.5(ws)-.25 G(lashes for half notes and longer)
+-2.5 E F1(noteheads = "slash")105.336 724 Q EP
+%%Page: 148 154
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(48 -)-2.5 E(Usually such sl\
+ash marks do not include a stem, so you may wish to also set)69.336 96 Q
+/F1 10/Courier@0 SF(stemlen=0)105.336 114 Q F0(If you just w)69.336 140
+Q(ant speci\214c chords to be slashes, you can use the chord head shape\
+ o)-.1 E -.15(ve)-.15 G(rride:).15 E F1
+(1: b;[ hs "allslash"; len 0 ]... ;;;)105.336 158 Q(bar)105.336 170 Q
+127.836 179.6 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 320 0 rlineto 0 61 neg rlineto closepath stroke grestore
+EEND 160 702 320 320 -61 61 126.836 240.6 PBEGIN
+%%BeginDocument: mugex99.ps
+%%BoundingBox: 160 702 480 763
+save
+1039846316 1039845534 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+1 linenum
+%  S_FEED
+612.29 803.00 468.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.08 725.00 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+226.10 731.00 1.000000 4n
+0.70 setlinewidth
+222.42 730.25 moveto
+222.42 710.00 lineto stroke
+287.28 731.00 1.000000 fillslashhead
+348.84 731.00 1.000000 fillslashhead
+411.63 731.00 1.000000 fillslashhead
+restore
+%  S_BAR
+6 linenum
+0.70 setlinewidth
+467.65 743.00 moveto
+467.65 719.00 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 260.6 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.19 Br)72.836 260.6 R(eath marks)-.252
+E 69.336 278.6 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 2.924(Ac)72.26 278.6 S .424(omma in a lar)
+-2.924 F .424(ge font can be used as a breath mark.)-.18 F .423
+(Something in the range of 20 to 30 points usually)5.423 F
+(looks good; you can adjust to your preference.)69.336 290.6 Q/F1 10
+/Courier@0 SF(1: c;d;2e;)105.336 308.6 Q
+(rom \(24\) above all dist 0: 4.5 ",";)105.336 320.6 Q(bar)105.336 332.6
+Q(1: e;d;2c;)105.336 356.6 Q(bar)105.336 368.6 Q 91.836 378.2 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 392 0 rlineto 0 61 neg rlineto closepath stroke grestore
+EEND 128 692 392 392 -61 61 90.836 439.2 PBEGIN
+%%BeginDocument: mugex100.ps
+%%BoundingBox: 128 692 520 753
+save
+1039846316 1039845534 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+576.29 792.97 504.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+156.08 714.97 1.000000 gclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+187.05 702.97 1.000000 4n
+0.70 setlinewidth
+180.82 702.97 moveto
+193.28 702.97 lineto stroke
+190.73 703.72 moveto
+190.73 723.97 lineto stroke
+227.94 705.97 1.000000 4n
+231.62 706.72 moveto
+231.62 726.97 lineto stroke
+274.76 708.97 1.000000 2n
+278.65 709.72 moveto
+278.65 729.97 lineto stroke
+/Times-Roman findfont
+24 scalefont
+setfont
+319.55 740.45 moveto
+(, ) show
+restore
+%  S_BAR
+9 linenum
+0.70 setlinewidth
+338.51 732.97 moveto
+338.51 708.97 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+352.19 708.97 1.000000 4n
+355.87 709.72 moveto
+355.87 729.97 lineto stroke
+393.08 705.97 1.000000 4n
+396.76 706.72 moveto
+396.76 726.97 lineto stroke
+439.90 702.97 1.000000 2n
+433.45 702.97 moveto
+446.34 702.97 lineto stroke
+443.79 703.72 moveto
+443.79 723.97 lineto stroke
+restore
+%  S_BAR
+12 linenum
+0.70 setlinewidth
+503.65 732.97 moveto
+503.65 708.97 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman 
+%%Pages: 2
+%%EndDocument
+end PEND 69.336 459.2 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.20 Or)72.836 459.2 R
+(gan pedal heel and toe marks)-.14 E 69.336 477.2 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .278
+(Mup does not include characters specially for the standard or)72.114
+477.2 R -.05(ga)-.18 G 2.778(np).05 G .279
+(edal heel and toe indications, b)-2.778 F .279(ut a U in)-.2 F(helv)
+69.336 489.2 Q .741
+(etica font and the acc_hat music symbol can be used. Y)-.15 F .74
+(ou may w)-1.1 F .74(ant to mak)-.1 F 3.24(et)-.1 G .74
+(hem a bit smaller than)-3.24 F(the def)69.336 501.2 Q
+(ault size, so de\214ning macros for them may be useful.)-.1 E/F1 10
+/Courier@0 SF(score)105.336 519.2 Q(clef = bass)130.336 531.2 Q
+(// define strings for the organ pedal heel and toe marks)105.336 555.2
+Q(define HEEL "\\s\(-3\)\\f\(HB\)U" @)105.336 567.2 Q
+(define TOE "\\s\(-1\)\\\(acc_hat\)" @)105.336 579.2 Q(music)105.336
+603.2 Q(1: a-;b-;e;f;)105.336 627.2 Q(rom below 1: 1 HEEL; 2 TOE;)
+105.336 639.2 Q(rom above 1: 3 TOE; 4 HEEL;)105.336 651.2 Q(bar)105.336
+663.2 Q 127.836 672.8 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 71 rlineto 320 0 rlineto 0 71 neg rlineto closepath stroke grestore
+EEND 160 691 320 320 -71 71 126.836 743.8 PBEGIN
+%%BeginDocument: mugex101.ps
+%%BoundingBox: 160 691 480 762
+save
+1930114009 1930113259 sv
+1.000000 1.000000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+2 linenum
+%  S_FEED
+396.29 1157.33 468.00 5 1.000000 1.000000 stf
+%  S_CLEFSIG
+192.33 731.33 1.000000 fclef
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+226.97 716.33 1.000000 4n
+0.70 setlinewidth
+230.65 717.08 moveto
+230.65 737.33 lineto stroke
+288.41 719.33 1.000000 4n
+292.09 720.08 moveto
+292.09 740.33 lineto stroke
+349.84 728.33 1.000000 4n
+346.16 727.58 moveto
+346.16 707.33 lineto stroke
+412.12 731.33 1.000000 4n
+408.43 730.58 moveto
+408.43 710.33 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+408.88 745.76 moveto
+/Helvetica-Bold findfont
+9 scalefont
+setfont
+(U ) show
+/Times-Roman findfont
+12 scalefont
+setfont
+345.52 746.30 moveto
+349.84 746.22 0.916667 acc_hat
+354.16 746.30 moveto
+/Times-Roman findfont
+11 scalefont
+setfont
+( ) show
+/Times-Roman findfont
+12 scalefont
+setfont
+223.73 700.04 moveto
+/Helvetica-Bold findfont
+9 scalefont
+setfont
+(U ) show
+/Times-Roman findfont
+12 scalefont
+setfont
+284.08 697.63 moveto
+288.41 697.55 0.916667 acc_hat
+292.73 697.63 moveto
+/Times-Roman findfont
+11 scalefont
+setfont
+( ) show
+restore
+%  S_BAR
+15 linenum
+0.70 setlinewidth
+467.65 737.33 moveto
+467.65 713.33 lineto stroke
+%  Printing header/footer
+showpage
+restore
+%%DocumentFonts: /Times-Roman /Helvetica-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND EP
+%%Page: 149 155
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(49 -)-2.5 E 69.336 104
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.21 Generating)72.836 104 R
+(blank staff paper)3.5 E 69.336 122 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .835
+(It is possible to use Mup to generate blank music staf)72.671 122 R
+3.336(fp)-.25 G(aper)-3.336 E 5.836(.Y)-.55 G .836
+(ou simply use an input \214le that contains)-6.936 F 1.098
+(measure spaces, each ending with an in)69.336 134 R(visbar)-.4 E 6.097
+(.Y)-.55 G 1.097(ou can control whether you w)-7.197 F 1.097
+(ant clefs, time signatures,)-.1 F .423
+(braces, etc., and can control the spacing of staf)69.336 146 R .423
+(fs using the scoresep parameter)-.25 F 5.424(.H)-.55 G .424
+(ere is a simple input that)-5.424 F
+(will generate a page with 8 completely blank staf)69.336 158 Q(fs.)-.25
+E/F1 10/Courier@0 SF(score)105.336 176 Q 35(scoresep=9,100 //)130.336
+188 R(spread staffs out nicely)6 E 41(stafflines=5n //)130.336 200 R
+(don't print any clefs)6 E 21(label="" //)130.336 212 R
+(make sure left edges line up both on first)6 E 40(label2="" //)130.336
+224 R(and on subsequent lines)24 E 28(topmargin=1 //)130.336 236 R
+(allow extra margin to write in header/footer)6 E(bottommargin=1)130.336
+248 Q 40(time=4/4n //)130.336 260 R(don't print any time signature)6 E
+(music)105.336 272 Q(define SCORE)105.336 296 Q(1: ms;)130.336 308 Q 21
+(invisbar //)130.336 320 R(no bar line at the end of the staff)6 E(@)
+105.336 332 Q(define SCORE_NEWSCORE)105.336 356 Q(SCORE)130.336 368 Q
+(newscore)130.336 380 Q(@)105.336 392 Q
+(// print 8 staffs, with newscore between each)105.336 416 Q
+(SCORE_NEWSCORE)105.336 428 Q(SCORE_NEWSCORE)105.336 440 Q
+(SCORE_NEWSCORE)105.336 452 Q(SCORE_NEWSCORE)105.336 464 Q
+(SCORE_NEWSCORE)105.336 476 Q(SCORE_NEWSCORE)105.336 488 Q
+(SCORE_NEWSCORE)105.336 500 Q(SCORE)105.336 512 Q 69.336 538 EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 14/Times-Bold@0 SF 3.5(13.22 Con)72.836 538 R -.14(ve)-.56 G
+(rting Mup \214les to other f).14 E(ormats)-.35 E 69.336 556 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 1.132
+(Since Mup generates PostScript, almost an)72.968 556 R 3.632(yP)-.15 G
+1.132(ostScript tool can be used on its output. In particular)-3.632 F
+3.631(,t)-.4 G(he)-3.631 E .668
+("ps2pdf" tool that comes with Ghostscript can con)69.336 568 R -.15(ve)
+-.4 G .668(rt Mup output to PDF format, and the "ps2epsi" tool,).15 F
+1.572(which also comes with Ghostscript, con)69.336 580 R -.15(ve)-.4 G
+1.572
+(rts a PostScript \214le to an Encapsulated PostScript \(EPS\) \214le.)
+.15 F(Man)69.336 592 Q 3.23(yt)-.15 G -.15(ex)-3.23 G 3.23(tp).15 G .731
+(rocessing and graphics programs will let you import EPS \214les, so th\
+is can let you insert Mup)-3.23 F(output into some other document.)
+69.336 604 Q .388(There is a package called "psutils" a)69.336 622 R
+-.25(va)-.2 G .388(ilable on most Linux archi).25 F -.15(ve)-.25 G .388
+(s, that contains v).15 F .388(arious Postscript tools.)-.25 F .351(The\
+se include "psnup" which lets you print multiple pages on one sheet of \
+paper with more \215e)69.336 634 R .352(xibility than)-.15 F(Mup')69.336
+646 Q 2.5(sp)-.55 G(anelsperpage parameter)-2.5 E 2.5(,a)-.4 G
+(nd "psselect" which prints a subset of pages.)-2.5 E -1.1(Yo)69.336 664
+S 2.509(uc)1.1 G .009
+(an check the user donated programs page on Arkkra')-2.509 F 2.509(sw)
+-.55 G .009(eb site for other programs for processing Mup)-2.509 F
+(input or output.)69.336 676 Q EP
+%%Page: 150 156
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(50 -)-2.5 E 69.336 103
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(14. MIDI)73.086 103 R(OUTPUT)3.75 E
+69.336 121 EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF 2.012
+(Mup will optionally produce MIDI output \(using the -m command line ar)
+73.848 121 R 4.513(gument\). Mup)-.18 F 2.013(is \214rst and)4.513 F
+.266(foremost a music publication program, so its MIDI capabilities ha)
+69.336 133 R .566 -.15(ve a f)-.2 H .766 -.25(ew l).15 H 2.766
+(imitations. Ho).25 F(we)-.25 E -.15(ve)-.25 G 1.066 -.4(r, t).15 H .266
+(he MIDI).4 F .567(output is quite useful for "proofreading" \(or perha\
+ps we should say "proof-listening"\).)69.336 145 R .568
+(It is often easier to)5.568 F .182(spot a typo in Mup input by listeni\
+ng to it than to look at the output. Mup pro)69.336 157 R .181
+(vides enough MIDI control to)-.15 F .911
+(do virtually all of what MIDI supports, and will be adequate for man)
+69.336 169 R 3.411(yp)-.15 G .911(eople. Others ho)-3.411 F(we)-.25 E
+-.15(ve)-.25 G 1.712 -.4(r, m).15 H .912(ay \214nd).4 F(the)69.336 181 Q
+2.5(yw)-.15 G(ant a separate MIDI editor for really serious MIDI w)-2.6
+E(ork.)-.1 E .535(The follo)69.336 199 R .535
+(wing section assumes a general kno)-.25 F .535
+(wledge of MIDI. If you are not f)-.25 F .534
+(amiliar with MIDI, there are)-.1 F(man)69.336 211 Q 2.5(yb)-.15 G
+(ooks a)-2.5 E -.25(va)-.2 G
+(ilable on the subject at most music stores or computer book stores.).25
+E .959(Each v)69.336 229 R .959(oice is put on a separate MIDI track. T\
+he \214rst track contains general information such as k)-.2 F 1.26 -.15
+(ey a)-.1 H(nd).15 E .276(time signature. The ne)69.336 241 R .276
+(xt track will be for staf)-.15 F 2.776(f1)-.25 G 2.776(,v)-2.776 G .276
+(oice 1. If staf)-2.976 F 2.776(f1h)-.25 G .275(as a second v)-2.776 F
+.275(oice, that will be the ne)-.2 F(xt)-.15 E
+(track, otherwise it will be v)69.336 253 Q(oice 1 of staf)-.2 E 2.5(f2)
+-.25 G 2.5(,i)-2.5 G 2.5(fa)-2.5 G -.15(ny)-2.5 G 2.5(,a)-.5 G
+(nd so forth, one track for each v)-2.5 E(oice, top to bottom.)-.2 E
+.483(Output is in MIDI \214le format 1, with a def)69.336 271 R .483
+(ault of 120 quarter notes per minute, 192 ticks per quarter note.)-.1 F
+.04(MIDI channel 1 is used by def)69.336 283 R .04(ault for all v)-.1 F
+.04(oices. If you w)-.2 F .04(ant to use dif)-.1 F .04
+(ferent instrument sounds for dif)-.25 F(ferent)-.25 E -.2(vo)69.336 295
+S 1.006(ices, you will need to specify a dif).2 F 1.006
+(ferent channel for each v)-.25 F 1.006
+(oice, then specify the MIDI "program" for)-.2 F(that v)69.336 307 Q
+(oice. This is demonstrated in some of the e)-.2 E
+(xamples later in this section.)-.15 E 1.037
+(Mup MIDI output will handle repeats and \214rst and second endings, b)
+69.336 325 R 1.037(ut it does not kno)-.2 F 3.537(wa)-.25 G -.15(ny)
+-3.537 G 1.037(thing about).15 F .852("D.S. al coda" or an)69.336 337 R
+.852(ything of that sort.)-.15 F .852(It is possible to w)5.852 F .852
+(ork around this limitation to some e)-.1 F .853(xtent using)-.15 F
+2.702(macros. F)69.336 349 R .201(or e)-.15 F .201(xample, a section be\
+tween a "sign" and a "jump to coda" symbol could be put inside a macro)
+-.15 F .294(de\214nition, then the macro can be called. Then later in t\
+he piece, where the "D. S." occurs the macro can be)69.336 361 R
+(called ag)69.336 373 Q(ain if MIDI is de\214ned. F)-.05 E(or e)-.15 E
+(xample:)-.15 E EP
+%%Page: 151 157
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(51 -)-2.5 E/F1 10/Courier@0
+SF(// an introductory section, ends with a sign)105.336 96 Q
+(1: c;d;e;f;)105.336 108 Q(mussym above all: 5 "sign";)105.336 120 Q
+(bar)105.336 132 Q(// define macro for section between sign and)105.336
+156 Q(// symbol to "jump to coda")105.336 168 Q(define SECTION)105.336
+180 Q(1: g;a;g;;)105.336 192 Q(mussym above all: 5 "coda";)105.336 204 Q
+(bar)105.336 216 Q(@)105.336 228 Q
+(// print/play the section just defined by)105.336 252 Q(// the macro)
+105.336 264 Q(SECTION)105.336 276 Q(// now do the music up to the D.S.)
+105.336 300 Q(1: e;f;2g;)105.336 312 Q(ital above 1: 1 "D. S. al Coda";)
+105.336 324 Q(dblbar)105.336 336 Q
+(// human player would now flip back to)105.336 360 Q
+(// the sign, so do the MIDI equivalent:)105.336 372 Q
+(// play that section again.)105.336 384 Q(ifdef MIDI)105.336 396 Q
+(SECTION)130.336 408 Q(endif)105.336 420 Q(// now do the coda)105.336
+444 Q(1: e;d;2c;)105.336 456 Q(rom above 1: 0 "Coda";)105.336 468 Q
+(endbar)105.336 480 Q F0 1.123
+(Mup mainly just outputs the note information.)69.336 506 R 1.122
+(Mup will recognize octa)6.123 F 1.422 -.15(ve m)-.2 H 1.122
+(arks, and mo).15 F 1.422 -.15(ve n)-.15 H 1.122(otes up or).15 F(do)
+69.336 518 Q .808(wn appropriately)-.25 F 5.808(.I)-.65 G 3.308(tr)
+-5.808 G .808(ecognizes piano pedal marks.)-3.308 F .809
+(It does not attempt to interpret tempo or dynamics)5.809 F .561(marks \
+speci\214ed by "rom," "boldital," etc. or ornaments in "mussym" stateme\
+nt.)69.336 530 R .56(It does interpret rehearsal)5.56 F 1.133
+(marks as cue points.)69.336 542 R 1.134
+(It handles grace notes, rolls, slashes, and alternation groups.)6.133 F
+-1.1(Yo)6.134 G 3.634(uc)1.1 G 1.134(an control ho)-3.634 F(w)-.25 E(le)
+69.336 554 Q -.05(ga)-.15 G
+(to the music is by using the Mup "release" parameter).05 E(.)-.55 E
+.673(Some styles of music are often written in "swing time," meaning th\
+e players are e)69.336 572 R .672(xpected to play pairs of)-.15 F 1.458
+(notes with the \214rst twice as long as the second, e)69.336 584 R -.15
+(ve)-.25 G 3.958(nt).15 G 1.458(hough the)-3.958 F 3.958(ya)-.15 G 1.458
+(re written as if the)-3.958 F 3.958(yw)-.15 G 1.458(ere the same)-3.958
+F 1.028
+(duration, or as if the \214rst were three times as long as the second.)
+69.336 596 R 1.028(The most common e)6.028 F 1.027(xample w)-.15 F 1.027
+(ould be)-.1 F .696(where the written notation sho)69.336 608 R .696
+(ws tw)-.25 F 3.196(oe)-.1 G .697(ighth notes lik)-3.196 F 3.197(e8)-.1
+G .697(;; or a dotted rh)-3.197 F .697(ythm lik)-.05 F 3.197(e8)-.1 G
+.697(.;16; b)-3.197 F .697(ut the musician)-.2 F("kno)69.336 620 Q 1.363
+(ws" that the composer really intended it to be played as if it were a \
+triplet {4;8;}3; The swingunit)-.25 F
+(parameter can be used to get Mup MIDI output to automatically follo)
+69.336 632 Q 2.5(wt)-.25 G(hat performance con)-2.5 E -.15(ve)-.4 G
+(ntion.).15 E 2.731(AM)69.336 650 S .231
+(IDI editing program will probably be necessary to add some ef)-2.731 F
+2.731(fects. Ho)-.25 F(we)-.25 E -.15(ve)-.25 G 1.031 -.4(r, i).15 H
+2.731(ti).4 G 2.732(sp)-2.731 G .232(ossible to specify)-2.732 F
+(certain directi)69.336 662 Q -.15(ve)-.25 G 2.5(sf).15 G(or MIDI.)-2.5
+E(The)5 E 2.5(ya)-.15 G(re of the form:)-2.5 E/F2 10/Times-Bold@0 SF
+(midi)105.336 680 Q/F3 10/Times-Italic@0 SF 2.5(SV)6 G F2(:)-2.5 E F3
+(be)6 E(gintime "k)-.4 E -.3(ey)-.1 G(wor).3 E(d=value";)-.37 E F0(The)
+69.336 700 Q F3(S)2.617 E F0(and)2.617 E F3(V)2.617 E F0 .116
+(specify the staf)2.617 F 2.616(fa)-.25 G .116(nd v)-2.616 F .116
+(oice for which the directi)-.2 F .416 -.15(ve i)-.25 H 2.616(st).15 G
+2.616(oa)-2.616 G(pply)-2.616 E 2.616(.A)-.65 G 2.616(se)-2.616 G(lse)
+-2.616 E .116(where in Mup, an omitted)-.25 F -.2(vo)69.336 712 S .338
+(ice will def).2 F .338(ault to v)-.1 F .338(oice 1, and both staf)-.2 F
+2.838(fa)-.25 G .338(nd v)-2.838 F .338(oice can be gi)-.2 F -.15(ve)
+-.25 G 2.838(na).15 G 2.838(sal)-2.838 G 2.838(ist. Certain)-2.838 F -.1
+(ke)2.838 G(yw)-.05 E .339(ords apply to the)-.1 F
+(entire score. In that case the form)69.336 724 Q EP
+%%Page: 152 158
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(52 -)-2.5 E/F1 10
+/Times-Bold@0 SF(midi all:)105.336 96 Q/F2 10/Times-Italic@0 SF(be)6 E
+(gintime "k)-.4 E -.3(ey)-.1 G(wor).3 E(d=value";)-.37 E F0 .1
+(is used instead.)69.336 116 R .099(The items speci\214ed using "all" a\
+re placed on the \214rst track, the track containing score-wide)5.1 F
+(information. The)69.336 128 Q 2.5(ya)-.15 G(re not applied to the v)
+-2.5 E(oices on the other tracks.)-.2 E(The)69.336 146 Q F2(be)2.606 E
+(gintime)-.4 E F0 2.606(,a)C 2.606(se)-2.606 G(lse)-2.606 E .106
+(where in Mup, gi)-.25 F -.15(ve)-.25 G 2.606(st).15 G .106
+(he beat into the measure where the MIDI output is to be placed.)-2.606
+F .206(If notes are to be turned on or of)69.336 158 R 2.706(fa)-.25 G
+2.706(tt)-2.706 G .205(he same instant in time as the)-2.706 F F2(be)
+2.705 E(gintime)-.4 E F0 2.705<2c8c>C .205(rst all "note of)-2.705 F
+.205(f" commands)-.25 F(are generated, then the "midi" command e)69.336
+170 Q -.15(ve)-.25 G(nts, then "note on" commands.).15 E(The)69.336 188
+Q F2 -.1(ke)3.344 G(ywor)-.2 E(d=value)-.37 E F0(gi)3.344 E -.15(ve)-.25
+G 3.344(ss).15 G .845
+(peci\214c information of what MIDI output to generate. The follo)-3.344
+F .845(wing k)-.25 F -.15(ey)-.1 G -.1(wo).15 G(rds).1 E
+(are currently supported:)69.336 200 Q F1 -.1(ke)76.926 218 S(yw).1 E
+31.385(ord v)-.1 F 73.235(alues meaning)-.1 F(midi S V)64.44 E(midi all)
+15 E .4 LW 435.986 222.5 69.336 222.5 DL F0 30.82(program 0-127)69.336
+232 R(program change \(ne)40.83 E 2.5(wi)-.25 G 24.45(nstrument\) yes)
+-2.5 F(no)38.205 E 24.72(parameter 0-127,0-127)69.336 244 R 120.02
+(parameter yes)15 F(yes)36.54 E 33.6(channel 1-16)69.336 256 R 128.9
+(channel yes)45.83 F(no)38.205 E 12.5(chanpressure 0-127)69.336 268 R
+(channel pressure \(after touch\))40.83 E 34.04(yes yes)43.38 F 39.7
+(tempo 10-1000)69.336 280 R(tempo, quarter notes per minute)30.83 E
+35.705(no yes)36.685 F 33.59(seqnum 0-65535)69.336 292 R
+(sequence number)30.83 E 34.04(yes yes)92.8 F(te)69.336 304 Q 49.85
+(xt te)-.15 F 46.81(xt te)-.15 F(xt meta e)-.15 E -.15(ve)-.25 G 99.45
+(nt yes).15 F(yes)36.54 E(cop)69.336 316 Q 26.47(yright te)-.1 F 46.81
+(xt cop)-.15 F(yright notice)-.1 E 34.04(yes yes)97.33 F 43.04(name te)
+69.336 328 R 46.81(xt sequence/track)-.15 F 76.42(name yes)2.5 F(yes)
+36.54 E 21.92(instrument te)69.336 340 R 46.81(xt instrument)-.15 F
+93.06(name yes)2.5 F(yes)36.54 E(mark)69.336 352 Q 36.48(er te)-.1 F
+46.81(xt mark)-.15 F(er meta e)-.1 E -.15(ve)-.25 G 86.08(nt yes).15 F
+(yes)36.54 E 50.82(cue te)69.336 364 R 46.81(xt cue)-.15 F 123.06
+(point yes)2.5 F(yes)36.54 E 48.59(port 0-127)69.336 376 R(MIDI port)
+40.83 E 34.04(yes yes)121.12 F(on)69.336 388 Q -.15(ve)-.4 G 23.03
+(locity 1-127).15 F(note on v)40.83 E 95.71(elocity yes)-.15 F(no)38.205
+E(of)69.336 400 Q(fv)-.25 E 21.22(elocity 0-127)-.15 F(note of)40.83 E
+2.5(fv)-.25 G 94.3(elocity yes)-2.65 F(no)38.205 E(he)69.336 412 Q 52.91
+(xh)-.15 G .3 -.15(ex d)-52.91 H 28.21(ata arbitrary).15 F(MIDI data)2.5
+E 34.04(yes yes)83.64 F .034(The k)69.336 430 R -.15(ey)-.1 G -.1(wo).15
+G .034(rds can be abbre).1 F .034
+(viated to their \214rst three or more letters, e)-.25 F .033
+(xcept "chanpressure" which requires at)-.15 F .389(least \214v)69.336
+442 R 2.889(el)-.15 G .389(etters to dif)-2.889 F .389(ferentiate it fr\
+om "channel" \("cha" or "chan" will be interpreted as channel\).)-.25 F
+.39(In most)5.39 F .342(cases, the "=" is follo)69.336 454 R .342
+(wed by either a number or some te)-.25 F .342
+(xt. Exceptions to this are discussed in the ne)-.15 F .342(xt fe)-.15 F
+(w)-.25 E(paragraphs.)69.336 466 Q 1.446(The "parameter" k)69.336 484 R
+-.15(ey)-.1 G -.1(wo).15 G 1.446(rd is follo).1 F 1.446
+(wed by 2 numbers, separated by a comma.)-.25 F 1.447
+(The \214rst is the parameter)6.446 F(number)69.336 496 Q 2.926(,t)-.4 G
+.426(he second is the parameter v)-2.926 F 2.926(alue. Thus)-.25 F .425
+(to set parameter 7 \(which is the v)2.926 F .425
+(olume parameter\) to 90)-.2 F(for v)69.336 508 Q(oice 2 of staf)-.2 E
+2.5(f3)-.25 G 2.5(,s)-2.5 G(tarting at the be)-2.5 E
+(ginning of the measure, you can use:)-.15 E/F3 10/Courier@0 SF
+(midi 3 2: 0 "parameter=7,90";)105.336 526 Q F0 .098(The "on)69.336 552
+R -.15(ve)-.4 G .098(locity" and "of).15 F(fv)-.25 E .098(elocity" k)
+-.15 F -.15(ey)-.1 G -.1(wo).15 G .098(rds can ha).1 F .398 -.15(ve o)
+-.2 H .098(ne or more v).15 F .098
+(alues, separated by commas. If there is)-.25 F .09(only one v)69.336
+564 R .09(alue, it applies to all notes in each chord. If there is more\
+ than one v)-.25 F .09(alue, the \214rst v)-.25 F .09(alue applies to)
+-.25 F .445(the top note of the chord, the second v)69.336 576 R .445
+(alue to the second-from-the-top note, and so forth. If there are more)
+-.25 F .092(notes in a chord than there are v)69.336 588 R .092
+(alues speci\214ed, the last v)-.25 F .091
+(alue speci\214ed applies to all of the remaining notes.)-.25 F 1.107
+(So, for e)69.336 600 R 1.107(xample, if you w)-.15 F 1.107
+(ant to emphasize the top note of each chord because it is the melody)
+-.1 F 3.607(,y)-.65 G 1.107(ou can)-3.607 F(specify tw)69.336 612 Q 2.5
+(ov)-.1 G(alues, as in)-2.75 E F3(midi 1: 1 "onvelocity=76, 60";)105.336
+630 Q F0(which w)69.336 650 Q(ould cause the top note to ha)-.1 E .3
+-.15(ve a ve)-.2 H(locity of 76 and all other notes to ha).15 E .3 -.15
+(ve a ve)-.2 H(locity of 60.).15 E .384(The "he)69.336 668 R .384
+(x" form can be used to insert an)-.15 F 2.884(ya)-.15 G .384
+(rbitrary MIDI data into the MIDI \214le. The v)-2.884 F .384
+(alue consists of an)-.25 F(y)-.15 E -2.15 -.25(ev e)69.336 680 T 2.5
+(nn).25 G(umber of he)-2.5 E(xadecimal digits.)-.15 E
+(Spaces and tabs can be included in the v)5 E
+(alue \214eld for readability)-.25 E(.)-.65 E .939(Note that Mup uses t\
+he MIDI standard, which numbers instruments from 0 through 127, b)69.336
+698 R .939(ut some MIDI)-.2 F(playback programs follo)69.336 710 Q 2.5
+(wac)-.25 G(on)-2.5 E -.15(ve)-.4 G
+(ntion of numbering them from 1 through 128.).15 E(Here are some e)
+69.336 728 Q(xamples:)-.15 E EP
+%%Page: 153 159
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(53 -)-2.5 E/F1 10/Courier@0
+SF(midi all: 0 "tempo=72";)105.336 96 Q
+(midi 1-2 1-2: 0 "channel=2"; 0 "program=14"; 3.5 "program=76";)105.336
+108 Q(midi all: 3 "hex= ff 00 02 00 01";)105.336 120 Q
+(// sequence number 1)18 E
+(midi 3,6: 0 "channel=5"; 0 "prog=15"; 0 "instr=dulcimer";)105.336 132 Q
+(// set parameter 7 \(usually volume\) to 100)105.336 144 Q
+(midi 2: "par = 7, 100";)105.336 156 Q F0(Here is a more e)69.336 182 Q
+(xtensi)-.15 E .3 -.15(ve ex)-.25 H(ample of ho).15 E 2.5(wm)-.25 G
+(idi commands might be used in a song:)-2.5 E EP
+%%Page: 154 160
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(54 -)-2.5 E/F1 10/Courier@0
+SF(score)105.336 96 Q(staffs=2)130.336 108 Q(vscheme=2o)130.336 120 Q
+(staff 2)105.336 144 Q(clef=bass)130.336 156 Q(voice 2 2)105.336 180 Q
+(// Make the bottom voice more staccato)130.336 192 Q(release=50)130.336
+204 Q(music)105.336 228 Q(// Set the tempo.)105.336 252 Q
+(// Start out at 108 quarter notes per minute,)105.336 264 Q
+(// but on count 4, slow down to 96 per minute.)105.336 276 Q
+(midi all: 0 "tempo=108"; 4 "tempo=96";)105.336 288 Q
+(// Put each voice on a different channel)105.336 312 Q
+(// using a different instrument sound.)105.336 324 Q
+(// The program numbers correspond to the)105.336 336 Q
+(// General MIDI sounds as noted.)105.336 348 Q
+(midi 1 1: 0 "channel=1"; 0 "program=68";)105.336 360 Q(//oboe)12 E
+(midi 1 2: 0 "channel=2"; 0 "program=11";)105.336 372 Q(//vibraphone)12
+E(midi 2 1: 0 "channel=6"; 0 "program=60";)105.336 384 Q(//french horn)
+12 E(midi 2 2: 0 "channel=4"; 0 "program=35";)105.336 396 Q
+(//fretless bass)12 E(// Make the top voice louder, and put an)105.336
+420 Q(// accent on the third beat)105.336 432 Q
+(midi 1 1: 0 "onvelocity=86"; 3 "onvelocity=100"; 4 "onvel=86";)105.336
+444 Q(// Set maximum reverb on french horn part,)105.336 468 Q
+(// starting at the second beat.)105.336 480 Q
+(// \(Reverb is parameter 91\))105.336 492 Q
+(midi 2 1: 2 "parameter=91, 127";)105.336 504 Q
+(// Set chorus on oboe to 75, from the beginning.)105.336 528 Q
+(// \(Chorus is parameter 93\))105.336 540 Q
+(midi 1 1: 0 "param=93, 75";)105.336 552 Q
+(// Pan the bass part to middle of left side.)105.336 576 Q
+(// \(Pan is parameter 10, with a value of 0 being hard left,)105.336
+588 Q(// 64 in the center, and 127 being hard right, so 32 is)105.336
+600 Q(// half way to the left.\))105.336 612 Q
+(midi 2 2: 0 "parameter=10, 32";)105.336 624 Q
+(// Now the music to be played...)105.336 648 Q 6(11)105.336 660 S 6(:e)
+-6 G(;d;2c;)-6 E 6(12)105.336 672 S 6(:c)-6 G(;b-;2g-;)-6 E 6(21)105.336
+684 S 6(:g)-6 G(;f;2e;)-6 E 6(22)105.336 696 S 6(:c)-6 G(;g-;2c;)-6 E
+(bar)105.336 708 Q EP
+%%Page: 155 161
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(55 -)-2.5 E 69.336 103
+EBEGIN
+0 0.1 0.5 setrgbcolor
+EEND/F0 15/Times-Bold@0 SF 3.75(15. CONCLUSION)73.086 103 R 69.336 121
+EBEGIN
+0 0 0 setrgbcolor
+EEND/F0 10/Times-Roman@0 SF .497(The Mup program pro)72.333 121 R .496
+(vides a con)-.15 F -.15(ve)-.4 G .496(nient w).15 F .496
+(ay to produce high-quality musical scores. W)-.1 F 2.996(eh)-.8 G .496
+(ope you enjo)-2.996 F(y)-.1 E 1.769(using it.)69.336 133 R 1.769
+(Appendix A gi)6.769 F -.15(ve)-.25 G 4.269(sas).15 G 1.769
+(ample input \214le, demonstrating man)-4.269 F 4.27(yo)-.15 G 4.27(ft)
+-4.27 G 1.77(he features of Mup. Y)-4.27 F 1.77(ou can)-1.1 F(do)69.336
+145 Q 1.084(wnload additional sample songs from the Arkkra Enterprises \
+web site listed belo)-.25 F 4.884 -.65(w. T)-.25 H 1.084
+(he web site also).65 F 1.644(includes se)69.336 157 R -.15(ve)-.25 G
+1.644(ral programs written by Mup users that may mak).15 F 4.144(eM)-.1
+G 1.645(up e)-4.144 F -.15(ve)-.25 G 4.145(nm).15 G 1.645
+(ore useful for you.)-4.145 F(Once)6.645 E(you')69.336 169 Q 1.442 -.15
+(ve u)-.5 H 1.141(sed Mup for a while, you may \214nd the Quick Referen\
+ce helpful for remembering details of the).15 F(Mup language.)69.336 181
+Q(If you ha)69.336 199 Q .3 -.15(ve c)-.2 H
+(omments or questions, please contact:).15 E(Arkkra Enterprises)141.336
+211 Q 2.22 -1.11(P. O)141.336 223 T 2.5(.B)1.11 G(ox 315)-2.5 E -.8(Wa)
+141.336 235 S(rren).8 E(ville, IL 60555)-.4 E(support@arkkra.com)141.336
+259 Q(http://www)141.336 283 Q(.arkkra.com)-.65 E EP
+%%Page: 156 162
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(56 -)-2.5 E/F1 16
+/Times-Bold@0 SF -.4(Ap)244.416 324 S(pendix A).4 E
+(Example of a Mup input \214le)189.544 372 Q EP
+%%Page: 157 163
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(57 -)-2.5 E/F1 10/Courier@0
+SF(//!Mup-Arkkra)105.336 96 Q(// sample of a Mup input file)105.336 120
+Q(header)105.336 144 Q(title \(18\) "The Star Spangled Banner")130.336
+156 Q(title ital \(12\) "\(The United States National Anthem\)")130.336
+168 Q(title \(9\) "Text: Francis Scott Key" "Tune: J. S. Smith")130.336
+180 Q(title \(9\) "")130.336 192 Q("arr: William J. Krauss")12 E(score)
+105.336 216 Q(topmargin = 0.5)130.336 228 Q(bottommargin = 0.5)130.336
+240 Q(leftmargin = 0.65)130.336 252 Q(rightmargin = 0.65)130.336 264 Q
+(scale = 0.65)130.336 276 Q(packfact = 1.3)130.336 288 Q(key = 3#)
+130.336 300 Q(time = 3/4)130.336 312 Q(staffs = 2)130.336 324 Q
+(brace = 1-2)130.336 336 Q(barstyle = 1-2)130.336 348 Q(measnum = y)
+130.336 360 Q(vscheme = 2o)130.336 372 Q(beamstyle = 4,4,4)130.336 384 Q
+(endingstyle = top)130.336 396 Q(staff 2)105.336 420 Q(clef = bass)
+130.336 432 Q(define LYRICS lyrics between 1&2: @)105.336 456 Q(music)
+105.336 480 Q(// Starts on a pickup, so use space)130.336 492 Q
+(// at beginning of measure.)130.336 504 Q
+(// Voices are in unison for the first)130.336 516 Q
+(// few notes, so specify two voices)130.336 528 Q(// at once.)130.336
+540 Q 6(11)130.336 552 S(-2: 2s; 8.e<>; 16c;)-6 E 6(21)130.336 564 S
+(-2: 2s; 8.e<>; 16c;)-6 E(LYRICS 2s; 4;)130.336 576 Q([1] "Oh_";)22 E
+(// Since the first two sections are)130.336 588 Q
+(// almost the same, use a repeat)130.336 600 Q(repeatstart)130.336 612
+Q 6(11)130.336 636 S 6(:a)-6 G(-; c; e;)-6 E 6(12)130.336 648 S 6(:a)-6
+G(-; c; b-;)-6 E 6(21)130.336 660 S 6(:a)-6 G(-; a; b;)-6 E 6(22)130.336
+672 S 6(:a)-6 G(-; a; g;)-6 E 33(LYRICS [1])130.336 684 R
+("say. can you";)6 E(\\)12 E([2] "stripes and bright";)180.336 696 Q
+(bar)130.336 708 Q 6(11)130.336 732 S 6(:2)-6 G(a; 8.c+; 16b;)-6 E EP
+%%Page: 158 164
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(58 -)-2.5 E/F1 10/Courier@0
+SF 6(12)130.336 96 S 6(:2)-6 G(c; 8.; 16;)-6 E 6(21)130.336 108 S 6(:2)
+-6 G(a; 8.g; 16;)-6 E 6(22)130.336 120 S 6(:2)-6 G(f; 8.e#; 16;)-6 E 33
+(LYRICS [1])130.336 132 R("see, by the";)6 E(\\)12 E
+([2] "stars, through the";)180.336 144 Q(bar)130.336 156 Q 6(11)130.336
+180 S 6(:a)-6 G 6(;c)-6 G 6(;d)-6 G(#;)-6 E 6(12)130.336 192 S 6(:c)-6 G
+6(;;b)-6 G(-;)-6 E 6(21)130.336 204 S 6(:a)-6 G 6(;;;)-6 G 6(22)130.336
+216 S 6(:f)-6 G 6(;;b)-6 G(-;)-6 E 33(LYRICS [1])130.336 228 R
+("dawn's ear-ly";)6 E(\\)12 E([2] "per-il-ous";)180.336 240 Q(bar)
+130.336 252 Q 6(11)130.336 276 S 6(:e)-6 G 6(;r)-6 G 6(;8)-6 G(e; ;)-6 E
+6(12)130.336 288 S 6(:b)-6 G(-; r; 8b-; ;)-6 E 6(21)130.336 300 S 6(:g)
+-6 G 6(;r)-6 G 6(;8)-6 G(g; ;)-6 E 6(22)130.336 312 S 6(:e)-6 G 6(;r)-6
+G 6(;8)-6 G(e; ;)-6 E 33(LYRICS [1])130.336 324 R("light what so";)6 E
+(\\)12 E([2] "fight, o'er the";)180.336 336 Q(bar)130.336 348 Q 6(11)
+130.336 372 S 6(:4)-6 G(.c+; 8b; 4a;)-6 E 6(12)130.336 384 S 6(:4)-6 G
+(.e; 8; 4;)-6 E 6(21)130.336 396 S 6(:4)-6 G(.a; 8g; 4a;)-6 E 6(22)
+130.336 408 S 6(:4)-6 G(.a-; 8b-; 4c;)-6 E 33(LYRICS [1])130.336 420 R
+("proud-ly we";)6 E(\\)12 E([2] "ram-parts we";)180.336 432 Q(bar)
+130.336 444 Q 6(11)130.336 468 S 6(:2)-6 G(g; 8.f; 16g;)-6 E 6(12)
+130.336 480 S 6(:2)-6 G(e; 8.; 16;)-6 E 6(21)130.336 492 S 6(:2)-6 G
+(b; 8.; 16;)-6 E 6(22)130.336 504 S 6(:2)-6 G(e; 8.d; 16;)-6 E 33
+(LYRICS [1])130.336 516 R("hailed, At the";)6 E(\\)12 E
+([2] "watched, were so";)180.336 528 Q(bar)130.336 540 Q 6(11)130.336
+564 S 6(:a)-6 G 6(;;e)-6 G(;)-6 E 6(12)130.336 576 S 6(:e)-6 G 6(;;;)-6
+G 6(21)130.336 588 S 6(:a)-6 G 6(;;e)-6 G(;)-6 E 6(22)130.336 600 S 6
+(:c)-6 G 6(;;e)-6 G(;)-6 E 33(LYRICS [1])130.336 612 R
+("twi-light's last";)6 E(\\)12 E([2] "gal-lant-ly";)180.336 624 Q
+(bar ending "1.")130.336 636 Q(1-2 1-2: c; 8a-; r; 8.e; 16c;)130.336 660
+Q 33(LYRICS [1])130.336 672 R("gleam-ing, whose broad";)6 E
+(repeatend ending "2.")130.336 684 Q 6(11)130.336 708 S 6(:c)-6 G 6(;8)
+-6 G(a-; r; 8.c+; 16;)-6 E 6(12)130.336 720 S 6(:c)-6 G 6(;8)-6 G
+(a-; r; 8.e; 16;)-6 E 6(21)130.336 732 S 6(:c)-6 G 6(;8)-6 G
+(a-; r; 8.a; 16;)-6 E EP
+%%Page: 159 165
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(59 -)-2.5 E/F1 10/Courier@0
+SF 6(22)130.336 96 S 6(:c)-6 G 6(;8)-6 G(a-; r; 8.a-; 16;)-6 E 33
+(LYRICS [2])130.336 108 R("stream-ing? And the";)6 E(bar endending)
+130.336 120 Q 6(11)130.336 144 S 6(:c)-6 G(+; d+; e+;)-6 E 6(12)130.336
+156 S 6(:e)-6 G 6(;;;)-6 G 6(21)130.336 168 S 6(:a)-6 G 6(;b)-6 G 6(;c)
+-6 G(+;)-6 E 6(22)130.336 180 S 6(:a)-6 G(-; ; ;)-6 E
+(// continue to mark as verse 2 from now on,)130.336 192 Q
+(// so that the lyrics will line up properly)130.336 204 Q
+(// with the lyrics of the second ending.)130.336 216 Q 33(LYRICS [2])
+130.336 228 R("rock-ets' red";)6 E(bar)130.336 240 Q
+(// Define a mapping, and use the chord-at-a-time input method for the)
+105.336 264 Q(// next several measures.)105.336 276 Q
+(Specify the voices in bottom to top order.)12 E(define M)105.336 288 Q
+6([22)12 G 6(;21)-6 G 6(;12)-6 G -6 6(;11] @)-6 H
+(M: a-c+ee+; rrrr; 8a-bed+; a-aec+;)130.336 312 Q 33(LYRICS [2])130.336
+324 R("glare, the bombs";)6 E(bar)130.336 336 Q(M: egeb; egec+; eged+;)
+130.336 360 Q 33(LYRICS [2])130.336 372 R("burst-ing in";)6 E(bar)
+130.336 384 Q(M: eged+; rrrr; eged+;)130.336 408 Q 33(LYRICS [2])130.336
+420 R("air, gave";)6 E(bar)130.336 432 Q(M: 4.a-aec+; 8b-geb; 4caea;)
+130.336 456 Q 33(LYRICS [2])130.336 468 R("proof through the";)6 E(bar)
+130.336 480 Q(M: 2ebeg; 8.ebdf; 16ebdg;)130.336 504 Q 33(LYRICS [2])
+130.336 516 R("night that our";)6 E(bar)130.336 528 Q
+(M: faca; facc; b-ab-d#;)130.336 552 Q 33(LYRICS [2])130.336 564 R
+("flag was still";)6 E(bar)130.336 576 Q(M: egb-e; rrrr; egb-e;)130.336
+600 Q 33(LYRICS [2])130.336 612 R("there. Oh";)6 E(bar)130.336 624 Q 6
+(11)130.336 648 S 6(:4)-6 G(a; ; 8<>; g;)-6 E 6(12)130.336 660 S 6(:4)-6
+G(c; b-; 4a-;)-6 E 6(21)130.336 672 S 6(:e)-6 G 6(;;;)-6 G 6(22)130.336
+684 S 6(:a)-6 G(-; b-; c;)-6 E 33(LYRICS [2])130.336 696 R
+("say, does that";)6 E(bar)130.336 708 Q 6(11)130.336 732 S 6(:f)-6 G 6
+(;;;)-6 G EP
+%%Page: 160 166
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(60 -)-2.5 E/F1 10/Courier@0
+SF 6(12)130.336 96 S 6(:d)-6 G 6(;;e)-6 G(;)-6 E 6(21)130.336 108 S 6
+(:a)-6 G 6(;;a)-6 G(#;)-6 E 6(22)130.336 120 S 6(:d)-6 G 6(;;c)-6 G(;)-6
+E 33(LYRICS [2])130.336 132 R("star-span-gled";)6 E(bar)130.336 144 Q 6
+(11)130.336 168 S 6(:4)-6 G(b; 8d+<>; c+; b<>; a;)-6 E 6(12)130.336 180
+S 6(:4)-6 G(d; 4f; ;)-6 E 6(21)130.336 192 S 6(:b)-6 G 6(;8)-6 G
+(<>; a#; b<>; b#;)-6 E 6(22)130.336 204 S 6(:b)-6 G(-; 8<>; c; d<>; d#;)
+-6 E 33(LYRICS [2])130.336 216 R("ban-ner yet";)6 E(bar)130.336 228 Q
+(mussym\(12\) 1-2: 2 "ferm";)130.336 252 Q 6(11)130.336 264 S 6(:a)-6 G
+(<>; 8g; r; e; ;)-6 E 6(12)130.336 276 S 6(:4)-6 G(.e; 8r; e; ;)-6 E 6
+(21)130.336 288 S 6(:c)-6 G(+<>; 8b; r; g; ;)-6 E 6(22)130.336 300 S 6
+(:4)-6 G(.e; 8r; d; ;)-6 E 33(LYRICS [2])130.336 312 R
+("wave_ o'er the";)6 E(bar)130.336 324 Q 6(11)130.336 348 S 6(:4)-6 G
+(.a<>; 8b; c+; d+;)-6 E 6(12)130.336 360 S 6(:4)-6 G(.e<>; 8; ; ;)-6 E 6
+(21)130.336 372 S 6(:4)-6 G(.a<>; 8g; a; ;)-6 E 6(22)130.336 384 S 6(:4)
+-6 G(.c<>; 8e; a-; b-;)-6 E 33(LYRICS [2])130.336 396 R("land_ of the";)
+6 E(bar)130.336 408 Q(mussym\(12\) 1-2: 1 "ferm";)130.336 432 Q 6(11)
+130.336 444 S 6(:e)-6 G(+; r; 8a; b;)-6 E 6(12)130.336 456 S 6(:e)-6 G 6
+(;r)-6 G 6(;8)-6 G(d; ;)-6 E 6(21)130.336 468 S 6(:a)-6 G 6(;r)-6 G 6
+(;8)-6 G(a; ;)-6 E 6(22)130.336 480 S 6(:c)-6 G 6(;r)-6 G 6(;8)-6 G
+(f; fn;)-6 E 33(LYRICS [2])130.336 492 R("free and the";)6 E(bar)130.336
+504 Q 6(11)130.336 528 S 6(:4)-6 G(.c+; 8d+; 4b;)-6 E 6(12)130.336 540 S
+6(:4)-6 G(.e; 8; 4d;)-6 E 6(21)130.336 552 S 6(:4)-6 G(.a; 8; 4g;)-6 E 6
+(22)130.336 564 S 6(:4)-6 G(.e; 8; 4;)-6 E 33(LYRICS [2])130.336 576 R
+("home of the";)6 E(bar)130.336 588 Q 6(11)130.336 612 S 6(:2)-6 G
+(a; 4s;)-6 E 6(12)130.336 624 S 6(:2)-6 G(c; 4s;)-6 E 6(21)130.336 636 S
+6(:2)-6 G(e; 4s;)-6 E 6(22)130.336 648 S 6(:2)-6 G(a-; 4s;)-6 E 33
+(LYRICS [2])130.336 660 R("brave?";)6 E(endbar)130.336 672 Q EP
+%%Page: 161 167
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(61 -)-2.5 E 11.836 96 EBEGIN
+gsave 0 0.25 0.75 setrgbcolor 0 636 rlineto 552 0 rlineto 0 636 neg rlineto closepath stroke grestore
+EEND 24 127 552 552 -636 636 10.836 732 PBEGIN
+%%BeginDocument: mugex102.ps
+%%BoundingBox: 24 127 576 763
+save
+1930114009 1930113259 sv
+0.650000 0.650000 scale
+%  S_SSV
+(/tmp/ugexiM5077) inputfile
+12 linenum
+%  S_SSV
+29 linenum
+%  S_FEED
+334.29 1513.68 869.54 5 1.000000 1.000000 stf
+334.29 1404.11 869.54 5 1.000000 1.000000 stf
+117.79 1093.68 960.11 brace
+0.70 setlinewidth
+118.29 1093.68 moveto
+118.29 960.11 lineto stroke
+%  S_CLEFSIG
+130.08 1075.68 1.000000 gclef
+130.33 978.11 1.000000 fclef
+144.70 1093.68 1.000000 sharp
+151.34 1084.68 1.000000 sharp
+157.98 1096.68 1.000000 sharp
+144.70 978.11 1.000000 sharp
+151.34 969.11 1.000000 sharp
+157.98 981.11 1.000000 sharp
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+164.30 1081.68 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+164.30 1069.66 moveto
+(4) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+164.30 972.11 moveto
+(3) show
+/NewCenturySchlbk-Bold findfont
+16 scalefont
+setfont
+164.30 960.09 moveto
+(4) show
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+41 linenum
+206.76 1025.96 moveto
+232.29 1025.96 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+186.17 1025.96 moveto
+(Oh) show
+191.32 1069.68 1.000000 4n
+200.58 1072.68 1.000000 dot
+195.00 1070.43 moveto
+195.00 1088.52 lineto stroke
+228.25 1063.68 1.000000 4n
+222.02 1063.68 moveto
+234.49 1063.68 lineto stroke
+231.94 1064.43 moveto
+231.94 1082.52 lineto stroke
+newpath
+194.65 1090.02 moveto
+232.29 1084.02 lineto
+232.29 1081.02 lineto
+194.65 1087.02 lineto
+closepath
+fill
+newpath
+231.59 1079.02 moveto
+223.52 1080.33 lineto
+223.52 1077.33 lineto
+231.59 1076.02 lineto
+closepath
+fill
+191.32 1069.68 1.000000 4n
+200.58 1072.68 1.000000 dot
+187.64 1068.93 moveto
+187.64 1050.83 lineto stroke
+228.25 1063.68 1.000000 4n
+222.02 1063.68 moveto
+234.49 1063.68 lineto stroke
+224.57 1062.93 moveto
+224.57 1044.83 lineto stroke
+newpath
+187.29 1052.33 moveto
+224.92 1046.33 lineto
+224.92 1043.33 lineto
+187.29 1049.33 lineto
+closepath
+fill
+newpath
+224.22 1051.33 moveto
+216.16 1052.64 lineto
+216.16 1049.64 lineto
+224.22 1048.33 lineto
+closepath
+fill
+191.32 1064.58 moveto
+191.39 1064.77 lineto
+195.95 1062.30 200.77 1060.55 205.86 1059.53 curveto
+210.94 1058.51 216.07 1058.26 221.23 1058.78 curveto
+221.22 1058.37 lineto
+216.02 1057.30 210.82 1057.28 205.62 1058.33 curveto
+200.42 1059.37 195.62 1061.39 191.24 1064.39 curveto
+fill
+205.58 1074.78 moveto
+205.59 1075.00 lineto
+209.65 1076.06 213.71 1076.06 217.77 1074.99 curveto
+221.82 1073.91 225.36 1071.91 228.36 1068.98 curveto
+228.15 1068.58 lineto
+224.93 1071.02 221.36 1072.75 217.45 1073.79 curveto
+213.54 1074.82 209.58 1075.08 205.57 1074.55 curveto
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+191.32 975.11 1.000000 4n
+200.58 975.11 1.000000 dot
+0.70 setlinewidth
+195.00 975.86 moveto
+195.00 993.95 lineto stroke
+228.25 969.11 1.000000 4n
+231.94 969.86 moveto
+231.94 987.95 lineto stroke
+newpath
+194.65 995.45 moveto
+232.29 989.45 lineto
+232.29 986.45 lineto
+194.65 992.45 lineto
+closepath
+fill
+newpath
+231.59 984.45 moveto
+223.52 985.76 lineto
+223.52 982.76 lineto
+231.59 981.45 lineto
+closepath
+fill
+191.32 975.11 1.000000 4n
+200.58 975.11 1.000000 dot
+187.64 974.36 moveto
+187.64 956.26 lineto stroke
+228.25 969.11 1.000000 4n
+224.57 968.36 moveto
+224.57 950.26 lineto stroke
+newpath
+187.29 957.76 moveto
+224.92 951.76 lineto
+224.92 948.76 lineto
+187.29 954.76 lineto
+closepath
+fill
+newpath
+224.22 956.76 moveto
+216.16 958.07 lineto
+216.16 955.07 lineto
+224.22 953.76 lineto
+closepath
+fill
+191.32 970.01 moveto
+191.39 970.20 lineto
+195.95 967.73 200.77 965.98 205.86 964.96 curveto
+210.94 963.94 216.07 963.69 221.23 964.21 curveto
+221.22 963.81 lineto
+216.02 962.73 210.82 962.72 205.62 963.76 curveto
+200.42 964.80 195.62 966.82 191.24 969.82 curveto
+fill
+205.58 980.21 moveto
+205.59 980.43 lineto
+209.65 981.50 213.71 981.49 217.77 980.42 curveto
+221.82 979.34 225.36 977.34 228.36 974.41 curveto
+228.15 974.01 lineto
+224.93 976.45 221.36 978.19 217.45 979.22 curveto
+213.54 980.26 209.58 980.51 205.57 979.98 curveto
+fill
+restore
+%  S_BAR
+44 linenum
+253.85 1084.68 1.000000 dot
+253.85 1078.68 1.000000 dot
+253.85 975.11 1.000000 dot
+253.85 969.11 1.000000 dot
+0.70 setlinewidth
+250.85 1093.68 moveto
+250.85 960.11 lineto stroke
+3.00 setlinewidth
+246.85 1093.68 moveto
+246.85 960.11 lineto stroke
+0.70 setlinewidth
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+46 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+263.40 1025.96 moveto
+(say.) show
+/Times-Roman findfont
+12 scalefont
+setfont
+311.82 1025.96 moveto
+(can) show
+/Times-Roman findfont
+12 scalefont
+setfont
+358.21 1025.96 moveto
+(you) show
+46 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+260.34 1012.64 moveto
+(stripes) show
+/Times-Roman findfont
+12 scalefont
+setfont
+311.66 1012.64 moveto
+(and) show
+/Times-Roman findfont
+12 scalefont
+setfont
+355.56 1012.64 moveto
+(bright) show
+268.16 1057.68 1.000000 4n
+261.92 1057.68 moveto
+274.39 1057.68 lineto stroke
+261.92 1063.68 moveto
+274.39 1063.68 lineto stroke
+271.84 1058.43 moveto
+271.84 1081.68 lineto stroke
+315.98 1063.68 1.000000 4n
+309.74 1063.68 moveto
+322.21 1063.68 lineto stroke
+319.66 1064.43 moveto
+319.66 1084.68 lineto stroke
+362.69 1069.68 1.000000 4n
+366.37 1070.43 moveto
+366.37 1090.68 lineto stroke
+268.16 1057.68 1.000000 4n
+261.92 1057.68 moveto
+274.39 1057.68 lineto stroke
+261.92 1063.68 moveto
+274.39 1063.68 lineto stroke
+264.47 1056.93 moveto
+264.47 1036.68 lineto stroke
+315.98 1063.68 1.000000 4n
+309.74 1063.68 moveto
+322.21 1063.68 lineto stroke
+312.29 1062.93 moveto
+312.29 1042.68 lineto stroke
+362.69 1060.68 1.000000 4n
+356.46 1063.68 moveto
+368.92 1063.68 lineto stroke
+359.01 1059.93 moveto
+359.01 1039.68 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+268.16 963.11 1.000000 4n
+0.70 setlinewidth
+271.84 963.86 moveto
+271.84 984.11 lineto stroke
+315.98 984.11 1.000000 4n
+319.66 984.86 moveto
+319.66 1005.11 lineto stroke
+362.69 987.11 1.000000 4n
+366.37 987.86 moveto
+366.37 1008.11 lineto stroke
+268.16 963.11 1.000000 4n
+264.47 962.36 moveto
+264.47 942.11 lineto stroke
+315.98 984.11 1.000000 4n
+312.29 983.36 moveto
+312.29 963.11 lineto stroke
+362.69 981.11 1.000000 4n
+359.01 980.36 moveto
+359.01 960.11 lineto stroke
+restore
+%  S_BAR
+53 linenum
+0.70 setlinewidth
+408.44 1093.68 moveto
+408.44 960.11 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+54 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+421.16 1025.96 moveto
+(see,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+496.19 1025.96 moveto
+(by) show
+/Times-Roman findfont
+12 scalefont
+setfont
+532.97 1025.96 moveto
+(the) show
+54 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+419.51 1012.64 moveto
+(stars,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+489.89 1012.64 moveto
+(through) show
+/Times-Roman findfont
+12 scalefont
+setfont
+532.97 1012.64 moveto
+(the) show
+425.75 1078.68 1.000000 2n
+429.65 1079.43 moveto
+429.65 1099.68 lineto stroke
+499.18 1084.68 1.000000 4n
+508.44 1084.68 1.000000 dot
+502.86 1085.43 moveto
+502.86 1103.85 lineto stroke
+536.62 1081.68 1.000000 4n
+540.30 1082.43 moveto
+540.30 1100.85 lineto stroke
+newpath
+502.51 1105.35 moveto
+540.65 1102.35 lineto
+540.65 1099.35 lineto
+502.51 1102.35 lineto
+closepath
+fill
+newpath
+539.95 1097.35 moveto
+531.89 1098.00 lineto
+531.89 1095.00 lineto
+539.95 1094.35 lineto
+closepath
+fill
+425.75 1063.68 1.000000 2n
+419.30 1063.68 moveto
+432.20 1063.68 lineto stroke
+421.85 1062.93 moveto
+421.85 1042.68 lineto stroke
+499.18 1063.68 1.000000 4n
+508.44 1060.68 1.000000 dot
+492.94 1063.68 moveto
+505.41 1063.68 lineto stroke
+495.49 1062.93 moveto
+495.49 1044.18 lineto stroke
+536.62 1063.68 1.000000 4n
+530.39 1063.68 moveto
+542.85 1063.68 lineto stroke
+532.94 1062.93 moveto
+532.94 1044.18 lineto stroke
+newpath
+495.14 1045.68 moveto
+533.29 1045.68 lineto
+533.29 1042.68 lineto
+495.14 1042.68 lineto
+closepath
+fill
+newpath
+532.59 1050.68 moveto
+524.52 1050.68 lineto
+524.52 1047.68 lineto
+532.59 1047.68 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+425.75 984.11 1.000000 2n
+0.70 setlinewidth
+429.65 984.86 moveto
+429.65 1005.11 lineto stroke
+499.18 981.11 1.000000 4n
+508.44 981.11 1.000000 dot
+502.86 981.86 moveto
+502.86 1000.61 lineto stroke
+536.62 981.11 1.000000 4n
+540.30 981.86 moveto
+540.30 1000.61 lineto stroke
+newpath
+502.51 1002.11 moveto
+540.65 1002.11 lineto
+540.65 999.11 lineto
+502.51 999.11 lineto
+closepath
+fill
+newpath
+539.95 997.11 moveto
+531.89 997.11 lineto
+531.89 994.11 lineto
+539.95 994.11 lineto
+closepath
+fill
+425.75 978.11 1.000000 2n
+421.85 977.36 moveto
+421.85 957.11 lineto stroke
+499.18 975.11 1.000000 4n
+489.82 975.11 1.000000 sharp
+508.44 975.11 1.000000 dot
+495.49 974.36 moveto
+495.49 955.61 lineto stroke
+536.62 975.11 1.000000 4n
+532.94 974.36 moveto
+532.94 955.61 lineto stroke
+newpath
+495.14 957.11 moveto
+533.29 957.11 lineto
+533.29 954.11 lineto
+495.14 954.11 lineto
+closepath
+fill
+newpath
+532.59 962.11 moveto
+524.52 962.11 lineto
+524.52 959.11 lineto
+532.59 959.11 lineto
+closepath
+fill
+restore
+%  S_BAR
+61 linenum
+0.70 setlinewidth
+554.71 1093.68 moveto
+554.71 960.11 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+62 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+560.28 1025.96 moveto
+(dawn's) show
+/Times-Roman findfont
+12 scalefont
+setfont
+643.21 1025.96 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+611.77 1025.96 moveto
+(ear) show
+/Times-Roman findfont
+12 scalefont
+setfont
+663.03 1025.96 moveto
+(ly) show
+62 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+595.07 1012.64 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+564.12 1012.64 moveto
+(per) show
+/Times-Roman findfont
+12 scalefont
+setfont
+639.29 1012.64 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+613.76 1012.64 moveto
+(il) show
+/Times-Roman findfont
+12 scalefont
+setfont
+661.20 1012.64 moveto
+(ous) show
+568.92 1078.68 1.000000 4n
+572.61 1079.43 moveto
+572.61 1099.68 lineto stroke
+616.41 1063.68 1.000000 4n
+610.18 1063.68 moveto
+622.64 1063.68 lineto stroke
+620.09 1064.43 moveto
+620.09 1084.68 lineto stroke
+665.36 1066.68 1.000000 4n
+656.00 1066.68 1.000000 sharp
+669.04 1067.43 moveto
+669.04 1087.68 lineto stroke
+568.92 1063.68 1.000000 4n
+562.69 1063.68 moveto
+575.16 1063.68 lineto stroke
+565.24 1062.93 moveto
+565.24 1042.68 lineto stroke
+616.41 1063.68 1.000000 4n
+610.18 1063.68 moveto
+622.64 1063.68 lineto stroke
+612.73 1062.93 moveto
+612.73 1042.68 lineto stroke
+665.36 1060.68 1.000000 4n
+659.12 1063.68 moveto
+671.59 1063.68 lineto stroke
+661.67 1059.93 moveto
+661.67 1039.68 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+568.92 984.11 1.000000 4n
+0.70 setlinewidth
+572.61 984.86 moveto
+572.61 1005.11 lineto stroke
+616.41 984.11 1.000000 4n
+620.09 984.86 moveto
+620.09 1005.11 lineto stroke
+665.36 984.11 1.000000 4n
+669.04 984.86 moveto
+669.04 1005.11 lineto stroke
+568.92 978.11 1.000000 4n
+565.24 977.36 moveto
+565.24 957.11 lineto stroke
+616.41 978.11 1.000000 4n
+612.73 977.36 moveto
+612.73 957.11 lineto stroke
+665.36 966.11 1.000000 4n
+661.67 965.36 moveto
+661.67 945.11 lineto stroke
+restore
+%  S_BAR
+69 linenum
+0.70 setlinewidth
+709.62 1093.68 moveto
+709.62 960.11 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+70 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+718.76 1025.96 moveto
+(light) show
+/Times-Roman findfont
+12 scalefont
+setfont
+806.74 1025.96 moveto
+(what) show
+/Times-Roman findfont
+12 scalefont
+setfont
+838.98 1025.96 moveto
+(so) show
+70 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+717.84 1012.64 moveto
+(fight,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+807.75 1012.64 moveto
+(o'er) show
+/Times-Roman findfont
+12 scalefont
+setfont
+837.99 1012.64 moveto
+(the) show
+724.23 1069.68 1.000000 4n
+727.91 1070.43 moveto
+727.91 1090.68 lineto stroke
+772.16 1093.68 1.000000 4rest
+812.56 1069.68 1.000000 4n
+816.24 1070.43 moveto
+816.24 1089.18 lineto stroke
+841.64 1069.68 1.000000 4n
+845.32 1070.43 moveto
+845.32 1089.18 lineto stroke
+newpath
+815.89 1090.68 moveto
+845.67 1090.68 lineto
+845.67 1087.68 lineto
+815.89 1087.68 lineto
+closepath
+fill
+724.23 1060.68 1.000000 4n
+718.00 1063.68 moveto
+730.46 1063.68 lineto stroke
+720.55 1059.93 moveto
+720.55 1039.68 lineto stroke
+772.16 1051.68 1.000000 4rest
+812.56 1060.68 1.000000 4n
+806.32 1063.68 moveto
+818.79 1063.68 lineto stroke
+808.87 1059.93 moveto
+808.87 1041.18 lineto stroke
+841.64 1060.68 1.000000 4n
+835.41 1063.68 moveto
+847.87 1063.68 lineto stroke
+837.96 1059.93 moveto
+837.96 1041.18 lineto stroke
+newpath
+808.52 1042.68 moveto
+838.31 1042.68 lineto
+838.31 1039.68 lineto
+808.52 1039.68 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+724.23 981.11 1.000000 4n
+0.70 setlinewidth
+727.91 981.86 moveto
+727.91 1002.11 lineto stroke
+772.16 990.11 1.000000 4rest
+812.56 981.11 1.000000 4n
+816.24 981.86 moveto
+816.24 1000.61 lineto stroke
+841.64 981.11 1.000000 4n
+845.32 981.86 moveto
+845.32 1000.61 lineto stroke
+newpath
+815.89 1002.11 moveto
+845.67 1002.11 lineto
+845.67 999.11 lineto
+815.89 999.11 lineto
+closepath
+fill
+724.23 975.11 1.000000 4n
+720.55 974.36 moveto
+720.55 954.11 lineto stroke
+772.16 960.11 1.000000 4rest
+812.56 975.11 1.000000 4n
+808.87 974.36 moveto
+808.87 955.61 lineto stroke
+841.64 975.11 1.000000 4n
+837.96 974.36 moveto
+837.96 955.61 lineto stroke
+newpath
+808.52 957.11 moveto
+838.31 957.11 lineto
+838.31 954.11 lineto
+808.52 954.11 lineto
+closepath
+fill
+restore
+%  S_BAR
+77 linenum
+0.70 setlinewidth
+869.19 1093.68 moveto
+869.19 960.11 lineto stroke
+%  S_FEED
+298.00 1320.11 869.54 5 1.000000 1.000000 stf
+/Times-Roman findfont
+11 scalefont
+setfont
+86.50 914.11 moveto
+(5) show
+298.00 1207.41 869.54 5 1.000000 1.000000 stf
+81.50 900.11 763.41 brace
+82.00 900.11 moveto
+82.00 763.41 lineto stroke
+550.59 914.11 moveto
+550.59 925.11 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+553.59 915.11 moveto
+(1.) show
+550.59 925.11 moveto
+709.87 925.11 lineto stroke
+709.87 925.11 moveto
+709.87 914.11 lineto stroke
+713.87 914.11 moveto
+713.87 925.11 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+716.87 915.11 moveto
+(2.) show
+713.87 925.11 moveto
+867.19 925.11 lineto stroke
+%  S_CLEFSIG
+93.79 882.11 1.000000 gclef
+94.04 781.41 1.000000 fclef
+108.41 900.11 1.000000 sharp
+115.05 891.11 1.000000 sharp
+121.69 903.11 1.000000 sharp
+108.41 781.41 1.000000 sharp
+115.05 772.41 1.000000 sharp
+121.69 784.41 1.000000 sharp
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+78 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+183.52 829.33 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+141.70 829.33 moveto
+(proud) show
+/Times-Roman findfont
+12 scalefont
+setfont
+200.47 829.33 moveto
+(ly) show
+/Times-Roman findfont
+12 scalefont
+setfont
+230.02 829.33 moveto
+(we) show
+78 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+178.32 816.01 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+144.00 816.01 moveto
+(ram) show
+/Times-Roman findfont
+12 scalefont
+setfont
+196.98 816.01 moveto
+(parts) show
+/Times-Roman findfont
+12 scalefont
+setfont
+230.02 816.01 moveto
+(we) show
+149.66 891.11 1.000000 4n
+158.92 891.11 1.000000 dot
+153.34 891.86 moveto
+153.34 912.11 lineto stroke
+202.79 888.11 1.000000 4n
+206.47 888.86 moveto
+206.47 909.11 lineto stroke
+209.50 909.11 1.000000 dnflag
+233.51 885.11 1.000000 4n
+237.20 885.86 moveto
+237.20 906.11 lineto stroke
+149.66 876.11 1.000000 4n
+158.92 873.11 1.000000 dot
+145.97 875.36 moveto
+145.97 855.11 lineto stroke
+202.79 876.11 1.000000 4n
+199.11 875.36 moveto
+199.11 855.11 lineto stroke
+202.13 855.11 1.000000 upflag
+233.51 876.11 1.000000 4n
+229.83 875.36 moveto
+229.83 855.11 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+149.66 787.41 1.000000 4n
+158.92 790.41 1.000000 dot
+0.70 setlinewidth
+153.34 788.16 moveto
+153.34 808.41 lineto stroke
+202.79 784.41 1.000000 4n
+206.47 785.16 moveto
+206.47 805.41 lineto stroke
+209.50 805.41 1.000000 dnflag
+233.51 787.41 1.000000 4n
+237.20 788.16 moveto
+237.20 808.41 lineto stroke
+149.66 766.41 1.000000 4n
+158.92 766.41 1.000000 dot
+145.97 765.66 moveto
+145.97 745.41 lineto stroke
+202.79 769.41 1.000000 4n
+199.11 768.66 moveto
+199.11 748.41 lineto stroke
+202.13 748.41 1.000000 upflag
+233.51 772.41 1.000000 4n
+229.83 771.66 moveto
+229.83 751.41 lineto stroke
+restore
+%  S_BAR
+85 linenum
+0.70 setlinewidth
+273.60 900.11 moveto
+273.60 763.41 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+86 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+284.58 829.33 moveto
+(hailed,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+358.92 829.33 moveto
+(At) show
+/Times-Roman findfont
+12 scalefont
+setfont
+390.65 829.33 moveto
+(the) show
+86 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+281.91 816.01 moveto
+(watched,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+356.09 816.01 moveto
+(were) show
+/Times-Roman findfont
+12 scalefont
+setfont
+391.64 816.01 moveto
+(so) show
+292.64 882.11 1.000000 2n
+296.54 882.86 moveto
+296.54 903.11 lineto stroke
+358.23 879.11 1.000000 4n
+374.85 879.11 1.000000 dot
+361.91 879.86 moveto
+361.91 898.94 lineto stroke
+394.31 882.11 1.000000 4n
+397.99 882.86 moveto
+397.99 901.94 lineto stroke
+newpath
+361.56 900.44 moveto
+398.34 903.44 lineto
+398.34 900.44 lineto
+361.56 897.44 lineto
+closepath
+fill
+newpath
+397.64 898.44 moveto
+389.58 897.77 lineto
+389.58 894.77 lineto
+397.64 895.44 lineto
+closepath
+fill
+292.64 876.11 1.000000 2n
+288.74 875.36 moveto
+288.74 855.11 lineto stroke
+365.59 876.11 1.000000 4n
+374.85 873.11 1.000000 dot
+361.91 875.36 moveto
+361.91 856.61 lineto stroke
+394.31 876.11 1.000000 4n
+390.63 875.36 moveto
+390.63 856.61 lineto stroke
+newpath
+361.56 858.11 moveto
+390.98 858.11 lineto
+390.98 855.11 lineto
+361.56 855.11 lineto
+closepath
+fill
+newpath
+390.28 863.11 moveto
+382.21 863.11 lineto
+382.21 860.11 lineto
+390.28 860.11 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+292.64 790.41 1.000000 2n
+0.70 setlinewidth
+296.54 791.16 moveto
+296.54 811.41 lineto stroke
+361.91 790.41 1.000000 4n
+371.17 790.41 1.000000 dot
+365.59 791.16 moveto
+365.59 809.91 lineto stroke
+394.31 790.41 1.000000 4n
+397.99 791.16 moveto
+397.99 809.91 lineto stroke
+newpath
+365.24 811.41 moveto
+398.34 811.41 lineto
+398.34 808.41 lineto
+365.24 808.41 lineto
+closepath
+fill
+newpath
+397.64 806.41 moveto
+389.58 806.41 lineto
+389.58 803.41 lineto
+397.64 803.41 lineto
+closepath
+fill
+292.64 778.41 1.000000 2n
+288.74 777.66 moveto
+288.74 757.41 lineto stroke
+361.91 775.41 1.000000 4n
+371.17 772.41 1.000000 dot
+358.23 774.66 moveto
+358.23 755.91 lineto stroke
+394.31 775.41 1.000000 4n
+390.63 774.66 moveto
+390.63 755.91 lineto stroke
+newpath
+357.88 757.41 moveto
+390.98 757.41 lineto
+390.98 754.41 lineto
+357.88 754.41 lineto
+closepath
+fill
+newpath
+390.28 762.41 moveto
+382.21 762.41 lineto
+382.21 759.41 lineto
+390.28 759.41 lineto
+closepath
+fill
+restore
+%  S_BAR
+93 linenum
+0.70 setlinewidth
+411.13 900.11 moveto
+411.13 763.41 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+94 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+443.03 829.33 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+418.15 829.33 moveto
+(twi) show
+/Times-Roman findfont
+12 scalefont
+setfont
+455.65 829.33 moveto
+(light's) show
+/Times-Roman findfont
+12 scalefont
+setfont
+504.01 829.33 moveto
+(last) show
+94 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+443.87 816.01 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+418.31 816.01 moveto
+(gal) show
+/Times-Roman findfont
+12 scalefont
+setfont
+489.29 816.01 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+457.81 816.01 moveto
+(lant) show
+/Times-Roman findfont
+12 scalefont
+setfont
+505.85 816.01 moveto
+(ly) show
+422.95 885.11 1.000000 4n
+426.64 885.86 moveto
+426.64 906.11 lineto stroke
+463.28 885.11 1.000000 4n
+466.96 885.86 moveto
+466.96 906.11 lineto stroke
+508.17 876.11 1.000000 4n
+511.85 876.86 moveto
+511.85 897.11 lineto stroke
+422.95 876.11 1.000000 4n
+419.27 875.36 moveto
+419.27 855.11 lineto stroke
+463.28 876.11 1.000000 4n
+459.60 875.36 moveto
+459.60 855.11 lineto stroke
+508.17 876.11 1.000000 4n
+504.49 875.36 moveto
+504.49 855.11 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+422.95 787.41 1.000000 4n
+0.70 setlinewidth
+426.64 788.16 moveto
+426.64 808.41 lineto stroke
+463.28 787.41 1.000000 4n
+466.96 788.16 moveto
+466.96 808.41 lineto stroke
+508.17 778.41 1.000000 4n
+511.85 779.16 moveto
+511.85 799.41 lineto stroke
+422.95 772.41 1.000000 4n
+419.27 771.66 moveto
+419.27 751.41 lineto stroke
+463.28 772.41 1.000000 4n
+459.60 771.66 moveto
+459.60 751.41 lineto stroke
+508.17 778.41 1.000000 4n
+504.49 777.66 moveto
+504.49 757.41 lineto stroke
+restore
+%  S_BAR
+100 linenum
+0.70 setlinewidth
+548.59 900.11 moveto
+548.59 763.41 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+102 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+589.78 829.33 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+554.06 829.33 moveto
+(gleam) show
+/Times-Roman findfont
+12 scalefont
+setfont
+599.20 829.33 moveto
+(ing,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+642.66 829.33 moveto
+(whose) show
+/Times-Roman findfont
+12 scalefont
+setfont
+676.65 829.33 moveto
+(broad) show
+562.38 870.11 1.000000 4n
+556.14 870.11 moveto
+568.61 870.11 lineto stroke
+566.06 870.86 moveto
+566.06 891.11 lineto stroke
+603.77 864.11 1.000000 4n
+597.54 864.11 moveto
+610.01 864.11 lineto stroke
+597.54 870.11 moveto
+610.01 870.11 lineto stroke
+607.46 864.86 moveto
+607.46 888.11 lineto stroke
+610.48 888.11 1.000000 dnflag
+628.61 900.11 1.000000 8rest
+650.31 876.11 1.000000 4n
+659.58 879.11 1.000000 dot
+653.99 876.86 moveto
+653.99 894.88 lineto stroke
+683.45 870.11 1.000000 4n
+677.22 870.11 moveto
+689.69 870.11 lineto stroke
+687.14 870.86 moveto
+687.14 888.88 lineto stroke
+newpath
+653.64 896.38 moveto
+687.49 890.38 lineto
+687.49 887.38 lineto
+653.64 893.38 lineto
+closepath
+fill
+newpath
+686.79 885.38 moveto
+678.72 886.84 lineto
+678.72 883.84 lineto
+686.79 882.38 lineto
+closepath
+fill
+562.38 870.11 1.000000 4n
+556.14 870.11 moveto
+568.61 870.11 lineto stroke
+558.69 869.36 moveto
+558.69 849.11 lineto stroke
+603.77 864.11 1.000000 4n
+597.54 864.11 moveto
+610.01 864.11 lineto stroke
+597.54 870.11 moveto
+610.01 870.11 lineto stroke
+600.09 863.36 moveto
+600.09 843.11 lineto stroke
+603.12 843.11 1.000000 upflag
+628.61 846.11 1.000000 8rest
+650.31 876.11 1.000000 4n
+659.58 879.11 1.000000 dot
+646.63 875.36 moveto
+646.63 857.34 lineto stroke
+683.45 870.11 1.000000 4n
+677.22 870.11 moveto
+689.69 870.11 lineto stroke
+679.77 869.36 moveto
+679.77 851.34 lineto stroke
+newpath
+646.28 858.84 moveto
+680.12 852.84 lineto
+680.12 849.84 lineto
+646.28 855.84 lineto
+closepath
+fill
+newpath
+679.42 857.84 moveto
+671.36 859.30 lineto
+671.36 856.30 lineto
+679.42 854.84 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+562.38 772.41 1.000000 4n
+0.70 setlinewidth
+566.06 773.16 moveto
+566.06 793.41 lineto stroke
+603.77 766.41 1.000000 4n
+607.46 767.16 moveto
+607.46 787.41 lineto stroke
+610.48 787.41 1.000000 dnflag
+628.61 793.41 1.000000 8rest
+650.31 778.41 1.000000 4n
+659.58 778.41 1.000000 dot
+653.99 779.16 moveto
+653.99 797.18 lineto stroke
+683.45 772.41 1.000000 4n
+687.14 773.16 moveto
+687.14 791.18 lineto stroke
+newpath
+653.64 798.68 moveto
+687.49 792.68 lineto
+687.49 789.68 lineto
+653.64 795.68 lineto
+closepath
+fill
+newpath
+686.79 787.68 moveto
+678.72 789.14 lineto
+678.72 786.14 lineto
+686.79 784.68 lineto
+closepath
+fill
+562.38 772.41 1.000000 4n
+558.69 771.66 moveto
+558.69 751.41 lineto stroke
+603.77 766.41 1.000000 4n
+600.09 765.66 moveto
+600.09 745.41 lineto stroke
+603.12 745.41 1.000000 upflag
+628.61 751.41 1.000000 8rest
+650.31 778.41 1.000000 4n
+659.58 778.41 1.000000 dot
+646.63 777.66 moveto
+646.63 759.64 lineto stroke
+683.45 772.41 1.000000 4n
+679.77 771.66 moveto
+679.77 753.64 lineto stroke
+newpath
+646.28 761.14 moveto
+680.12 755.14 lineto
+680.12 752.14 lineto
+646.28 758.14 lineto
+closepath
+fill
+newpath
+679.42 760.14 moveto
+671.36 761.60 lineto
+671.36 758.60 lineto
+679.42 757.14 lineto
+closepath
+fill
+restore
+%  S_BAR
+104 linenum
+707.87 891.11 1.000000 dot
+707.87 885.11 1.000000 dot
+707.87 778.41 1.000000 dot
+707.87 772.41 1.000000 dot
+0.70 setlinewidth
+711.87 900.11 moveto
+711.87 763.41 lineto stroke
+3.00 setlinewidth
+715.87 900.11 moveto
+715.87 763.41 lineto stroke
+0.70 setlinewidth
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+106 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+758.76 816.01 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+721.48 816.01 moveto
+(stream) show
+/Times-Roman findfont
+12 scalefont
+setfont
+767.07 816.01 moveto
+(ing?) show
+/Times-Roman findfont
+12 scalefont
+setfont
+815.15 816.01 moveto
+(And) show
+/Times-Roman findfont
+12 scalefont
+setfont
+848.71 816.01 moveto
+(the) show
+730.47 870.11 1.000000 4n
+724.23 870.11 moveto
+736.70 870.11 lineto stroke
+734.15 870.86 moveto
+734.15 891.11 lineto stroke
+772.22 864.11 1.000000 4n
+765.98 864.11 moveto
+778.45 864.11 lineto stroke
+765.98 870.11 moveto
+778.45 870.11 lineto stroke
+775.90 864.86 moveto
+775.90 888.11 lineto stroke
+778.92 888.11 1.000000 dnflag
+797.07 900.11 1.000000 8rest
+820.30 891.11 1.000000 4n
+829.57 891.11 1.000000 dot
+823.98 891.86 moveto
+823.98 910.61 lineto stroke
+852.37 891.11 1.000000 4n
+856.05 891.86 moveto
+856.05 910.61 lineto stroke
+newpath
+823.63 912.11 moveto
+856.40 912.11 lineto
+856.40 909.11 lineto
+823.63 909.11 lineto
+closepath
+fill
+newpath
+855.70 907.11 moveto
+847.64 907.11 lineto
+847.64 904.11 lineto
+855.70 904.11 lineto
+closepath
+fill
+730.47 870.11 1.000000 4n
+724.23 870.11 moveto
+736.70 870.11 lineto stroke
+726.78 869.36 moveto
+726.78 849.11 lineto stroke
+772.22 864.11 1.000000 4n
+765.98 864.11 moveto
+778.45 864.11 lineto stroke
+765.98 870.11 moveto
+778.45 870.11 lineto stroke
+768.53 863.36 moveto
+768.53 843.11 lineto stroke
+771.56 843.11 1.000000 upflag
+797.07 846.11 1.000000 8rest
+820.30 876.11 1.000000 4n
+829.57 873.11 1.000000 dot
+816.62 875.36 moveto
+816.62 856.61 lineto stroke
+852.37 876.11 1.000000 4n
+848.69 875.36 moveto
+848.69 856.61 lineto stroke
+newpath
+816.27 858.11 moveto
+849.04 858.11 lineto
+849.04 855.11 lineto
+816.27 855.11 lineto
+closepath
+fill
+newpath
+848.34 863.11 moveto
+840.27 863.11 lineto
+840.27 860.11 lineto
+848.34 860.11 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+730.47 772.41 1.000000 4n
+0.70 setlinewidth
+734.15 773.16 moveto
+734.15 793.41 lineto stroke
+772.22 766.41 1.000000 4n
+775.90 767.16 moveto
+775.90 787.41 lineto stroke
+778.92 787.41 1.000000 dnflag
+797.07 787.41 1.000000 8rest
+820.30 787.41 1.000000 4n
+829.57 790.41 1.000000 dot
+823.98 788.16 moveto
+823.98 806.91 lineto stroke
+852.37 787.41 1.000000 4n
+856.05 788.16 moveto
+856.05 806.91 lineto stroke
+newpath
+823.63 808.41 moveto
+856.40 808.41 lineto
+856.40 805.41 lineto
+823.63 805.41 lineto
+closepath
+fill
+newpath
+855.70 803.41 moveto
+847.64 803.41 lineto
+847.64 800.41 lineto
+855.70 800.41 lineto
+closepath
+fill
+730.47 772.41 1.000000 4n
+726.78 771.66 moveto
+726.78 751.41 lineto stroke
+772.22 766.41 1.000000 4n
+768.53 765.66 moveto
+768.53 745.41 lineto stroke
+771.56 745.41 1.000000 upflag
+797.07 751.41 1.000000 8rest
+820.30 766.41 1.000000 4n
+829.57 766.41 1.000000 dot
+816.62 765.66 moveto
+816.62 746.91 lineto stroke
+852.37 766.41 1.000000 4n
+848.69 765.66 moveto
+848.69 746.91 lineto stroke
+newpath
+816.27 748.41 moveto
+849.04 748.41 lineto
+849.04 745.41 lineto
+816.27 745.41 lineto
+closepath
+fill
+newpath
+848.34 753.41 moveto
+840.27 753.41 lineto
+840.27 750.41 lineto
+848.34 750.41 lineto
+closepath
+fill
+restore
+%  S_BAR
+111 linenum
+0.70 setlinewidth
+869.19 900.11 moveto
+869.19 763.41 lineto stroke
+%  S_FEED
+298.00 1123.41 869.54 5 1.000000 1.000000 stf
+/Times-Roman findfont
+11 scalefont
+setfont
+86.50 717.41 moveto
+(10) show
+298.00 1036.16 869.54 5 1.000000 1.000000 stf
+81.50 703.41 592.16 brace
+82.00 703.41 moveto
+82.00 592.16 lineto stroke
+%  S_CLEFSIG
+93.79 685.41 1.000000 gclef
+94.04 610.16 1.000000 fclef
+108.41 703.41 1.000000 sharp
+115.05 694.41 1.000000 sharp
+121.69 706.41 1.000000 sharp
+108.41 610.16 1.000000 sharp
+115.05 601.16 1.000000 sharp
+121.69 613.16 1.000000 sharp
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+113 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+172.42 647.69 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+140.28 647.69 moveto
+(rock) show
+/Times-Roman findfont
+12 scalefont
+setfont
+186.33 647.69 moveto
+(ets') show
+/Times-Roman findfont
+12 scalefont
+setfont
+232.00 647.69 moveto
+(red) show
+146.58 694.41 1.000000 4n
+150.26 695.16 moveto
+150.26 715.41 lineto stroke
+190.65 697.41 1.000000 4n
+194.33 698.16 moveto
+194.33 718.41 lineto stroke
+235.82 700.41 1.000000 4n
+239.50 701.16 moveto
+239.50 721.41 lineto stroke
+146.58 679.41 1.000000 4n
+142.90 678.66 moveto
+142.90 658.41 lineto stroke
+190.65 679.41 1.000000 4n
+186.96 678.66 moveto
+186.96 658.41 lineto stroke
+235.82 679.41 1.000000 4n
+232.14 678.66 moveto
+232.14 658.41 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+146.58 616.16 1.000000 4n
+0.70 setlinewidth
+150.26 616.91 moveto
+150.26 637.16 lineto stroke
+190.65 619.16 1.000000 4n
+194.33 619.91 moveto
+194.33 640.16 lineto stroke
+235.82 622.16 1.000000 4n
+229.59 622.16 moveto
+242.05 622.16 lineto stroke
+239.50 622.91 moveto
+239.50 643.16 lineto stroke
+146.58 595.16 1.000000 4n
+142.90 594.41 moveto
+142.90 574.16 lineto stroke
+190.65 595.16 1.000000 4n
+186.96 594.41 moveto
+186.96 574.16 lineto stroke
+235.82 595.16 1.000000 4n
+232.14 594.41 moveto
+232.14 574.16 lineto stroke
+restore
+%  S_BAR
+122 linenum
+0.70 setlinewidth
+277.54 703.41 moveto
+277.54 592.16 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+127 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+285.11 647.69 moveto
+(glare,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+371.78 647.69 moveto
+(the) show
+/Times-Roman findfont
+12 scalefont
+setfont
+392.14 647.69 moveto
+(bombs) show
+291.84 700.41 1.000000 4n
+295.53 701.16 moveto
+295.53 721.41 lineto stroke
+337.10 703.41 1.000000 4rest
+375.44 697.41 1.000000 4n
+379.12 698.16 moveto
+379.12 716.42 lineto stroke
+400.13 694.41 1.000000 4n
+403.82 695.16 moveto
+403.82 713.42 lineto stroke
+newpath
+378.77 717.92 moveto
+404.17 714.92 lineto
+404.17 711.92 lineto
+378.77 714.92 lineto
+closepath
+fill
+291.84 679.41 1.000000 4n
+288.16 678.66 moveto
+288.16 658.41 lineto stroke
+337.10 679.41 1.000000 4rest
+375.44 679.41 1.000000 4n
+371.76 678.66 moveto
+371.76 659.91 lineto stroke
+400.13 679.41 1.000000 4n
+396.45 678.66 moveto
+396.45 659.91 lineto stroke
+newpath
+371.41 661.41 moveto
+396.80 661.41 lineto
+396.80 658.41 lineto
+371.41 658.41 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+291.84 622.16 1.000000 4n
+0.70 setlinewidth
+285.61 622.16 moveto
+298.08 622.16 lineto stroke
+295.53 622.91 moveto
+295.53 643.16 lineto stroke
+337.10 616.16 1.000000 4rest
+375.44 619.16 1.000000 4n
+379.12 619.91 moveto
+379.12 638.18 lineto stroke
+400.13 616.16 1.000000 4n
+403.82 616.91 moveto
+403.82 635.18 lineto stroke
+newpath
+378.77 639.68 moveto
+404.17 636.68 lineto
+404.17 633.68 lineto
+378.77 636.68 lineto
+closepath
+fill
+291.84 595.16 1.000000 4n
+288.16 594.41 moveto
+288.16 574.16 lineto stroke
+337.10 592.16 1.000000 4rest
+375.44 595.16 1.000000 4n
+371.76 594.41 moveto
+371.76 575.66 lineto stroke
+400.13 595.16 1.000000 4n
+396.45 594.41 moveto
+396.45 575.66 lineto stroke
+newpath
+371.41 577.16 moveto
+396.80 577.16 lineto
+396.80 574.16 lineto
+371.41 574.16 lineto
+closepath
+fill
+restore
+%  S_BAR
+130 linenum
+0.70 setlinewidth
+428.49 703.41 moveto
+428.49 592.16 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+131 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+469.28 647.69 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+434.93 647.69 moveto
+(burst) show
+/Times-Roman findfont
+12 scalefont
+setfont
+482.73 647.69 moveto
+(ing) show
+/Times-Roman findfont
+12 scalefont
+setfont
+529.89 647.69 moveto
+(in) show
+441.89 691.41 1.000000 4n
+445.58 692.16 moveto
+445.58 712.41 lineto stroke
+486.54 694.41 1.000000 4n
+490.23 695.16 moveto
+490.23 715.41 lineto stroke
+532.21 697.41 1.000000 4n
+535.89 698.16 moveto
+535.89 718.41 lineto stroke
+441.89 679.41 1.000000 4n
+438.21 678.66 moveto
+438.21 658.41 lineto stroke
+486.54 679.41 1.000000 4n
+482.86 678.66 moveto
+482.86 658.41 lineto stroke
+532.21 679.41 1.000000 4n
+528.53 678.66 moveto
+528.53 658.41 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+441.89 613.16 1.000000 4n
+0.70 setlinewidth
+445.58 613.91 moveto
+445.58 634.16 lineto stroke
+486.54 613.16 1.000000 4n
+490.23 613.91 moveto
+490.23 634.16 lineto stroke
+532.21 613.16 1.000000 4n
+535.89 613.91 moveto
+535.89 634.16 lineto stroke
+441.89 607.16 1.000000 4n
+438.21 606.41 moveto
+438.21 586.16 lineto stroke
+486.54 607.16 1.000000 4n
+482.86 606.41 moveto
+482.86 586.16 lineto stroke
+532.21 607.16 1.000000 4n
+528.53 606.41 moveto
+528.53 586.16 lineto stroke
+restore
+%  S_BAR
+134 linenum
+0.70 setlinewidth
+573.19 703.41 moveto
+573.19 592.16 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+135 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+583.30 647.69 moveto
+(air,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+667.66 647.69 moveto
+(gave) show
+587.20 697.41 1.000000 4n
+590.89 698.16 moveto
+590.89 718.41 lineto stroke
+630.94 703.41 1.000000 4rest
+673.31 697.41 1.000000 4n
+676.99 698.16 moveto
+676.99 718.41 lineto stroke
+587.20 679.41 1.000000 4n
+583.52 678.66 moveto
+583.52 658.41 lineto stroke
+630.94 679.41 1.000000 4rest
+673.31 679.41 1.000000 4n
+669.63 678.66 moveto
+669.63 658.41 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+587.20 613.16 1.000000 4n
+0.70 setlinewidth
+590.89 613.91 moveto
+590.89 634.16 lineto stroke
+630.94 622.16 1.000000 4rest
+673.31 613.16 1.000000 4n
+676.99 613.91 moveto
+676.99 634.16 lineto stroke
+587.20 607.16 1.000000 4n
+583.52 606.41 moveto
+583.52 586.16 lineto stroke
+630.94 592.16 1.000000 4rest
+673.31 607.16 1.000000 4n
+669.63 606.41 moveto
+669.63 586.16 lineto stroke
+restore
+%  S_BAR
+138 linenum
+0.70 setlinewidth
+715.95 703.41 moveto
+715.95 592.16 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+139 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+724.22 647.69 moveto
+(proof) show
+/Times-Roman findfont
+12 scalefont
+setfont
+776.90 647.69 moveto
+(through) show
+/Times-Roman findfont
+12 scalefont
+setfont
+823.89 647.69 moveto
+(the) show
+730.68 694.41 1.000000 4n
+739.94 694.41 1.000000 dot
+734.36 695.16 moveto
+734.36 715.41 lineto stroke
+786.19 691.41 1.000000 4n
+789.87 692.16 moveto
+789.87 712.41 lineto stroke
+792.90 712.41 1.000000 dnflag
+827.55 688.41 1.000000 4n
+831.23 689.16 moveto
+831.23 709.41 lineto stroke
+730.68 679.41 1.000000 4n
+739.94 676.41 1.000000 dot
+727.00 678.66 moveto
+727.00 658.41 lineto stroke
+786.19 679.41 1.000000 4n
+782.51 678.66 moveto
+782.51 658.41 lineto stroke
+785.53 658.41 1.000000 upflag
+827.55 679.41 1.000000 4n
+823.86 678.66 moveto
+823.86 658.41 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+730.68 616.16 1.000000 4n
+739.94 619.16 1.000000 dot
+0.70 setlinewidth
+734.36 616.91 moveto
+734.36 637.16 lineto stroke
+786.19 613.16 1.000000 4n
+789.87 613.91 moveto
+789.87 634.16 lineto stroke
+792.90 634.16 1.000000 dnflag
+827.55 616.16 1.000000 4n
+831.23 616.91 moveto
+831.23 637.16 lineto stroke
+730.68 595.16 1.000000 4n
+739.94 595.16 1.000000 dot
+727.00 594.41 moveto
+727.00 574.16 lineto stroke
+786.19 598.16 1.000000 4n
+782.51 597.41 moveto
+782.51 577.16 lineto stroke
+785.53 577.16 1.000000 upflag
+827.55 601.16 1.000000 4n
+823.86 600.41 moveto
+823.86 580.16 lineto stroke
+restore
+%  S_BAR
+142 linenum
+0.70 setlinewidth
+869.19 703.41 moveto
+869.19 592.16 lineto stroke
+%  S_FEED
+298.00 952.16 869.54 5 1.000000 1.000000 stf
+/Times-Roman findfont
+11 scalefont
+setfont
+86.50 546.16 moveto
+(15) show
+298.00 855.84 869.54 5 1.000000 1.000000 stf
+81.50 532.16 411.84 brace
+82.00 532.16 moveto
+82.00 411.84 lineto stroke
+%  S_CLEFSIG
+93.79 514.16 1.000000 gclef
+94.04 429.84 1.000000 fclef
+108.41 532.16 1.000000 sharp
+115.05 523.16 1.000000 sharp
+121.69 535.16 1.000000 sharp
+108.41 429.84 1.000000 sharp
+115.05 420.84 1.000000 sharp
+121.69 432.84 1.000000 sharp
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+143 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+145.59 464.44 moveto
+(night) show
+/Times-Roman findfont
+12 scalefont
+setfont
+218.99 464.44 moveto
+(that) show
+/Times-Roman findfont
+12 scalefont
+setfont
+253.20 464.44 moveto
+(our) show
+151.73 514.16 1.000000 2n
+155.63 514.91 moveto
+155.63 535.16 lineto stroke
+223.47 511.16 1.000000 4n
+232.73 511.16 1.000000 dot
+227.15 511.91 moveto
+227.15 531.02 lineto stroke
+257.18 514.16 1.000000 4n
+260.86 514.91 moveto
+260.86 534.02 lineto stroke
+newpath
+226.80 532.52 moveto
+261.21 535.52 lineto
+261.21 532.52 lineto
+226.80 529.52 lineto
+closepath
+fill
+newpath
+260.51 530.52 moveto
+252.45 529.81 lineto
+252.45 526.81 lineto
+260.51 527.52 lineto
+closepath
+fill
+151.73 508.16 1.000000 2n
+147.83 507.41 moveto
+147.83 487.16 lineto stroke
+223.47 505.16 1.000000 4n
+232.73 505.16 1.000000 dot
+219.79 504.41 moveto
+219.79 485.66 lineto stroke
+257.18 505.16 1.000000 4n
+253.50 504.41 moveto
+253.50 485.66 lineto stroke
+newpath
+219.44 487.16 moveto
+253.85 487.16 lineto
+253.85 484.16 lineto
+219.44 484.16 lineto
+closepath
+fill
+newpath
+253.15 492.16 moveto
+245.08 492.16 lineto
+245.08 489.16 lineto
+253.15 489.16 lineto
+closepath
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+151.73 438.84 1.000000 2n
+0.70 setlinewidth
+155.63 439.59 moveto
+155.63 459.84 lineto stroke
+223.47 438.84 1.000000 4n
+232.73 438.84 1.000000 dot
+227.15 439.59 moveto
+227.15 458.34 lineto stroke
+257.18 438.84 1.000000 4n
+260.86 439.59 moveto
+260.86 458.34 lineto stroke
+newpath
+226.80 459.84 moveto
+261.21 459.84 lineto
+261.21 456.84 lineto
+226.80 456.84 lineto
+closepath
+fill
+newpath
+260.51 454.84 moveto
+252.45 454.84 lineto
+252.45 451.84 lineto
+260.51 451.84 lineto
+closepath
+fill
+151.73 426.84 1.000000 2n
+147.83 426.09 moveto
+147.83 405.84 lineto stroke
+223.47 426.84 1.000000 4n
+232.73 426.84 1.000000 dot
+219.79 426.09 moveto
+219.79 407.34 lineto stroke
+257.18 426.84 1.000000 4n
+253.50 426.09 moveto
+253.50 407.34 lineto stroke
+newpath
+219.44 408.84 moveto
+253.85 408.84 lineto
+253.85 405.84 lineto
+219.44 405.84 lineto
+closepath
+fill
+newpath
+253.15 413.84 moveto
+245.08 413.84 lineto
+245.08 410.84 lineto
+253.15 410.84 lineto
+closepath
+fill
+restore
+%  S_BAR
+146 linenum
+0.70 setlinewidth
+274.98 532.16 moveto
+274.98 411.84 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+147 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+282.67 464.44 moveto
+(flag) show
+/Times-Roman findfont
+12 scalefont
+setfont
+325.99 464.44 moveto
+(was) show
+/Times-Roman findfont
+12 scalefont
+setfont
+373.83 464.44 moveto
+(still) show
+287.31 517.16 1.000000 4n
+290.99 517.91 moveto
+290.99 538.16 lineto stroke
+330.65 502.16 1.000000 4n
+324.42 502.16 moveto
+336.88 502.16 lineto stroke
+334.33 502.91 moveto
+334.33 523.16 lineto stroke
+378.31 505.16 1.000000 4n
+368.96 505.16 1.000000 sharp
+381.99 505.91 moveto
+381.99 526.16 lineto stroke
+287.31 502.16 1.000000 4n
+281.08 502.16 moveto
+293.54 502.16 lineto stroke
+283.63 501.41 moveto
+283.63 481.16 lineto stroke
+330.65 502.16 1.000000 4n
+324.42 502.16 moveto
+336.88 502.16 lineto stroke
+326.97 501.41 moveto
+326.97 481.16 lineto stroke
+378.31 499.16 1.000000 4n
+372.08 502.16 moveto
+384.54 502.16 lineto stroke
+374.63 498.41 moveto
+374.63 478.16 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+287.31 435.84 1.000000 4n
+0.70 setlinewidth
+290.99 436.59 moveto
+290.99 456.84 lineto stroke
+330.65 435.84 1.000000 4n
+334.33 436.59 moveto
+334.33 456.84 lineto stroke
+378.31 435.84 1.000000 4n
+381.99 436.59 moveto
+381.99 456.84 lineto stroke
+287.31 429.84 1.000000 4n
+283.63 429.09 moveto
+283.63 408.84 lineto stroke
+330.65 429.84 1.000000 4n
+326.97 429.09 moveto
+326.97 408.84 lineto stroke
+378.31 417.84 1.000000 4n
+374.63 417.09 moveto
+374.63 396.84 lineto stroke
+restore
+%  S_BAR
+150 linenum
+0.70 setlinewidth
+421.37 532.16 moveto
+421.37 411.84 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+151 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+429.14 464.44 moveto
+(there.) show
+/Times-Roman findfont
+12 scalefont
+setfont
+523.16 464.44 moveto
+(Oh) show
+435.88 508.16 1.000000 4n
+439.56 508.91 moveto
+439.56 529.16 lineto stroke
+482.34 532.16 1.000000 4rest
+526.82 508.16 1.000000 4n
+530.50 508.91 moveto
+530.50 529.16 lineto stroke
+435.88 499.16 1.000000 4n
+429.64 502.16 moveto
+442.11 502.16 lineto stroke
+432.19 498.41 moveto
+432.19 478.16 lineto stroke
+482.34 490.16 1.000000 4rest
+526.82 499.16 1.000000 4n
+520.58 502.16 moveto
+533.05 502.16 lineto stroke
+523.13 498.41 moveto
+523.13 478.16 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+435.88 432.84 1.000000 4n
+0.70 setlinewidth
+439.56 433.59 moveto
+439.56 453.84 lineto stroke
+482.34 441.84 1.000000 4rest
+526.82 432.84 1.000000 4n
+530.50 433.59 moveto
+530.50 453.84 lineto stroke
+435.88 426.84 1.000000 4n
+432.19 426.09 moveto
+432.19 405.84 lineto stroke
+482.34 411.84 1.000000 4rest
+526.82 426.84 1.000000 4n
+523.13 426.09 moveto
+523.13 405.84 lineto stroke
+restore
+%  S_BAR
+154 linenum
+0.70 setlinewidth
+569.46 532.16 moveto
+569.46 411.84 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+155 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+576.91 464.44 moveto
+(say,) show
+/Times-Roman findfont
+12 scalefont
+setfont
+620.67 464.44 moveto
+(does) show
+/Times-Roman findfont
+12 scalefont
+setfont
+664.26 464.44 moveto
+(that) show
+581.67 517.16 1.000000 4n
+585.35 517.91 moveto
+585.35 538.16 lineto stroke
+626.16 517.16 1.000000 4n
+629.84 517.91 moveto
+629.84 538.16 lineto stroke
+668.74 517.16 1.000000 4n
+672.42 517.91 moveto
+672.42 536.23 lineto stroke
+696.74 514.16 1.000000 4n
+700.42 514.91 moveto
+700.42 533.23 lineto stroke
+newpath
+672.07 537.73 moveto
+700.77 534.73 lineto
+700.77 531.73 lineto
+672.07 534.73 lineto
+closepath
+fill
+581.67 502.16 1.000000 4n
+575.43 502.16 moveto
+587.90 502.16 lineto stroke
+577.98 501.41 moveto
+577.98 481.16 lineto stroke
+626.16 499.16 1.000000 4n
+619.93 502.16 moveto
+632.39 502.16 lineto stroke
+622.48 498.41 moveto
+622.48 478.16 lineto stroke
+668.74 496.16 1.000000 4n
+662.51 496.16 moveto
+674.97 496.16 lineto stroke
+662.51 502.16 moveto
+674.97 502.16 lineto stroke
+665.06 495.41 moveto
+665.06 475.16 lineto stroke
+674.77 522.26 moveto
+674.75 522.49 lineto
+678.42 524.07 682.24 524.60 686.21 524.05 curveto
+690.17 523.51 693.71 521.99 696.83 519.48 curveto
+696.66 519.05 lineto
+693.38 521.05 689.84 522.31 686.04 522.83 curveto
+682.24 523.35 678.49 523.08 674.80 522.04 curveto
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+581.67 426.84 1.000000 4n
+0.70 setlinewidth
+585.35 427.59 moveto
+585.35 447.84 lineto stroke
+626.16 426.84 1.000000 4n
+629.84 427.59 moveto
+629.84 447.84 lineto stroke
+668.74 426.84 1.000000 4n
+672.42 427.59 moveto
+672.42 447.84 lineto stroke
+581.67 414.84 1.000000 4n
+577.98 414.09 moveto
+577.98 393.84 lineto stroke
+626.16 417.84 1.000000 4n
+622.48 417.09 moveto
+622.48 396.84 lineto stroke
+668.74 420.84 1.000000 4n
+665.06 420.09 moveto
+665.06 399.84 lineto stroke
+restore
+%  S_BAR
+161 linenum
+0.70 setlinewidth
+722.52 532.16 moveto
+722.52 411.84 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+162 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+757.80 464.44 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+729.75 464.44 moveto
+(star) show
+/Times-Roman findfont
+12 scalefont
+setfont
+805.59 464.44 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+771.58 464.44 moveto
+(span) show
+/Times-Roman findfont
+12 scalefont
+setfont
+820.64 464.44 moveto
+(gled) show
+735.06 511.16 1.000000 4n
+738.74 511.91 moveto
+738.74 532.16 lineto stroke
+778.06 511.16 1.000000 4n
+781.74 511.91 moveto
+781.74 532.16 lineto stroke
+822.11 511.16 1.000000 4n
+825.79 511.91 moveto
+825.79 532.16 lineto stroke
+735.06 505.16 1.000000 4n
+731.37 504.41 moveto
+731.37 484.16 lineto stroke
+778.06 505.16 1.000000 4n
+774.38 504.41 moveto
+774.38 484.16 lineto stroke
+829.47 508.16 1.000000 4n
+825.79 507.41 moveto
+825.79 487.16 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+735.06 435.84 1.000000 4n
+0.70 setlinewidth
+738.74 436.59 moveto
+738.74 456.84 lineto stroke
+778.06 435.84 1.000000 4n
+781.74 436.59 moveto
+781.74 456.84 lineto stroke
+825.79 435.84 1.000000 4n
+816.44 435.84 1.000000 sharp
+829.47 436.59 moveto
+829.47 456.84 lineto stroke
+735.06 423.84 1.000000 4n
+731.37 423.09 moveto
+731.37 402.84 lineto stroke
+778.06 423.84 1.000000 4n
+774.38 423.09 moveto
+774.38 402.84 lineto stroke
+825.79 420.84 1.000000 4n
+822.11 420.09 moveto
+822.11 399.84 lineto stroke
+restore
+%  S_BAR
+168 linenum
+0.70 setlinewidth
+869.19 532.16 moveto
+869.19 411.84 lineto stroke
+%  S_FEED
+298.00 771.84 869.54 5 1.000000 1.000000 stf
+/Times-Roman findfont
+11 scalefont
+setfont
+86.50 365.84 moveto
+(20) show
+298.00 669.57 869.54 5 1.000000 1.000000 stf
+81.50 351.84 225.57 brace
+82.00 351.84 moveto
+82.00 225.57 lineto stroke
+%  S_CLEFSIG
+93.79 333.84 1.000000 gclef
+94.04 243.57 1.000000 fclef
+108.41 351.84 1.000000 sharp
+115.05 342.84 1.000000 sharp
+121.69 354.84 1.000000 sharp
+108.41 243.57 1.000000 sharp
+115.05 234.57 1.000000 sharp
+121.69 246.57 1.000000 sharp
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+169 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+163.61 290.12 moveto
+(-) show
+/Times-Roman findfont
+12 scalefont
+setfont
+139.36 290.12 moveto
+(ban) show
+/Times-Roman findfont
+12 scalefont
+setfont
+173.58 290.12 moveto
+(ner) show
+/Times-Roman findfont
+12 scalefont
+setfont
+221.23 290.12 moveto
+(yet) show
+144.67 339.84 1.000000 4n
+148.35 340.59 moveto
+148.35 360.84 lineto stroke
+177.39 345.84 1.000000 4n
+181.08 346.59 moveto
+181.08 364.93 lineto stroke
+206.42 342.84 1.000000 4n
+210.10 343.59 moveto
+210.10 361.93 lineto stroke
+224.88 339.84 1.000000 4n
+228.57 340.59 moveto
+228.57 359.03 lineto stroke
+263.39 336.84 1.000000 4n
+267.07 337.59 moveto
+267.07 356.03 lineto stroke
+newpath
+180.73 366.43 moveto
+210.45 363.43 lineto
+210.45 360.43 lineto
+180.73 363.43 lineto
+closepath
+fill
+newpath
+228.22 360.53 moveto
+267.42 357.53 lineto
+267.42 354.53 lineto
+228.22 357.53 lineto
+closepath
+fill
+144.67 324.84 1.000000 4n
+140.99 324.09 moveto
+140.99 303.84 lineto stroke
+177.39 330.84 1.000000 4n
+173.71 330.09 moveto
+173.71 309.84 lineto stroke
+224.88 330.84 1.000000 4n
+221.20 330.09 moveto
+221.20 309.84 lineto stroke
+230.92 344.94 moveto
+230.90 345.14 lineto
+236.32 346.73 241.84 347.26 247.46 346.74 curveto
+253.08 346.22 258.40 344.69 263.44 342.14 curveto
+263.34 341.75 lineto
+258.18 343.76 252.85 345.02 247.34 345.52 curveto
+241.84 346.03 236.37 345.77 230.93 344.75 curveto
+fill
+183.43 350.94 moveto
+183.40 351.17 lineto
+187.25 352.75 191.23 353.27 195.35 352.74 curveto
+199.47 352.20 203.19 350.67 206.50 348.16 curveto
+206.34 347.73 lineto
+202.87 349.73 199.16 350.99 195.19 351.51 curveto
+191.22 352.03 187.31 351.76 183.45 350.72 curveto
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+144.67 252.57 1.000000 4n
+0.70 setlinewidth
+148.35 253.32 moveto
+148.35 273.57 lineto stroke
+177.39 252.57 1.000000 4n
+181.08 253.32 moveto
+181.08 271.66 lineto stroke
+206.42 249.57 1.000000 4n
+197.07 249.57 1.000000 sharp
+210.10 250.32 moveto
+210.10 268.66 lineto stroke
+224.88 252.57 1.000000 4n
+228.57 253.32 moveto
+228.57 272.07 lineto stroke
+263.39 252.57 1.000000 4n
+254.03 252.57 1.000000 sharp
+267.07 253.32 moveto
+267.07 272.07 lineto stroke
+newpath
+180.73 273.16 moveto
+210.45 270.16 lineto
+210.45 267.16 lineto
+180.73 270.16 lineto
+closepath
+fill
+newpath
+228.22 273.57 moveto
+267.42 273.57 lineto
+267.42 270.57 lineto
+228.22 270.57 lineto
+closepath
+fill
+144.67 231.57 1.000000 4n
+140.99 230.82 moveto
+140.99 210.57 lineto stroke
+177.39 231.57 1.000000 4n
+173.71 230.82 moveto
+173.71 211.66 lineto stroke
+206.42 234.57 1.000000 4n
+202.74 233.82 moveto
+202.74 214.66 lineto stroke
+224.88 237.57 1.000000 4n
+221.20 236.82 moveto
+221.20 218.07 lineto stroke
+263.39 237.57 1.000000 4n
+245.40 237.57 1.000000 sharp
+259.71 236.82 moveto
+259.71 218.07 lineto stroke
+newpath
+173.36 213.16 moveto
+203.09 216.16 lineto
+203.09 213.16 lineto
+173.36 210.16 lineto
+closepath
+fill
+newpath
+220.85 219.57 moveto
+260.06 219.57 lineto
+260.06 216.57 lineto
+220.85 216.57 lineto
+closepath
+fill
+224.88 232.47 moveto
+224.97 232.71 lineto
+227.06 231.17 229.39 230.40 231.98 230.40 curveto
+234.57 230.40 236.90 231.17 238.99 232.71 curveto
+239.16 232.24 lineto
+237.21 230.18 234.82 229.15 231.98 229.15 curveto
+229.14 229.15 226.75 230.18 224.79 232.24 curveto
+fill
+177.39 226.47 moveto
+177.42 226.70 lineto
+181.11 225.66 184.87 225.39 188.67 225.91 curveto
+192.48 226.43 196.02 227.69 199.30 229.69 curveto
+199.47 229.26 lineto
+196.35 226.75 192.81 225.22 188.84 224.68 curveto
+184.87 224.14 181.05 224.66 177.37 226.25 curveto
+fill
+230.92 257.67 moveto
+230.88 257.87 lineto
+236.11 259.95 241.53 260.98 247.15 260.98 curveto
+252.77 260.98 258.20 259.95 263.42 257.87 curveto
+263.35 257.48 lineto
+258.06 259.00 252.66 259.76 247.15 259.76 curveto
+241.64 259.76 236.24 259.00 230.95 257.48 curveto
+fill
+183.43 257.67 moveto
+183.40 257.90 lineto
+187.25 259.48 191.23 260.00 195.35 259.46 curveto
+199.47 258.93 203.19 257.40 206.50 254.88 curveto
+206.34 254.46 lineto
+202.87 256.46 199.16 257.72 195.19 258.24 curveto
+191.22 258.75 187.31 258.49 183.45 257.45 curveto
+fill
+restore
+%  S_BAR
+175 linenum
+0.70 setlinewidth
+284.51 351.84 moveto
+284.51 225.57 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+177 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+290.74 290.12 moveto
+(wave) show
+/Times-Roman findfont
+12 scalefont
+setfont
+366.39 290.12 moveto
+(o'er) show
+/Times-Roman findfont
+12 scalefont
+setfont
+391.54 290.12 moveto
+(the) show
+298.55 336.84 1.000000 4n
+302.24 337.59 moveto
+302.24 357.84 lineto stroke
+331.82 333.84 1.000000 4n
+335.50 334.59 moveto
+335.50 354.84 lineto stroke
+338.52 354.84 1.000000 dnflag
+352.80 351.84 1.000000 8rest
+371.19 327.84 1.000000 4n
+374.88 328.59 moveto
+374.88 347.34 lineto stroke
+395.20 327.84 1.000000 4n
+398.88 328.59 moveto
+398.88 347.34 lineto stroke
+newpath
+374.53 348.84 moveto
+399.23 348.84 lineto
+399.23 345.84 lineto
+374.53 345.84 lineto
+closepath
+fill
+298.55 327.84 1.000000 4n
+307.82 324.84 1.000000 dot
+294.87 327.09 moveto
+294.87 306.84 lineto stroke
+352.80 309.84 1.000000 8rest
+371.19 327.84 1.000000 4n
+367.51 327.09 moveto
+367.51 308.34 lineto stroke
+395.20 327.84 1.000000 4n
+391.52 327.09 moveto
+391.52 308.34 lineto stroke
+newpath
+367.16 309.84 moveto
+391.87 309.84 lineto
+391.87 306.84 lineto
+367.16 306.84 lineto
+closepath
+fill
+304.59 341.94 moveto
+304.57 342.16 lineto
+309.11 343.74 313.78 344.27 318.57 343.74 curveto
+323.35 343.21 327.79 341.68 331.88 339.15 curveto
+331.75 338.74 lineto
+327.52 340.75 323.08 342.00 318.43 342.52 curveto
+313.78 343.03 309.17 342.77 304.60 341.73 curveto
+fill
+/Times-Roman findfont
+12 scalefont
+setfont
+322.78 356.85 moveto
+331.82 356.85 1.000000 ferm
+340.85 356.85 moveto
+restore
+%  S_STAFF
+% staff 2
+save
+298.55 255.57 1.000000 4n
+0.70 setlinewidth
+292.32 255.57 moveto
+304.79 255.57 lineto stroke
+302.24 256.32 moveto
+302.24 276.57 lineto stroke
+331.82 252.57 1.000000 4n
+335.50 253.32 moveto
+335.50 273.57 lineto stroke
+338.52 273.57 1.000000 dnflag
+352.80 255.57 1.000000 8rest
+371.19 246.57 1.000000 4n
+374.88 247.32 moveto
+374.88 266.07 lineto stroke
+395.20 246.57 1.000000 4n
+398.88 247.32 moveto
+398.88 266.07 lineto stroke
+newpath
+374.53 267.57 moveto
+399.23 267.57 lineto
+399.23 264.57 lineto
+374.53 264.57 lineto
+closepath
+fill
+298.55 240.57 1.000000 4n
+307.82 240.57 1.000000 dot
+294.87 239.82 moveto
+294.87 219.57 lineto stroke
+352.80 225.57 1.000000 8rest
+371.19 237.57 1.000000 4n
+367.51 236.82 moveto
+367.51 218.07 lineto stroke
+395.20 237.57 1.000000 4n
+391.52 236.82 moveto
+391.52 218.07 lineto stroke
+newpath
+367.16 219.57 moveto
+391.87 219.57 lineto
+391.87 216.57 lineto
+367.16 216.57 lineto
+closepath
+fill
+304.59 260.67 moveto
+304.57 260.88 lineto
+309.11 262.47 313.78 263.00 318.57 262.47 curveto
+323.35 261.94 327.79 260.41 331.88 257.88 curveto
+331.75 257.47 lineto
+327.52 259.47 323.08 260.73 318.43 261.24 curveto
+313.78 261.76 309.17 261.50 304.60 260.46 curveto
+fill
+/Times-Roman findfont
+12 scalefont
+setfont
+322.78 275.58 moveto
+331.82 275.58 1.000000 ferm
+340.85 275.58 moveto
+restore
+%  S_BAR
+183 linenum
+0.70 setlinewidth
+417.31 351.84 moveto
+417.31 225.57 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+184 linenum
+450.98 290.12 moveto
+480.84 290.12 lineto stroke
+/Times-Roman findfont
+12 scalefont
+setfont
+424.41 290.12 moveto
+(land) show
+/Times-Roman findfont
+12 scalefont
+setfont
+494.41 290.12 moveto
+(of) show
+/Times-Roman findfont
+12 scalefont
+setfont
+514.14 290.12 moveto
+(the) show
+431.05 336.84 1.000000 4n
+440.32 336.84 1.000000 dot
+434.73 337.59 moveto
+434.73 357.84 lineto stroke
+476.81 339.84 1.000000 4n
+480.49 340.59 moveto
+480.49 360.84 lineto stroke
+483.52 360.84 1.000000 dnflag
+496.89 342.84 1.000000 4n
+500.57 343.59 moveto
+500.57 362.92 lineto stroke
+517.79 345.84 1.000000 4n
+521.48 346.59 moveto
+521.48 365.92 lineto stroke
+newpath
+500.22 364.42 moveto
+521.83 367.42 lineto
+521.83 364.42 lineto
+500.22 361.42 lineto
+closepath
+fill
+431.05 327.84 1.000000 4n
+440.32 324.84 1.000000 dot
+427.37 327.09 moveto
+427.37 306.84 lineto stroke
+476.81 327.84 1.000000 4n
+473.13 327.09 moveto
+473.13 306.84 lineto stroke
+476.15 306.84 1.000000 upflag
+496.89 327.84 1.000000 4n
+493.21 327.09 moveto
+493.21 308.34 lineto stroke
+517.79 327.84 1.000000 4n
+514.11 327.09 moveto
+514.11 308.34 lineto stroke
+newpath
+492.86 309.84 moveto
+514.46 309.84 lineto
+514.46 306.84 lineto
+492.86 306.84 lineto
+closepath
+fill
+431.05 322.74 moveto
+431.08 322.92 lineto
+437.42 321.30 443.87 320.49 450.42 320.49 curveto
+456.96 320.49 463.41 321.30 469.75 322.92 curveto
+469.80 322.57 lineto
+463.54 320.32 457.07 319.20 450.42 319.20 curveto
+443.76 319.20 437.29 320.32 431.03 322.57 curveto
+fill
+445.32 341.94 moveto
+445.26 342.14 lineto
+450.12 344.69 455.29 346.22 460.75 346.74 curveto
+466.21 347.26 471.57 346.73 476.83 345.14 curveto
+476.80 344.75 lineto
+471.52 345.77 466.21 346.03 460.87 345.52 curveto
+455.52 345.01 450.35 343.76 445.37 341.75 curveto
+fill
+restore
+%  S_STAFF
+% staff 2
+save
+431.05 249.57 1.000000 4n
+440.32 252.57 1.000000 dot
+0.70 setlinewidth
+434.73 250.32 moveto
+434.73 270.57 lineto stroke
+476.81 246.57 1.000000 4n
+480.49 247.32 moveto
+480.49 267.57 lineto stroke
+483.52 267.57 1.000000 dnflag
+496.89 249.57 1.000000 4n
+500.57 250.32 moveto
+500.57 269.07 lineto stroke
+517.79 249.57 1.000000 4n
+521.48 250.32 moveto
+521.48 269.07 lineto stroke
+newpath
+500.22 270.57 moveto
+521.83 270.57 lineto
+521.83 267.57 lineto
+500.22 267.57 lineto
+closepath
+fill
+431.05 234.57 1.000000 4n
+440.32 234.57 1.000000 dot
+427.37 233.82 moveto
+427.37 213.57 lineto stroke
+476.81 240.57 1.000000 4n
+473.13 239.82 moveto
+473.13 219.57 lineto stroke
+476.15 219.57 1.000000 upflag
+496.89 228.57 1.000000 4n
+493.21 227.82 moveto
+493.21 208.49 lineto stroke
+517.79 231.57 1.000000 4n
+514.11 230.82 moveto
+514.11 211.49 lineto stroke
+newpath
+492.86 209.99 moveto
+514.46 212.99 lineto
+514.46 209.99 lineto
+492.86 206.99 lineto
+closepath
+fill
+431.05 229.47 moveto
+431.05 229.65 lineto
+437.65 229.01 444.22 229.20 450.77 230.21 curveto
+457.31 231.23 463.63 233.04 469.73 235.64 curveto
+469.83 235.30 lineto
+463.91 232.08 457.62 229.96 450.97 228.93 curveto
+444.31 227.89 437.67 228.02 431.05 229.30 curveto
+fill
+445.32 254.67 moveto
+445.30 254.87 lineto
+450.56 256.46 455.91 256.99 461.38 256.47 curveto
+466.84 255.95 472.00 254.42 476.86 251.87 curveto
+476.76 251.48 lineto
+471.77 253.48 466.61 254.74 461.26 255.25 curveto
+455.91 255.76 450.60 255.50 445.33 254.47 curveto
+fill
+restore
+%  S_BAR
+190 linenum
+0.70 setlinewidth
+539.91 351.84 moveto
+539.91 225.57 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+192 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+547.50 290.12 moveto
+(free) show
+/Times-Roman findfont
+12 scalefont
+setfont
+614.27 290.12 moveto
+(and) show
+/Times-Roman findfont
+12 scalefont
+setfont
+644.33 290.12 moveto
+(the) show
+552.14 348.84 1.000000 4n
+555.82 349.59 moveto
+555.82 369.84 lineto stroke
+587.85 351.84 1.000000 4rest
+618.59 336.84 1.000000 4n
+622.28 337.59 moveto
+622.28 356.76 lineto stroke
+647.98 339.84 1.000000 4n
+651.66 340.59 moveto
+651.66 359.76 lineto stroke
+newpath
+621.93 358.26 moveto
+652.01 361.26 lineto
+652.01 358.26 lineto
+621.93 355.26 lineto
+closepath
+fill
+552.14 327.84 1.000000 4n
+548.46 327.09 moveto
+548.46 306.84 lineto stroke
+587.85 321.84 1.000000 4rest
+618.59 324.84 1.000000 4n
+614.91 324.09 moveto
+614.91 305.34 lineto stroke
+647.98 324.84 1.000000 4n
+644.30 324.09 moveto
+644.30 305.34 lineto stroke
+newpath
+614.56 306.84 moveto
+644.65 306.84 lineto
+644.65 303.84 lineto
+614.56 303.84 lineto
+closepath
+fill
+/Times-Roman findfont
+12 scalefont
+setfont
+543.10 371.85 moveto
+552.14 371.85 1.000000 ferm
+561.18 371.85 moveto
+restore
+%  S_STAFF
+% staff 2
+save
+552.14 249.57 1.000000 4n
+0.70 setlinewidth
+555.82 250.32 moveto
+555.82 270.57 lineto stroke
+587.85 261.57 1.000000 4rest
+618.59 249.57 1.000000 4n
+622.28 250.32 moveto
+622.28 269.07 lineto stroke
+647.98 249.57 1.000000 4n
+651.66 250.32 moveto
+651.66 269.07 lineto stroke
+newpath
+621.93 270.57 moveto
+652.01 270.57 lineto
+652.01 267.57 lineto
+621.93 267.57 lineto
+closepath
+fill
+552.14 234.57 1.000000 4n
+548.46 233.82 moveto
+548.46 213.57 lineto stroke
+587.85 225.57 1.000000 4rest
+618.59 243.57 1.000000 4n
+614.91 242.82 moveto
+614.91 224.07 lineto stroke
+647.98 243.57 1.000000 4n
+639.53 243.57 1.000000 nat
+644.30 242.82 moveto
+644.30 224.07 lineto stroke
+newpath
+614.56 225.57 moveto
+644.65 225.57 lineto
+644.65 222.57 lineto
+614.56 222.57 lineto
+closepath
+fill
+/Times-Roman findfont
+12 scalefont
+setfont
+543.10 272.58 moveto
+552.14 272.58 1.000000 ferm
+561.18 272.58 moveto
+restore
+%  S_BAR
+198 linenum
+0.70 setlinewidth
+670.10 351.84 moveto
+670.10 225.57 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+199 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+677.01 290.12 moveto
+(home) show
+/Times-Roman findfont
+12 scalefont
+setfont
+727.06 290.12 moveto
+(of) show
+/Times-Roman findfont
+12 scalefont
+setfont
+749.28 290.12 moveto
+(the) show
+683.67 342.84 1.000000 4n
+692.93 342.84 1.000000 dot
+687.35 343.59 moveto
+687.35 363.84 lineto stroke
+729.54 345.84 1.000000 4n
+733.23 346.59 moveto
+733.23 366.84 lineto stroke
+736.25 366.84 1.000000 dnflag
+752.94 339.84 1.000000 4n
+756.62 340.59 moveto
+756.62 360.84 lineto stroke
+683.67 327.84 1.000000 4n
+692.93 324.84 1.000000 dot
+679.99 327.09 moveto
+679.99 306.84 lineto stroke
+729.54 327.84 1.000000 4n
+725.86 327.09 moveto
+725.86 306.84 lineto stroke
+728.89 306.84 1.000000 upflag
+752.94 324.84 1.000000 4n
+749.25 324.09 moveto
+749.25 303.84 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+683.67 249.57 1.000000 4n
+692.93 252.57 1.000000 dot
+0.70 setlinewidth
+687.35 250.32 moveto
+687.35 270.57 lineto stroke
+729.54 249.57 1.000000 4n
+733.23 250.32 moveto
+733.23 270.57 lineto stroke
+736.25 270.57 1.000000 dnflag
+752.94 246.57 1.000000 4n
+756.62 247.32 moveto
+756.62 267.57 lineto stroke
+683.67 240.57 1.000000 4n
+692.93 240.57 1.000000 dot
+679.99 239.82 moveto
+679.99 219.57 lineto stroke
+729.54 240.57 1.000000 4n
+725.86 239.82 moveto
+725.86 219.57 lineto stroke
+728.89 219.57 1.000000 upflag
+752.94 240.57 1.000000 4n
+749.25 239.82 moveto
+749.25 219.57 lineto stroke
+restore
+%  S_BAR
+205 linenum
+0.70 setlinewidth
+787.49 351.84 moveto
+787.49 225.57 lineto stroke
+%  S_CHHEAD
+%  S_STAFF
+% staff 1
+save
+206 linenum
+/Times-Roman findfont
+12 scalefont
+setfont
+796.68 290.12 moveto
+(brave?) show
+804.65 336.84 1.000000 2n
+808.55 337.59 moveto
+808.55 357.84 lineto stroke
+804.65 321.84 1.000000 2n
+798.21 321.84 moveto
+811.10 321.84 lineto stroke
+800.76 321.09 moveto
+800.76 300.84 lineto stroke
+restore
+%  S_STAFF
+% staff 2
+save
+804.65 240.57 1.000000 2n
+0.70 setlinewidth
+808.55 241.32 moveto
+808.55 261.57 lineto stroke
+804.65 228.57 1.000000 2n
+800.76 227.82 moveto
+800.76 207.57 lineto stroke
+restore
+%  S_BAR
+211 linenum
+0.70 setlinewidth
+864.04 351.84 moveto
+864.04 225.57 lineto stroke
+3.00 setlinewidth
+868.04 351.84 moveto
+868.04 225.57 lineto stroke
+0.70 setlinewidth
+%  Printing header/footer
+/Times-Roman findfont
+18 scalefont
+setfont
+376.16 1148.50 moveto
+(The Star Spangled Banner) show
+/Times-Italic findfont
+12 scalefont
+setfont
+381.99 1135.68 moveto
+(\(The United States National Anthem\)) show
+/Times-Roman findfont
+9 scalefont
+setfont
+72.00 1126.07 moveto
+(Text: Francis Scott Key) show
+/Times-Roman findfont
+9 scalefont
+setfont
+807.22 1126.07 moveto
+(Tune: J. S. Smith) show
+/Times-Roman findfont
+9 scalefont
+setfont
+72.00 1116.46 moveto
+/Times-Roman findfont
+9 scalefont
+setfont
+790.16 1116.46 moveto
+(arr: William J. Krauss) show
+showpage
+restore
+%%DocumentFonts: /Times-Roman /Times-Italic /NewCenturySchlbk-Bold 
+%%Pages: 2
+%%EndDocument
+end PEND EP
+%%Page: 162 168
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(62 -)-2.5 E(INDEX)269.786 98
+Q(abo)69.336 122 Q -1.28 -.15(ve .)-.15 H(.............................\
+.......................................................................\
+............................33, 43, 71, 73, 78, 80).15 E -2.43(accents \
+.......................................................................\
+.......................................................................\
+...22,)69.336 134 R(65, 67)2.5 E -2.43(accidentals ....................\
+.......................................................................\
+................................17,)69.336 146 R(20, 63, 121, 135)2.5 E
+(adjusting output)69.336 158 Q(........................................\
+.......................................................................\
+.............................129)2.27 E(alignment of lyrics)69.336 170 Q
+(......................................................................\
+....................................................48, 113, 129)1.45 E
+(alignment of te)69.336 182 Q -1.18(xt ................................\
+.......................................................................\
+................................69,)-.15 F(75)2.5 E -.5(all ...........\
+.......................................................................\
+........................................................48,)69.336 194 R
+(71, 74, 74, 151)2.5 E -.77(alternation ...............................\
+.......................................................................\
+.........................................32,)69.336 206 R(151)2.5 E -.22
+(analysis .............................................................\
+......................................................................7\
+4,)69.336 218 R(102, 105, 106)2.5 E(angle brack)69.336 230 Q -.38(ets .\
+.......................................................................\
+.............................................................20,)-.1 F
+(46, 48)2.5 E(ar)69.336 242 Q(guments, command line)-.18 E(............\
+.......................................................................\
+............................11, 127, 150)1.08 E(Arkkra Enterprises)
+69.336 254 Q(..........................................................\
+.......................................................................\
+.......155)1.19 E -1.88(backslash .....................................\
+.......................................................................\
+.......................................13,)69.336 266 R(95)2.5 E -1.59(\
+backspace .............................................................\
+.......................................................................\
+..............63,)69.336 278 R(69)2.5 E -.77(bar ......................\
+.......................................................................\
+........2,)69.336 290 R(8, 13, 15, 37, 72, 84, 85, 103, 110, 138)2.5 E
+-2.16(barstyle ........................................................\
+.......................................................................\
+...................103,)69.336 302 R(110)2.5 E -2.44(beaming ..........\
+.......................................................................\
+....................................................21,)69.336 314 R
+(27, 105, 138)2.5 E -1.05(beamstyle ...................................\
+.......................................................................\
+........................27,)69.336 326 R(28, 105, 138)2.5 E -1.05(beats\
+ ......................................................................\
+......................................................22,)69.336 338 R
+(72, 72, 105, 135, 152)2.5 E(be)69.336 350 Q -.35(gintime .............\
+.......................................................................\
+..............................71,)-.15 F(72, 72, 78, 79, 80, 151)2.5 E
+(belo)69.336 362 Q .31(w.)-.25 G(......................................\
+.......................................................................\
+...............6, 17, 33, 43, 71, 78, 80)-.31 E -2.44(bend ............\
+.......................................................................\
+.......................................................................\
+.......53)69.336 374 R -1.32(between ..................................\
+.......................................................................\
+......................................43,)69.336 386 R(71, 73)2.5 E -.22
+(block ................................................................\
+...........................................................14,)69.336
+398 R(14, 88, 106, 141, 145)2.5 E -.78(bold ...........................\
+..............................................................68,)69.336
+410 R(71, 73, 74, 86, 102, 105, 106, 109, 110, 113)2.5 E -1.06(boldital\
+ ......................................................................\
+......................68,)69.336 422 R
+(71, 73, 74, 86, 102, 105, 106, 109, 110)2.5 E -1.34
+(bottom ...........................4,)69.336 434 R(13, 13, 14, 14, 16, \
+43, 71, 72, 73, 82, 84, 84, 89, 93, 103, 106, 121, 123, 125, 150)2.5 E
+(bottommar)69.336 446 Q -1.99(gin .....................................\
+.......................................................................\
+....................................106)-.18 F(box)69.336 458 Q(ed te)
+-.15 E -2.14(xt .......................................................\
+.......................................................................\
+..........................70)-.15 F -2.15(brace .......................\
+.......................................................................\
+..........................................33,)69.336 470 R
+(107, 110, 112)2.5 E(brack)69.336 482 Q -2.33(et ......................\
+.......................................................................\
+..............21,)-.1 F(24, 33, 44, 107, 110, 112, 136)2.5 E
+(breath marks)69.336 494 Q(............................................\
+.......................................................................\
+...............................148).07 E -.2(cadenza ..................\
+.......................................................................\
+................................................................143)
+69.336 506 R(cancelk)69.336 518 Q .07 -.15(ey .)-.1 H(.................\
+.......................................................................\
+.............................................................107).15 E
+-1.88(capo ............................................................\
+.......................................................................\
+..............................54)69.336 530 R -2.43(center ............\
+.......................................................................\
+..........................................................13,)69.336 542
+R(45, 86, 95)2.5 E -1.6(channel .......................................\
+.......................................................................\
+....................................150,)69.336 554 R(152)2.5 E -2.16(c\
+hant ..................................................................\
+.......................................................................\
+...............48,)69.336 566 R(131)2.5 E -.77
+(chord .................................................2,)69.336 578 R
+(15, 21, 34, 73, 74, 78, 80, 82, 102, 105, 106, 108, 110, 116, 121, 121)
+2.5 E -.22(chorddist ..................................................\
+.......................................................................\
+74,)69.336 590 R(108, 109, 109, 129)2.5 E(circled te)69.336 602 Q -.06(\
+xt ....................................................................\
+.......................................................................\
+...........70)-.15 F -.49(clef ........................................\
+..................................................................3,)
+69.336 614 R(8, 18, 25, 39, 40, 63, 108, 108, 121)2.5 E -1.88(coda ....\
+.......................................................................\
+.......................................................................\
+.......65,)69.336 626 R(150)2.5 E(command line ar)69.336 638 Q -1.42(gu\
+ments .................................................................\
+...............................................11,)-.18 F(127, 150)2.5 E
+-1.61(comments ........................................................\
+.......................................................................\
+.............8,)69.336 650 R(13, 155)2.5 E(conte)69.336 662 Q -1.18(xts\
+ ......................................................................\
+...........................................3,)-.15 F
+(8, 14, 15, 89, 93, 102, 129)2.5 E(cop)69.336 674 Q -1.23(yright ......\
+.......................................................................\
+..............................................................14,)-.1 F
+(65, 152)2.5 E -.48(crescendo .........................................\
+...................................................................71,)
+69.336 686 R(76, 79, 102, 105, 106, 109)2.5 E(cross-staf)69.336 698 Q
+2.5(fb)-.25 G -2.45(eams ..............................................\
+.......................................................................\
+................31,)-2.5 F(135)2.5 E(cross-staf)69.336 710 Q 2.5(fs)-.25
+G -2.18(tems ..........................................................\
+.......................................................................\
+.............25)-2.5 F(cue notes)69.336 722 Q(.........................\
+.......................................................................\
+.............................................21, 52, 67)2.01 E(curv)
+69.336 734 Q 2.44(e.)-.15 G(...........................................\
+.......................................................................\
+..........................13, 46, 84, 91)-2.44 E EP
+%%Page: 163 169
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(63 -)-2.5 E(custom beaming)
+69.336 96 Q(...........................................................\
+.....................................................................27\
+, 54, 105)1.17 E(dashed line)69.336 108 Q(.............................\
+.......................................................................\
+................................37, 76, 80, 90)1.73 E
+(dashed ties and slurs)69.336 120 Q(...................................\
+.......................................................................\
+...........19, 20, 27, 27)2.01 E(deb)69.336 132 Q -.02(ugging .........\
+.......................................................................\
+.................................................................8,)-.2
+F(129)2.5 E -2.42(decrescendo .........................................\
+......................................................................7\
+1,)69.336 144 R(79, 102, 105, 106, 109)2.5 E -2.44(de\214ne ...........\
+.......................................................................\
+.......................................................................\
+......95)69.336 156 R -.49(defoct .....................................\
+.......................................................................\
+....................................18,)69.336 168 R(25, 108)2.5 E
+(diacritical marks)69.336 180 Q(.......................................\
+.......................................................................\
+................................69).07 E(diamond-shaped notes)69.336 192
+Q(.....................................................................\
+...................................................21, 52, 64)2.29 E
+-2.45(diminished ......................................................\
+.......................................................................\
+....65,)69.336 204 R(74, 102, 126)2.5 E -2.45(dist ....................\
+.......................................................................\
+......................................................109,)69.336 216 R
+(109, 129)2.5 E(di)69.336 228 Q -2.48(vision ..........................\
+.......................................................................\
+.........................................................109)-.25 F
+(dotted line)69.336 240 Q(.............................................\
+.......................................................................\
+.......................37, 84, 90)2 E(dotted note)69.336 252 Q(........\
+.......................................................................\
+...............16, 21, 33, 43, 65, 105, 116, 125, 135)2.28 E
+(dotted ties and slurs)69.336 264 Q(...................................\
+.......................................................................\
+............19, 20, 27, 27)2.28 E(drum clef)69.336 276 Q(..............\
+.......................................................................\
+..........................................................108, 121).9 E
+(D. S.)69.336 288 Q(...................................................\
+.......................................................................\
+..............................65, 150)1.72 E -1.33(duration ...........\
+.......................................................................\
+...........13,)69.336 300 R(15, 27, 71, 76, 77, 78, 79, 80, 81, 105)2.5
+E -1.33(dynamics ......................................................\
+...................................................1,)69.336 312 R
+(14, 48, 71, 102, 105, 106, 151)2.5 E -1.05(east ......................\
+.......................................................................\
+.....................................................................84)
+69.336 324 R -1.61(endings ............................................\
+.......................................................................\
+...........40,)69.336 336 R(74, 102, 110, 150)2.5 E -1.61(endingstyle .\
+.......................................................................\
+........................................................40,)69.336 348 R
+(40, 110, 114)2.5 E(error messages)69.336 360 Q(.......................\
+.......................................................................\
+........................4, 6, 102, 126, 129)2.3 E -2.15 -.25(ev e)69.336
+372 T 2.5(np).25 G -1.75(ages .........................................\
+.......................................................................\
+.................................9,)-2.5 F(140)2.5 E(\214gured bass)
+69.336 384 Q(..........................................................\
+.............................................................69, 74, 10\
+2, 105, 106)1.45 E -1.89(\215ags ......................................\
+.......................................................................\
+......................................21,)69.336 396 R(63, 105)2.5 E
+-.78(\215at ...........................................................\
+............................................................3,)69.336
+408 R(4, 17, 63, 74, 102, 112, 126)2.5 E -1.61(font ...................\
+.......................................................................\
+..........5,)69.336 420 R(22, 40, 48, 68, 71, 74, 86, 95, 110, 113)2.5 E
+(fontf)69.336 432 Q -.12(amily ........................................\
+.......................................................................\
+..............22,)-.1 F(48, 74, 95, 110)2.5 E -1.88(footer ............\
+.......................................................................\
+......................................5,)69.336 444 R
+(10, 84, 89, 93, 110, 121)2.5 E -1.88(fret ............................\
+.......................................................................\
+................................................................51)
+69.336 456 R -1.61(Ghostscript ........................................\
+.......................................................................\
+.............................6,)69.336 468 R(11, 68)2.5 E -.78(glissand\
+o .....................................................................\
+.......................................................................\
+.............90)69.336 480 R(grace notes)69.336 492 Q(.................\
+.......................................................................\
+....................................21, 22, 52, 72, 151)1.74 E -.5(grid\
+s .....................................................................\
+.......................................................................\
+......14,)69.336 504 R(76, 110)2.5 E -1.33(guitar .....................\
+.......................................................................\
+...........................................................50,)69.336
+516 R(147)2.5 E -2.15(header ..........................................\
+.......................................................................\
+.5,)69.336 528 R(10, 14, 84, 89, 93, 110, 121)2.5 E -2.16(heel. .......\
+.......................................................................\
+.......................................................................\
+..........148)69.336 540 R -2.43(hidechanges ..........................\
+.......................................................................\
+....................................................41)69.336 552 R
+-1.88(ifdef ...........................................................\
+.......................................................................\
+.......................96,)69.336 564 R(151)2.5 E(impro)69.336 576 Q
+-.91(visation .........................................................\
+.......................................................................\
+................147)-.15 F -2.44(include ..............................\
+.......................................................................\
+..................................................9,)69.336 588 R(100)
+2.5 E(in)69.336 600 Q -2.32(visbar ....................................\
+.......................................................................\
+.........................................37,)-.4 F(129)2.5 E -1.89(ital\
+ics ...................................................................\
+........48,)69.336 612 R
+(68, 71, 73, 74, 80, 86, 102, 105, 106, 109, 110, 113)2.5 E -.23(justi\
+\214cation ............................................................\
+.......................................................................\
+..............5,)69.336 624 R(86)2.5 E -.1(ke)69.336 636 S 2.5(ys)-.05 G
+-1.35(ignature ........................................................\
+.....................3,)-2.5 F
+(8, 39, 41, 102, 102, 112, 121, 121, 126, 126)2.5 E -1.33(labels ......\
+.......................................................................\
+......................................................40,)69.336 648 R
+(40, 69, 107, 112)2.5 E(leftmar)69.336 660 Q -1.98(gin ................\
+.......................................................................\
+.................................................93,)-.18 F(113, 140)2.5
+E(le)69.336 672 Q -.05(ga)-.15 G -2.24(to .............................\
+.......................................................................\
+.....................................................22,).05 F(65)2.5 E
+-.5(length ............................................................\
+.......................................................................\
+...................23,)69.336 684 R(123)2.5 E -.5(line ................\
+.......................................................................\
+.......................................................13,)69.336 696 R
+(84, 90, 138)2.5 E -.22(lyrics ........................................\
+...........................................................5,)69.336 708
+R(14, 14, 43, 69, 74, 102, 105, 106, 113)2.5 E -.22(lyricsalign .......\
+.......................................................................\
+.........................................................48,)69.336 720
+R(113, 129)2.5 E -1.88(macros .........................................\
+.......................................................................\
+.............................8,)69.336 732 R(9, 95, 150)2.5 E EP
+%%Page: 164 170
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(64 -)-2.5 E
+(manual placement)69.336 96 Q(.........................................\
+.......................................................................\
+.....46, 90, 135, 135)1.46 E -.22(map .................................\
+.......................................................................\
+.........................................................34)69.336 108 R
+(mar)69.336 120 Q -1.15(gin ...........................................\
+............................................................84,)-.18 F
+(86, 106, 113, 119, 126, 129, 140)2.5 E -1.32
+(measure .....................2,)69.336 132 R(8, 15, 17, 18, 19, 24, 27\
+, 37, 42, 47, 69, 72, 82, 85, 93, 105, 110, 114, 125, 138, 152)2.5 E
+(measure numbers)69.336 144 Q(.........................................\
+.......................................................................\
+......40, 41, 110, 114)1.74 E(measure repeat)69.336 156 Q(.............\
+.......................................................................\
+......................................................17, 65)1.75 E
+(measure rest)69.336 168 Q(............................................\
+.......................................................................\
+...........................17, 42)1.74 E -.77(MIDI ....................\
+.......................................................................\
+..............1,)69.336 180 R(9, 18, 50, 109, 112, 121, 135, 150)2.5 E
+(mid-measure parameter changes)69.336 192 Q(...........................\
+.......................................................................\
+...................25).1 E -1.33(mordent ..............................\
+.......................................................................\
+......................................................64)69.336 204 R
+-1.61(mouse ...........................................................\
+.......................................................................\
+............................12)69.336 216 R -.78(MS-DOS ...............\
+.......................................................................\
+...........................................................1,)69.336 228
+R(7, 11)2.5 E -1.06(multirest .........................................\
+.......................................................................\
+................................8,)69.336 240 R(13, 42)2.5 E -2.45(mupd\
+isp ...................................................................\
+.......................................................................\
+.................11)69.336 252 R -1.89(mupprnt ........................\
+.......................................................................\
+............................................................11)69.336
+264 R(music conte)69.336 276 Q -1.18(xt ...............................\
+.......................................................................\
+........3,)-.15 F(14, 15, 84, 89, 95, 129)2.5 E -1.34(mussym ..........\
+.......................................................................\
+........................71,)69.336 288 R(73, 77, 90, 102, 105, 106, 151)
+2.5 E(neutral clef)69.336 300 Q(.......................................\
+.......................................................................\
+..............................108, 121)1.74 E(ne)69.336 312 Q -.79(wpag\
+e .....................................................................\
+.......................................................................\
+13,)-.25 F(93, 129)2.5 E(ne)69.336 324 Q -.51(wscore ..................\
+.......................................................................\
+..................................................13,)-.25 F(93, 129)2.5
+E -1.61(north .........................................................\
+.......................................................................\
+................................84)69.336 336 R -1.61(notes ....2,)
+69.336 348 R(8, 14, 16, 19, 33, 42, 45, 48, 63, 67, 72, 72, 80, 84, 84,\
+ 85, 105, 108, 109, 116, 128, 135, 150, 151)2.5 E(numbering pages)69.336
+360 Q(.................................................................\
+......................................................................1\
+0, 94).9 E(octa)69.336 372 Q -.95 -.15(ve .)-.2 H(.....................\
+..................................................................2, 17\
+, 20, 71, 80, 102, 102, 105, 108, 126, 151).15 E(odd pages)69.336 384 Q
+(......................................................................\
+.......................................................................\
+.....9, 140)1.73 E -2.16(ornaments ....................................\
+.......................................................................\
+...............................64,)69.336 396 R(71, 151)2.5 E(pack)
+69.336 408 Q -.15(ex)-.1 G 1.43(p.).15 G(..............................\
+.......................................................................\
+...........................................116, 129)-1.43 E(packf)69.336
+420 Q -1.77(act .......................................................\
+.......................................................................\
+...................116,)-.1 F(129)2.5 E -.22(padding ..................\
+.......................................................................\
+....................................................23,)69.336 432 R
+(39, 135)2.5 E(page footer)69.336 444 Q(...............................\
+.......................................................................\
+..........5, 10, 84, 89, 93, 110, 121)1.74 E(page header)69.336 456 Q(.\
+.......................................................................\
+.................................5, 10, 14, 84, 89, 93, 110, 121)1.47 E
+-1.88(pageheight ......................................................\
+.......................................................................\
+........................117)69.336 468 R(page number)69.336 480 Q(.....\
+.......................................................................\
+..................................................................10, 9\
+4).07 E(page)69.336 492 Q -1.91(width .................................\
+.......................................................................\
+..............................................117)-.25 F -.48(paragraph\
+ ......................................................................\
+.......................................................................\
+...........87)69.336 504 R -1.87(parameters ...........................\
+.......................................................................\
+.............3,)69.336 516 R(13, 14, 96, 102, 129, 152)2.5 E -2.15(pare\
+ntheses ...............................................................\
+.......................................................................\
+....16,)69.336 528 R(17, 51)2.5 E -2.16(pedal .........................\
+.......................................................................\
+........................5,)69.336 540 R(64, 71, 81, 105, 117, 151)2.5 E
+-1.33(pedstyle ........................................................\
+.......................................................................\
+....................81,)69.336 552 R(117)2.5 E -.77(percussion ........\
+.......................................................................\
+......................................................................1\
+21)69.336 564 R -1.6(phrase ...........................................\
+.......................................................................\
+............................5,)69.336 576 R(14, 71, 78)2.5 E
+(piano reduction)69.336 588 Q(.........................................\
+.......................................................................\
+.............................145)2.01 E(pickup measure)69.336 600 Q(...\
+.......................................................................\
+...........................................................4, 10, 16)
+1.46 E(piled te)69.336 612 Q -.35(xt ..................................\
+.......................................................................\
+..........................................69,)-.15 F(75)2.5 E -.5(pitch\
+ ......................................................................\
+..........................................2,)69.336 624 R
+(16, 17, 18, 18, 19, 20, 26, 121)2.5 E -1.62(PostScript ...............\
+.......................................................................\
+....................................................1,)69.336 636 R
+(6, 11, 68)2.5 E -1.89(print ..........................................\
+...................................1,)69.336 648 R
+(6, 7, 11, 13, 72, 84, 86, 110, 121, 121, 125, 127, 135)2.5 E -1.06(quo\
+ting ..................................................................\
+.......................................................................\
+...................97)69.336 660 R -.77(reduction .....................\
+.......................................................................\
+...........................................................145)69.336
+672 R(re)69.336 684 Q -.9(gistration ..................................\
+.......................................................................\
+.........................................1,)-.15 F(10)2.5 E
+(rehearsal marks)69.336 696 Q(.........................................\
+........................................................40, 74, 102, 11\
+0, 114, 118, 151)1.47 E -.76(release ..................................\
+.......................................................................\
+....................................................25)69.336 708 R
+-2.43(repeat ..........................................................\
+.......................................................................\
+..33,)69.336 720 R(37, 65, 147, 150)2.5 E -2.44(rest ..................\
+.......................................................................\
+..........................8,)69.336 732 R
+(16, 18, 22, 42, 45, 64, 85, 128)2.5 E EP
+%%Page: 165 171
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(65 -)-2.5 E -.49(restart ..\
+.......................................................................\
+.......................................................................\
+..............37)69.336 96 R(rightmar)69.336 108 Q -.04(gin ...........\
+.......................................................................\
+...................................................93,)-.18 F(119, 140)
+2.5 E -1.89(roll ......................................................\
+.......................................................................\
+................................81,)69.336 120 R(90)2.5 E -1.05(roman .\
+.......................................................................\
+..........40,)69.336 132 R
+(48, 68, 71, 73, 74, 86, 102, 105, 106, 110, 113)2.5 E -.49(scale .....\
+.......................................................................\
+.......................................................................\
+...119,)69.336 144 R(129)2.5 E -1.6
+(score ..................................1,)69.336 156 R(3, 4, 5, 8, 14\
+, 39, 40, 48, 49, 74, 93, 95, 102, 107, 112, 114, 120, 128, 151, 155)2.5
+E -1.04(scorepad ......................................................\
+.......................................................................\
+...................120,)69.336 168 R(129)2.5 E -2.43(scoresep .........\
+.......................................................................\
+.......................................................................\
+..121)69.336 180 R -.5(scrolling ......................................\
+.......................................................................\
+.............................................11)69.336 192 R -1.61(semi\
+colon .................................................................\
+.....................................2,)69.336 204 R
+(13, 15, 21, 33, 43, 72, 102, 129)2.5 E(shaped notes)69.336 216 Q(.....\
+.......................................................................\
+..............................................14, 20, 22, 56, 114).62 E
+(share)69.336 228 Q -.1(wa)-.25 G -.68(re .............................\
+.......................................................................\
+................................................1,).1 F(10)2.5 E -2.16(\
+sharp .................................................................\
+...................................................3,)69.336 240 R
+(4, 17, 63, 74, 102, 112, 126)2.5 E -1.05(size ........................\
+......................................................................5\
+,)69.336 252 R(22, 40, 48, 68, 68, 74, 78, 86, 86, 113, 121)2.5 E -.5(s\
+lash ..................................................................\
+............................................7,)69.336 264 R
+(22, 22, 33, 52, 70, 75, 147, 151)2.5 E -1.89(slide ...................\
+.......................................................................\
+.......................................................................\
+52)69.336 276 R -1.61(slope ...........................................\
+.......................................................................\
+......................................32,)69.336 288 R(103)2.5 E -.5(sl\
+ur ....................................................................\
+.......................................................................\
+.................20,)69.336 300 R(27)2.5 E -2.17(small ................\
+.......................................................................\
+.......................................................11,)69.336 312 R
+(19, 21, 67)2.5 E -2.17(south .........................................\
+.......................................................................\
+................................................84)69.336 324 R -.21
+(space ...........................................................2,)
+69.336 336 R
+(4, 8, 13, 16, 18, 23, 39, 45, 47, 47, 68, 116, 120, 122, 128, 135)2.5 E
+-.2(spacing ...........................................................\
+.......................................................................\
+........\(see)69.336 348 R(padding\))2.5 E -.21(staccato ..............\
+.......................................................................\
+......................................................................2\
+2)69.336 360 R(staf)69.336 372 Q 1.98(f.)-.25 G(....................13,\
+ 14, 15, 43, 48, 69, 71, 74, 81, 82, 84, 102, 107, 108, 110, 112, 122, \
+122, 127, 150, 151)-1.98 E(staf)69.336 384 Q 2.5(fp)-.25 G -.23(aper ..\
+.......................................................................\
+.......................................................................\
+.....149)-2.5 F(staf)69.336 396 Q -1.36(\215ines ......................\
+.......................................................................\
+.....................................................50,)-.25 F(121)2.5
+E(staf)69.336 408 Q -2.46(fpad ........................................\
+.......................................................................\
+...................................122,)-.25 F(129)2.5 E(staf)69.336 420
+Q -1.35(fsep ..........................................................\
+.......................................................................\
+.................123,)-.25 F(129)2.5 E -1.89(stem .....................\
+.......................................................................\
+.....................................22,)69.336 432 R
+(22, 32, 63, 84, 128)2.5 E(stem direction)69.336 444 Q(................\
+.......................................................................\
+.......................................22, 22, 31, 127).06 E
+(stem length)69.336 456 Q(.............................................\
+.......................................................................\
+..........................23, 123).61 E -2.16(stepsize ................\
+..........................................................13,)69.336 468
+R(23, 39, 85, 108, 109, 109, 120, 121, 122, 123, 135)2.5 E -2.17(string\
+s ............................................................14,)69.336
+480 R(22, 22, 22, 40, 40, 44, 67, 72, 80, 86, 95, 107, 110, 112, 121)2.5
+E -.78(strum ..........................................................\
+.......................................................................\
+............................147)69.336 492 R -.77(subscript/superscript\
+ ......................................................................\
+.................................................................69)
+69.336 504 R(swing time)69.336 516 Q(..................................\
+.......................................................................\
+....................................124, 151).33 E -1.61(syllable .....\
+.......................................................................\
+.......................................................................\
+.....5,)69.336 528 R(43)2.5 E -1.9(sylposition ........................\
+.......................................................................\
+................................................49,)69.336 540 R(124)2.5
+E -.49(tablature ......................................................\
+.......................................................................\
+...............50,)69.336 552 R(79, 121)2.5 E -.22(tag ................\
+.......................................................................\
+..................................................21,)69.336 564 R
+(23, 39, 84, 135)2.5 E -.5(tempo ......................................\
+.......................................................................\
+.............................1,)69.336 576 R(14, 151, 152)2.5 E(te)
+69.336 588 Q(xt strings)-.15 E(........................................\
+.............14, 22, 22, 22, 40, 40, 44, 67, 72, 80, 86, 95, 107, 110, \
+112, 121).48 E -.5(tie ................................................\
+.......................................................................\
+.................................19,)69.336 600 R(26, 52)2.5 E -1.34(ti\
+l .....................................................................\
+.......................................................................\
+.........................73)69.336 612 R -.78(time ....................\
+.................................................................2,)
+69.336 624 R(15, 21, 32, 33, 43, 63, 71, 72, 85, 105, 116, 125)2.5 E
+(time signature)69.336 636 Q(..........................................\
+............................3, 8, 15, 17, 39, 40, 41, 72, 85, 121, 125,\
+ 138, 150).06 E -1.34(timeunit ........................................\
+.......................................................................\
+....................................16,)69.336 648 R(125)2.5 E -1.06(ti\
+tle ...................................................................\
+.......................................................................\
+........5,)69.336 660 R(13, 14, 86)2.5 E -.22(toe. ....................\
+.......................................................................\
+.....................................................................14\
+8)69.336 672 R -.78
+(top ...............................................13,)69.336 684 R(14\
+, 43, 71, 72, 73, 82, 84, 84, 89, 93, 103, 106, 110, 121, 123, 126, 150)
+2.5 E(topmar)69.336 696 Q -1.43(gin ...................................\
+.......................................................................\
+............................................126)-.18 F -.77(transpose .\
+.......................................................................\
+.....................................50,)69.336 708 R
+(54, 75, 102, 121, 126, 143)2.5 E -.49(track ..........................\
+.......................................................................\
+.............................................................150)69.336
+720 R -2.45(trill .....................................................\
+.......................................................................\
+...........................64,)69.336 732 R(77, 90)2.5 E EP
+%%Page: 166 172
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(66 -)-2.5 E -1.88(triplets \
+.......................................................................\
+.......................................................................\
+\(see)69.336 96 R(tuplets\))2.5 E -2.17(tuplets .......................\
+.......................................................................\
+........................................................33,)69.336 108 R
+(135)2.5 E -1.61(turn .................................................\
+.......................................................................\
+..........................................64)69.336 120 R
+(uncollapseable space)69.336 132 Q(....................................\
+.......................................................................\
+............................16).36 E -.77(undef .......................\
+.......................................................................\
+.................................................................96)
+69.336 144 R -.77(underline ...........................................\
+.......................................................................\
+.......................................69)69.336 156 R -1.87(underscore\
+ ......................................................................\
+...........................................................8,)69.336 168
+R(45, 69, 76, 95)2.5 E -2.45(units ....................................\
+.......................................................................\
+....................................................126)69.336 180 R
+-.49(UNIX .............................................................\
+.......................................................................\
+......................8,)69.336 192 R(11)2.5 E -.15(ve)69.336 204 S -.07
+(locity ...............................................................\
+.......................................................................\
+...................152).15 F -.15(ve)69.336 216 S -1.45(rse ...........\
+.......................................................................\
+............................................................5,).15 F
+(44, 69, 145)2.5 E -2.17(visible ......................................\
+..........................................................8,)69.336 228
+R(8, 8, 43, 50, 71, 84, 103, 110, 122, 127)2.5 E -.2(vo)69.336 240 S
+-1.96(ice .............................................................\
+.................................4,).2 F
+(14, 15, 15, 78, 82, 90, 102, 128, 135, 150)2.5 E -.78(with ...........\
+.......................................................................\
+.......................................................................\
+..22,)69.336 252 R(54)2.5 E -.15(ve)69.336 264 S(rtical motion).15 E(..\
+.......................................................................\
+.......................................................................\
+69)1.32 E -.49(vscheme ................................................\
+.......................................................................\
+...........................78,)69.336 276 R(128)2.5 E -.1(wa)69.336 288
+S(vy lines)-.1 E(......................................................\
+.......................................................................\
+....................76, 90)1.75 E -1.33(west ..........................\
+.......................................................................\
+................................................................84)
+69.336 300 R(X-shaped notes)69.336 312 Q(..............................\
+.......................................................................\
+...............................21, 52, 64).07 E 69.336 324 EBEGIN
+%-marker2-
+EEND EP
+%%Trailer
+end
+%%EOF
diff --git a/mup/docs/uguide/adjust.html b/mup/docs/uguide/adjust.html
new file mode 100644 (file)
index 0000000..0eec931
--- /dev/null
@@ -0,0 +1,74 @@
+<HTML>
+<HEAD><TITLE>
+Adjusting Mup output
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="debug.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="invisbar.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Adjusting Output
+</H2>
+<P>
+Mup does its best to lay out the music in an aesthetically pleasing way.
+Often, however, you may want to make adjustments. Perhaps the last part of
+a piece spilled over onto a third page and you'd like to squeeze it all on
+two pages, or a page turn falls at an awkward spot. There are several
+mechanisms available for making adjustments. They have already been discussed
+individually in various sections of this document, but this section tries to
+pull things together.
+</P>
+<P>
+<A HREF="newscore.html">The "newscore" or "newpage" commands</A>
+can be used to force where breaks occur.
+This may be useful for ensuring a section ends at the end of a score or page.
+</P>
+<P>
+If you want to get a little more or less on each page, it is usually best
+to start with changing the
+<A HREF="param.html#scale">scale,</A>
+<A HREF="param.html#stscale">staffscale,</A>
+<A HREF="param.html#packfact">packfact,</A>
+and/or
+<A HREF="param.html#packexp">packexp</A>
+parameters.
+You may want to experiment with changing these individually first, to get
+a feel for how they work, as trying to change all of them at once may lead to
+interactions that change things more radically than you might expect.
+Changing staffscale in score context lets you adjust the size of the
+music without affecting the size of the text in headers and footers.
+Adjusting the margins is sometimes helpful as well. Other parameters which
+might be useful in some situations are:
+<A HREF="param.html#scorepad">scorepad,</A>
+<A HREF="param.html#scoresep">scoresep,</A>
+<A HREF="param.html#staffpad">staffpad,</A>
+and
+<A HREF="param.html#staffsep">staffsep.</A>
+</P>
+<P>
+The
+<A HREF="param.html#dist">dist,</A>
+<A HREF="param.html#dyndist">dyndist,</A>
+and
+<A HREF="param.html#chdist">chorddist</A>
+parameters are useful if
+you want items to line up vertically. The &quot;dist&quot; option can be used
+on rom, bold, ital, boldital, octave, mussym, crescendo and decrescendo
+statements, and on rehearsal marks, to force something where you want it.
+</P>
+<P>
+The appearance of lyrics can be adjusted using the
+<A HREF="param.html#lyrfont">lyricsfont,</A>
+<A HREF="param.html#lyrfam">lyricsfontfamily,</A>
+<A HREF="param.html#lyrsize">lyricssize,</A>
+and
+<A HREF="param.html#lyralign">lyricsalign</A>
+parameters.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="debug.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="invisbar.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/altinp.html b/mup/docs/uguide/altinp.html
new file mode 100644 (file)
index 0000000..7bb143e
--- /dev/null
@@ -0,0 +1,177 @@
+<HTML>
+<HEAD><TITLE>
+Chord-at-a-time input style
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="tuplets.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="bars.html">next page --&gt;</A>
+</P>
+             
+<H2>
+Chord-at-a-time input style
+</H2>
+<P>
+There is an alternate input style, in which you enter music
+a chord at a time, rather than a voice at a time. In this style, the
+specification before the colon gives one or more patterns that tells
+how to map notes to staffs and voices.
+</P>
+<P>
+Suppose you want to print some
+music in a style which is common for many traditional hymns:
+it is to be printed on two staffs, each staff will always have
+exactly two notes, and the rhythm is exactly the same for all voices.
+With chord at a time input, you specify, for each note in a chord,
+which staff and voice to map that note. Since there are four notes in
+each chord, there will be four mappings listed. You want the bottom
+two notes to get mapped to staff 2, and the top two notes to staff 1.
+This is shown as
+<BR><PRE>
+// Bass to staff 2 voice 1
+// |    Tenor to staff 2 voice 1
+// |    |    Alto to staff 1 voice 1
+// |    |    |    Soprano to staff 1 voice 1
+[  2 1; 2 1; 1 1; 1 1 ]
+</PRE><BR>
+Each item in the semicolon-separated list tells how to map one note.
+So the first note in each chord will get mapped to staff 2 voice 1.
+The second note in each chord will also get mapped to staff 2 voice 1.
+The third and fourth notes will get mapped to staff 1 voice 1.
+</P>
+<P>
+Since voice 1 is, as always, the default, this could be written more
+compactly as just:
+<BR><PRE>
+[ 2; 2; 1; 1 ]
+</PRE><BR>
+If you wanted to input notes from top to bottom instead
+(in soprano-alto-tenor-bass order, rather than bass-tenor-alto-soprano order),
+you could use:
+<BR><PRE>
+// Soprano
+//    Alto
+//       Tenor
+//          Bass
+[  1; 1; 2; 2 ]
+</PRE><BR>
+If you wanted to use two separate voices on each staff (going
+back to bottom-to-top order), you could specify:
+<BR><PRE>
+// Bass to staff 2 voice 2
+// |    Tenor to staff 2 voice 1
+// |    |    Alto to staff 1 voice 2
+// |    |    |    Soprano to staff 1 voice 1
+[  2 2; 2 1; 1 2; 1 1  ]
+</PRE><BR>
+</P>
+<P>
+Now let's put these mappings with music data.
+<BR><PRE>
+score
+    staffs=2
+    vscheme=2f
+staff 2
+   clef=bass
+
+music
+
+[ 2; 2; 1; 1 ] : facf;dgfb;2cgec+;
+bar
+
+[ 1 1; 1 2; 2 1; 2 2 ] : fcaf;bfgd;2c+egc;
+bar
+</PRE><BR>
+<IMG SRC="mugex31.gif" ALT="Picture of Mup output"><BR>
+In the first measure, the first two notes listed in each chord are mapped
+to staff 2, voice 1, while the third and fourth notes listed in each chord
+are mapped to staff 1 voice 1. In the second measure, two voices are
+used and notes are entered in descending order. Note that each note takes
+on the correct default octave for whichever staff it is mapped to.
+</P>
+<P>
+It is also possible to use rests or spaces for some of the voices.
+<BR><PRE>
+score
+  key=3&amp;
+  vscheme=2f
+
+music
+
+[ 1 2; 1 1 ]: rb; eg; ca; gr;
+bar
+
+[ 1 2; 1 1 ]: er; sr; 8sf; se; 4sg;
+bar
+</PRE><BR>
+<IMG SRC="mugex32.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+Chord attributes and interchord attributes (like tie, slur, xnote,
+len, and alt) can be specified just like
+for voice-at-a-time input. Note attributes (like ? and ~) apply to
+the note wherever it gets mapped, and items that apply to the chord as
+a whole will be applied to all the notes.
+<BR><PRE>
+[1 2; 1 1] : [cue; xnote; len 6] b-e; [with &gt; ] ce&amp; slur; dg~; c?g;
+</PRE><BR>
+<IMG SRC="mugex33.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+It is possible to map a note to more than one place by using ranges,
+and/or by giving a list of staffs and voices,
+separated by ampersands. This may be useful,
+for example, if several voices are in unison.
+In the next example, the first note in each chord will be mapped to voice
+1 of staffs 1 through 3, as well as to voice 2 of staff 1, while the
+second note in each chord will be mapped to voice 2 of staffs 2 and 3.
+<BR><PRE>
+[ 1-3 1  &amp;  1 2;  2-3 2 ] : ec;fd;ge;af;
+</PRE><BR>
+<IMG SRC="mugex34.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+It is also possible to specify more than one bracketed mapping.
+Each must include a mapping for a different number of notes.
+So, for example, if some chords in a measure have two notes and
+others have three, you can define two maps: one for two notes,
+and one for three. The example below demonstrates placing alto
+and soprano as two voices on one staff, but sometimes the alto
+part splits.
+<BR><PRE>
+// For chords with two notes,
+// map the first to staff 1 voice 2 (alto),
+// and the second to staff 1 voice 1 (soprano).
+// For chords with three notes,
+// map the first two notes to staff 1 voice 2
+// (first and second alto part),
+// and the third to staff 1 voice 1 (soprano).
+[ 1 2; 1 1 ] [ 1 2; 1 2; 1 1 ]: cec+;df;eg;a-fc+;
+</PRE><BR>
+<IMG SRC="mugex35.gif" ALT="Picture of Mup output"><BR>
+If mappings of different chords need to vary by something other than
+the number of notes in the chord, then you will have to use
+the voice-at-a-time input style.
+</P>
+<P>
+Since the mapping specifications can get rather complex,
+and they may be used many times during a song,
+it is usually best to define
+<A HREF="macros.html">macros</A>
+for them, and possibly even put the macro definitions in
+<A HREF="include.html">an "include" file.</A>
+</P>
+<P>
+You can use the different input styles in different measures of a single
+song, and use different mappings in different measures.
+You can even mix the two input styles within a measure,
+but a given staff/voice
+can only appear on one line of input per measure. So, for example,
+you could choose to input staffs 1 and 2 of a song in chord-at-a-time
+input style, and staff 3 in voice-at-a-time style.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="tuplets.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="bars.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/bars.html b/mup/docs/uguide/bars.html
new file mode 100644 (file)
index 0000000..b674bca
--- /dev/null
@@ -0,0 +1,348 @@
+<HTML>
+<HEAD><TITLE>
+Bar Lines
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="altinp.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="multirst.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Bar lines
+</H2>
+<P>
+Each measure must be ended with a &quot;bar&quot; of some kind. There are several kinds:
+<TABLE BORDER=4>
+<TR>
+<TD><B>Keyword</B></TD>        <TD><B>Meaning</B></TD>
+</TR>
+<TR>
+<TD>bar</TD>   <TD>ordinary bar line</TD>
+</TR>
+<TR>
+<TD>dblbar</TD>        <TD>double bar</TD>
+</TR>
+<TR>
+<TD>repeatstart</TD>   <TD>beginning of repeated section</TD>
+</TR>
+<TR>
+<TD>repeatboth</TD>    <TD>end of one repeated section and beginning of another</TD>
+</TR>
+<TR>
+<TD>repeatend</TD>     <TD>end of repeated section</TD>
+</TR>
+<TR>
+<TD>endbar</TD>        <TD>heavy double bar line used at end of song</TD>
+</TR>
+<TR>
+<TD>invisbar</TD>      <TD>no bar line printed</TD>
+</TR>
+<TR>
+<TD>restart</TD>       <TD>end staffs and begin anew</TD>
+</TR>
+</TABLE>
+
+</P>
+<P>
+In addition, the bar and dblbar types can be preceded
+by the word &quot;dashed&quot; or &quot;dotted&quot; to produce dashed or dotted bar lines.
+</P>
+<P>
+<BR><PRE>
+1: mr;
+bar
+1: mr;
+dblbar
+1: mr;
+dashed bar
+1: mr;
+dotted dblbar
+1: mr;
+repeatstart
+1: mr;
+repeatboth
+1: mr;
+repeatend
+1: mr;
+endbar
+</PRE><BR>
+<IMG SRC="mugex36.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+When a repeatstart would end up at the end of a score,
+it will automatically get moved to the beginning of the following score.
+In that case, it isn't clear what kind of bar line you would like to
+have put at the end of the original score. By default, Mup will use
+an ordinary bar, but in some cases--like if the repeatstart begins
+a new section, or there is also a key change--you might want to have
+a dblbar instead. You can get a dblbar there by specifying dblbar in
+parentheses before the repeatstart:
+<BR><PRE>
+(dblbar) repeatstart
+</PRE><BR>
+Actually, you are allowed to specify any bar type in the parentheses,
+but dblbar or possibly invisbar are probably the only ones likely to be useful.
+If the repeatstart ends up in the middle of a score, so that it doesn't
+need to get moved to the beginning of the next score, the parenthesized
+bar type is not needed, so it is just ignored.
+</P>
+<P>
+Sometimes music is printed without bar lines. The &quot;invisbar&quot; can be used in
+this case, to fulfill Mup's requirement to specify some sort of bar after
+every measure without actually printing bar lines.
+</P>
+<P>
+<A NAME="restart">The restart is a special kind of bar. It follows immediately after another</A>
+bar line without any intervening music data. (That is, you can't have
+any notes. You can use score or staff context things, like changing time or
+key signature.) It would be most commonly used for something like a short coda.
+<BR><PRE>
+score
+       staffs=2
+       brace=1-2
+staff 2
+       clef=bass
+music
+
+1-2: c;d;e;f;
+rom above 1: 3 &quot;D.C. al Coda&quot;;
+dblbar
+
+// The restart follows a bar
+// without any music data in between.
+restart
+
+rom above 1: 1 &quot;Coda&quot;;
+1-2: f;e;d;c;
+endbar
+</PRE><BR>
+<IMG SRC="mugex37.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+There are several optional directives that can follow the bar line keyword.
+They can be specified in any order and are described below.
+</P>
+<H3>
+Bar line padding
+</H3>
+<P>
+<A NAME="bpad">One optional directive is padding.</A>
+It can be used to force Mup to place extra white space to
+the left of the bar line. It is specified by the keyword &quot;pad&quot; followed
+by a number of stepsizes of padding to add. For example:
+<BR><PRE>
+dblbar pad 3
+</PRE><BR>
+would add 3 stepsizes of padding.
+</P>
+<H3>
+Bar line location tag
+</H3>
+<P>
+<A NAME="btag">It is also possible to associate a</A>
+<A HREF="tags.html">location tag</A>
+with a bar line.
+For example:
+<BR><PRE>
+// Associate tag &quot;_bar6&quot; with bar line
+bar =_bar6
+
+// Do double bar with an extra stepsize of
+// padding, and associate tag &quot;q&quot;
+// with the bar line
+dblbar pad 1 =q
+</PRE><BR>
+</P>
+<P>
+The y coordinate of a bar line is not very useful. Special rules apply if
+a bar line happens to be placed at the end of a score. Any locations taken
+relative to the bar that would be to the right of the bar are treated as
+if the bar line were at the beginning of the following score,
+just beyond the clef and time and key signatures, if any.
+</P>
+<H3>
+Endings
+</H3>
+<P>
+<A NAME="endings">First and second endings, etc. can be designated at bar lines.</A>
+This is done with the keyword &quot;ending,&quot; followed by a
+quoted string to use as the label for the ending that should begin at the
+bar line. An ending will span bars until either another ending is specified,
+the piece ends, or the
+special keyword &quot;endending&quot; is used. Examples:
+<BR><PRE>
+bar ending &quot;1.&quot;
+repeatend ending &quot;2-3&quot;
+endbar endending
+</PRE><BR>
+</P>
+<P>
+The ending label will always be
+forced into 12 point times roman font. If you change font or size or include
+special characters in the ending label,
+the output is not likely to be aligned properly.
+</P>
+<P>
+<A HREF="param.html#endingst">The "endingstyle" parameter</A>
+controls where endings are placed.
+Endings cannot start at or cross over a restart bar.
+</P>
+<H3>
+Rehearsal marks
+</H3>
+<P>
+<A NAME="reh">Rehearsal letters or numbers</A>
+can be specified on any bar line. There are four formats:
+<BR>
+<B>rehearsal let</B>
+<BR>
+<B>rehearsal num</B>
+<BR>
+<B>rehearsal mnum</B>
+<BR>
+<B>rehearsal &quot;</B><I>label</I><B>&quot;</B>
+</P>
+<P>
+In the first example, a rehearsal letter will be placed on the bar. The
+first occurrence of this will become rehearsal &quot;A&quot;, the next &quot;B&quot;, and so
+forth. The second format works in a similar fashion except that numbers are
+used rather than letters. With the third format, the current measure
+number is used. With the last format, any arbitrary string
+within the quotes will be used. The keyword &quot;rehearsal&quot; can be
+abbreviated to &quot;reh&quot; if you wish. Only one rehearsal mark is allowed on
+any one bar, but the types can be mixed throughout the composition.
+(Note that mixing &quot;num&quot; with &quot;mnum&quot; is likely to be very confusing, however.)
+The rehearsal marks can be intermixed with other bar options:
+<BR><PRE>
+1: 1c;
+dblbar reh num ending &quot;1&quot;
+1: 1e;
+repeatend pad 1 =_xyz reh let ending &quot;2.&quot;
+1: 1g;
+bar rehearsal &quot;Duet&quot;
+1: 1ce;
+endbar endending
+</PRE><BR>
+<IMG SRC="mugex38.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+The rehearsal marks are normally put directly above the bar
+line. However, if the bar line falls at the end of a score, the rehearsal
+mark will be placed at the beginning of the following score, after the
+<A HREF="param.html#clef">clef,</A>
+<A HREF="param.html#key">key signature,</A>
+and
+<A HREF="param.html#time">time signature.</A>
+<A HREF="param.html#endingst">The "endingstyle" parameter</A>
+is used to determine which staffs get rehearsal marks.
+<A HREF="param.html#rehstyle">The "rehstyle" parameter</A>
+specifies whether to put rehearsal marks inside a box or a circle
+or leave them plain.
+</P>
+<P>
+The rehearsal keyword may be followed by a specification for <I>fontfamily</I>,
+<I>font</I>, and/or <B>(</B><I>size</I><B>)</B>.
+Once specified, these remain in effect
+for any future rehearsal marks, until explictly changed. Some examples:
+<BR><PRE>
+bar rehearsal helvetica bold (14) let
+repeatend reh newcentury num
+invisbar reh rom (10) mnum
+</PRE><BR>
+</P>
+<P>
+After all the options listed above, you may specify &quot;dist <I>N</I>&quot; where
+<I>N</I> is some number of stepsizes. This will override the
+<A HREF="param.html#dist">dist parameter</A>
+for determining how close to the staff to place the rehearsal mark.
+If the number is followed by a &quot;!&quot; Mup will place the mark exactly
+that far from the top of the staff, even if it overwrites other things;
+otherwise the value specifies a minimum distance.
+<BR><PRE>
+rehearsal num dist 5     // at least 5 stepsizes away
+reh bold &quot;A1&quot; dist 2 !   // exactly 2 stepsizes away
+</PRE><BR>
+</P>
+<H3>
+Setting the measure number
+</H3>
+<P>
+<A NAME="setmnum">Mup keeps track of</A>
+<A HREF="param.html#measnum">measure numbers</A>
+automatically, but sometimes you may want
+to override this to set the current measure number to some specific value.
+This is done by adding mnum=<I>number</I> on a bar line,
+which will set the current measure number to the given <I>number</I>.
+<BR><PRE>
+// Set the current measure number to 50
+dblbar mnum=50
+</PRE><BR>
+</P>
+<H3>
+Setting rehearsal letter or number
+</H3>
+<P>
+<A NAME="setreh">If you are using the "rehearsal let" or "rehearsal num" styles,</A>
+you can set those to specific values too, similarly to how mnum can be set.
+This might be useful, for example, if you have a single input file that
+contains multiple songs or movements, and you want the rehearsal marks
+to start over at the beginning of each song or movement.
+</P>
+<P>
+The rehearsal number can be set on any bar line using num=<I>N</I>, where
+<I>N</I> is a number, typically 1.
+<BR><PRE>
+bar num=1
+</PRE><BR>
+The rehearsal letter can be set in a similar way, using let=&quot;<I>X</I>&quot; where
+<I>X</I> is either a single upper case letter, A to Z, or two upper case
+letters, AA to ZZ.
+<BR><PRE>
+dblbar let=&quot;A&quot; reh let
+</PRE><BR>
+</P>
+<H3>
+Hiding time/key signature and clef changes
+</H3>
+<P>
+<A NAME="hide">Generally in printed music, when a</A>
+<A HREF="param.html#time">time signature</A>
+<A HREF="param.html#key">or key signature</A>
+change occurs at the beginning of a score, these changes are also printed at
+the very end of the previous score,
+to make it clear there is a change coming up.
+Mup normally does this, but occasionally you may not want that behavior.
+Sometimes you may want to make a new score appear like the beginning
+of a new piece. If you wish to suppress the printing of time signature,
+key signature, and clef
+changes at the end of the preceding score,
+you can use the &quot;hidechanges&quot;
+keyword on the bar line at which the changes occur.
+Hidechanges cannot be used on a restart bar.
+<BR><PRE>
+1: c;d;e;f;
+bar
+// change time/key with normal treatment
+
+newscore
+score time=5/4 ; key = 1&amp;
+music
+1: d;e;f;2g;
+// don't show changes at end of previous score
+bar hidechanges        
+
+newscore
+
+score time=6/4 ; key = 2#
+music
+1: d;e;f;2.g;
+bar
+</PRE><BR>
+<IMG SRC="mugex39.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="altinp.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="multirst.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/basics.html b/mup/docs/uguide/basics.html
new file mode 100644 (file)
index 0000000..29981b6
--- /dev/null
@@ -0,0 +1,315 @@
+<HTML>
+<HEAD><TITLE>
+"Mup Basics"
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="intro.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="running.html">next page --&gt;</A>
+</P>
+          
+<H1>
+MUP BASICS
+</H1>
+<P>
+This section introduces the Mup language, giving some simple examples to
+give you the flavor of a Mup input file.
+Subsequent sections will go into greater detail.
+</P>
+<H2>
+Notes and chords
+</H2>
+<P>
+Music is described one measure at a time. Each note is specified by its pitch
+value, &quot;a&quot; to &quot;g.&quot; As an example, the first measure of &quot;Three Blind
+Mice&quot; can be described like this:
+<BR><PRE>
+1:    4e; 4d; 2c;
+</PRE><BR>
+<IMG SRC="mugex2.gif" ALT="Picture of Mup output"><BR>
+The &quot;1:&quot; at the beginning of the line tells Mup that we are describing
+the notes on staff number 1. In this very simple example, we only have one
+staff, but later we'll do songs with more than one.
+Each staff of each measure is normally put on a separate line.
+</P>
+<P>
+The first three notes of &quot;Three Blind Mice&quot; are E, D, and C. For Mup
+input, these pitches are given in lower case to avoid having to use the shift
+key. No octave information was specified in this simple example, so Mup
+would use its default, which in this case would be the octave beginning
+with middle C.
+</P>
+<P>
+The first two notes are quarter notes, and the last note is a half
+note. Time values of notes are given as shown in the example. A quarter
+note is marked by a 4, a half note by 2, a sixteenth note by a 16, etc.
+</P>
+<P>
+A semicolon is used to separate chords. In this simple example, each chord
+has only a single note in it, but it is possible to have lots of notes in one
+<A HREF="chordinp.html">chord.</A>
+</P>
+<P>
+At the end of each measure, we have to tell Mup what kind of
+<A HREF="bars.html">bar line</A>
+to draw. The standard bar line is just called &quot;bar.&quot; So a complete
+description of the first measure would be:
+<BR><PRE>
+1:    4e; 4d; 2c;
+bar
+</PRE><BR>
+</P>
+<P>
+To save typing, Mup allows a lot of shortcuts. One such shortcut is that
+it assumes that unless you tell it otherwise, each note in the measure is
+like the note before. You can leave out the second 4, because if you
+don't specify a time value, Mup will assume the note is the same length
+as the previous note.
+</P>
+<P>
+The same sort of idea works with pitches. The third measure of &quot;Three Blind
+Mice&quot; could be stated like this:
+<BR><PRE>
+1: 4g;8f;;2e;
+bar
+</PRE><BR>
+<IMG SRC="mugex3.gif" ALT="Picture of Mup output"><BR>
+The third note has no information given at all in this example--there is
+only a semicolon. In this case, Mup will get both pitch and time value from
+the previous note, so the actual third note in this measure would be an
+eighth note with pitch F.
+</P>
+<P>
+You may have noticed that this example doesn't have spaces between chords.
+There are only a few places where the Mup language requires you to put spaces.
+However, you can always put some in other places to make things easier to read.
+</P>
+<H2>
+Parameters
+</H2>
+<P>
+Printed music contains a lot more than just notes and bar lines. Among other
+things, each staff normally begins with a clef, key signature, and time
+signature. Mup provides default values for these, which you can then
+override if you want something different. In the examples so far, we didn't
+override anything, so Mup would assume its default values, which are
+treble clef, a key signature with no sharps or flats, and a time signature
+of 4/4.
+</P>
+<P>
+There is a long
+<A HREF="param.html">list of "parameters" that can be set.</A>
+Things like clef
+and key signature are among them. Parameters can be changed with a line of the
+form:
+<BR><PRE>
+<I>parameter_name</I>=<I>value</I>
+</PRE><BR>
+For example, suppose we have a song written in 6/8 time in the key of D major.
+We can convey this information to Mup like this:
+<BR><PRE>
+score
+  time=6/8
+  key=2#
+
+music
+  1: 4d;8e;4f;8d;
+  bar
+</PRE><BR>
+<IMG SRC="mugex4.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+Note that in this example, the key was specified as two sharps.
+You can also specify the key by name:
+<BR><PRE>
+  key = d major
+</PRE><BR>
+</P>
+<P>
+These parameters give a very different sort of information than the notes of
+a measure, so they go in a separate section of the input file.
+Each section of the file describes information for a specific
+<A HREF="contexts.html">"context."</A>
+Information about musical notes is given in &quot;music&quot; context,
+while things that apply in general to the whole
+score are given in &quot;score&quot; context.
+Once you start a measure in music context, you have to complete that measure
+before switching to another context, but otherwise you can pretty much
+change from one context to another as necessary.
+Each new context section is headed by its name (e.g.,
+&quot;music&quot; or &quot;score&quot;).
+At the beginning of input, music context is assumed.
+</P>
+<P>
+Here is a more complicated example:
+<BR><PRE>
+score
+       staffs=2
+       key=3&amp;
+       time=2/4
+
+music
+1: ceg;;
+2: 2c;
+bar
+</PRE><BR>
+<IMG SRC="mugex5.gif" ALT="Picture of Mup output"><BR>
+This example starts by setting some parameters. First it states that this
+piece of music should be printed with two staffs, instead of the default of
+only one. Then it gives a key signature. Since there is no &quot;flat&quot; symbol
+on a standard computer keyboard, Mup uses the &quot;&amp;&quot; symbol for flat.
+The time signature is then set to 2/4.
+</P>
+<P>
+Next we find the keyword &quot;music,&quot; which indicates the end of parameters
+and the beginning of the music. Data is given for both staff 1 and staff 2.
+Staff 1 has two chords in the measure. The first is a C minor triad (it's
+minor since the key is three flats). No time value is specified for this
+chord. Since it is the very first chord of the piece, Mup cannot use the
+previous chord's time value, because there is no previous chord. 
+In this case, Mup falls back to using the denominator (bottom number)
+of the time signature,
+so the chord is a quarter note. Incidentally, if Mup has to back up to
+previous notes to deduce pitch and/or time values, it only goes back as far
+as the beginning of the current measure. That means the default time value
+for the first chord of every measure in this piece would be quarter note.
+The second chord on staff 1 is the same as the first, since only a semicolon
+is specified. 
+</P>
+<P>
+Staff 2 has only a single chord, consisting of a half note with pitch C.
+Mup checks to make sure the time values on each staff add up to the time
+signature--no more or less--and will print an error message if they don't.
+If you have something like a &quot;pickup&quot; measure, which doesn't add up to the
+time signature, you can specify &quot;space&quot; rather than a chord,
+to account for the rest of the time.
+</P>
+<P>
+Some parameters can be set on a per-staff basis as well as for the entire
+score. Mup also allows for
+<A HREF="param.html#vscheme">up to three independent voices on each staff,</A>
+and each voice can have parameters
+set that apply to only that voice. To get the
+value of a parameter, Mup always starts at the most specific place it could
+be defined and works toward the most general. In other words, it will first
+see if the parameter is set for the current voice. If not, it will see if
+it is set for the current staff. If not, it will use the value set for the
+entire score. Staff parameters are set in &quot;staff&quot; context, and voice parameters
+are set in &quot;voice&quot; context.
+As an example:
+<BR><PRE>
+score
+       staffs=3
+       key=1&amp;
+staff 2
+       key=2&amp;
+       clef=bass
+music
+1: 2f;a;
+2: 2c;f;
+3: 1f;
+bar
+</PRE><BR>
+<IMG SRC="mugex6.gif" ALT="Picture of Mup output"><BR>
+Staff 2 will have two flats, whereas the other staffs will have one flat.
+Staff 2 will use the bass clef, whereas the other staffs will use treble
+clef (since that is the default when none is specified).
+<A HREF="param.html">The complete list of Mup parameters</A>
+includes
+information about whether they can be set for an individual staff
+or voice, or just for the score as a whole.
+</P>
+<H2>
+Page headers and footers
+</H2>
+<P>
+Mup allows you to specify a
+<A HREF="headfoot.html">header and/or footer</A>
+to put on the first page,
+as well as a header and/or footer to use on subsequent pages. These can
+include a page number that will be incremented automatically as pages are
+printed. The headers and footers can be customized as you like, with
+different fonts and sizes of text and items centered or left or right
+justified. There is also a shortcut
+<A HREF="prnttext.html">"title" command</A>
+that can be used to create a canned format title. For example:
+<BR><PRE>
+title &quot;Three Blind Mice&quot;
+</PRE><BR>
+will create a centered title. You can also get left and right justified titles.
+</P>
+<H2>
+Lyrics
+</H2>
+<P>
+You can specify
+<A HREF="lyrics.html">lyrics</A>
+for as many verses as you like. They are specified
+somewhat like notes. As an example:
+<BR><PRE>
+1: 4e;d;2c;
+lyrics 1: 4;;2; &quot;Three blind mice,&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex7.gif" ALT="Picture of Mup output"><BR>
+This example describes the lyrics to go with staff 1. There are three lyric
+syllables, having time values of quarter note, quarter note, and half note.
+The actual syllables are given inside the double quotes.
+Incidentally, since in this example the time values for the lyrics
+are the same as those of the notes, the time values don't actually need to
+be specified; if no lyrics time values are given, Mup assumes they
+match the note time values.
+</P>
+<H2>
+Miscellaneous
+</H2>
+<P>
+Mup provides a way to
+<A HREF="textmark.html">print arbitrary text</A>
+(like &quot;allegro&quot;) and
+<A HREF="mussym.html">musical symbols</A>
+(like a fermata). It can also print
+<A HREF="phrase.html">phrase marks,</A>
+<A HREF="pedal.html">piano pedal marks,</A>
+etc. The placement of these items is specified in terms
+of &quot;counts&quot; into the measure. For example:
+<BR><PRE>
+boldital below 1: 3 &quot;mf&quot;;
+</PRE><BR>
+<IMG SRC="mugex8.gif" ALT="Picture of Mup output"><BR>
+tells Mup to print &quot;mf&quot; in bold-italics below staff 1, at count 3 of the
+measure.
+You can also print
+<A HREF="chrdattr.html#withlist">marks associated with specific chords.</A>
+All of these facilities are described in detail in following sections.
+</P>
+<H2>
+Displaying, printing, and playing music
+</H2>
+<P>
+Once you have an input file, you can run Mup on it to get the printed
+version of the music. Entering:
+<BR><PRE>
+mup <I>myfile</I>
+</PRE><BR>
+from a command line prompt or selecting Run &gt; Display from Mupmate
+will cause Mup to read <I>myfile</I>, which should contain text in the Mup
+input language. If there are no errors in <I>myfile</I>, PostScript output
+will be produced, which can be displayed on the screen or printed via
+Mupmate or other programs. Mup can also produce
+<A HREF="midi.html">MIDI output,</A>
+which can then be played on your speakers.
+</P>
+<P>
+If you are using Ghostscript, but without Mupmate,
+two utility programs are included with Mup
+for
+<A HREF="utilpgms.html">displaying and printing music</A>
+using Ghostscript.
+These are described in more detail in the next section.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="intro.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="running.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/brackmac.html b/mup/docs/uguide/brackmac.html
new file mode 100644 (file)
index 0000000..e1b8c60
--- /dev/null
@@ -0,0 +1,71 @@
+<HTML>
+<HEAD><TITLE>
+Bracketing notes across staffs
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="manual.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="crossbar.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Bracketing notes across staffs
+</H2>
+<P>
+In keyboard music, sometimes a bracket is drawn to indicate that
+notes from two staffs are to be played
+with the same hand. The bracket is really just a vertical line with short
+horizontal lines at each end. But if you need to make lots of brackets,
+a macro with parameters can be very helpful.
+<BR><PRE>
+score
+  staffs=2
+
+staff 2
+  clef=bass
+  vscheme=2f
+
+// Define a macro to draw a bracket to show that notes on two
+// different staffs are to be played with the same hand.
+// The parameters are location tags for the top and bottom notes
+// to be included in the bracket.
+define BRACK(TOP, BOT)
+// Draw a short horizontal line 0.5 stepsizes above the top note
+line (TOP.w - 2, TOP.n + 0.5) to (TOP.w - 1, TOP.n + 0.5)
+// Draw a vertical line from 0.5 stepsizes above the top note
+// to 0.5 stepsizes below the bottom note.
+// Do all the 'x' coordinates relative to the same note (in
+// this case the top), so that if the top and bottom chord happen
+// to be different widths, the line will still be vertical.
+line (TOP.w - 2, TOP.n + 0.5) to (TOP.w - 2, BOT.s - 0.5)
+// Draw short horizontal line just below and left of the bottom note.
+line (TOP.w - 2, BOT.s - 0.5) to (TOP.w - 1, BOT.s - 0.5)
+@
+
+music
+
+// For each chord that is to get a bracket, add some padding to
+// make sure there is enough room, and set a location tag
+// on the top and bottom notes.
+1: [pad 2] ce =a;[] df =b; [] d =c; [] ce =d;
+2: [pad 2] g =e; [] a =f; [] af =g; [] g =h;
+2 2: 2cc-; 4g-; cc-;
+// Now draw the brackets, using the tags as parameters
+BRACK (a, e)
+BRACK (b, f)
+BRACK (c, g)
+BRACK (d, h)
+bar
+</PRE><BR>
+<IMG SRC="mugex92.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+Note that Mup supports
+<A HREF="crossst.html">cross-staff stems, which is another way to notate a chord that is split</A>
+across two staffs, and may often be a better choice.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="manual.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="crossbar.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/breathmk.html b/mup/docs/uguide/breathmk.html
new file mode 100644 (file)
index 0000000..5665ac1
--- /dev/null
@@ -0,0 +1,32 @@
+<HTML>
+<HEAD><TITLE>
+Breath marks
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="slashmrk.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="heeltoe.html">next page --&gt;</A>
+</P>
+          
+<H2>
+Breath marks
+</H2>
+<P>
+A comma in a large font can be used as a breath mark.
+Something in the range of 20 to 30 points usually looks good;
+you can adjust to your preference.
+<BR><PRE>
+1: c;d;2e;
+rom (24) above all dist 0: 4.5 &quot;,&quot;;
+bar
+
+1: e;d;2c;
+bar
+</PRE><BR>
+<IMG SRC="mugex100.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="slashmrk.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="heeltoe.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/cadenza.html b/mup/docs/uguide/cadenza.html
new file mode 100644 (file)
index 0000000..8fb814a
--- /dev/null
@@ -0,0 +1,35 @@
+<HTML>
+<HEAD><TITLE>
+Cadenzas
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="multsong.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="trnspose.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Cadenzas
+</H2>
+<P>
+Cadenzas or cadenza-like passages are often written
+with an arbitrary number of notes per measure.
+One way to accomplish this is to use a
+<A HREF="tuplets.html">tuplet</A>
+with the appropriate number of notes.
+<BR><PRE>
+score
+       time = 3/4
+
+music
+
+1: { [cue]... 16g- bm;b-;c;d;e;f;g;a;b;a;g;f;e;d;c;b-;g- ebm;} 17n,2.;
+bar
+</PRE><BR>
+<IMG SRC="mugex97.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="multsong.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="trnspose.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/chant.html b/mup/docs/uguide/chant.html
new file mode 100644 (file)
index 0000000..16a68c1
--- /dev/null
@@ -0,0 +1,92 @@
+<HTML>
+<HEAD><TITLE>
+Chant
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="invisbar.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="sharehd.html">next page --&gt;</A>
+</P>
+          
+<H2>
+Chant
+</H2>
+<P>
+Here is an example that shows some techniques you might use when
+writing chant.
+<BR><PRE>
+1: 1a;
+lyrics 1: &quot;This&lt;^ is an example of one way&gt;&quot;;
+bar
+
+1: d;e;2f;
+lyrics 1: &quot;to do chant.&quot;;
+bar
+
+1: 1f;
+lyrics 1: &quot;when&lt;^ there are many words for a&gt;&quot;;
+bar
+
+1: d;f;2;
+lyrics 1: &quot;sin-gle note.&quot;;
+dblbar
+
+newscore
+// Note use of 'n' to not print the time signature
+score time=7/4n
+music
+1: a;;;b;g;2a;
+lyrics 1: &quot;When there are man-y notes,&quot;;
+bar
+
+score time=8/4n
+music
+1: d;e;f;e;f;8e;;2;
+lyrics 1: &quot;You might change the time sig-na-ture&quot;;
+bar
+
+score time=5/4n
+music
+1: a;e;;2d;
+lyrics 1: &quot;on ev-ery bar,&quot;;
+bar
+
+score time=7/4n
+music
+1: e;f;e;d;c;2d;
+lyrics 1: &quot;to match the syl-la-bles.&quot;;
+dblbar
+
+newscore
+
+score time=8/4n
+music
+// Note use of 'n' to not print tuplet number/bracket
+1: {d;e;f;g;e;2d;;}10n,1/2; 
+lyrics 1: &quot;You can al-so use tup-lets,&quot;;
+invisbar
+
+1: {f;g;e;2d;e;2.d;}9n,1/2;
+lyrics 1: &quot;A-long with in-vis-bars.&quot;;
+dblbar
+
+newscore
+
+score stemlen=0
+music
+
+1: d+;c+;b;g;2a;;
+lyrics 1: &quot;Set stem-len to ze-ro,&quot;;
+invisbar
+
+1: {f;2e;4d;c;1d;}9n,1/2;
+lyrics 1: &quot;to get stem-less notes.&quot;;
+endbar
+</PRE><BR>
+<IMG SRC="mugex89.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="invisbar.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="sharehd.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/chordinp.html b/mup/docs/uguide/chordinp.html
new file mode 100644 (file)
index 0000000..5ad1a46
--- /dev/null
@@ -0,0 +1,393 @@
+<HTML>
+<HEAD><TITLE>
+Specifying chords
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="music.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="noteattr.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Specifying chords
+</H2>
+<H3>
+Staff and voice
+</H3>
+<P>
+The description of the music for one voice begins with the staff and voice
+number, followed by a colon. For example:
+<BR><PRE>
+3 1:
+</PRE><BR>
+indicates that the remainder of the line contains musical information for voice
+1 of staff 3. If the &quot;voice&quot; number is omitted, voice 1 is assumed. Thus
+<BR><PRE>
+3:
+</PRE><BR>
+is equivalent to the previous example.
+Both the staff and voice can be given as a list. This may be useful if
+several staffs have the same notes, or multiple voices on a staff have the
+same notes. For example:
+<BR><PRE>
+1-4 2:         // voice 2 of staffs 1, 2, 3, and 4
+1,2,4:         // voice 1 of staffs 1, 2, and 4,
+1,3,6-7 1-2:   // voices 1 and 2 on staffs 1, 3, 6 and 7
+5-8 1,2:       // voices 1 and 2 on staffs 5, 6, 7, and 8
+</PRE><BR>
+</P>
+<P>
+If you want notes to go to one voice on some staffs
+and a different voice on others,
+this can be specified using an ampersand. For example:
+<BR><PRE>
+1 1 &amp; 3 2:
+</PRE><BR>
+will cause the music to go to voice 1 of staff 1 as well as to voice
+2 of staff 3. Various styles can be combined:
+<BR><PRE>
+// Voices 1 and 2 on staff 2,
+// as well as voice 2 on staff 4
+// and voice 1 on staffs 6, 7, and 9
+2 1-2 &amp; 4 2 &amp; 6-7,9 1:
+</PRE><BR>
+</P>
+<P>
+It is possible to have up to
+40
+<A HREF="param.html#staffs">staffs</A>
+and up to
+<A HREF="param.html#vscheme">three voices per staff.</A>
+While there can be voice crossings, in general voice 1 should be the &quot;top&quot;
+voice, voice 2 the &quot;bottom&quot; voice, and voice 3 the &quot;middle&quot; or &quot;extra&quot; voice.
+With the first two voices, Mup tries hard to avoid any &quot;collisions&quot;
+between notes, rests, and other things. Since voice 3 is an extra voice,
+there are some cases when overlap with the other voices
+is basically unavoidable, but there are some techniques
+discussed later that let you
+<A HREF="chrdattr.html">tweak placement</A>
+when necessary.
+</P>
+<P>
+As an alternative to this voice-at-a-time input style, there is
+also a chord-at-a-time input style, which will be covered
+<A HREF="altinp.html">later.</A>
+</P>
+<H3>
+Chord duration information
+</H3>
+<P>
+The rest of the line contains a list of chords, with a semicolon at the
+end of each chord. Each chord has a
+<A NAME="duration">time value.</A>
+The time values of all
+the chords in the line must add up to the
+<A HREF="param.html#time">time signature.</A>
+Time values are given as follows:
+<TABLE BORDER=4>
+<TR>
+<TD><B>Input</B></TD>  <TD><B>Meaning</B></TD>
+</TR>
+<TR>
+<TD>1/4</TD>   <TD>quadruple whole (not valid for notes)</TD>
+</TR>
+<TR>
+<TD>1/2</TD>   <TD>double whole</TD>
+</TR>
+<TR>
+<TD>1</TD>     <TD>whole</TD>
+</TR>
+<TR>
+<TD>2</TD>     <TD>half</TD>
+</TR>
+<TR>
+<TD>4</TD>     <TD>quarter</TD>
+</TR>
+<TR>
+<TD>8</TD>     <TD>eighth</TD>
+</TR>
+<TR>
+<TD>16</TD>    <TD>sixteenth</TD>
+</TR>
+<TR>
+<TD>32</TD>    <TD>thirty-second</TD>
+</TR>
+<TR>
+<TD>64</TD>    <TD>sixty-fourth</TD>
+</TR>
+<TR>
+<TD>128</TD>   <TD>128th</TD>
+</TR>
+<TR>
+<TD>256</TD>   <TD>256th</TD>
+</TR>
+</TABLE>
+
+</P>
+<P>
+Any of these time values can be followed by one or more dots, to indicate
+a dotted note. Each dot increases the time value by 50% of the preceding
+note or dot.
+</P>
+<P>
+It is also possible to specify time as two or more times to be added together.
+For example, 2+8 would indicate the time of a half note plus the time of
+an eighth note, or in other words, a half note tied to an eighth note.
+The expression can also include subtractions, like 2.-16. When subtractions
+are present, it isn't clear what time values you want Mup to use,
+so it will start with the largest possible time value and add enough
+additional chords to add up to the total. For example, if you were to use
+1-4, indicating a whole note minus a quarter note,
+Mup will use a dotted half note, even though there are a number of
+other ways to represent that total time, such as a half note tied to a
+quarter note.
+</P>
+<P>
+If a time value is not specified for the first chord in a measure for a
+given voice, the default timeunit value
+is used. You can set the default value using the
+<A HREF="param.html#timeunit">"timeunit" parameter</A>
+as described in the
+<A HREF="param.html">"Parameters" section.</A>
+If that parameter is not set, the default is the denominator (bottom
+number) of the
+<A HREF="param.html#time">time signature.</A>
+For chords after the first, if a time value is not specified, the time
+value for the previous chord is used.
+</P>
+<H3>
+Notes, rests, or spaces
+</H3>
+<P>
+<A NAME="letter">There are three kinds of "chords."</A>
+The first type consists of one or more
+pitches, given by the letters &quot;a&quot; through &quot;g&quot;.
+<A NAME="pitchpar">Parentheses</A>
+can be placed around the pitch if you want
+the note to be printed in parentheses.
+(If the pitch is modified by an
+<A HREF="chordinp.html#acc">accidental</A>
+or
+<A HREF="chordinp.html#oct">octave,</A>
+which will be
+discussed later, those must also be included inside the parentheses.)
+<A NAME="restspc">The second is a rest, which</A>
+is designated by the letter r. The third type is a &quot;space,&quot; designated
+by the letter s. Space is basically
+a placeholder that takes up time, but doesn't print anything. It is useful
+when a certain voice only has notes during part of the measure. It can also
+be useful for specifying &quot;pickup&quot; measures to account for the time before
+the first note in the measure. For example:
+<BR><PRE>
+// a pickup measure
+1: 2.s;8.c;16d;
+bar
+1: e;g;e;c;
+endbar
+</PRE><BR>
+<IMG SRC="mugex9.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+If all voices contain spaces, no space is actually taken up on output.
+Most of the time, this will be what you want. For example,
+when you are using space for a pickup, the
+space is just to add up to a measure, and you don't want any actual blank space
+at the beginning of the piece. Once in a while, however, you
+may want space to actually be allocated on output, perhaps
+to be able to allow space for some special notation. In that case,
+you prefix the &quot;s&quot; with a &quot;u&quot; to indicate an uncollapseable space.
+</P>
+<P>
+If a given voice is omitted for a particular measure,
+Mup defaults to a measure of space.
+</P>
+<H4>
+Measure duration
+</H4>
+<P>
+<A NAME="measdur">There is a special duration of "m," which means an entire measure.</A>
+It can only be used with a rest, space, or &quot;rpt&quot; (repeat). For example:
+<BR><PRE>
+1 1: mr;
+1 2: ms;
+</PRE><BR>
+</P>
+<P>
+A measure rest looks like a whole rest, but is centered in the measure.
+It should be used when a whole measure is a rest, regardless of the time
+signature.
+However, if you want to force use of a symbol other than the whole rest
+symbol, you can specify a duration before the mr, and the rest symbol for that
+duration will be drawn instead.
+<BR><PRE>
+4mr;   // use a quarter rest symbol
+1/4mr;  // use a quadruple whole rest symbol
+2.. mr;  // use a double-dotted half rest
+</PRE><BR>
+</P>
+<P>
+Using &quot;m rpt&quot; will cause the
+measure repeat symbol to be printed, indicating
+the measure is just like the previous measure. Measures repeats
+will automatically be numbered, unless the
+<A HREF="param.html#nummrpt">numbermrpt parameter</A>
+is set to n. If there is more than one voice, you only need to
+specify the mrpt on voice 1. If you do specify other voices as well,
+they must be either a mrpt or ms.
+<BR><PRE>
+1: c;d;e;f;
+bar
+
+// another measure just like the first
+1: m rpt;
+bar
+
+// the space between m and rpt is optional
+1: mrpt;
+bar
+</PRE><BR>
+<IMG SRC="mugex10.gif" ALT="Picture of Mup output"><BR>
+</P>
+<H4>
+Accidentals
+</H4>
+<P>
+<A NAME="acc">Each pitch letter in a chord may be followed by an accidental.</A>
+Valid accidentals are:
+<TABLE BORDER=4>
+<TR>
+<TD><B>Input</B></TD>  <TD><B>Meaning</B></TD>
+</TR>
+<TR>
+<TD><TT>#</TT></TD>    <TD>sharp</TD>
+</TR>
+<TR>
+<TD><TT>&amp;</TT></TD>        <TD>flat</TD>
+</TR>
+<TR>
+<TD><TT>x</TT></TD>    <TD>double sharp</TD>
+</TR>
+<TR>
+<TD><TT>&amp;&amp;</TT></TD>   <TD>double flat</TD>
+</TR>
+<TR>
+<TD><TT>n</TT></TD>    <TD>natural</TD>
+</TR>
+</TABLE>
+
+</P>
+<P>
+The accidental can be placed inside
+parentheses if you want it to be printed
+within parentheses.
+</P>
+<H4>
+Octave
+</H4>
+<P>
+<A NAME="oct">An octave indicator may be specified after the pitch letter</A>
+or optional accidental.
+The octave can be specified in either of two ways:
+absolute or relative. A number from 0 to 9 is
+used to specify an absolute octave. Octaves run from C up to B. Octave 4 is
+the octave starting on middle C. Octave 3 is the octave below that, etc.
+A relative octave is specified by one or more plus or minus signs, and
+indicates that number of octaves above or below the default octave. For
+example:
+<BR><PRE>
+c      // c in the default octave
+e++    // e two octaves above default octave
+f#---  // f# three octaves below default octave
+b&amp;6        // b flat in octave 6
+</PRE><BR>
+</P>
+<P>
+The default octave can be set using the
+<A HREF="param.html#defoct">"defoct" parameter,</A>
+which is described in the
+<A HREF="param.html">"Parameters" section.</A>
+If that parameter is not
+set, the default octave is the octave containing the note associated with
+the middle line of the staff, based on the current
+<A HREF="param.html#clef">clef.</A>
+In other words, the default octaves are:
+<TABLE BORDER=4>
+<TR>
+<TD><B>Clef</B></TD>   <TD><B>Octave</B></TD>
+</TR>
+<TR>
+<TD>frenchviolin</TD>  <TD>5</TD>
+</TR>
+<TR>
+<TD>8treble</TD>       <TD>5</TD>
+</TR>
+<TR>
+<TD>treble</TD>        <TD>4</TD>
+</TR>
+<TR>
+<TD>soprano</TD>       <TD>4</TD>
+</TR>
+<TR>
+<TD>mezzosoprano</TD>  <TD>4</TD>
+</TR>
+<TR>
+<TD>alto</TD>  <TD>4</TD>
+</TR>
+<TR>
+<TD>treble8</TD>       <TD>3</TD>
+</TR>
+<TR>
+<TD>tenor</TD> <TD>3</TD>
+</TR>
+<TR>
+<TD>baritone</TD>      <TD>3</TD>
+</TR>
+<TR>
+<TD>bass</TD>  <TD>3</TD>
+</TR>
+</TABLE>
+
+</P>
+<H3>
+Shorthand notations
+</H3>
+<P>
+<A NAME="shorthnd">If a chord is omitted, the values for the previous chord are reused. This</A>
+works for pitches, rests, and spaces. For normal,
+<A HREF="param.html#stlines">5-line staffs,</A>
+the pitches for the first chord of every measure
+must always be specified, since there is no previous chord.
+</P>
+<P>
+Putting all these things together, here are some examples:
+<BR><PRE>
+// Two eighth notes, each b#, followed by an eighth
+// note d, eighth note e, and half note e, with the
+// last 3 notes being in the next higher octave.
+1 1: 8b#; ; d+; e+; 2;
+
+// Whole note C-E-G chord in default octave
+// for voice 2 of staff 1
+1 2: 1ceg;
+
+// Four quarter notes on staff 2, voice 1.
+// The last is in the octave above the default octave.
+2: 4g; a; b; c+;
+</PRE><BR>
+<IMG SRC="mugex11.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+For
+<A HREF="param.html#stlines">1-line staffs,</A>
+it is never necessary to specify a pitch, since all notes
+go on the single staff line. You can, however, specify a pitch if you wish.
+The pitch will be ignored for the purposes of printing, but will be
+used for
+<A HREF="midi.html">MIDI output.</A>
+If you don't specify a pitch, it is arbitrarily set to middle C.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="music.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="noteattr.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/chrdattr.html b/mup/docs/uguide/chrdattr.html
new file mode 100644 (file)
index 0000000..a6b76b1
--- /dev/null
@@ -0,0 +1,392 @@
+<HTML>
+<HEAD><TITLE>
+Chord attributes
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="noteattr.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="midmeas.html">next page --&gt;</A>
+</P>
+          
+<H3>
+Chord attributes
+</H3>
+<P>
+<A NAME="attrib">There are optional attributes that are associated with an entire chord</A>
+rather than an individual note. These are put inside square brackets
+before the list of notes and the time value.
+There are several classes of information:
+<UL>
+<LI>
+<A HREF="chrdattr.html#chstyle">chord style (grace, cue, diam, or xnote)</A>
+<LI>
+<A HREF="chrdattr.html#shaped">head shape</A>
+<LI>
+<A HREF="chrdattr.html#withlist">symbols to be printed with a chord</A>
+<LI>
+<A HREF="chrdattr.html#slashes">slashes</A>
+<LI>
+<A HREF="chrdattr.html#stemdir">stem direction</A>
+<LI>
+<A HREF="chrdattr.html#stemlen">stem length</A>
+<LI>
+<A HREF="chrdattr.html#pad">padding</A>
+<LI>
+<A HREF="chrdattr.html#ctag">chord location tag</A>
+<LI>
+<A HREF="chrdattr.html#hoffset">horizontal offset</A>
+<LI>
+<A HREF="chrdattr.html#dist">rest distance</A>
+</UL>
+</P>
+<P>
+Each class of information is
+separated from the other by a semicolon. All classes are optional, and can
+occur in any order.
+</P>
+<H4>
+Chord style
+</H4>
+<P>
+<A NAME="chstyle">Several chord styles can be specified.</A>
+<A NAME="cue">Grace note chords are designated by the word "grace," or cue note chords by "cue."</A>
+Grace notes can be specified as any undotted time value of eighth note or
+shorter, but are treated as taking no time. The time value given is merely used
+to specify how many flags or beams to put on the grace note.
+You can also specify a quarter note grace note, which will be printed as a
+small, stemless note, as is used to show
+<A HREF="tabstaff.html#prebend">a "prebend" in guitar music.</A>
+(Actually, you can force a stem if you want, by specifying a
+<A HREF="chrdattr.html#stemlen">len, as is described later.)</A>
+Cue notes have time like regular notes, but they are printed smaller.
+If there are several grace notes in a row, they will be beamed automatically.
+However, you cannot mix quarter (stemless) grace notes with shorter ones.
+Cue notes follow the same beaming rules as regular notes.
+</P>
+<P>
+It is also possible to specify &quot;diam,&quot; or &quot;xnote.&quot;
+In the case of &quot;diam,&quot; the chords will be drawn with diamond-shaped notes,
+while with &quot;xnote,&quot; the chords will be
+drawn with X-shaped notes. A diamond shaped
+note head will be used for xnotes that are half note or longer.
+Here are some examples:
+<BR><PRE>
+[grace]
+<BR>
+[xnote]
+<BR>
+[cue; xnote]
+<BR>
+[diam]
+</PRE><BR>
+</P>
+<H4>
+Head shape
+</H4>
+<P>
+If you want to have the
+<A NAME="shaped">note heads in a chord</A>
+use a shape other than the
+normal shapes, you use hs followed by the name of the head shape in quotes.
+There is an entire
+<A HREF="shaped.html">section on shaped notes,</A>
+so only the basics are covered here. The xnote and diam
+<A HREF="chrdattr.html#chstyle">described above</A>
+are really just shorthands for two common head shapes.
+The method using hs lets you use many other note head styles,
+such as a slash, or triangle. 
+<BR><PRE>
+1: [hs &quot;righttri&quot;]cf; [hs &quot;slash&quot;]fa;
+</PRE><BR>
+</P>
+<P>
+The
+<A HREF="shaped.html">section on shaped notes</A>
+lists all the builtin head shape names,
+and explains how you can define your own.
+</P>
+<H4>
+Symbols to be printed with a chord
+</H4>
+<P>
+<A NAME="withlist">It is possible to specify one or more musical symbols or text strings to be printed with a chord.</A>
+This is typically used for
+things like staccato and accent marks. The word &quot;with&quot; 
+is followed by one or more things to print. If there are more than one, they
+are separated by commas. They will be printed outwards from the notes in
+the order specified.
+The &quot;with&quot; list is only allowed on note groups, not rests.
+The list can include symbols from the following table:
+<TABLE BORDER=4>
+<TR>
+<TD><B>Symbol</B></TD> <TD><B>Meaning</B></TD>
+</TR>
+<TR>
+<TD><TT>.</TT></TD>    <TD>staccato</TD>
+</TR>
+<TR>
+<TD><TT>-</TT></TD>    <TD>legato</TD>
+</TR>
+<TR>
+<TD><TT>&gt;</TT></TD> <TD>accent</TD>
+</TR>
+<TR>
+<TD><TT>^</TT></TD>    <TD>accent</TD>
+</TR>
+</TABLE>
+
+</P>
+<P>
+<A HREF="textstr.html">A quoted string</A>
+can also be specified (e.g., &quot;ff&quot;, &quot;adagio&quot;, etc.).
+This will be printed in the font and size specified by the
+<A HREF="param.html#fontfam">"fontfamily,"</A>
+<A HREF="param.html#font">"font,"</A>
+and
+<A HREF="param.html#size">"size"</A>
+parameters. Any of the
+<A HREF="textstr.html#symlist">special music characters can be printed by using the usual convention,</A>
+e.g., \(ferm) for a fermata.
+(This is described in a
+<A HREF="textstr.html">later section.)</A>
+However, it is usually preferable to use the printing of
+<A HREF="textmark.html">text strings relative to beats.</A>
+</P>
+<P>
+Here are some examples:
+<BR><PRE>
+[with ., -]
+[with ^, &quot;\(ferm)&quot;]
+[with &quot;sfz&quot;; cue]
+</PRE><BR>
+</P>
+<P>
+If the symbols acc_hat, ferm, or wedge are used by themselves in a &quot;with&quot;
+list item, they are handled specially. If the stem direction is such that
+the upside down versions of these characters should be used, the upside down
+version will be used.
+</P>
+<H4>
+Slashes
+</H4>
+<P>
+<A NAME="slashes">Diagonal lines to be drawn through the stem of the group</A>
+can be specified using
+<BR><PRE>
+slash <I>N</I>
+</PRE><BR>
+where <I>N</I> is the number of slashes to draw. In the case of
+<A HREF="chrdattr.html#chstyle">grace notes,</A>
+<I>N</I> can only be 1, which will produce a grace note with a slash through it.
+In the case of other notes, <I>N</I> can be 1 or greater, and is used to
+specify tremolo or repetition of the note group. Examples:
+<BR><PRE>
+[slash 2]
+[grace; slash 1]
+</PRE><BR>
+</P>
+<H4>
+Stem direction
+</H4>
+<P>
+The chord stem direction can be specified as &quot;up&quot; or &quot;down&quot;.
+<A NAME="stemdir">Normally Mup chooses the stem direction, but once in a while you</A>
+may want to override its choice. There are some restrictions.
+You cannot specify a direction on grace notes. All chords beamed
+together and the pair of chords in an
+<A HREF="ichdattr.html#alt">alternation pair</A>
+(described later)
+must have the same stem direction.
+Examples:
+<BR><PRE>
+[up]
+[down]
+</PRE><BR>
+</P>
+<P>
+For voice 3, stem direction works a little differently. By default, the
+stem direction for voice 3 is up,
+but for voice 3 on any given staff, when you specify a stem
+direction, that direction will remain in effect until explicitly changed.
+Thus, for example, if you want all voice 3 stems on a given staff
+in an entire song to
+be down, you only need to specify &quot;[down]&quot; on the first chord.
+</P>
+<H4>
+Stem len
+</H4>
+<P>
+<A NAME="stemlen">Normally, Mup sets stem lengths as appropriate, but sometimes you might</A>
+want to make a stem longer or shorter than normal. This is done with
+the keyword &quot;len&quot; followed by a length in stepsizes.
+Some examples:
+<BR><PRE>
+[ len 14 ]
+[ len 7; up ]
+</PRE><BR>
+</P>
+<P>
+You cannot specify stem length on chords inside of beams.
+The len can be set to 0 to produce a note head with no stem at all.
+</P>
+<P>
+There is a
+<A HREF="param.html#stemlen">stemlen parameter</A>
+that can be used to set the default stem length.
+If you don't want any stems, setting that parameter to 0 is more
+convenient than setting len to 0 on each chord individually.
+</P>
+<P>
+On beamed chords, Mup will sometimes shorten a stem slightly
+from its normal minimum length. By default it will never shorten by
+more than one stemsize, but there is a
+<A HREF="param.html#sshorten">stemshorten parameter</A>
+that lets you adjust how much it will shorten. If you don't want Mup
+to ever shorten stems, you can set this parameter to zero.
+</P>
+<H4>
+Padding
+</H4>
+<P>
+Sometimes it may be desirable to space notes somewhat differently than
+Mup would normally place them.
+<A NAME="pad">It is possible to specify "padding" before any note group.</A>
+This is done by specifying the word &quot;pad&quot; followed
+by a number of stepsizes of white space padding to add before the chord.
+The number can be fractional, as in 0.5 or 2.25.
+For example:
+<BR><PRE>
+[ pad 2.5 ]
+</PRE><BR>
+</P>
+<P>
+The padding can also be negative. Padding affects the minimum amount of
+width allocated to a chord, so you can use positive padding values to
+force additional room in front of a chord, or negative padding to allow
+things closer together.
+</P>
+<H4>
+Chord location tag
+</H4>
+<P>
+<A NAME="ctag">It is possible to set a location tag</A>
+which is
+associated with an entire chord
+rather than an individual note. This
+<A HREF="tags.html">tag</A>
+is specified like
+<A HREF="noteattr.html#ntag">location tags for notes,</A>
+with an &quot;=&quot; followed by a name, but is inside
+the square brackets rather than after a note.
+<BR><PRE>
+3: 2cf; [=h] egc+;
+1: [cue; with &gt;; =_ch] fa;
+</PRE><BR>
+</P>
+<H4>
+Horizontal offset
+</H4>
+<P>
+<A NAME="hoffset">A horizontal offset can be applied to a chord by specifying "ho" followed</A>
+by a number of stepsizes. The number can be positive or negative,
+and can include a fractional part. A positive number will cause the chord to
+be placed that far right of where the horizontal center of the chord
+would normally be; a negative number will place it that far to the left.
+It is also possible to simply specify a &quot;+&quot; or &quot;-&quot; which says to place the
+chord to the right or left,
+as close as possible without running into something.
+</P>
+<P>
+A horizontal offset is most commonly used on the third voice of a staff,
+although it can be used on other voices too.
+By default, Mup places third
+voice chords as close as it thinks is safe for avoiding
+most collisions. Sometimes it may actually be okay visually
+to place the chord a little closer than that,
+or perhaps there is a better &quot;nook&quot; to tuck it into on the left side.
+By specifying a horizontal offset, you can place chords anywhere you want.
+Mup makes no checks to avoid collisions when you specify a horizontal
+offset, so this attribute needs to be used with some care.
+</P>
+<P>
+Here is an example of the use of horizontal offset and stem direction
+on voice 3.
+<BR><PRE>
+score
+  vscheme=3f
+
+music
+1 1: c+;b;a;c+;
+1 2: e;d;e;f;
+1 3: [ho+1] g; [ho-5.2; down]; [ho-] f; [ho+; up] a;
+bar
+</PRE><BR>
+<IMG SRC="mugex16.gif" ALT="Picture of Mup output"><BR>
+</P>
+<H4>
+Rest distance
+</H4>
+<P>
+<A NAME="dist">Usually Mup's placement of rests is satisfactory, but once in a while</A>
+you might want to force a rest to be placed a little higher or lower
+than Mup would place it. You can specify a &quot;dist&quot; which is the number
+of stepsizes from the center of the staff to place the rest symbol,
+with positive numbers being above the center and negative numbers below.
+If the staff is
+<A HREF="param.html#xpose">transposed,</A>
+the placement of the rest symbol will be adjusted accordingly.
+<BR><PRE>
+// The first and last rests are in normal position.
+// The second is forced higher, the third is forced lower.
+1: r; [dist 6]; [dist -4]; r;
+bar
+</PRE><BR>
+<IMG SRC="mugex17.gif" ALT="Picture of Mup output"><BR>
+</P>
+<H4>
+Repeated attributes
+</H4>
+<P>
+<A NAME="rptattr">If two or more chords in a row have the same bracketed attributes,</A>
+there are two shorthand notations. Specifying an empty set of brackets &quot;[]&quot;
+means to use the same attributes as were specified on the previous chord.
+The previous chord must be within the same measure.
+Some examples:
+<BR><PRE>
+1: [cue] 4c;[]d;[grace; slash 1] 8f;2e;
+bar
+
+1: d; [with .,-]d; []e; []f;
+bar
+</PRE><BR>
+<IMG SRC="mugex18.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+The other shorthand is to put 3 dots after a set of bracketed items.
+This means to repeat the same bracketed items on all chords for the
+rest of the measure, or until a new set of bracketed items is specified.
+If you wish to cancel this before the end of a measure but without
+specifying a new set, the special set &quot;[-]&quot; can be used.
+<BR><PRE>
+// put staccato marks on all notes
+1: [with .]... c; d; e; g;
+bar
+// put several cue size notes in the middle of a measure
+1: c; [cue]... 8d; f; e; g; [-] 4c+;
+bar
+</PRE><BR>
+<IMG SRC="mugex19.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+You can use more than one set of backets on a single chord.
+For example &quot;[len 5][down]&quot; and &quot;[len 5;down]&quot; are equivalent.
+However, [-] can only be used by itself, and if you want to use [] along
+with another backeted set of items (to duplicate the items on the previous
+chord plus add some more), the empty [] needs to be first, before the
+other set of items.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="noteattr.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="midmeas.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/cmdargs.html b/mup/docs/uguide/cmdargs.html
new file mode 100644 (file)
index 0000000..0e9c601
--- /dev/null
@@ -0,0 +1,409 @@
+<HTML>
+<HEAD><TITLE>
+Mup Options
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="running.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="utilpgms.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Mup Options
+</H2>
+<P>
+Mup accepts a number
+of options.
+When invoking Mup from a command line,
+the options are specified by a dash followed by a letter.
+On Windows/MS-DOS
+systems, you can substitute a slash instead of the dash.
+If you are using Mupmate, you will use the &quot;Set Options&quot; form off
+of the &quot;Run&quot; menu to set the options.
+You just fill values into the form, and Mupmate will 
+take care of the details of running Mup with your values,
+so you won't use the dash and letter shown below at all.
+Some of the options listed below are not available from Mupmate,
+either because they are meant for debugging, and thus not generally
+of interest to most users, or because Mupmate handles the appropriate
+details automatically.
+The options to the mup command (in alphabetical order) are:
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<A NAME="coption"><B>-c</B> <I>N</I></A>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Run &gt; Set Options &gt; Enable Auto Multirest and Min Measures to Combine
+<BR>&nbsp;&nbsp;<BR>
+
+Combine consecutive measures of all rests or spaces into
+<A HREF="multirst.html">multirests</A>
+(multiple measures of rest printed as a single measure,
+usually with the number of
+<A HREF="param.html#prmultn">measures of rest printed</A>
+above the staff).
+Any time there
+are <I>N</I> or more measures in a row that consist entirely of rests or spaces,
+they will be replaced by a multirest. The combining of measures 
+stops when there is a visible staff that contains notes
+or lyrics, or that contain
+<A HREF="textmark.html">text</A>
+or
+<A HREF="mussym.html">musical symbols</A>
+after the first beat of the measure,
+or when there are
+<A HREF="param.html">parameter changes</A>
+on a visible staff or in score context that
+<A HREF="param.html#visible">change</A>
+<A HREF="param.html#clef">clef,</A>
+<A HREF="param.html#key">key,</A>
+or
+<A HREF="param.html#time">time signature,</A>
+or when there is a
+<A HREF="bars.html">bar line</A>
+other than an ordinary bar.
+This option is most likely to be useful when printing a subset of staffs,
+where the particular staff(s) you are printing have long periods of rests.
+See information about
+<A HREF="cmdargs.html#soption">the -s option</A>
+and the
+<A HREF="param.html#visible">"visible" parameter</A>
+below.
+This option overrides the
+<A HREF="param.html#restcomb">restcombine parameter.</A>
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<B>-C</B>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Option not available (only used for debugging).
+<BR>&nbsp;&nbsp;<BR>
+
+This option is only used in connection with
+<A HREF="cmdargs.html#Eoption">the -E option.</A>
+It specifies that comments
+are to be passed through rather than deleted.
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<A NAME="dbgoption"><B>-d</B> <I>N</I></A>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Option not available (only used for debugging).
+<BR>&nbsp;&nbsp;<BR>
+
+Print debugging information. <I>N</I> is a bitmap, so you can turn on multiple
+debugging levels by adding up the flag values. For example, if you want to
+turn on both level 2 and level 4 tracing, <I>N</I> would be 6 (because 2+4=6).
+<DL>
+<DT>1
+<DD>
+input syntax/grammar analysis tracing
+<DT>2
+<DD>
+high level parse phase tracing
+<DT>4
+<DD>
+low level parse phase tracing
+<DT>8
+<DD>
+reserved
+<DT>16
+<DD>
+high level placement phase tracing
+<DT>32
+<DD>
+low level placement phase tracing
+<DT>64
+<DD>
+reserved
+<DT>128
+<DD>
+contents of the main internal list
+<DT>256
+<DD>
+high level print or MIDI phase tracing
+<DT>512
+<DD>
+low level print or MIDI phase tracing
+</DL>
+<I>N</I> can be specified in decimal, octal
+(by using a leading zero), or hex (by using a leading 0x).
+This information is intended for debugging of
+Mup itself and thus is not likely to be of use to the average user,
+and is not available from Mupmate.
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<A NAME="doption"><B>-D</B> <I>MACRO[=macro-def]</I></A>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Run &gt; Set Options &gt; Macro Definitions
+<BR>&nbsp;&nbsp;<BR>
+
+Define
+the
+<A HREF="macros.html">macro</A>
+<I>MACRO</I>. The macro name must consist of
+upper case letters, digits, and underscores, beginning
+with an upper case letter. The <I>macro_def</I> is optional, and gives the
+text of the macro. On UNIX, Linux, or similar
+systems, if it contains any white space
+or other special characters, it must be quoted. On other systems, white
+space may not be allowed.
+The -D option can be specified multiple times, if you wish to
+define more than one macro.
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<B>-e</B> <I>errfile</I>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Option not needed. Mupmate automatically saves and displays error output.
+<BR>&nbsp;&nbsp;<BR>
+
+Place the error message output into <I>errfile</I> instead of writing it to
+the standard error output stream.
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<A NAME="Eoption"><B>-E</B></A>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Option not needed (only used for debugging).
+<BR>&nbsp;&nbsp;<BR>
+
+Rather than produce PostScript or MIDI output, just expand
+macros
+and includes,
+and write the result to the standard output stream.
+Comments in the input are deleted, unless the -C option is also specified.
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<B>-f</B> <I>outfile</I>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Option not needed. Mupmate automatically creates appropriate output file.
+<BR>&nbsp;&nbsp;<BR>
+
+Place the PostScript output into <I>outfile</I> instead of writing to
+the standard output.
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<A NAME="Foption"><B>-F</B></A>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Run &gt; Write PostScript File
+<BR>&nbsp;&nbsp;<BR>
+
+This is like the <B>-f</B> option, except the name of the output file is
+derived from the name of the Mup input file. If the name of the Mup input
+file ends with a &quot;.mup&quot; suffix, the generated PostScript output
+file will end with a &quot;.ps&quot; suffix instead.
+If the name of the Mup input file ends with
+a &quot;.MUP&quot; suffix, the PostScript file will end with a &quot;.PS&quot; suffix.
+Otherwise, a &quot;.ps&quot; suffix will be appended to the end of the Mup
+input file name. If multiple input files are listed, the last is used.
+If none are specified (input is read from standard input),
+the name &quot;stdin.ps&quot; will be used for the output file.
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<A NAME="moption"><B>-m</B> <I>midifile</I></A>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Option not needed. Mupmate automatically creates appropriate output file.
+<BR>&nbsp;&nbsp;<BR>
+
+Instead of generating PostScript output,
+generate standard
+<A HREF="midi.html">MIDI (Musical Instrument Digital Interface) output,</A>
+and put it in <I>midifile</I>.
+This option also causes the
+<A HREF="macros.html">macro</A>
+&quot;MIDI&quot; to become defined.
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<B>-M</B>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Run &gt; Write MIDI File
+<BR>&nbsp;&nbsp;<BR>
+
+This is like the <B>-m</B> option, except the name of the MIDI file is
+derived from the name of the Mup input file. If the name of the Mup input
+file ends with a &quot;.mup&quot; suffix, the generated MIDI file will end with
+a &quot;.mid&quot; suffix instead. If the name of the Mup input file ends with
+a &quot;.MUP&quot; suffix, the MIDI file will end with a &quot;.MID&quot; suffix.
+Otherwise, a &quot;.mid&quot; suffix will be appended to the end of the Mup
+input file name. If multiple input files are listed, the last is used.
+If none are specified (input is read from standard input),
+the name &quot;stdin.mid&quot; will be used for the MIDI file.
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<A NAME="ooption"><B>-o</B> <I>pagelist</I></A>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Run &gt; Set Options &gt; Pages to Display
+<BR>&nbsp;&nbsp;<BR>
+
+Print only the pages
+given in <I>pagelist</I>. The <I>pagelist</I> can be
+a comma-separated list of numbers or ranges, where a range is two numbers
+separated by a dash. For example, -o1,7-9,12-14 would print pages 1, 7, 8,
+9, 12, 13, and 14. Alternately, the <I>pagelist</I> can be the special
+keyword &quot;odd&quot; or &quot;even&quot; which will cause all odd or even numbered pages
+to be printed. This may be useful if you have a printer that only makes
+single-sided copies, but you wish to print Mup output double-sided. You could
+print odd-numbered pages, then turn the paper over and feed the pages
+through again for the even-numbered pages. 
+Pages will be printed in the order specified, so you can print pages in
+other than ascending order if you wish, or even print the same page
+more than once. Printing pages in non-ascending order is most likely to
+be useful when printing more than one page of music on a single physical
+page, using the
+<A HREF="param.html#panels">panelsperpage parameter.</A>
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<A NAME="poption"><B>-p</B> <I>N</I></A>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Run &gt; Set Options &gt; First Page's Page Number
+<BR>&nbsp;&nbsp;<BR>
+
+Start numbering pages
+at <I>N</I> instead of at 1.
+This can be set inside the Mup input file
+with
+<A HREF="param.html#firstpg">the "firstpage" parameter,</A>
+but the command line option will override the parameter.
+If <B>-o</B> and <B>-p</B> are used together, the page numbers given in the
+<B>-o</B><I>pagelist</I> must be the printed page numbers. For example, if you
+use -p10 and want to print just the second page,
+you would need to specify -o11.
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<B>-r</B>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Config &gt; Registration Form
+<BR>&nbsp;&nbsp;<BR>
+
+Print a copy of the
+<A HREF="register.html">Mup shareware registration form</A>
+to standard output.
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<A NAME="soption"><B>-s</B> <I>stafflist</I></A>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Run &gt; Set Options &gt; Staffs to Display/Play
+<BR>&nbsp;&nbsp;<BR>
+
+Only print the staffs that are included in <I>stafflist</I>.
+The <I>stafflist</I> can be a
+comma-separated list of staff numbers or ranges, such as &quot;1,5&quot; or &quot;1-3,7-8&quot;
+but no spaces are allowed in the list.
+If the -m or -M option is also used, to produce
+<A HREF="midi.html">MIDI output,</A>
+this option controls which staffs are played rather than which
+are printed.
+If you want only a single voice to be printed or played, you can follow
+a staff number or range with <B>v1</B> or <B>v2</B> or <B>v3</B>
+to restrict to voice 1, 2 or 3
+respectively, such as &quot;1v2&quot; or &quot;1-4v1,5-6v2&quot;. Otherwise
+all voices on the staff are printed or played. 
+You can't specify a list or range for voices;
+if you only want to make two out of three voices visible,
+you have to specify them separately, like &quot;1v2,1v3&quot;.
+<A HREF="param.html#visible">See also the "visible" parameter.</A>
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<B>-v</B>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Help &gt; About Mupmate
+<BR>&nbsp;&nbsp;<BR>
+
+Print the Mup version number. When invoked from command line,
+Mup will then exit. This document is for version 5.3.
+<HR>
+<CODE>Command line:&nbsp;</CODE>
+<A NAME="xoption"><B>-x</B><I>M</I><B>,</B><I>N</I></A>
+<BR>
+<CODE>Mupmate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</CODE>
+Run &gt; Set Options &gt; Extract Measures
+<BR>&nbsp;&nbsp;<BR>
+
+Extract measures <I>M</I> through <I>N</I> of the song. This allows you to print
+or play a part of a song. The comma and second value are optional;
+if not specified, the default is to go to the end of the piece.
+Positive values specify the number of measures from the beginning of the piece,
+while negative values are relative to the end, with -1 referring to the
+last measure of the song.
+So -x1,-1 means the entire song, if the song doesn't have a pickup measure.
+If the song has a pickup measure, that is specified by 0.
+So for a song with a pickup, -x0,-1 would mean the entire song,
+and -x0,0 would mean just the pickup measure.
+As other examples, -x-1,-1 means just the final measure of the song,
+-x2 means starting after the first full measure, -x3,4 means only
+measures 3 and 4, and -x6,6 means just measure 6.
+The starting measure is not allowed to be inside an ending.
+A common use for this option might be to
+<A HREF="midi.html">generate a MIDI file</A>
+for just a few measures. For example, if you were
+trying to tweak tempo values for a ritard in the last 2 measures of a song,
+you could use -x-2 to listen to just those measures.
+<HR>
+</P>
+<P>
+When invoked from command line, the options, if any,
+can be followed by one or more <I>files</I> in the format
+described in this User's Guide. If no <I>files</I> are specified,
+standard input is read.
+If several <I>files</I> are listed, they are effectively concatenated together
+and treated as one big file. Since there are some things (such as
+<A HREF="headfoot.html">header and footer)</A>
+that are only allowed to occur once, if you have several independent
+pieces, Mup should be called on each individually rather than trying to
+print them all with one command.
+If a specified file does not exist, and its name does not already end
+with .mup or .MUP, then Mup will append .mup to the specified name and
+attempt to open that.
+</P>
+<P>
+If you just want to create a PostScript output file, for printing on a
+PostScript printer, or viewing with a tool such as GSview, you can
+use the -f option, as in
+<BR><PRE>
+    mup -f outfile.ps infile.mup
+</PRE><BR>
+Or on Unix, Linux or MS-DOS command window,
+you could redirect the output into a
+file using the &gt; character, as in:
+<BR><PRE>
+    mup infile.mup &gt; outfile.ps
+</PRE><BR>
+</P>
+<P>
+For more debugging, in addition to the
+<A HREF="cmdargs.html#dbgoption">-d option,</A>
+if the environment variable MUP_BB is set to &quot;bcfgnsu&quot; or any subset
+of those letters, the generated output will include &quot;bounding
+boxes&quot; for the things Mup internally calls bars (b), chords (c), feeds (f),
+grpsyls (g), header/footer and top/bottom (h),
+notes (n), staffs (s), and stuff (u).
+While this is intended for use in debugging Mup itself, it may also
+help you understand why Mup places things the way it does,
+since in general, Mup only allows bounding boxes to overlap according
+to specific rules. If viewed with a color PostScript viewer (not
+<A HREF="utilpgms.html">mupdisp,</A>
+which is covered below), these boxes will be in color.
+<BR>
+<HR>
+* UNIX is a registered trademark of X/Open Company Limited
+<BR>
+MS-DOS and Windows are registered trademarks of Microsoft Corporation
+<BR>
+PostScript is a trademark of Adobe Systems Incorporated
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="running.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="utilpgms.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/contexts.html b/mup/docs/uguide/contexts.html
new file mode 100644 (file)
index 0000000..2a145c7
--- /dev/null
@@ -0,0 +1,135 @@
+<HTML>
+<HEAD><TITLE>
+Mup Contexts
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="gensyn.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="music.html">next page --&gt;</A>
+</P>
+            
+<H2>
+Contexts
+</H2>
+<P>
+There is always a current Mup &quot;context&quot; that is in effect.
+When Mup begins reading input, it is operating in &quot;music&quot; context, which
+is where music, lyrics, barlines, and other related things
+are described. You can change to another
+context by entering its name. A context remains in effect until
+another context is named.
+The contexts are:
+<DL>
+<DT>
+<A HREF="headfoot.html">header</A>
+<DD>
+to define what goes at the top of the first page, typically
+the title, composer, etc.
+<DT>
+<A HREF="headfoot.html">footer</A>
+<DD>
+to define what goes at the bottom of the first page,
+typically a copyright notice, performance notes, etc.
+<DT>
+<A HREF="headfoot.html">header2</A>
+<DD>
+to define what is to be printed on the top of pages after the first page.
+<DT>
+<A HREF="headfoot.html">footer2</A>
+<DD>
+to define what is to be printed on the bottom of pages after the first page.
+<DT>
+<A HREF="headfoot.html">top</A>
+<DD>
+to define what is to be printed on the top of page.
+This gets printed below the header (or header2), if any.
+If the output is not already at the beginning of a new page,
+a new page is started.
+Unlike header, which can only be used once, and is used only on the very
+first page, top can be used multiple times. In a song with multiple movements,
+you might use top to put a title at the beginning of each movement.
+<DT>
+<A HREF="headfoot.html">bottom</A>
+<DD>
+to define what is to be printed on the bottom of page.
+This gets printed above the footer (or footer2), if any.
+If the output is not already at the beginning of a new page,
+a new page is started.
+Unlike footer, which can only be used once, and is used only on the very
+first page, bottom can be used multiple times.
+<DT>
+<A HREF="headfoot.html">top2</A>
+<DD>
+to define what is to be printed on the top of pages
+after the page that uses &quot;top.&quot;
+If the output is not already at the beginning of a new page,
+a new page is started.
+<DT>
+<A HREF="headfoot.html">bottom2</A>
+<DD>
+to define what is to be printed on the bottom of pages
+after the page that uses &quot;bottom.&quot;
+If the output is not already at the beginning of a new page,
+a new page is started.
+<DT>
+<A HREF="prnttext.html#block">block</A>
+<DD>
+to define a block that contains text rather than music.
+<DT>
+score
+<DD>
+to define
+<A HREF="param.html">parameters</A>
+that apply to the entire score.
+<DT>
+staff <I>S</I>
+<DD>
+to define
+<A HREF="param.html">parameters</A>
+to be used for staff <I>S</I>,
+where <I>S</I> is a number from 1 to 40.
+<DT>
+voice <I>S V</I>
+<DD>
+to define
+<A HREF="param.html">parameters</A>
+for a particular voice <I>V</I> on staff <I>S</I>.
+The voice <I>V</I> can be either 1, 2, or 3.
+<I>S</I> is a staff number from 1 to 40.
+<DT>
+<A HREF="textmark.html#grids">grids</A>
+<DD>
+to define grids (typically for guitar)
+<DT>
+<A HREF="shaped.html">headshapes</A>
+<DD>
+to define what note head shapes to use for notes of various durations.
+This context is rarely used, and is described in the chapter on
+<A HREF="shaped.html">shaped notes.</A>
+<DT>
+<A HREF="music.html">music</A>
+<DD>
+to define everything else. This includes
+<A HREF="chordinp.html">notes,</A>
+<A HREF="lyrics.html">lyrics,</A>
+<A HREF="bars.html">bar lines,</A>
+<A HREF="phrase.html">phrase marks,</A>
+<A HREF="textmark.html">tempo and dynamic marks, etc.</A>
+</DL>
+</P>
+<P>
+Most contexts are optional. An input file
+just needs to contain either at least one measure of music
+or at least one
+<A HREF="prnttext.html#block">block.</A>
+<A HREF="headfoot.html">The \fBheader, footer, header2,\fP and \fBfooter2\fP</A>
+contexts may be placed anywhere in the file, but each can be used only once.
+The other contexts may appear any number of times
+in any order, and the order in which they occur is significant in
+determining the output produced.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="gensyn.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="music.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/cres.html b/mup/docs/uguide/cres.html
new file mode 100644 (file)
index 0000000..df494d6
--- /dev/null
@@ -0,0 +1,45 @@
+<HTML>
+<HEAD><TITLE>
+Crescendo and decrescendo marks
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="phrase.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="octave.html">next page --&gt;</A>
+</P>
+           
+<H2>
+Crescendo and decrescendo marks
+</H2>
+<P>
+The &quot;&lt;&quot; and &quot;&gt;&quot; statements are used to specify crescendo and decrescendo marks
+respectively. Each mark must include a begintime and duration.
+The begintime can include a grace back up specification,
+to make the mark apply to grace notes.
+Some examples:
+<BR><PRE>
+1-2: c;d;e;f;
+&lt; below 1: 1 til 2; 3 til 4.5;
+3: 2c;g;
+&gt; between 2&amp;3: 1.7 til 2m + 1;
+bar
+1-2: d;e;2g;
+3: 2d;a;
+&lt; 2,3: 2 til 3.8;
+bar
+1-2: e;g;2c;
+3: 2.e;4c;
+endbar
+</PRE><BR>
+<IMG SRC="mugex75.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+The placement of crescendo and decrescendo marks can be controlled
+by setting the
+<A HREF="param.html#dyndist">dyndist parameter.</A>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="phrase.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="octave.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/crossbar.html b/mup/docs/uguide/crossbar.html
new file mode 100644 (file)
index 0000000..dbe709c
--- /dev/null
@@ -0,0 +1,73 @@
+<HTML>
+<HEAD><TITLE>
+Cross-bar beaming
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="brackmac.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="mixtsig.html">next page --&gt;</A>
+</P>
+          
+<H2>
+Cross-bar beaming
+</H2>
+<P>
+Generally, beams do not cross bar lines, and Mup follows that rule.
+However, if you want beams to cross a bar line, there are at least two
+possible approaches to getting the
+desired effect. The first is to explicitly specify
+<A HREF="chrdattr.html#stemlen">stem lengths</A>
+such that all the beams in the various measures will lie on the same line.
+You can then use the
+<A HREF="linecurv.html">line command</A>
+to fill in the gaps in the beams across the bar lines.
+</P>
+<P>
+The other approach is to draw in the bar line using the &quot;line&quot; construct.
+To do this you first tell Mup that a measure is twice as long as is really
+is, so that you can put two actual measures inside what Mup thinks is a
+single measure. Here is an example.
+<BR><PRE>
+// First make an empty measure ending with an
+// invisible bar. This is for the sole purpose
+// of allowing the real time signature to be
+// printed and would not be necessary if we
+// wanted to cross a bar line other than
+// the very first bar line of the piece.
+1: ms;
+invisbar
+
+// Now, make the effective time signature twice
+// as long as the real time signature, but use 'n' so this fake
+// time signature is not actually printed.
+// Set up for beaming across the entire double-length measure.
+// (You could could use other beamstyles if you wish, or custom beaming.)
+score time=8/4n
+beamstyle=1/2
+music
+
+// Now do the double-length measure. On the chord
+// just after where we want a bar line, add some extra
+// padding and set a location tag so that we can draw
+// a bar line relative to the tag.
+1: 8c;e;f;d;g;e;f;a; [pad 3; =a]g;e;f;a;g;d+;4c+;
+// Also set a location tag on the next bar line,
+// so that we can get the vertical endpoints of the
+// bar line that we draw from the endpoints of the
+// normal Mup-supplied bar line.
+bar =b
+
+// Now draw the bar line that goes through the beam.
+// Use the horizontal position relative to the &quot;a&quot;
+// location tag on the chord in the second actual measure,
+// and get the vertical endpoints from the &quot;b&quot; tag
+// associated with the next bar line.
+line (a.w + 1, b.y + 4) to (a.w + 1, b.y - 4)
+</PRE><BR>
+<IMG SRC="mugex93.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="brackmac.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="mixtsig.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/crossst.html b/mup/docs/uguide/crossst.html
new file mode 100644 (file)
index 0000000..8e32ac4
--- /dev/null
@@ -0,0 +1,63 @@
+<HTML>
+<HEAD><TITLE>
+Cross-staff stems
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="midmeas.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="ichdattr.html">next page --&gt;</A>
+</P>
+         
+<H3>
+Cross-staff stems
+</H3>
+<P>
+Sometimes, on music for instruments that use more than one staff,
+you may want some of the notes of a chord to be printed on
+the staff above or below, rather than using a lot of leger lines.
+You can specify this by putting the word &quot;with&quot; before the notes that
+are to go on the other staff, and following those notes with &quot;above&quot; or &quot;below&quot;
+to specify which is the other staff.
+For example:
+<BR><PRE>
+score
+       staffs=2
+staff 2
+       clef=bass
+music
+
+1: 1e+g+c++;
+2: cc+; ee+; g with g+ above; with c+c++ above;
+bar
+
+1: cc+; g with g- below; e with e- below; with cc- below;
+2: 1c-e-g-;
+bar
+</PRE><BR>
+<IMG SRC="mugex21.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+The notes for the other staff have to follow the notes on the normal staff in
+the input.  As is shown in the example,
+it is possible to have <I>all</I> the notes on the &quot;other&quot; staff, if you wish.
+The octave is specified as if the note were on the normal staff;
+Mup will automatically adjust appropriately for the other staff's clef.
+Once in a while, Mup may not be able to figure out how to completely
+avoid colliding with other notes; in that case you can use the
+<A HREF="chrdattr.html#hoffset">horizontal offset</A>
+that was described earlier.
+</P>
+<P>
+For
+<A HREF="midi.html">MIDI</A>
+purposes, only the normal staff's key signature and accidentals are
+considered, so if the other staff has a different
+<A HREF="param.html#key">key signature</A>
+or accidentals that should really apply to these notes, you will have
+to supply accidentals explicitly.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="midmeas.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="ichdattr.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/debug.html b/mup/docs/uguide/debug.html
new file mode 100644 (file)
index 0000000..bf675b8
--- /dev/null
@@ -0,0 +1,37 @@
+<HTML>
+<HEAD><TITLE>
+Mup debugging
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="param.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="adjust.html">next page --&gt;</A>
+</P>
+           
+<H2>
+Debugging
+</H2>
+<P>
+Since Mup requires its input in a fairly strict format, when a song is put
+in, it may contain &quot;typos.&quot; Generally, the error messages that Mup prints
+will give you an idea of what is wrong. However, sometimes Mup is not able
+to recognize that something is wrong until some distance beyond the actual
+error. If you can't find anything wrong with the line that Mup lists as
+being in error, try looking at the end of the previous line, or even earlier
+lines. Some of the most common problems are missing semicolons and missing
+quotes. Missing quote marks tend to be especially confusing to Mup, and may
+cause many error messages, even though there is only one problem.
+Another common problem that may cause a very large number of error messages is
+forgetting to state &quot;music&quot; to enter music context.
+</P>
+<P>
+Often listening to
+<A HREF="midi.html">MIDI output</A>
+is much more effective at spotting things like wrong notes and missing
+accidentals than trying to find them by eye.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="param.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="adjust.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/fontfile.html b/mup/docs/uguide/fontfile.html
new file mode 100644 (file)
index 0000000..1d18585
--- /dev/null
@@ -0,0 +1,39 @@
+<HTML>
+<HEAD><TITLE>
+Mup font files
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="include.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="param.html">next page --&gt;</A>
+</P>
+            
+<H2>
+Installing other fonts
+</H2>
+<P>
+The &quot;fontfile&quot; statement is used to override a Mup font with
+some other font. You may place one or more of these anywhere in Mup input.
+This might be used either because you'd like a different
+style of printing, or because you need a different alphabet.
+<A HREF="../mkmupfnt.ps">The "mkmupfnt" program</A>
+that is distributed with Mup
+can be used to generate a font description file. You can then use
+<BR><PRE>
+       fontfile &quot;file&quot;
+</PRE><BR>
+in your Mup program, where the given &quot;file&quot; is the name of the font
+description file. The manual page for mkmupfnt describes how to use that
+program. It also describes the format of the font description file,
+in case you wish to generate it by some means
+other than the mkmupfnt program.
+</P>
+<P>
+Mup searches for fontfiles via the MUPPATH mechanism, just like for
+<A HREF="include.html">included files.</A>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="include.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="param.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/gensyn.html b/mup/docs/uguide/gensyn.html
new file mode 100644 (file)
index 0000000..d5e78b8
--- /dev/null
@@ -0,0 +1,137 @@
+<HTML>
+<HEAD><TITLE>
+Mup General Syntax
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="utilpgms.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="contexts.html">next page --&gt;</A>
+</P>
+         
+<H1>
+MUP FILE STRUCTURE
+</H1>
+<P>
+Mup files do not have to follow any naming convention,
+although on systems that use file name suffixes to associate a file
+with an application, it is traditional to use .mup for the suffix.
+It can also be useful to put a special &quot;magic string&quot;
+on the first line of Mup files.
+This magic string is completely optional, but having it there
+makes it easy for both people
+and programs to identify the file as Mup input.
+The standard recommended value for this string is:
+<BR><PRE>
+//!Mup-Arkkra
+</PRE><BR>
+with exactly that spacing and capitalization.
+If the file uses features of newer versions of Mup, and thus would
+not work with older versions, you can add a dash and
+the minimim version number the file requires, as in:
+<BR><PRE>
+//!Mup-Arkkra-5.3
+</PRE><BR>
+</P>
+<H2>
+Mup General Syntax
+</H2>
+<P>
+Any number of spaces and tabs can be put in
+almost anywhere except in the middle of a word.
+Each statement goes on a separate line.
+If for some reason you wish to split a statement onto several lines,
+each but the last must end with a &quot;\&quot; (backslash) character, to
+tell Mup to treat the next line as a continuation of the current line.
+Blank lines can be put between statements to make things easier to read.
+</P>
+<P>
+Comments begin with two slashes and continue to end of line. All comments
+will be totally ignored by Mup, and are for your own use to remind yourself
+of something. For example:
+<BR><PRE>
+// Note: in some early manuscripts, this chord had an accent
+</PRE><BR>
+</P>
+<P>
+Staffs are numbered from top to bottom, starting at staff 1.
+</P>
+<P>
+Several different units are used for distances. One is inches or
+centimeters. (There is a
+<A HREF="param.html#units">units parameter</A>
+that is used to select which you want to use.) Another
+is &quot;stepsizes.&quot; One stepsize is half the distance between two staff lines.
+In the horizontal dimension, &quot;counts&quot; are sometimes used. A &quot;count&quot;
+refers to the musical duration of a note with a duration of the denominator
+(bottom number) of the time signature.
+The actual distance on the page will vary depending
+on how Mup determines notes should be placed.
+When you use a
+<A HREF="param.html#time">time signature</A>
+with two or more fractions added together,
+as in 3/4 + 3/8, the &quot;count&quot; is the largest denominator, which would be
+8 in the example just given.
+</P>
+<P>
+Upper and lower case letters are not interchangeable. Thus, for example,
+&quot;SCORE&quot; is not the same as &quot;score.&quot;
+</P>
+<P>
+Most lines of input end with a semicolon. There are some kinds of input that
+do not require an ending semicolon, but Mup will allow semicolons on those
+too, so that if you can't
+remember if a given command requires a semicolon or not, you can just use one
+anyway. For the examples in this User's Guide, semicolons are not used when
+they are not necessary.*
+<HR>
+* The commands on which the ending semicolon is optional are:
+<A HREF="bars.html">bar,</A>
+<A HREF="multirst.html">multirest,</A>
+<A HREF="param.html">setting of parameters,</A>
+<A HREF="prnttext.html">print, left, right, center, title,</A>
+<A HREF="newscore.html">newscore, newpage,</A>
+<A HREF="linecurv.html">line, and curve.</A>
+Semicolons are not allowed after commands that indicate entering a new
+<A HREF="contexts.html">context (header, footer, music, staff, grids, etc.).</A>
+A newline after those commands is optional,
+although often a good idea for readability.
+</P>
+<P>
+In
+<A HREF="music.html">music context,</A>
+newlines are required to separate commands: music data, bar lines, rolls,
+commands to print strings, dynamic marks, lyrics, etc. all must each
+end with a newline. In
+<A HREF="textmark.html#grids">grids context</A>
+and
+<A HREF="shaped.html#hdshape">headshape context,</A>
+each pair of strings must end with a newline.
+In other contexts, there are a few cases where newlines between commands
+are optional, although you may wish to use them anyway to improve readability.
+</P>
+<P>
+Mup supports
+<A HREF="macros.html">macros and conditionals (like 'if' and 'ifdef')</A>
+that can be placed anywhere in input, except in the middle of words,
+numbers, or strings; they needn't be on separate lines.
+</P>
+<P>
+In a number of statements, Mup expects a text string. All strings must be
+enclosed in double quotes. For example:
+<BR><PRE>
+&quot;This is a string.&quot;
+&quot;Allegro&quot;
+</PRE><BR>
+</P>
+<P>
+A string can contain any combination of letters, numbers, spaces,
+and punctuation.
+It can also contain various things that will cause printing of special music
+characters, change font and size, and so forth. Those things are covered in
+<A HREF="textstr.html">the chapter on text strings.</A>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="utilpgms.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="contexts.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/headfoot.html b/mup/docs/uguide/headfoot.html
new file mode 100644 (file)
index 0000000..697a5f5
--- /dev/null
@@ -0,0 +1,199 @@
+<HTML>
+<HEAD><TITLE>
+Mup header and footers
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="newscore.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="macros.html">next page --&gt;</A>
+</P>
+           
+<H2>
+Headers and footers
+</H2>
+<P>
+Mup provides ways to put headers and footers on pages of output.
+Often you may want a certain kind of header and footer on the first
+page, but a different kind on any subsequent pages, so Mup makes it
+easy to do that. Mup also offers two different &quot;layers&quot; of headers and
+footers. These layers may be particularly useful if you have a single Mup
+file that contains multiple songs, or multiple movements of a song.
+In that case, there may be certain things that you want printed in
+headers and footers throughout,
+like the current page number and the name of the entire collection,
+but other things that you want to have change with each new song or
+movement.
+</P>
+<P>
+The &quot;outer&quot; layer is specified by four contexts: header, footer, header2,
+and footer2. The &quot;inner&quot; layer is specified by four contexts:
+top, bottom, top2, and bottom2.
+All of these contexts are optional.
+The outer contexts can only be specified once per file.
+The inner contexts can be specified more than once per file, and
+each time a set of them occurs, a new page is started.
+On output pages, all of these contexts are placed horizontally
+between the left and right margins, and vertically the
+elements appear in the following order:
+ (topmargin)
+header
+top
+ (one or more scores of music or blocks of text)
+bottom
+footer
+ (bottommargin)
+</P>
+<P>
+Which version is used--the one with or without the &quot;2&quot; suffix--depends
+on which page is being printed. The items in header and footer
+appear on only the very first page,
+while those in header2 and footer2 appear on all subsequent pages.
+Somewhat similarly, the items in top and bottom will appear on the page
+that is started when they are encountered in the input,
+while top2 and bottom2 will then be used on all subsequent pages.
+However, you can specify a new top and/or bottom later,
+that will then to used for one page, and you can specify
+a new top2 and/or bottom2 later which will replace the previous top2/bottom2.
+Note, however, that if you change top2 but not top,
+that new top2 is used immediately on the new page,
+whereas if you change both, the new top applies
+to the immediately following new page,
+and the new top2 isn't used until the following page. Subsequent pages
+will use top2 in either case.
+</P>
+<P>
+Some examples may help.
+First a simple case: suppose you have a single song, and you'd like a title
+at the top of the first page. This is straightforward:
+<BR><PRE>
+top
+    title &quot;Here is the Title&quot;
+</PRE><BR>
+For this simple example, it would work just as well to use &quot;header&quot; instead
+of &quot;top,&quot; so you can use either one, although top is slightly more flexible.
+Later we'll see some examples where you might use both header and top in
+the same file, for different kinds of titles.
+</P>
+<P>
+Now suppose you'd like to make the title bigger and bolder, and would like
+to add a subtitle and composer information, as well as add a copyright
+notice to the bottom of the page.
+<BR><PRE>
+top
+   title bold (18) &quot;Here is the Title&quot;
+   title ital (14) &quot;Here is a subtitle&quot;
+   title &quot;Lyrics: Ann Author&quot; &quot;Composer: Me&quot;
+bottom
+   title &quot;\(copyright) Copyright 2003 by Ann Author and Me&quot;
+</PRE><BR>
+Again, in this simple example,
+you could use &quot;header&quot; and &quot;footer&quot; rather than &quot;top&quot; and &quot;bottom.&quot;
+</P>
+<P>
+Now suppose the song is long enough to take several pages,
+and you would like to repeat the title along with the page number on
+all pages after the first. To accomplish this, you could add:
+<BR><PRE>
+top2
+  title &quot;Here is the Title - \%&quot;
+</PRE><BR>
+The \% is a special marker that will get replaced on each page
+with the current page number. While it can be used in any text string,
+it is probably only likely to be useful in these header and footer kinds
+of contexts.
+<A NAME="pagenum">Another special marker</A>
+is \#, which will be replaced by the page number of the final page.
+This could be useful for doing something like &quot;page \% of \#.&quot;
+</P>
+<P>
+As a variation, perhaps you'd prefer the information at the bottom of
+the page.
+<BR><PRE>
+bottom2
+   title &quot;This is the title&quot;  &quot;Page \%&quot;
+</PRE><BR>
+In this variation, two separate text strings are specified,
+so the first string will be left justified and the second will be
+right justified.
+</P>
+<P>
+Note that if you give a top2 or bottom2, 
+but it turns out there aren't any additional pages,
+they would never actually get used.
+But it wouldn't hurt to have set them.
+</P>
+<P>
+Now let's consider a more complicated example, using both outer and inner
+contexts. Suppose you are publishing a book of songs,
+entitled &quot;My Favorite Songs,&quot; and you want to put that title at the top
+of every page throughout the book, and you want a page number at the bottom
+of each page except the first.
+You could get that much using:
+<BR><PRE>
+header
+   title &quot;My Favorite Songs&quot;
+header2
+   title &quot;My Favorite Songs&quot;
+footer2
+   title &quot;\%&quot;
+</PRE><BR>
+But suppose that in addition, you want each song to have its title on its
+first page in big print, and on subsequent pages in regular size print.
+To get this, at the beginning of each song, you could use top and top2:
+<BR><PRE>
+top
+   title (18) &quot;This is the Song Title&quot;
+top2
+   title &quot;This is the Song Title&quot;
+</PRE><BR>
+</P>
+<P>
+A composition with multiple movements can be handled similarly,
+by giving header, footer, header2, and footer2 (or any subset thereof)
+for the composition as a whole,
+and then giving new top, bottom, top2, and bottom2 definition (or any subset)
+at the beginning of each new movement.
+</P>
+<P>
+These contexts are conceptually in a separate coordinate space,
+which will be overlaid on each page coordinate space.
+When in these contexts,
+<A HREF="tags.html#wintag">the _win special tag</A>
+applies to
+the header or footer window rather than the space between the header and
+footer as it does in the music context.
+</P>
+<P>
+Since headers or footers will expand as necessary, the
+<A HREF="tags.html#wintag">value of _win.s and _win.y</A>
+may be changed by any of the statements in the context. At any given
+time, they refer to the boundaries as defined by what has been printed
+so far. Thus, if the first line of a header contains an 18 point title,
+after that, _win.s would be 18 points below _win.n.
+It the header then contained a 12 point title, after that it
+would be 31 points below _win.n (12 points for the title string, plus 1 point
+of padding that is added between lines printed).
+</P>
+<P>
+In addition to the &quot;title&quot; commands used in the examples above,
+you can also use
+<A HREF="prnttext.html">the "print," "left," "right," or "center" commands.</A>
+In most
+cases you will want to use &quot;nl&quot; for the <I>location</I> on those commands
+to place things. If you don't specify a <I>location</I> for the first of these
+commands in a header or footer, Mup will start at the left margin, just far
+enough down from the top to accommodate the text string to be printed.
+These contexts can also contain settings of the
+<A HREF="param.html#font">font,</A>
+<A HREF="param.html#fontfam">fontfamily,</A>
+and
+<A HREF="param.html#size">size</A>
+parameters.
+These parameter values will be used until the end of the context or until
+set again to some other value.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="newscore.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="macros.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/heeltoe.html b/mup/docs/uguide/heeltoe.html
new file mode 100644 (file)
index 0000000..11eed09
--- /dev/null
@@ -0,0 +1,40 @@
+<HTML>
+<HEAD><TITLE>
+Organ pedal heel/toe marks
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="breathmk.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="muspaper.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Organ pedal heel and toe marks
+</H2>
+<P>
+Mup does not include characters specially for the standard organ pedal
+heel and toe indications, but a U in helvetica font and the acc_hat
+music symbol can be used. You may want to make them a bit smaller than
+the default size, so defining macros for them may be useful.
+<BR><PRE>
+score
+       clef = bass
+
+// define strings for the organ pedal heel and toe marks
+define HEEL &quot;\s(-3)\f(HB)U&quot; @
+define TOE &quot;\s(-1)\(acc_hat)&quot; @
+
+music
+
+1: a-;b-;e;f;
+rom below 1: 1 HEEL; 2 TOE;
+rom above 1: 3 TOE; 4 HEEL;
+bar
+</PRE><BR>
+<IMG SRC="mugex101.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="breathmk.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="muspaper.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/ichdattr.html b/mup/docs/uguide/ichdattr.html
new file mode 100644 (file)
index 0000000..010e0bf
--- /dev/null
@@ -0,0 +1,382 @@
+<HTML>
+<HEAD><TITLE>
+Inter-chord attributes
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="crossst.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="tuplets.html">next page --&gt;</A>
+</P>
+          
+<H3>
+Inter-chord attributes
+</H3>
+<P>
+In addition to the
+<A HREF="chrdattr.html">chord attributes</A>
+that can appear in the square brackets
+before time and pitch information, there are a few attributes that are
+specified after the time and pitch information. These are attributes that
+start or end on the chord but also affect other chords. There are several
+such attributes:
+<UL>
+<LI>
+<A HREF="ichdattr.html#tie">chord ties</A>
+<LI>
+<A HREF="ichdattr.html#slur">chord slurs</A>
+<LI>
+<A HREF="ichdattr.html#custbeam">custom beaming</A>
+<LI>
+<A HREF="ichdattr.html#crossbm">cross-staff beams</A>
+<LI>
+<A HREF="ichdattr.html#alt">alternation</A>
+<LI>
+<A HREF="ichdattr.html#slope">slope</A>
+</UL>
+</P>
+<P>
+If several of these are specified on a single chord, they may be in any
+order, separated by commas.
+</P>
+<H4>
+Chord ties
+</H4>
+<P>
+<A NAME="tie">If all notes in a chord are to be tied to the following chord,</A>
+the keyword &quot;tie&quot;
+can be placed at the end of the chord. As was mentioned earlier,
+<A HREF="noteattr.html#ntie">individual notes can be tied using a "~" symbol.</A>
+Thus:
+<BR><PRE>
+ceg tie;
+</PRE><BR>
+is equivalent to
+<BR><PRE>
+c~e~g~;
+</PRE><BR>
+The word &quot;tie&quot; may be preceded by the word &quot;dotted&quot; or &quot;dashed&quot; to
+produce dotted or dashed ties, otherwise normal, solid ties are drawn.
+The word &quot;tie&quot; may be followed by the word &quot;up&quot; or &quot;down&quot; to specify the
+direction of each curve's bulge. If neither is specified, Mup will
+determine an appropriate direction, so you only need to give a direction
+if you wish to override Mup's choice.
+</P>
+<P>
+You can also produce the effect of tying chords by using additive time
+values. For example, the following lines produce the same output:
+<BR><PRE>
+1: 2ceg tie;8;;4;  // explicit tie
+
+1: 2+8ceg;8;4; // tie implied by added time values
+</PRE><BR>
+</P>
+<H4>
+Chord slurs
+</H4>
+<P>
+<A NAME="slur">The keyword "slur" can be placed at the end of a chord to indicate</A>
+that each note in the chord is to be slurred to the corresponding
+note in the following chord. In other words, the top note of the chord
+is slurred to the top note of the following chord, the second from the
+top note in the first chord to the second from the top note in the
+second chord, etc.
+Thus the following 2 measures give equivalent output:
+<BR><PRE>
+1: 2f&lt;d&gt; a&lt;b&gt; c+&lt;d+&gt;; dbd+;
+bar
+
+1: 2fac+ slur; dbd+;
+bar
+</PRE><BR>
+<IMG SRC="mugex22.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+The chord with the &quot;slur&quot; keyword
+and the chord that follows it must have the same number of notes.
+The word &quot;slur&quot; may be preceded by the word &quot;dotted&quot; or &quot;dashed&quot; to
+produce dotted or dashed slurs, otherwise normal, solid slurs are drawn.
+The word &quot;slur&quot; may be followed by the word &quot;up&quot; or &quot;down&quot; to specify the
+direction of each curve's bulge. If neither is specified, Mup will
+determine an appropriate direction, so you only need to give a direction
+if you wish to override Mup's choice.
+</P>
+<H4>
+Custom beaming
+</H4>
+<P>
+Normally, notes of eighth or shorter duration are automatically beamed
+according to the specification of
+<A HREF="param.html#beamstyl">the "beamstyle" parameter.</A>
+<A NAME="custbeam">Occasionally, you may wish to</A>
+override the default beaming style for a particular situation.
+This is done using the &quot;bm&quot; and &quot;ebm&quot; keywords. The &quot;bm&quot; (short for &quot;beam&quot;)
+is placed at the end of the chord which is the first to be beamed.
+The  &quot;ebm&quot; (short for &quot;end beam&quot;) is placed at the end of the last chord.
+Both chords must be in the same measure. If there is any custom beaming
+specified for a given voice in a given measure, the default beamstyle
+is turned off for that voice for the entire measure, meaning that only
+what you explicitly specify to be beamed will be beamed.
+An example:
+<BR><PRE>
+// The d, e, and f will be beamed together,
+// but other 8th notes will not be.
+1: 4c; 8; d bm; e; f ebm; g; a;
+bar
+
+// First two chords beamed together.
+// Second chord is tied to third chord.
+1: 8.fa bm; 16gc+ tie, ebm; 2; 8a; g;
+bar
+</PRE><BR>
+<IMG SRC="mugex23.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+In the absence of custom beaming, Mup will beam notes together
+using the
+<A HREF="param.html#beamstyl">beamstyle parameter,</A>
+if that parameter is set.
+The beamstyle parameter is a list of time values that add up to
+a measure. Each time value tells how many chords to beam together.
+For example, a 2 means to beam a half note worth of chords together,
+whereas 1.. would indicate that a double dotted whole note worth of
+chords should be beamed together.
+Here are some examples of how the beamstyle parameter works.
+<BR><PRE>
+// beam each quarter note worth of notes together,
+// breaking the beaming at each quarter note boundary
+score beamstyle = 4,4,4,4
+music
+1: 8c;d;e;f;g;a;b;c+;
+bar
+1: 8c;d;4e;f;8g;c;
+bar
+
+// beam each half note worth of notes together,
+// breaking the beaming at each half note boundary
+score beamstyle = 2,2
+music
+1: 8c;d;e;f;g;a;b;c+;
+bar
+// the middle two eighth notes will not be beamed together,
+// because they are on opposite sides of the half note boundary
+1: 8c;4d;8e;f;4g;8c;
+bar
+
+// beam each whole note worth of notes together
+score beamstyle = 1
+music
+1: 8c;d;e;f;g;a;b;c+;
+bar
+1: 8c;4d;8e;f;4g;8c;
+bar
+
+// in 9/8 time, beam each dotted quarter note worth of notes together
+score time = 9/8 ; beamstyle = 4., 4., 4.
+music
+1: 8c;d;e;d;e;f;e;f;g;
+bar
+// the eight notes will not be beamed together,
+// because they are on opposite side of the dotted quarter boundary
+1: 4.c;4d;8e;8f;4g;
+bar
+
+// in each measure, beam the first dotted half worth of notes together,
+// then beam the remaining dotted quarter worth of notes together
+score beamstyle = 2., 4.
+music
+1: 8c;d;e;d;e;f;e;f;g;
+bar
+
+// in each measure, beam the first dotted quarter worth of notes together
+// then beam the remaining dotted half worth of notes together
+score beamstyle = 4., 2.;
+music
+1: 8c;d;e;d;e;f;e;f;g;
+bar
+</PRE><BR>
+<IMG SRC="mugex24.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+The value of the beamstyle parameter is remembered for
+any later changes back to the same time signature.
+For example, suppose you set
+<BR><PRE>
+time=4/4
+beamstyle=4,4,4,4
+</PRE><BR>
+then later in the piece switched to
+<BR><PRE>
+time=3/4
+beamstyle=4,4,4
+</PRE><BR>
+Then any time you went back to 4/4 or 3/4, the beamstyle you had set for that
+time signature would automatically be set as well.
+You could, of course, override the automatic setting
+with a new beamstyle if you wished.
+</P>
+<P>
+Normally Mup will break beams whenever it encounters a rest or space,
+but if you or specify an &quot;r&quot; at the end of the
+beamstyle parameter, it will beam across rests
+of eighth note or shorter duration. Similarly, specifying an &quot;s&quot; at the
+end of the beamstyle parameter will cause it to beam across spaces of
+eighth note or shorter. Specifying both (in either order) will result
+in beaming across both. Mup will also beam across eighth note or
+shorter rests or spaces inside of custom beams.
+</P>
+<P>
+Sometimes, if there are many short notes beamed together, you may wish to
+subdivide the beams into smaller groupings, where the outer, or primary
+beam remains unbroken, but the inner, or secondary beams are broken
+periodically. When using custom beaming, this is specified by &quot;esbm&quot;
+(&quot;end subbeam&quot; or &quot;end secondary beam&quot;)
+on the chord after which you want the break to occur.
+When using beamstyle, parentheses are used to indicate what sets of
+secondary beams are to be included in a given outer beam.
+<BR><PRE>
+score
+beamstyle=(4,4),(4,4)
+music
+
+// use the beamstyle parameter
+1: 16c;d;e;f; g;a;b;c+; c+;b;a;g; 32f;e;f;e;d;c;d;c;
+bar
+
+// use custom beaming
+1: 16c bm;d;e;f;g;a esbm;b;c+;c+;b;a;g esbm;f;e;d;c ebm;
+bar
+</PRE><BR>
+<IMG SRC="mugex25.gif" ALT="Picture of Mup output"><BR>
+</P>
+<H4>
+Cross-staff beams
+</H4>
+<P>
+In keyboard music,
+<A NAME="crossbm">sometimes notes on adjacent staffs are beamed together.</A>
+Mup will do this with a variation on
+<A HREF="ichdattr.html#custbeam">custom beaming.</A>
+A bm and ebm must be specified on both staffs, and in each case the
+bm is followed by a qualifier:
+on the first of the two staffs, &quot;bm with staff below&quot; must
+be specified, while on the second staff you use &quot;bm with staff above&quot;.
+For every point in time for the duration of the beam, one staff
+must have a chord with notes in it, and the other staff must have
+a space chord. (This is somewhat different than ordinary,
+non-cross-staff beams controlled by the
+<A HREF="param.html#beamstyl">beamstyle parameter,</A>
+where spaces are not allowed unless beaming across spaces
+is specifically requested.)
+The two &quot;bm&quot; marks must occur at the same time in the
+measure. Similarly, the two &quot;ebm&quot; marks must
+occur at the same time in each staff.
+Grouping subbeams using &quot;esbm&quot; is not supported on cross-staff beams.
+</P>
+<P>
+Some examples:
+<BR><PRE>
+1: 8f bm with staff below; a; 4s ebm; 4s bm with staff below; 8b; d ebm;
+2: 4s bm with staff above; 8a; b ebm; b bm with staff above; d; 4s ebm;
+bar
+</PRE><BR>
+<IMG SRC="mugex26.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+Normally the beam will be drawn between the staffs, but
+you can force the beam to be above or below all the notes by specifying a
+<A HREF="chrdattr.html#stemdir">stem direction.</A>
+You can also adjust the appearance of the beam by giving
+<A HREF="chrdattr.html#stemlen">stems lengths</A>
+for the first and last chords in the beam.
+<BR><PRE>
+1: [up]8f bm with staff below;a;4s ebm;4s bm with staff below;8b;[len 11]d ebm;
+2: 4s bm with staff above;8a;b ebm;[down;len 14]b bm with staff above;d;4s ebm;
+bar
+</PRE><BR>
+<IMG SRC="mugex27.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+If a cross-staff beam includes
+<A HREF="tuplets.html">tuplets,</A>
+the tuplet numbers will not
+be printed. You would have to print them yourself using either
+<A HREF="prnttext.html">a "print" statement</A>
+or
+<A HREF="stuff.html">a "boldital" statement.</A>
+</P>
+<P>
+It is possible for cross-staff beams to collide with other items, such as
+<A HREF="stuff.html">dynamic marks.</A>
+In these cases, you may need to move the other items. Another
+thing you might try is
+<A HREF="chrdattr.html#stemlen">specifying stem lengths</A>
+to alter where the beams get placed, or
+<A HREF="prnttext.html">printing</A>
+a blank string between the staffs to cause them to get placed further apart.
+If you specify a
+<A HREF="ichdattr.html#slope">slope,</A>
+you have to specify it on the staff having notes in the first chord,
+not the staff with space.
+<A HREF="chrdattr.html#slashes">Slashes</A>
+are not allowed on cross-staff beams.
+</P>
+<P>
+Mup doesn't directly allow cross-staff grace note beams.
+However, you may be able simulate the effect by using cue note chords
+along with invisible time signature changes and possibly invisible bar lines.
+See the
+<A HREF="invisbar.html">section on "Special uses of invisbar"</A>
+for more details.
+</P>
+<P>
+You may want to also look at the section on
+<A HREF="crossst.html">cross-staff stems,</A>
+for an alternate way to handles some cases where you might
+use cross-staff beams.
+</P>
+<H4>
+Alternation
+</H4>
+<P>
+<A NAME="alt">Alternation pairs</A>
+can be specified using &quot;alt <I>N</I>&quot; where <I>N</I>
+is a number. An alternation
+pair is two chords that are to played alternately in quick succession
+but are not written out as such. This is shown by drawing <I>N</I> beams
+between the stems of the chords. The note value you specify for each
+chord must be the same, and the time value of each must equal the time
+taken by the pair. For example, if the pair takes up the time of a half
+note, each chord would be a half note.
+Here is an example:
+<BR><PRE>
+// Alternate between c and c an octave
+// higher. Total time taken is that of
+// a half note. Two &quot;beam&quot;-like lines
+// will be drawn to show the alternation.
+1: 2c alt 2; 2c+;2g;
+bar
+</PRE><BR>
+<IMG SRC="mugex28.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+Alternation is not allowed on cross-staff beams.
+</P>
+<H4>
+Slope
+</H4>
+<P>
+<A NAME="slope">On the first chord of a set of chords that are beamed together,</A>
+you can specify a
+beam angle from -45 to 45 degrees.
+This will override whatever angle Mup would have used.
+<BR><PRE>
+1: 8g slope 11; b; g slope 0; b;  g slope -5.75; b;
+bar
+</PRE><BR>
+<IMG SRC="mugex29.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="crossst.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="tuplets.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/ifclause.html b/mup/docs/uguide/ifclause.html
new file mode 100644 (file)
index 0000000..2a9ca72
--- /dev/null
@@ -0,0 +1,249 @@
+<HTML>
+<HEAD><TITLE>
+Generalized conditionals
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="macros.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="include.html">next page --&gt;</A>
+</P>
+          
+<H3>
+Generalized conditionals
+</H3>
+<P>
+Mup also supports more general &quot;if&quot; clauses. If you happen to be
+familiar with the preprocessors for the C and C++ programming
+languages, Mup &quot;if&quot; clauses are very similar.
+If you're not, that's okay, since things are explained below.
+Also, some of the operations are really very rarely needed, so if
+you find some of them confusing, you just can skip past this section;
+you'll likely never have a need for the complicated operations anyway.
+</P>
+<P>
+The general form is
+<BR><PRE>
+<B>if</B> <I>condition</I> <B>then</B> <I>Mup statements</I> <B>else</B> <I>Mup statements</I> <B>endif</B>
+</PRE><BR>
+As with the &quot;ifdef,&quot; the &quot;else&quot; and second set of Mup statements is optional.
+</P>
+<P>
+One form of &quot;if&quot; is really just a variation of ifdef. It uses the
+keyword &quot;defined&quot; followed by a macro name. So
+<BR><PRE>
+  ifdef DUET
+</PRE><BR>
+could also be written
+<BR><PRE>
+  if defined DUET then
+</PRE><BR>
+You may put a set of parentheses around the macro name for clarity
+if you wish:
+<BR><PRE>
+  if defined(DUET) then
+</PRE><BR>
+</P>
+<P>
+The ! is used to mean &quot;not,&quot; so
+<BR><PRE>
+  ifndef TRIO
+</PRE><BR>
+could also be written as
+<BR><PRE>
+  if ! defined(TRIO) then
+</PRE><BR>
+</P>
+<P>
+So far, this just looks longer, so what's the advantage?
+The difference is that ifdef and ifndef can only be used to check if a single
+macro is defined or not, whereas the &quot;if&quot; condition is much more general,
+and therefore much more powerful.
+Decisions can be based on the values of macros, not just whether they are
+defined or not, and can also be based on more than one macro at a time,
+Here is an example of a condition based on several macros at once:
+<BR><PRE>
+ if defined(FULL_SCORE) &amp;&amp; defined(TRANSPOSE_UP) &amp;&amp; ! defined(MIDI) then
+</PRE><BR>
+would be true only if both FULL_SCORE and TRANSPOSE_UP were defined,
+but MIDI was not defined. The &amp;&amp; means &quot;and.&quot;
+There is also || which means &quot;or,&quot; so
+<BR><PRE>
+ if defined(CELLO) || defined(STRINGBASS)
+</PRE><BR>
+would be true as long as at least one of the macros was defined.
+</P>
+<P>
+The condition can also include numbers and macros used as numeric values
+in arithmetic and comparisons.  For example,
+<BR><PRE>
+  define STAFFS 3 @
+  define S 5 @
+  if STAFFS &gt; 5 then
+     // ... this would not be executed, since 3 is not greater than 5
+  endif
+  if 2 &lt;= STAFFS then
+     // ... This would be executed, since 2 is less than or equal to 3
+  endif
+  if STAFFS + 1 == S - 1 then
+     // ... This would be executed, since 3+1 equals 5-1
+  endif
+</PRE><BR>
+Note that the symbol to test for &quot;equals&quot; is two equals signs, not just
+one. This is to be consistent with what is used in the C and C++ languages.
+The operators for comparisons are:
+<TABLE BORDER=4>
+<TR>
+<TD>&lt;</TD>  <TD>less than</TD>
+</TR>
+<TR>
+<TD>&gt;</TD>  <TD>greater than</TD>
+</TR>
+<TR>
+<TD>&lt;=</TD> <TD>less than or equal</TD>
+</TR>
+<TR>
+<TD>&gt;=</TD> <TD>greater than or equal</TD>
+</TR>
+<TR>
+<TD>==</TD>    <TD>equal</TD>
+</TR>
+<TR>
+<TD>!=</TD>    <TD>not equal</TD>
+</TR>
+</TABLE>
+
+</P>
+<P>
+Note that the values in the conditions can only be either literal numbers
+or macros whose values evaluate to a number. They cannot be things like
+<A HREF="param.html">Mup parameters.</A>
+A macro which is not defined is treated as having a value of zero.
+Macro values are substituted for macro names just as elsewhere in Mup,
+so if you use a macro whose resulting value does not evaulate to a number,
+you may get an error or other unexpected result.
+</P>
+<P>
+If you are familiar with &quot;octal&quot; and &quot;hexadecimal&quot; numbers, they can be
+used, following the C language convention of a leading zero for octal
+or a leading 0x for hexadecimal. (If you're not familiar with these
+numbers or conventions, don't worry about it; it's never really necessary
+to use them. Just make sure you don't accidentally start a number other
+than a zero with a zero).
+</P>
+<P>
+Values are limited to 32-bit signed numbers. (If you don't know
+what that means, all you need to know is that you
+can only use numbers between -2147483648 and 2147483647.
+</P>
+<P>
+Before we introduce the remaining operators, it would be good to discuss
+two concepts, called precedence and associativity. These determine the
+order in which operations are done. Consider the following expression:
+<BR><PRE>
+   5 + 3 * 8
+</PRE><BR>
+What is its value? If we just went left to right, we would add 5 and 3,
+getting 8, then multiple by 8, for a final value of 64. However,
+multiplication is generally considered to have higher &quot;precedence&quot;
+than addition, meaning that multiplications should be done before additions.
+In other words, the expression should actually be treated as
+<BR><PRE>
+   5 + (3 * 8)
+</PRE><BR>
+so we would first multiply 3 by 8, getting 24, and then add 5 and 24,
+obtaining a final answer of 29.
+</P>
+<P>
+If you really intended the 64 meaning, that could be shown by parentheses,
+indicating you want the addition to be done first:
+<BR><PRE>
+   (5 + 3) * 8
+</PRE><BR>
+</P>
+<P>
+Associativity determines whether operators of equal precedence are done
+left to right or right to left. Parentheses and
+all of the operators that have two
+operands associate left to right, while all the others
+associate right to left. For example, since addition and subtraction
+associate left to right, the expression
+<BR><PRE>
+  10 - 6 - 1
+</PRE><BR>
+would be evaluated by first subtracting 6 from 10 to get 4,
+then subtracting 1, yielding 3.
+If they associated right to left, first 1 would be subtracted from 6
+to get 5, which would then be subtracted from 10, yielding 5.
+So using different associativity can lead to different answers!
+</P>
+<P>
+Since the &quot;not&quot; operator and unary minus associate right to left,
+in the expression
+<BR><PRE>
+  ! - (5)
+</PRE><BR>
+the unary minus would be applied first to get -5, then the &quot;not&quot; would be
+applied. But what does &quot;not -5&quot; mean? The &quot;not&quot; operator will treat its
+operand as a boolean value, with a value of zero meaning false, and
+any non-zero value being true. Since -5 is not zero, it represents &quot;true,&quot;
+and &quot;not true&quot; would be &quot;false,&quot; or zero.  By the way,
+any operator that yields a boolean result
+(not, logical and, logical or, less than, greater than,
+less than or equal, greater than or equal, equal, or not equal) will
+always yield 1 for true, even though any non-zero value could mean true.
+</P>
+<P>
+The operators are listed below. Those on the same line have the same
+precedence, with those on each line having higher precedence than the
+lines below.
+<TABLE BORDER=4>
+<TR>
+<TD><B>operators</B></TD>      <TD><B>operations</B></TD>      <TD><B>associativity</B></TD>
+</TR>
+<TR>
+<TD><TT>( )</TT></TD>  <TD>grouping</TD>       <TD>left to right</TD>
+</TR>
+<TR>
+<TD><TT>! ~ - +</TT></TD>      <TD>not, one's complement, unary minus, unary plus</TD> <TD>right to left</TD>
+</TR>
+<TR>
+<TD><TT>* / %</TT></TD>        <TD>multiply, divide, modulo</TD>       <TD>left to right</TD>
+</TR>
+<TR>
+<TD><TT>+ -</TT></TD>  <TD>add, subtract</TD>  <TD>left to right</TD>
+</TR>
+<TR>
+<TD><TT>&lt;&lt; &gt;&gt;</TT></TD>    <TD>left shift, right shift</TD>        <TD>left to right</TD>
+</TR>
+<TR>
+<TD><TT>&lt; &lt;= &gt; &gt;=</TT></TD>        <TD>less than, less or equal, greater than, greater or equal</TD>       <TD>left to right</TD>
+</TR>
+<TR>
+<TD><TT>== !=</TT></TD>        <TD>equal, not equal</TD>       <TD>left to right</TD>
+</TR>
+<TR>
+<TD><TT>&amp;</TT></TD>        <TD>bitwise AND</TD>    <TD>left to right</TD>
+</TR>
+<TR>
+<TD><TT>^</TT></TD>    <TD>bitwise XOR</TD>    <TD>left to right</TD>
+</TR>
+<TR>
+<TD><TT>|</TT></TD>    <TD>bitwise OR</TD>     <TD>left to right</TD>
+</TR>
+<TR>
+<TD><TT>&amp;&amp;</TT></TD>   <TD>logical AND</TD>    <TD>left to right</TD>
+</TR>
+<TR>
+<TD><TT>||</TT></TD>   <TD>logical OR</TD>     <TD>left to right</TD>
+</TR>
+<TR>
+<TD><TT>? :</TT></TD>  <TD>interrogation</TD>  <TD>right to left</TD>
+</TR>
+</TABLE>
+
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="macros.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="include.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/include.html b/mup/docs/uguide/include.html
new file mode 100644 (file)
index 0000000..6a8c19a
--- /dev/null
@@ -0,0 +1,39 @@
+<HTML>
+<HEAD><TITLE>
+Mup include files
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="ifclause.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="fontfile.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Include
+</H2>
+<P>
+The &quot;include&quot; statement can be used to include the contents of one file
+inside another.
+<BR><PRE>
+<B>include &quot;</B><I>filename</I><B>&quot;</B>
+</PRE><BR>
+causes input to be read from the specified <I>filename</I>. When the end
+of that file is reached, reading of input resumes from the original file
+after the include statement.
+</P>
+<P>
+If the <I>filename</I> cannot be found as is, and it is not an absolute
+path, and if the environment variable MUPPATH is set, Mup will search
+for the file in each directory listed in MUPPATH. On Unix systems, the
+directories are separated by colons. On systems with DOS-like file naming
+conventions, they are separated by semicolons.
+The MUPPATH may be useful if, for example, you have a number of &quot;boilerplate&quot;
+files that you want to include in lots of songs. You can put them in
+some directory and set MUPPATH to list that directory, then any Mup
+files you have can refer to them.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="ifclause.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="fontfile.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/index.html b/mup/docs/uguide/index.html
new file mode 100644 (file)
index 0000000..b71dc9b
--- /dev/null
@@ -0,0 +1,257 @@
+<HTML>
+<HEAD><TITLE>
+Mup User's Guide
+</TITLE></HEAD>
+<BODY>
+
+<P>
+This is the on-line version of the Mup User's Guide, giving information
+about how to use the Mup Music Publication program.
+</P>
+<H2>
+Mup Background Information
+</H2>
+<A HREF="intro.html">Introduction to Mup</A>
+<BR>
+<A HREF="basics.html">Quick tutorial on Mup basics</A>
+<BR>
+<A HREF="running.html">Running Mup</A>
+<BR>
+<A HREF="cmdargs.html">Mup Options</A>
+<BR>
+<A HREF="utilpgms.html">Mup utility programs for displaying and printing music</A>
+<BR>
+<A HREF="gensyn.html">Mup General syntax information</A>
+<BR>
+<A HREF="contexts.html">Mup contexts</A>
+<BR>
+<HR>
+<H2>
+Basic Standard Music Notation
+</H2>
+<A HREF="music.html">Specifying Mup music input</A>
+<BR>
+<A HREF="chordinp.html">Chords (pitch, duration, and other attributes)</A>
+<BR>
+<UL>
+<LI>
+<A HREF="chordinp.html#letter">Notes, rests, or spaces</A>
+<LI>
+<A HREF="chordinp.html#measdur">Measure duration</A>
+<LI>
+<A HREF="chordinp.html#acc">Accidentals</A>
+<LI>
+<A HREF="chordinp.html#oct">Octave</A>
+<LI>
+<A HREF="chordinp.html#shorthnd">Shorthand notations</A>
+<LI>
+<A HREF="noteattr.html">Note attributes</A>
+<UL>
+<LI>
+<A HREF="noteattr.html#small">Small note head</A>
+<LI>
+<A HREF="noteattr.html#ntie">Note tie</A>
+<LI>
+<A HREF="noteattr.html#nslur">Slurs</A>
+<LI>
+<A HREF="noteattr.html#ntag">Note location tag</A>
+</UL>
+<LI>
+<A HREF="chrdattr.html">Chord attributes</A>
+<UL>
+<LI>
+<A HREF="chrdattr.html#chstyle">Chord style (grace, cue, xnote, diamond)</A>
+<LI>
+<A HREF="chrdattr.html#withlist">Symbols to be printed with a chord</A>
+<LI>
+<A HREF="chrdattr.html#slashes">Slashes</A>
+<LI>
+<A HREF="chrdattr.html#pad">Chord padding</A>
+<LI>
+<A HREF="chrdattr.html#ctag">Chord location tag</A>
+<LI>
+<A HREF="chrdattr.html#dist">Rest distance</A>
+<LI>
+<A HREF="chrdattr.html#rptattr">Shorthand for repeated attributes</A>
+</UL>
+<LI>
+<A HREF="midmeas.html">Mid-measure parameter changes</A>
+<LI>
+<A HREF="crossst.html">Cross-staff stems</A>
+<LI>
+<A HREF="ichdattr.html">Inter-chord attributes</A>
+<UL>
+<LI>
+<A HREF="ichdattr.html#tie">Chord ties</A>
+<LI>
+<A HREF="ichdattr.html#slur">Chord slurs</A>
+<LI>
+<A HREF="ichdattr.html#custbeam">Custom beaming</A>
+<LI>
+<A HREF="ichdattr.html#crossbm">Cross-staff beams</A>
+<LI>
+<A HREF="ichdattr.html#alt">Alternation groups</A>
+</UL>
+<LI>
+<A HREF="tuplets.html">Tuplets</A>
+</UL>
+<BR>
+<A HREF="altinp.html">Chord-at-a-time input style</A>
+<BR>
+<A HREF="bars.html">Bar lines</A>
+<BR>
+<UL>
+<LI>
+<A HREF="bars.html#bpad">Bar line padding</A>
+<LI>
+<A HREF="bars.html#btag">Bar line location tag</A>
+<LI>
+<A HREF="bars.html#endings">Endings</A>
+<LI>
+<A HREF="bars.html#reh">Rehearsal marks</A>
+<LI>
+<A HREF="bars.html#setmnum">Setting the measure number</A>
+<LI>
+<A HREF="bars.html#hide">Hiding time/key signature and clef changes</A>
+</UL>
+<A HREF="multirst.html">Multirests</A>
+<BR>
+<A HREF="lyrics.html">Lyrics</A>
+<HR>
+<H2>
+Tablature
+</H2>
+<A HREF="tabstaff.html">Tablature notation</A>
+<HR>
+<H2>
+Shaped notes
+</H2>
+<A HREF="shaped.html">Shaped notes</A>
+<HR>
+<H2>
+Text Strings
+</H2>
+<A HREF="textstr.html">Mup text strings</A>
+<HR>
+<H2>
+Tempo, dynamic marks, ornaments, etc.
+</H2>
+<A HREF="stuff.html">General Information</A>
+<BR>
+<A HREF="textmark.html">Text</A>
+<BR>
+<A HREF="textmark.html#grids">Guitar grids</A>
+<BR>
+<A HREF="mussym.html">Music symbols</A>
+<BR>
+<A HREF="phrase.html">Phrase marks</A>
+<BR>
+<A HREF="cres.html">Crescendo and decrescendo marks</A>
+<BR>
+<A HREF="octave.html">Octave marks</A>
+<BR>
+<A HREF="pedal.html">Piano pedal marks</A>
+<BR>
+<A HREF="roll.html">Rolls</A>
+<HR>
+<H2>
+Tags, printing text, lines and curves
+</H2>
+<A HREF="tags.html">Location tags</A>
+<BR>
+<A HREF="prnttext.html">Printing text</A>
+<BR>
+<A HREF="linecurv.html">Lines and curves</A>
+<HR>
+<H2>
+Miscellaneous Mup features
+</H2>
+<A HREF="newscore.html">Newscore and newpage</A>
+<BR>
+<A HREF="headfoot.html">Page headers and footers</A>
+<BR>
+<A HREF="macros.html">Macros</A>
+<BR>
+<A HREF="ifclause.html">Generalized if clauses</A>
+<BR>
+<A HREF="include.html">Include files</A>
+<BR>
+<A HREF="fontfile.html">Installing other fonts</A>
+<BR>
+<HR>
+<H2>
+Mup Parameters
+</H2>
+<A HREF="param.html">Mup parameters</A>
+<HR>
+<H2>
+Hints
+</H2>
+<A HREF="debug.html">Debugging</A>
+<BR>
+<A HREF="adjust.html">Adjusting output</A>
+<BR>
+<A HREF="invisbar.html">Special uses of invisible bars</A>
+<BR>
+<A HREF="chant.html">Chant</A>
+<BR>
+<A HREF="sharehd.html">Forcing shared note heads</A>
+<BR>
+<A HREF="mantup.html">Manually placed tuplet numbers</A>
+<BR>
+<A HREF="manual.html">Manual placement of notes</A>
+<BR>
+<A HREF="brackmac.html">Bracketing notes across staffs</A>
+<BR>
+<A HREF="crossbar.html">Cross-bar beaming</A>
+<BR>
+<A HREF="mixtsig.html">Mixed time signatures</A>
+<BR>
+<A HREF="oddeven.html">Different margins for odd/even pages</A>
+<BR>
+<A HREF="trnspose.html">Transposition</A>
+<BR>
+<A HREF="tempochg.html">Marking complicated tempo changes</A>
+<BR>
+<A HREF="multsong.html">Placing several songs on one page</A>
+<BR>
+<A HREF="cadenza.html">Cadenzas</A>
+<BR>
+<A HREF="verses.html">Placing verses below the scores</A>
+<BR>
+<A HREF="pianored.html">Automatic piano reduction</A>
+<BR>
+<A HREF="slashmrk.html">Diagonal slash marks</A>
+<BR>
+<A HREF="breathmk.html">Breath marks</A>
+<BR>
+<A HREF="heeltoe.html">Organ pedal heel and toe marks</A>
+<BR>
+<A HREF="muspaper.html">Generating blank staff paper</A>
+<BR>
+<A HREF="pstools.html">Converting Mup files to other formats</A>
+<HR>
+<H2>
+MIDI output
+</H2>
+<A HREF="midi.html">MIDI output</A>
+<BR>
+<HR>
+<ADDRESS>
+Arkkra Enterprises
+<BR>
+P. O. Box 315
+<BR>
+Warrenville, IL 60555
+<BR>
+<A HREF="mailto:support@arkkra.com">support@arkkra.com</A>
+<BR>
+<A HREF="http://www.arkkra.com">http://www.arkkra.com</A>
+</ADDRESS>
+<BR>
+<HR>
+Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises
+<HR><P>
+&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="intro.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/intro.html b/mup/docs/uguide/intro.html
new file mode 100644 (file)
index 0000000..6a698a4
--- /dev/null
@@ -0,0 +1,63 @@
+<HTML>
+<HEAD><TITLE>
+Introduction to Mup
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="index.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="basics.html">next page --&gt;</A>
+</P>
+           
+<H1>
+INTRODUCTION
+</H1>
+<P>
+The music publisher program called &quot;Mup&quot; takes a text file describing
+music as input, and generates PostScript*
+output for printing that music.
+The input file can be created using your favorite text editor, or with the
+help of the companion Mupmate program, or generated
+from any other source, such as another program. The input must be written
+in a special language designed especially for describing music. The majority
+of the Mup User's Guide is the explanation of this language and how to use it.
+</P>
+<P>
+Mup has the power to print almost any kind of music, everything from
+a single melody line to full orchestral or choral scores complete with
+tempo and dynamic marks. In addition to standard 5-line staffs, it can handle
+1-line staffs (typically used for percussion),
+and tablature notation (typically used for guitar).
+Because Mup can do so much, it takes a while to
+master its entire language. However, it has built-in default values for
+many things, so that you can start using it for simple songs after
+<A HREF="basics.html">learning just the basics,</A>
+then learn the more complicated features as you need them.
+Mup also has an option to produce
+<A HREF="midi.html">output in the standard Musical Instrument Digital Interface (MIDI) format.</A>
+</P>
+<P>
+Mup is shareware. That means you may try it out before buying it, and that
+you may make copies for others, but anyone who wants to keep and
+use Mup must pay a shareware registration fee. Running Mup with the -r
+option (or /r option for MS-DOS** or Windows**)
+will print the
+<A HREF="register.html">registration form,</A>
+with the relevant information.
+Or if you are using Mupmate, the menu-driven interface on top of Mup,
+you can get the registration form from the Config Menu.
+Anyone may download an unregistered copy of Mup via ftp from ftp.arkkra.com
+or via a Web browser from www.arkkra.com.
+Music generated by an unregistered copy of Mup will include a notice
+stating the program is unregistered, but all the features of a registered
+copy are included.
+<BR>
+<HR>
+* PostScript is a trademark of Adobe Systems Incorporated
+<BR>
+** MS-DOS and Windows are trademarks of Microsoft Corporation
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="index.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="basics.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/invisbar.html b/mup/docs/uguide/invisbar.html
new file mode 100644 (file)
index 0000000..b41402f
--- /dev/null
@@ -0,0 +1,81 @@
+<HTML>
+<HEAD><TITLE>
+Special uses of invisbar
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="adjust.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="chant.html">next page --&gt;</A>
+</P>
+            
+<H2>
+Special uses of invisbar
+</H2>
+<P>
+The &quot;invisbar&quot; can be used
+to force Mup into
+doing something in the middle of a bar that it normally would allow
+to happen only at a bar line.
+Suppose, for example, you wish to place a
+<A HREF="bars.html#reh">rehearsal letter</A>
+in the middle of a measure. This could be accomplished as follows:
+<BR><PRE>
+// assume we are in 4/4 time, but want
+// a rehearsal letter by count 3
+// of the measure
+
+// do first part of measure and use &quot;space&quot;
+// for last part so time values will add up
+// properly to a full measure
+1: 4c;d;2s;
+
+// put in invisible bar with rehearsal letter
+invisbar rehearsal let
+
+// now do the last half of the measure,
+// this time with space at the beginning
+1: 2s;4e;c;
+bar
+</PRE><BR>
+<IMG SRC="mugex87.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+As another example of invisbar use, suppose you want to add a &quot;courtesy&quot;
+key signature at the end of a repeated section to remind the player that the
+beginning of the repeated section is in a different key. This can be done
+by adding an empty measure whose sole purpose is to produce this key signature.
+<BR><PRE>
+score key=3&amp;
+music
+1: g;f;e;d;
+repeatstart
+1: c;e;f;g;
+dblbar
+score key=0&amp;
+music
+1: g;f;e;d;
+bar ending &quot;1.&quot;
+1: f;e;2c;
+// add a courtesy key signature,
+// to remind player the beginning
+// of the repeated section is in
+// a different key
+invisbar
+score key=3&amp;
+music
+1: ms;
+repeatend ending &quot;2.&quot;
+1: e;d;2c;
+endbar
+</PRE><BR>
+<IMG SRC="mugex88.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+You can use a similar technique to insert time signatures, clefs, etc.
+at unusual places.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="adjust.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="chant.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/linecurv.html b/mup/docs/uguide/linecurv.html
new file mode 100644 (file)
index 0000000..fda9187
--- /dev/null
@@ -0,0 +1,134 @@
+<HTML>
+<HEAD><TITLE>
+Lines and curves
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="prnttext.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="newscore.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Lines and curves
+</H2>
+<P>
+The &quot;line&quot; statement is used for drawing lines. Its format is:
+<BR><PRE>
+<I>linetype</I> <B>line (</B><I>X1, Y1</I><B>) to (</B><I>X2, Y2</I><B>)</B>
+</PRE><BR>
+The <I>linetype</I> can be &quot;wide,&quot; &quot;medium,&quot; &quot;wavy,&quot; &quot;dotted,&quot; &quot;dashed,&quot;
+or it can be omitted, which means narrow.
+The wavy line could be used for glissandos. It could also be used
+for manually drawing rolls and trills, although it should rarely if ever
+be necessary to resort to this, since the
+<A HREF="roll.html">roll</A>
+and
+<A HREF="mussym.html">mussym</A>
+statements will usually suffice and are much easier to use.
+Narrow, dashed, or dotted lines would typically be used for voice crossings.
+The medium line is about twice as wide as a
+narrow line, and a wide line is about twice as wide as a medium line.
+</P>
+<P>
+The X and Y coordinates are specified as was described
+in the section on
+<A HREF="tags.html">"Location tags."</A>
+<BR><PRE>
+score
+  vscheme=2f
+  staff2 clef=bass
+
+music
+1 1: c+ =c;e =e;g;c+;
+1 2: e =_e;g =_g;c =_c;s;
+2 1: 2.s;4g =_gg;
+2 2: 1ce;
+line (c.e + 2, c.y) to (e.w - 2, e.y)
+line (_e.e + 2, _e.y) to (_g.w - 2, _g.y)
+dashed line (_c.e + 1, _c.y) to (_gg.w - 1, _gg.y)
+bar
+</PRE><BR>
+<IMG SRC="mugex83.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+It is possible to print a text string by the line by adding
+<BR><PRE>
+<B>with </B><I>fontfamily font </I><B>(</B><I>size</I><B>) &quot;</B><I>string</I><B>&quot;</B>
+</PRE><BR>
+at the end of the &quot;line&quot; statement. Only the keyword &quot;with&quot; and the
+text string itself are required; the font and size information is optional.
+As usual, the
+<A HREF="param.html#fontfam">fontfamily,</A>
+<A HREF="param.html#font">font,</A>
+and
+<A HREF="param.html#size">size</A>
+parameter values are used to get values if the optional items are
+omitted. The most common usage for printing a string with a line is probably
+for glissandos.
+<BR><PRE>
+1: 2d =n; g+ =m;
+wavy line (n.e + 1.5, n.y) to (m.w - 1.5, m.y) with ital (9) &quot;gliss.&quot;
+bar
+</PRE><BR>
+<IMG SRC="mugex84.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+Arbitrary curves can be drawn using the &quot;curve&quot; statement:
+<BR><PRE>
+<I>linetype</I> <B>curve (</B><I>X1,Y1</I><B>) to (</B><I>X2,Y2</I><B>) to (</B><I>X3,Y3</I><B>)</B> <I>...</I>
+</PRE><BR>
+When using this form of the &quot;curve&quot; statement,
+at least three coordinates must be specified; more are permitted.
+The <I>linetype</I> can be &quot;medium,&quot; &quot;wide,&quot; &quot;dashed,&quot;
+or &quot;dotted,&quot; or omitted.
+A curve will be drawn through the specified points in the specified order.
+<BR><PRE>
+score
+staffs=2
+
+staff 2
+  clef=bass
+
+music
+1: 4.s;[=c] 8e; [=d] g; [=e] e;4s;
+2: [=a] 8c;g; [=b] c+;4.s; [=f] 8c+; [=g] c;
+medium curve (a.x, a.n+1) to (b.x, b.n+15) to (c.x, c.n+4) \
+               to (d.x, d.n+3) to (e.x, e.n+3) \
+               to (f.x, f.n+11) to (g.x, g.n+1)
+bar
+</PRE><BR>
+<IMG SRC="mugex85.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+An alternative way to specify a curve is to only specify the two endpoints,
+along one or more &quot;bulge&quot; values, given in stepsizes.
+Suppose a single bulge value <I>n</I> is given. To find the midpoint of
+the resulting curve, imagine a line is drawn between the two endpoints,
+then from the midpoint of that line, move perpendicular to the line for 
+<I>n</I> stepsizes.
+A positive <I>n</I> will cause the curve to bulge
+to the left as you move from the start point to the end point,
+while a negative <I>n</I> will make it bulge to the right.
+If two bulge values are given, bulges are calculated from the 1/3 and
+2/3 point of the line between the endpoints; with three points, at 1/4,
+1/2, and 3/4, and so forth. Multiple bulge values are separated by commas.
+<BR><PRE>
+1: c =_c1; f; f; d =_d1;
+medium curve (_c1.x, _c1.y + 8) to (_d1.x, _d1.y + 10) bulge 3
+bar
+
+1: g =_g1; e+; d+; a =_a1;
+dotted curve (_g1.x, _g1.y - 2) to (_a1.x, _a1.y - 2) bulge -4.3
+bar
+
+1: g =_g2; a; d+; c+ =_c2;
+curve  (_g2.x, _g2.y - 2) to (_c2.x, _c2.y + 2) bulge -2.5, 4
+bar
+</PRE><BR>
+<IMG SRC="mugex86.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="prnttext.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="newscore.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/lyrics.html b/mup/docs/uguide/lyrics.html
new file mode 100644 (file)
index 0000000..682a81c
--- /dev/null
@@ -0,0 +1,399 @@
+<HTML>
+<HEAD><TITLE>
+Lyrics
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="multirst.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="tabstaff.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Lyrics
+</H2>
+<P>
+Lyrics are specified in a somewhat similar manner to
+<A HREF="chordinp.html">note groups.</A>
+Lyrics for each staff are specified with the word &quot;lyrics&quot;
+optionally followed by a <I>place</I>,
+followed by the <I>staff number</I>, followed by a colon, then the timing and
+syllable information.
+</P>
+<P>
+The <I>place</I>, if specified, can be &quot;above&quot; or &quot;below,&quot; to
+indicate whether the lyrics are to be printed above or below the given
+staff. The default is below.
+</P>
+<P>
+The <I>staff number</I> can be a single number or list of ranges of numbers.
+It can also be given as the keyword &quot;all,&quot; which will place the lyrics
+above the top visible staff or below the bottom visible staff.
+</P>
+<P>
+The place can also be specified as &quot;between <I>M</I><B>&amp;</B><I>N</I>&quot;
+where <I>M</I> and <I>N</I> are numbers.
+This will cause the lyrics to printed approximately halfway between staff
+<I>M</I> and staff <I>N</I>. <I>N</I> must be exactly one greater than <I>M</I>.
+<BR><PRE>
+lyrics 1:
+lyrics above 2,3:
+lyrics between 1&amp;2, 3&amp;4:
+</PRE><BR>
+</P>
+<P>
+If you want the same lyrics above some staffs but below others,
+you can specify several places and list of staffs, separated by semicolons.
+For example:
+<BR><PRE>
+lyrics above 1,3 ; below 2,4 ; between 5&amp;6 :
+</PRE><BR>
+</P>
+<P>
+After the colon comes a list of
+time values.
+Time values are separated by semicolons and are specified as they are
+for notes: &quot;2&quot; for half notes, &quot;8.&quot; for dotted eight, etc.
+</P>
+<P>
+If the time values for lyrics are the same as the time values for the notes
+on the staff, the time values need not be specified. If you don't
+specify them, Mup will derive the appropriate values from the music input.
+If you list more than one staff, the time values will be derived from the
+first staff you list. Usually, the time values will be derived from voice 1,
+but if voice 1 music data doesn't exist or is invisible,
+or if the lyrics are explicitly specified as &quot;below&quot;
+and there is a visible voice 2, then voice 2 will be used.
+Voice 3, if any, is never used for automatically
+deriving time values for lyrics.
+Some examples:
+<BR><PRE>
+
+1: c;d;e;f;
+lyrics 1: &quot;The sun will shine&quot;;
+// The time values will be all quarter notes,
+// as derived from the music on staff 1
+bar
+
+1: 8g;4.f;4g;a;
+lyrics 1: &quot;up-on the earth.&quot;;
+// The derived time values will be 8;4.;4;;
+bar
+
+// In these examples, time values will be taken
+// from staff 4, since it is the first one listed.
+// In the last case, because &quot;below&quot; is specified explicitly,
+// the times will be taken from voice 2
+// if there is a visible voice 2; in all the other cases
+// it will be taken from voice 1 if voice 1 music
+// has been entered and is visible.
+lyrics 4,7,9: &quot;for-ev-er&quot;;
+lyrics above 4-6: &quot;nev-er-more&quot;;
+lyrics between 4&amp;5,6&amp;7: &quot;this is it&quot;;
+lyrics below 4,2: &quot;and so forth&quot;;
+</PRE><BR>
+The line describing the music from which to derive the times
+must appear in the input prior to the lyrics line that is deriving the times.
+If chords in the music are tied or slurred together, Mup will 
+treat those chords as being for a single syllable.
+However, there may be some 
+circumstances in which the rules Mup uses to derive time values may not
+yield what you want, in which case you will have to explicitly specify the times
+for that measure.
+</P>
+<P>
+Following the time values is a list of one or more
+verse numbers and lyric strings containing the words of the lyrics.
+The verse number(s) are given within square brackets. If no verse is
+specified on the first set of lyrics for a staff and
+place, verse 1 is assumed.
+On subsequent lyrics strings for that staff and place,
+the verse number is assumed to be one more than the previous verse number.
+Thus you only need to explicitly specify a verse
+number if you want to skip over a verse or supply them out of order.
+</P>
+<P>
+Verse numbers need not be consecutive.
+The staff number and verse number can be given as lists or ranges.
+Another example:
+<BR><PRE>
+1-2: 4.c+;8c;{4e;f;g;}3;
+lyrics below 1-2: 4.;8;{4;;;}3; \
+        &quot;This is some-thing else.&quot;; \
+        [4,5] &quot;How do you like this?&quot;; \
+        [2-3,6] &quot;Now try this out too.&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex41.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+In this example, the lyrics will go below staffs 1 and 2. There are
+5 syllables. The first is a dotted quarter in length, the second is
+an eighth, and the last three make up a quarter note triplet. The first
+string is for verse 1, since no verse number was specified. The second
+string will be used for verses 4 and 5, and the last string for verses
+2, 3, and 6.
+</P>
+<P>
+<A NAME="centered">You can also specify a verse number of "c" which means the verse is</A>
+to be centered vertically. This is useful if you have a refrain that
+is identical for several verses, and you don't want to have it printed
+multiple times.
+<BR><PRE>
+1: c;;e;;
+lyrics 1: ;;2s; [1] &quot;verse one&quot;; [2] &quot;verse two&quot;;
+lyrics 1: 2s;4;; [c] &quot;The refrain&quot;;  // centered lyrics
+bar
+</PRE><BR>
+<IMG SRC="mugex42.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+The lyrics string is followed by a semicolon.
+There must normally be one syllable in the lyrics string for each time value.
+<A HREF="lyrics.html#except">(There is one exception,</A>
+discussed later.)
+Syllables are separated in the lyrics string by white space,
+a dash, or an underscore. 
+</P>
+<P>
+Sometimes a syllable is to be held out for several counts
+or over several notes. This can be indicated by dashes or underscores.
+If the syllable in the lyric string ends with a dash, on output the dash
+will be placed halfway between the given syllable and the next syllable.
+If the distance between the two syllables is long, several evenly-spaced
+dashes will be printed.
+If a syllable in the lyric string ends with an underscore,
+an underscore line will be printed from the end of the
+current syllable to the edge of the last note associated with the syllable.
+</P>
+<P>
+Here are some examples:
+<BR><PRE>
+// Verse 1. The first two words have the
+// duration of a quarter note each.
+// The last word lasts a half note.
+1: e;d;2c;
+lyrics 1: 4;;2; [1] &quot;Three blind mice&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex43.gif" ALT="Picture of Mup output"><BR>
+<BR><PRE>
+// examples of above lyrics with dash and underscore
+1: 4d&lt;&gt;;e;8g;b;4a;
+lyrics above 1: &quot;now_ or nev-er&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex44.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+Mup does its best to figure out where to end dashes or underscores. However,
+if there isn't a following syllable after a dash or underscore, Mup would
+extend the dash or underscore to the end of the piece, which may not be
+what you want. There are a few other cases where Mup may be unable to
+properly deduce where you had intended an underscore to end.
+You can manually halt the dash or underscore by adding in
+an &quot;empty syllable,&quot; consisting of &quot;&lt;&gt;&quot;. Normally, the angle brackets are
+used inside lyrics to enclose special non-lyrics items, as will be
+<A HREF="lyrics.html#lyrext">described a bit later.</A>
+However, if they are used by themselves with nothing between them,
+they essentially mean a syllable with no text.
+<BR><PRE>
+1: 2c;4d&lt;&gt;;e;
+lyrics 1: &quot;last word._&quot;;
+bar
+
+1: 4d;e;f;g;
+// add empty syllable to end the underscore
+lyrics 1: 1; &quot;&lt;&gt;&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex45.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+Occasionally, a single chord is used for more than one syllable.
+If the syllables are within the same word, it is sufficient to omit the
+dashes between syllables, so that Mup will treat them as a single syllable.
+However, if the syllables are in separate words,
+a &quot;~&quot; can be used in place of a space between the syllables.
+On output, Mup will replace the &quot;~&quot;
+with a space and a small, curved line below the space, indicating that the
+syllables on either side are to be joined. For example:
+<BR><PRE>
+1: b;a;2g;
+lyrics 1: ;;2; &quot;man-y~a day&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex46.gif" ALT="Picture of Mup output"><BR>
+If you don't want the curved line,
+you can use the special character name &quot;\(space)&quot; instead of a
+literal space.
+<A HREF="textstr.html#space">That special space character</A>
+is printed like a normal space on output,
+but is not considered a space for the purposes of determining syllable
+boundaries. Alternately,
+<A HREF="lyrics.html#lyrext">a technique using angle brackets,</A>
+described later, can be used.
+</P>
+<P>
+If several verses use the same time values, you can specify them all on
+one input line.
+For example:
+<BR><PRE>
+1: d;f;a;g;
+lyrics 1: [1] &quot;this is verse one&quot;; \
+       [2] &quot;this is verse two&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex47.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+In this example,
+because of the \ at the end of the first line, both verses are effectively
+on the same input line.
+</P>
+<P>
+<A NAME="except">Occasionally, lyrics may occur during only part of a measure.</A>
+This case can be handled by specifying &quot;space&quot;
+by using an &quot;s&quot; after time values that have no
+lyric syllable associated with them. For example:
+<BR><PRE>
+1: 2r;g;
+lyrics 1: 2s;; [1] &quot;Now&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex48.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+In this example, the first half note of the measure is a space, so there will
+be no lyric there. The second half note of the measure will have the word &quot;Now&quot;
+as its lyric. Note that the &quot;s&quot; does not work quite the same way with lyrics
+as it does with notes. With notes, &quot;2s;;&quot; would mean two half-note spaces,
+because the space would be used as default for the following chord where no
+notes were specified. With lyrics, &quot;2s;;&quot; means a half note space, followed
+by a half note lyric; the space is not carried forward as a default.
+</P>
+<P>
+If you don't specify any time values, relying on Mup to derive the time values
+from the corresponding music time values, any rests and spaces in the music
+will be translated to lyric spaces. If the first note entered in a chord
+is tied to or slurred to the following chord, that following chord
+will also be translated to a lyric space, since you most likely want
+a single syllable to span both chords in that case.
+</P>
+<P>
+<A NAME="lyrext">Occasionally, you may want to print something within a lyric string</A>
+which isn't really a lyric syllable.
+The most common example of this would be
+that you may want to print verse numbers. Other possibilities may include
+associating a dynamic mark (e.g., &quot;mf&quot;) with a particular verse, or
+marking a section for a subset of the singers (e.g., &quot;Men:&quot; or &quot;Solo:&quot;).
+These extra things are specified within angle brackets. They can be placed
+immediately before or after any syllable.
+Mup will not consider them when lining up the syllable with notes.
+Normally, it will assume there is enough
+space to print them rather than reserving space for them. If you want Mup
+to ensure there is enough space to print them, put a &quot;^&quot; immediately
+after the &quot;&lt;&quot;.
+</P>
+<P>
+Some examples:
+<BR><PRE>
+1: f;e;d;c;
+lyrics 1: &quot;&lt;1. &gt;This is verse one.&quot;;
+bar
+1: 2g;4;;
+lyrics 1: 2s;4;; &quot;&lt;^\f(TX)ff\f(PV) &gt;Loud-er&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex49.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+The &lt; &gt; construct can also be used to fine-tune the placement of syllables.
+The placement of syllables is governed in general by the
+<A HREF="param.html#lyralign">lyricsalign parameter.</A>
+Sometimes, however, you may want to adjust the placement of specific syllables.
+Suppose you have a long syllable, like &quot;strength&quot; and would like
+to shift it leftward somewhat. Entering it as &quot;&lt;str&gt;ength&quot; would
+cause Mup to move the syllable farther to the left than it normally would.
+<BR><PRE>
+1: c;d;e;f;
+lyrics 1: &quot;This strength not moved.&quot;; \
+        &quot;This &lt;str&gt;ength was moved.&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex50.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+Angle brackets may also be useful for entering
+chant, where many words
+are to be associated with a single note. For example:
+<BR><PRE>
+lyrics 1: &quot;All&lt;^ these words will be treated like one syllable.&gt;&quot;;
+</PRE><BR>
+</P>
+<P>
+The font and size to use for lyrics is initially determined
+from the
+<A HREF="param.html#lyrfam">"lyricsfontfamily,"</A>
+<A HREF="param.html#lyrfont">"lyricsfont"</A>
+and
+<A HREF="param.html#lyrsize">"lyricssize"</A>
+parameters for the appropriate staff.
+If &quot;all&quot; is used for the staff number, the score parameters are used.
+In the case of &quot;between,&quot; the parameters for the staff above are used for
+determining the font and size.
+The usual \f and \s forms can be used to
+<A HREF="textstr.html">change these values</A>
+for a given verse. Lyrics fontfamily, font and size values
+are maintained separately for each
+combination of staff number, verse number, and place, and are carried forward
+from one measure to the next. Thus, for example, if you want one verse to
+be printed in roman and another in italics (perhaps one is in English and the
+other in another language), you need only put a &quot;\f(TI)&quot; at the beginning of
+the syllable string for the first measure of the second verse, and all
+subsequent syllables for that verse will be in italics.
+Setting the
+<A HREF="param.html#lyrfam">"lyricsfontfamily,"</A>
+<A HREF="param.html#lyrfont">"lyricsfont"</A>
+or
+<A HREF="param.html#lyrsize">"lyricssize"</A>
+parameters will reset the values for
+all verses of the staff (if set in
+<A HREF="contexts.html">staff context),</A>
+or the entire score (if set in
+<A HREF="contexts.html">score context).</A>
+</P>
+<P>
+Another way to align a syllable in a particular way is to precede the
+syllable with a |. If the | is preceded by a number (optionally signed),
+the left edge of the syllable will be placed that many points from the
+horizontal &quot;middle&quot; of the chord.
+If there isn't a number before it, the value is obtained from the
+<A HREF="param.html#sylpos">sylposition parameter.</A>
+Negative values are to the left, and will usually be what you want.
+This alignment method is particularly useful for lining up multiple verses,
+either to get verse numbers to line up or to align words at the beginning
+of a poetic line. The | goes after anything in angle brackets.
+<BR><PRE>
+1: 8c;d;4e;8e;g;4c+;
+lyrics 1: &quot;&lt;1. &gt;|\&quot;How are you?\&quot; -7|He asked her.&quot;; \
+          &quot;&lt;2. &gt;|\&quot;I am fine,\&quot; -7|She re-plied.&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex51.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+A few more examples of lyrics:
+<BR><PRE>
+1,3-4: c;8e;;4d;r;
+2: c+;8g;;4b;;
+lyrics between 1&amp;2,3&amp;4: 4;8;;4;s; &quot;This is a test.&quot;;
+lyrics above 2: 2s;4;; &quot;The end.&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex52.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="multirst.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="tabstaff.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/macros.html b/mup/docs/uguide/macros.html
new file mode 100644 (file)
index 0000000..4274b8d
--- /dev/null
@@ -0,0 +1,211 @@
+<HTML>
+<HEAD><TITLE>
+Mup macros
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="headfoot.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="ifclause.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Macros
+</H2>
+<H3>
+Simple Macros (without parameters)
+</H3>
+<P>
+Macros can be defined to avoid retyping or to give mnemonic names to
+things. A macro is defined with the following syntax:
+<BR><PRE>
+<B>define</B> <I> macro_name macro_text</I> <B>@</B>
+</PRE><BR>
+</P>
+<P>
+The <I>macro_name</I> consists of one or more upper case letters, digits,
+and underscores, with the first character being a letter.
+The <I>macro_text</I> can be any text. It can be any length from empty
+to many pages. The &quot;@&quot; terminates the macro. A literal &quot;@&quot; can be
+placed in the <I>macro_text</I> by preceding it with a backslash.
+If you want a literal backslash in the <I>macro_text</I>, it also must
+be preceded by a backslash.
+</P>
+<P>
+A macro is called by stating the <I>macro_name</I> in the input. The
+<I>macro_name</I> is replaced by the <I>macro_text</I>. 
+A macro can be defined at any point in the input. It can be used as
+often as desired any time after it has been defined. A given <I>macro_name</I>
+can be redefined as many times as desired, with each new definition
+overwriting the previous definition.
+</P>
+<P>
+As an example, suppose you are printing an orchestral score, and the oboe
+part happens to be on staff 5. Rather than having to remember which staff
+it is, you could define a macro:
+<BR><PRE>
+define OBOE 5: @
+</PRE><BR>
+Not only is the name easier to remember than a number, but if you later
+decide to move the oboe part to a different place in the score, only the
+macro definition and perhaps a few other things would have to be changed.
+</P>
+<P>
+Another common use of macros might be if a musical motif occurs several
+times. You could define a macro for the motive:
+<BR><PRE>
+define SCALE 8c;d;e;f;g;a;b;c+; @
+</PRE><BR>
+then do something like:
+<BR><PRE>
+OBOE SCALE
+</PRE><BR>
+</P>
+<P>
+It is possible to remove the definition of a macro using the &quot;undef&quot;
+statement:
+<BR><PRE>
+undef OBOE
+</PRE><BR>
+</P>
+<P>
+It is possible to have parts of the input skipped over depending on whether
+certain macros are defined or not. This is done using
+&quot;ifdef,&quot; &quot;else,&quot; and &quot;endif.&quot; The keyword &quot;ifdef&quot; is followed by
+a macro name. If a macro by that name is currently defined,
+Mup will continue
+reading and processing input normally. If it finds a matching &quot;else,&quot;
+it will skip over input until the matching &quot;endif.&quot;
+If the macro is not currently defined, Mup will skip over the input
+until it finds a matching &quot;else&quot; or &quot;endif.&quot;  There is also
+an &quot;ifndef&quot; command that uses the opposite logic: it will read the input
+up to the &quot;else&quot; or &quot;endif&quot; only if the macro is NOT defined.
+</P>
+<P>
+The ifdefs can be sprinkled between other items in the input;
+they need not be on separate lines. They can be nested. Examples:
+<BR><PRE>
+// make last c an octave higher if macro &quot;FRED&quot; is defined
+1: c;e;g;c ifdef FRED + endif;
+
+ifdef PIANO
+    staff 1 visible=n
+else
+    ifdef VIOLIN
+        staff 2 visible=n
+        staff 3 visible=n
+    endif
+endif
+</PRE><BR>
+</P>
+<P>
+<A HREF="cmdargs.html#doption">Macros can also be set from the command line using the -D option.</A>
+Only ordinary macros can be defined using the -D option,
+not macros with parameters.
+</P>
+<H3>
+Macros with parameters
+</H3>
+<P>
+<A NAME="macparm">Macros defined within Mup input can be defined to have "parameters."</A>
+This may be useful
+when you have something that is repeated with small variations.
+When defining a macro with parameters, the macro name must be followed
+immediately by a ( with no space between the end of the name and the
+parenthesis. The opening parenthesis is followed by one or more
+parameter names, separated by commas, and ending with a close parenthesis.
+Parameter names have the same rules as macro names: they consist of
+upper case letters, numbers, and underscores, starting with an upper case
+letter. The parameter names can then appear in the text of the macro
+definition where you want a value to be substituted.
+</P>
+<P>
+As an example, suppose you are doing a score with staffs 1 through 4
+for vocal parts, and staffs 5 and 6 for a piano accompaniment, and that
+you frequently want to mark a dymanics change at the same point in time
+below each of the vocal scores and between the two piano staffs.
+You could typically do this with something like:
+<BR><PRE>
+boldital below 1-4: 1 &quot;ff&quot;;
+boldital between 5&amp;6: 1 &quot;ff&quot;;
+</PRE><BR>
+but if you needed to do this lots of times, it could get tedious.
+So let's define a macro with parameters:
+<BR><PRE>
+define DYN( COUNT, VOLUME )
+boldital below 1-4: COUNT VOLUME;
+boldital between 5&amp;6: COUNT VOLUME;
+@
+</PRE><BR>
+This macro has two parameters,
+which have been given the names COUNT and VOLUME.
+When you call the macro, you will give them values.
+For example,
+<BR><PRE>
+DYN(1,&quot;ff&quot;)
+</PRE><BR>
+would give a VOLUME of &quot;ff&quot; at COUNT 1, whereas
+<BR><PRE>
+DYN(3.5,&quot;mp&quot;)
+</PRE><BR>
+would give a VOLUME of &quot;mp&quot; at COUNT 3.5.
+</P>
+<P>
+When calling a macro with parameters, the values to give the parameters
+are given inside parentheses. The values are separated by commas.
+The values in the parentheses are copied exactly as they are,
+including any spaces, newlines, macro names, etc.
+There are only a few exceptions to this:
+you can include a comma, closing parenthesis, or backslash
+as part of a parameter value by preceding it with a backslash, and
+a backslash followed by a newline
+in a parameter value will be discarded. Thus a macro call of
+<BR><PRE>
+MAC(\\\,\))
+</PRE><BR>
+has one parameter, the text of which is 3 characters long: a backslash,
+comma, and closing parenthesis.
+</P>
+<P>
+<A NAME="quoting">If in a macro definition a parameter is used inside backticks,</A>
+as in `NAME`, the value of the parameter will be placed
+inside double quotes. Thus, another way to do the example above would be:
+<BR><PRE>
+define DYN( COUNT, VOLUME )
+boldital below 1-4: COUNT `VOLUME`;
+boldital between 5&amp;6: COUNT `VOLUME`;
+@
+
+DYN(1,ff)
+DYN(3.5,mp)
+</PRE><BR>
+</P>
+<P>
+Conceptually, when the macro is expanded, the backticks are replaced
+by double quote marks, but in addition,
+any double quote mark found in the value being passed to the parameter will
+have a backslash inserted before it, and any backslash that occurs
+within double quotes in the value will also have a backslash inserted
+before it. Thus, for example:
+<BR><PRE>
+// If we define a macro like this:
+define QUOTED(X) `X` @
+
+// then for input    value passed is    `X` would be    which would print as
+
+print QUOTED(hello)       hello          &quot;hello&quot;          hello
+print QUOTED(&quot;hello&quot;)     &quot;hello&quot;        &quot;\&quot;hello\&quot;&quot;      &quot;hello&quot;
+print QUOTED(\\n)         \n             &quot;\n&quot;             a literal newline
+print QUOTED(&quot;\\n&quot;)       &quot;\n&quot;           &quot;\&quot;\\n\&quot;&quot;        &quot;\n&quot;
+</PRE><BR>
+</P>
+<P>
+Sometimes it can be a little tricky to get the number of backslashes right,
+or other details like that.
+<A HREF="cmdargs.html#Eoption">The -E Mup command line option</A>
+shows how macros will expand, which may help you figure out what to do.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="headfoot.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="ifclause.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/mantup.html b/mup/docs/uguide/mantup.html
new file mode 100644 (file)
index 0000000..823284c
--- /dev/null
@@ -0,0 +1,47 @@
+<HTML>
+<HEAD><TITLE>
+Manually placed tuplet numbers
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="sharehd.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="manual.html">next page --&gt;</A>
+</P>
+           
+<H2>
+Manually placed tuplet numbers
+</H2>
+<P>
+Generally, Mup will place
+<A HREF="tuplets.html">tuplet</A>
+numbers for you.
+However, you do need to print them yourself on
+<A HREF="ichdattr.html#crossbm">cross-staff beams.</A>
+And there may be cases where you choose
+to use 'n' to turn off Mup's automatic printing of tuplet numbers,
+in order to print them manually in a different place than Mup would.
+Mup normally uses newcentury boldital font for tuplet numbers, in 11-point
+size for regular notes and 9-point for cue notes.
+So to make your manually placed tuplet numbers
+look the same as automatic ones, you might use a
+<A HREF="macros.html">macro</A>
+something like this:
+<BR><PRE>
+define TUPNUM(NUM) &quot;\f(NX)\s(11)&quot; +`NUM` @
+1: { 8c; d; e; } 3n; 2.us;         
+rom above 1 dist0: 1.34 TUPNUM(3);
+bar
+</PRE><BR>
+Or another approach would be something like this:
+<BR><PRE>
+define TN(NUM,WHERE,D,N) newcentury boldital WHERE dist D: N `NUM`;@
+1: { 8c; d; e; } 3n; 2.us;         
+TN(3,above 1,0,1.34)
+bar
+</PRE><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="sharehd.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="manual.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/manual.html b/mup/docs/uguide/manual.html
new file mode 100644 (file)
index 0000000..190c9e4
--- /dev/null
@@ -0,0 +1,92 @@
+<HTML>
+<HEAD><TITLE>
+Manual placement of notes
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="mantup.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="brackmac.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Manual placement of notes
+</H2>
+<P>
+Mup supports up to three voices per staff. If you need more than that, such as
+when 4 notes of different lengths occur on the same beat, it is possible
+to position extra notes manually.
+Manually positioned notes will not be included in
+<A HREF="midi.html">MIDI output.</A>
+</P>
+<P>
+First of all, unless the fourth voice is vertically far away from the other two,
+you'll probably need to reserve some
+extra space to the left or right of the other chords. This can be done
+by adding a bit of
+<A HREF="chrdattr.html#pad">padding to the chord.</A>
+If you want the extra note on the left of the regular
+voices, add padding to whichever regular voice is leftmost. If you want it
+on the right, the padding will have to go on the following note, or on
+the bar line if you are on the last chord of a measure. The amount of
+padding to add may have to be determined by trial and error; 5 stepsizes
+is a good first guess. Next, set a
+<A HREF="tags.html">location tag</A>
+<A HREF="noteattr.html#ntag">on one of the notes</A>
+in one of the regular groups.
+The manually-positioned note will be placed relative to
+that location tag. The x will be slightly left or right of the
+west or east of the existing group; something like 3 stepsizes might be
+a good first guess. The y can be specified in terms of
+stepsizes up from the note you used for the location tag. You can use a
+<A HREF="prnttext.html">print statement</A>
+using one of the special
+<A HREF="textstr.html#symlist">music characters,</A>
+such as:
+dblwhole, 1n, up2n, dn2n, up4n, up32n, etc. If the note needs ledger lines,
+dots, or accidentals, these too have to be manually positioned,
+which can be a bit tricky. Here is a simple example:
+<BR><PRE>
+score
+vscheme=3o
+beamstyle=4,4,4,4
+
+music
+1 1: [pad 4] 4g =h; a; b; a;
+1 2: 4.c;8;2;
+1 3: [down] 8e;; [ho 0] 2.f;
+print (h.w - 2.3, h.y + 3) &quot;\(up2n)&quot;
+bar
+</PRE><BR>
+<IMG SRC="mugex90.gif" ALT="Picture of Mup output"><BR>
+In this example, 4 stepsizes of padding
+was added to the quarter note g of voice 1
+on staff 1. A location tag &quot;h&quot; was set to this note. After the information
+about the second voice on staff 1, a half note was manually placed
+2.3 stepsizes left of the first voice and at pitch c+ (3 steps up from the g).
+</P>
+<P>
+If you also need to place an accidental and/or dots, more padding should be
+requested, and additional print statements used for each item. For example,
+you could specify perhaps 5 stepsizes of padding, then add:
+<BR><PRE>
+print (h.w - 5, h.y + 3) &quot;\(flat)&quot;
+</PRE><BR>
+<IMG SRC="mugex91.gif" ALT="Picture of Mup output"><BR>
+to place a flat sign in front of the c.
+</P>
+<P>
+Ledger lines needed by the notes also have to be
+placed manually, using the &quot;line&quot;
+command. If the note is more than three steps above or below the staff, more
+than one ledger line would be needed, and each would need to be specified
+separately. The y coordinate of the each ledger line would be the same
+as the y coordinate of the note,
+plus or minus some number of step sizes. The length of
+the line depends on the note head. About 4.5 stepsizes is a good estimate for
+most notes, but a double whole needs more like 6 stepsizes.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="mantup.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="brackmac.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/midi.html b/mup/docs/uguide/midi.html
new file mode 100644 (file)
index 0000000..93731d8
--- /dev/null
@@ -0,0 +1,333 @@
+<HTML>
+<HEAD><TITLE>
+Mup MIDI output
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="pstools.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>                                                                                   
+<H1>
+MIDI OUTPUT
+</H1>
+<P>
+Mup will optionally produce MIDI output
+<A HREF="cmdargs.html#moption">(using the -m command line argument).</A>
+Mup is first and foremost a music publication program,
+so its MIDI capabilities have a few limitations.
+However, the MIDI output is quite useful for &quot;proofreading&quot;
+(or perhaps we should say &quot;proof-listening&quot;).
+It is often easier to spot a typo in Mup input by
+listening to it than to look at the output. Mup provides enough MIDI
+control to do virtually all of what MIDI supports, and will be adequate
+for many people. Others however, may find they want a separate MIDI editor
+for really serious MIDI work.
+</P>
+<P>
+The following section assumes a general knowledge of MIDI. If you are not
+familiar with MIDI, there are many books available on the subject
+at most music stores or computer book stores.
+</P>
+<P>
+Each
+<A HREF="param.html#vscheme">voice</A>
+is put on a separate MIDI track. The first track contains
+general information such as key and time signature. The next track will be for
+staff 1, voice 1. If staff 1 has a second voice, that will be the next
+track, otherwise it will be voice 1 of staff 2, if any, and so forth,
+one track for each voice, top to bottom.
+</P>
+<P>
+Output is in MIDI file format 1, with a default of 120 quarter notes
+per minute, 192 ticks per quarter note. MIDI channel 1 is used by default for
+all voices. If you want to use different instrument sounds for different
+voices, you will need to specify a different channel for each voice, then
+specify the MIDI &quot;program&quot; for that voice. This is demonstrated in some
+of the examples later in this section.
+</P>
+<P>
+Mup MIDI output will handle
+<A HREF="bars.html">repeats</A>
+and
+<A HREF="bars.html#endings">first and second endings,</A>
+but it does not know anything about &quot;D.S. al coda&quot; or anything of that sort. 
+It is possible to work around this limitation to some extent using
+<A HREF="macros.html">macros.</A>
+For example, a section between a &quot;sign&quot; and a &quot;jump to coda&quot; symbol could
+be put inside a macro definition, then the macro can be called. Then later
+in the piece, where the &quot;D. S.&quot; occurs the macro can be called again if MIDI
+is defined. For example:
+<BR><PRE>
+// an introductory section, ends with a sign
+1: c;d;e;f;
+mussym above all: 5 &quot;sign&quot;;
+bar
+
+// define macro for section between sign and
+// symbol to &quot;jump to coda&quot;
+define SECTION
+1: g;a;g;;
+mussym above all: 5 &quot;coda&quot;;
+bar
+@
+
+// print/play the section just defined by
+// the macro
+SECTION
+
+// now do the music up to the D.S.
+1: e;f;2g;
+ital above 1: 1 &quot;D. S. al Coda&quot;;
+dblbar
+
+// human player would now flip back to
+// the sign, so do the MIDI equivalent:
+// play that section again.
+ifdef MIDI
+       SECTION
+endif
+
+// now do the coda
+1: e;d;2c;
+rom above 1: 0 &quot;Coda&quot;;
+endbar
+</PRE><BR>
+</P>
+<P>
+Mup mainly just outputs the note information.
+Mup will recognize
+<A HREF="octave.html">octave marks,</A>
+and move notes up or down appropriately.
+It recognizes
+<A HREF="pedal.html">piano pedal marks.</A>
+It does not attempt to interpret tempo or dynamics marks
+specified by
+<A HREF="textmark.html">"rom," "boldital," etc. or ornaments in</A>
+<A HREF="mussym.html">"mussym" statement.</A>
+It does interpret
+<A HREF="bars.html#reh">rehearsal marks</A>
+as cue points.
+It handles
+<A HREF="chrdattr.html#chstyle">grace notes,</A>
+<A HREF="roll.html">rolls,</A>
+<A HREF="chrdattr.html#slashes">slashes,</A>
+and
+<A HREF="ichdattr.html#alt">alternation groups.</A>
+You can control how legato the music is by using
+<A HREF="param.html#release">the Mup "release" parameter.</A>
+</P>
+<P>
+Some styles of music are often
+written in &quot;swing time,&quot; meaning the
+players are expected to play pairs of notes with the first twice
+as long as the second, even though they are written as if they were the
+same duration, or as if the first were three times as long as the second.
+The most common example would be where the written notation shows
+two eighth notes like 8;; or a dotted rhythm like 8.;16;
+but the musician &quot;knows&quot; that the composer really intended it
+to be played as if it were a triplet {4;8;}3;
+The
+<A HREF="param.html#swing">swingunit</A>
+parameter can be used to get Mup MIDI output to automatically follow
+that performance convention.
+</P>
+<P>
+A MIDI editing program will probably be necessary to add some effects.
+However, it is possible to specify certain directives for MIDI.
+They are of the form:
+<BR><PRE>
+<B>midi</B> <I>S V</I><B>:</B> <I>begintime &quot;keyword=value&quot;;</I>
+</PRE><BR>
+The <I>S</I> and <I>V</I> specify the staff and voice for which the directive is
+to apply. As elsewhere in Mup, an omitted voice will default to voice 1,
+and both staff and voice can be given as a list.
+Certain keywords apply to the entire score. In that case the form
+<BR><PRE>
+<B>midi all:</B> <I>begintime &quot;keyword=value&quot;;</I>
+</PRE><BR>
+is used instead.
+The items specified using &quot;all&quot; are placed on the first track, the track
+containing score-wide information. They are not applied to the
+voices on the other tracks.
+</P>
+<P>
+The <I>begintime</I>, as elsewhere in Mup,
+gives the beat into the measure where the MIDI output is to be placed.
+If notes are to be turned on or off at the same instant in time as the
+<I>begintime</I>, first all &quot;note off&quot; commands are generated, then the &quot;midi&quot;
+command events, then &quot;note on&quot; commands.
+</P>
+<P>
+The <I>keyword=value</I> gives specific information of
+what MIDI output to generate. The following keywords are currently supported:
+<TABLE BORDER=4>
+<TR>
+<TD><B>keyword</B></TD>        <TD><B>values</B></TD>  <TD><B>meaning</B></TD> <TD><B>midi S V</B></TD>        <TD><B>midi all</B></TD>
+</TR>
+<TR>
+<TD>program</TD>       <TD>0-127</TD>  <TD>program change (new instrument)</TD>        <TD>yes</TD>    <TD>no</TD>
+</TR>
+<TR>
+<TD>parameter</TD>     <TD>0-127,0-127</TD>    <TD>parameter</TD>      <TD>yes</TD>    <TD>yes</TD>
+</TR>
+<TR>
+<TD>channel</TD>       <TD>1-16</TD>   <TD>channel</TD>        <TD>yes</TD>    <TD>no</TD>
+</TR>
+<TR>
+<TD>chanpressure</TD>  <TD>0-127</TD>  <TD>channel pressure (after touch)</TD> <TD>yes</TD>    <TD>yes</TD>
+</TR>
+<TR>
+<TD>tempo</TD> <TD>10-1000</TD>        <TD>tempo, quarter notes per minute</TD>        <TD>no</TD>     <TD>yes</TD>
+</TR>
+<TR>
+<TD>seqnum</TD>        <TD>0-65535</TD>        <TD>sequence number</TD>        <TD>yes</TD>    <TD>yes</TD>
+</TR>
+<TR>
+<TD>text</TD>  <TD>text</TD>   <TD>text meta event</TD>        <TD>yes</TD>    <TD>yes</TD>
+</TR>
+<TR>
+<TD>copyright</TD>     <TD>text</TD>   <TD>copyright notice</TD>       <TD>yes</TD>    <TD>yes</TD>
+</TR>
+<TR>
+<TD>name</TD>  <TD>text</TD>   <TD>sequence/track name</TD>    <TD>yes</TD>    <TD>yes</TD>
+</TR>
+<TR>
+<TD>instrument</TD>    <TD>text</TD>   <TD>instrument name</TD>        <TD>yes</TD>    <TD>yes</TD>
+</TR>
+<TR>
+<TD>marker</TD>        <TD>text</TD>   <TD>marker meta event</TD>      <TD>yes</TD>    <TD>yes</TD>
+</TR>
+<TR>
+<TD>cue</TD>   <TD>text</TD>   <TD>cue point</TD>      <TD>yes</TD>    <TD>yes</TD>
+</TR>
+<TR>
+<TD>port</TD>  <TD>0-127</TD>  <TD>MIDI port</TD>      <TD>yes</TD>    <TD>yes</TD>
+</TR>
+<TR>
+<TD>onvelocity</TD>    <TD>1-127</TD>  <TD>note on velocity</TD>       <TD>yes</TD>    <TD>no</TD>
+</TR>
+<TR>
+<TD>offvelocity</TD>   <TD>0-127</TD>  <TD>note off velocity</TD>      <TD>yes</TD>    <TD>no</TD>
+</TR>
+<TR>
+<TD>hex</TD>   <TD>hex data</TD>       <TD>arbitrary MIDI data</TD>    <TD>yes</TD>    <TD>yes</TD>
+</TR>
+</TABLE>
+
+</P>
+<P>
+The keywords can be abbreviated to their first three or more letters,
+except &quot;chanpressure&quot; which requires at least five letters to differentiate
+it from &quot;channel&quot; (&quot;cha&quot; or &quot;chan&quot; will be interpreted as channel).
+In most cases, the &quot;=&quot; is followed by either a number or some text. Exceptions
+to this are discussed in the next few paragraphs.
+</P>
+<P>
+The &quot;parameter&quot; keyword is followed by 2 numbers, separated by a comma.
+The first is the parameter number, the second is the parameter value.
+Thus to set parameter 7 (which is the volume parameter) to 90 for voice
+2 of staff 3, starting at the beginning of the measure, you can use:
+<BR><PRE>
+midi 3 2: 0 &quot;parameter=7,90&quot;;
+</PRE><BR>
+</P>
+<P>
+The &quot;onvelocity&quot; and &quot;offvelocity&quot; keywords can have one or more values,
+separated by commas. If there is only one value, it applies to all notes
+in each chord. If there is more than one value, the first value applies
+to the top note of the chord, the second value to the second-from-the-top
+note, and so forth. If there are more notes in a chord than there are
+values specified, the last value specified applies to all of the remaining
+notes. So, for example, if you want to emphasize the top note of each
+chord because it is the melody, you can specify two values, as in
+<BR><PRE>
+midi 1: 1 &quot;onvelocity=76, 60&quot;;
+</PRE><BR>
+which would cause the top note to have a velocity of 76 and all other
+notes to have a velocity of 60.
+</P>
+<P>
+The &quot;hex&quot; form can be used to insert any arbitrary MIDI data into
+the MIDI file. The value consists of any even number of hexadecimal digits.
+Spaces and tabs can be included in the value field for readability.
+</P>
+<P>
+Note that Mup uses the MIDI standard,
+which numbers instruments from 0 through 127,
+but some MIDI playback programs follow a convention of numbering them
+from 1 through 128.
+</P>
+<P>
+Here are some examples:
+<BR><PRE>
+midi all: 0 &quot;tempo=72&quot;;
+midi 1-2 1-2: 0 &quot;channel=2&quot;; 0 &quot;program=14&quot;; 3.5 &quot;program=76&quot;;
+midi all: 3 &quot;hex= ff 00 02 00 01&quot;;   // sequence number 1
+midi 3,6: 0 &quot;channel=5&quot;; 0 &quot;prog=15&quot;; 0 &quot;instr=dulcimer&quot;;
+// set parameter 7 (usually volume) to 100
+midi 2: &quot;par = 7, 100&quot;;
+</PRE><BR>
+</P>
+<P>
+Here is a more extensive example of how midi commands might be used
+in a song:
+<BR><PRE>
+score
+       staffs=2
+       vscheme=2o
+
+staff 2
+       clef=bass
+
+voice 2 2
+       // Make the bottom voice more staccato
+       release=50
+
+music
+
+// Set the tempo.
+// Start out at 108 quarter notes per minute,
+// but on count 4, slow down to 96 per minute.
+midi all: 0 &quot;tempo=108&quot;; 4 &quot;tempo=96&quot;;
+
+// Put each voice on a different channel
+// using a different instrument sound.
+// The program numbers correspond to the
+// General MIDI sounds as noted.
+midi 1 1: 0 &quot;channel=1&quot;; 0 &quot;program=68&quot;;  //oboe
+midi 1 2: 0 &quot;channel=2&quot;; 0 &quot;program=11&quot;;  //vibraphone
+midi 2 1: 0 &quot;channel=6&quot;; 0 &quot;program=60&quot;;  //french horn
+midi 2 2: 0 &quot;channel=4&quot;; 0 &quot;program=35&quot;;  //fretless bass
+
+// Make the top voice louder, and put an
+// accent on the third beat
+midi 1 1: 0 &quot;onvelocity=86&quot;; 3 &quot;onvelocity=100&quot;; 4 &quot;onvel=86&quot;;
+
+// Set maximum reverb on french horn part,
+// starting at the second beat.
+// (Reverb is parameter 91)
+midi 2 1: 2 &quot;parameter=91, 127&quot;;
+
+// Set chorus on oboe to 75, from the beginning.
+// (Chorus is parameter 93)
+midi 1 1: 0 &quot;param=93, 75&quot;;
+
+// Pan the bass part to middle of left side.
+// (Pan is parameter 10, with a value of 0 being hard left,
+// 64 in the center, and 127 being hard right, so 32 is
+// half way to the left.)
+midi 2 2: 0 &quot;parameter=10, 32&quot;;
+
+// Now the music to be played...
+1 1: e;d;2c;
+1 2: c;b-;2g-;
+2 1: g;f;2e;
+2 2: c;g-;2c;
+bar
+</PRE><BR>
+</P>
+<HR>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="pstools.html">&lt;-- previous page</A>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A></P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/midmeas.html b/mup/docs/uguide/midmeas.html
new file mode 100644 (file)
index 0000000..78472c9
--- /dev/null
@@ -0,0 +1,59 @@
+<HTML>
+<HEAD><TITLE>
+Mid-measure parameter changes
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="chrdattr.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="crossst.html">next page --&gt;</A>
+</P>
+          
+<H3>
+Mid-measure parameter changes
+</H3>
+<P>
+The group attributes can optionally be preceded by mid-measure
+parameter changes.
+This is not used very often, but the most common
+use is to change the
+<A HREF="param.html#clef">clef</A>
+in the middle of a measure. There are two
+other parameters that can also be changed here:
+<A HREF="param.html#defoct">defoct</A>
+and
+<A HREF="param.html#release">release.</A>
+The change is enclosed in double angle brackets.
+After the opening angle bracket is the
+<A HREF="contexts.html">context</A>
+to which the changes applies (score, staff, or voice),
+followed by one or more parameter changes.
+<BR><PRE>
+1: c; e; &lt;&lt;score clef=bass&gt;&gt; 2g;
+bar
+</PRE><BR>
+<IMG SRC="mugex20.gif" ALT="Picture of Mup output"><BR>
+If there is more than one parameter listed, they are separated by semicolons.
+<BR><PRE>
+&lt;&lt; staff clef = tenor ; defoct = 4 &gt;&gt;
+</PRE><BR>
+</P>
+<P>
+If you wish to change parameters in more than one context, multiple
+angle-bracketed items can be given:
+<BR><PRE>
+2-3 2: 2c; &lt;&lt;score release=100&gt;&gt;&lt;&lt;staff clef=alto&gt;&gt;&lt;&lt;voice defoct=3&gt;&gt; c;
+</PRE><BR>
+</P>
+<P>
+If you specify &quot;staff&quot; or &quot;voice&quot; context, the specific staff(s) or voice(s)
+to which the changes apply is based on which staff(s) or voice(s)
+are being described on the input line. So in the example above,
+the clef is changed to alto on staffs 2 and 3, and the defoct is
+changed to 3 for voice 2 on both of those staffs. The release change
+applies to the entire score.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="chrdattr.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="crossst.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/mixtsig.html b/mup/docs/uguide/mixtsig.html
new file mode 100644 (file)
index 0000000..a8b497a
--- /dev/null
@@ -0,0 +1,71 @@
+<HTML>
+<HEAD><TITLE>
+Mixed time signatures
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="crossbar.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="oddeven.html">next page --&gt;</A>
+</P>
+          
+<H2>
+Mixed time signatures
+</H2>
+<P>
+<A NAME="mixdtime">Once in a while, music is written with different</A>
+time signatures
+on different staffs. Mup does not support this directly,
+but it is possible to simulate it
+for the case where the time signatures reduce to the same value, for example,
+3/4 and 6/8 time (since 6/8 taken as a fraction and reduced to lowest terms
+is 3/4). You can make the output use both 3/4 and 6/8 by using a non-printing
+time signature, then placing the time signatures manually. 
+Here is an example of how to do that:
+<BR><PRE>
+score
+       // set time signature to 3/4 but don't print it
+       time=3/4n
+       staffs=2
+
+staff 1
+       // We want this staff to be in 3/4 time,
+       // so beam things in groups of
+       // quarter note times.
+       beamstyle=4,4,4
+
+staff 2
+       // We want this staff to effectively be
+       // in 6/8 time, so we'll beam things
+       // in groups of dotted quarters.
+       beamstyle=4., 4.
+       // In real 6/8 time, the time unit would
+       // be eighth note, so make that the default
+       timeunit=8
+
+music
+
+// Add padding to the first chord on at least one
+// of the staffs, to make room for the manually placed
+// time signatures, and set location tags
+1: [pad 5; =t] c; 8d; e; f; g;
+2: [=s] g; f; g; 4.c;
+
+// Manually place the time signatures
+// They are printed in 16-point newcentury bold font,
+// relative to the location tags that were set.
+// First print the 3/4
+print (t.w - 4, t.y) &quot;\f(newcentury bold)\s(16)3&quot;; 
+print (t.w - 4, t.y - 4) &quot;\f(newcentury bold)\s(16)4&quot;; 
+
+// Then print the 6/8
+print (t.w - 4, s.y) &quot;\f(newcentury bold)\s(16)6&quot;; 
+print (t.w - 4, s.y - 4) &quot;\f(newcentury bold)\s(16)8&quot;; 
+bar
+</PRE><BR>
+<IMG SRC="mugex94.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="crossbar.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="oddeven.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/mugex10.gif b/mup/docs/uguide/mugex10.gif
new file mode 100644 (file)
index 0000000..25b774a
Binary files /dev/null and b/mup/docs/uguide/mugex10.gif differ
diff --git a/mup/docs/uguide/mugex100.gif b/mup/docs/uguide/mugex100.gif
new file mode 100644 (file)
index 0000000..75da3aa
Binary files /dev/null and b/mup/docs/uguide/mugex100.gif differ
diff --git a/mup/docs/uguide/mugex101.gif b/mup/docs/uguide/mugex101.gif
new file mode 100644 (file)
index 0000000..fd5b6e5
Binary files /dev/null and b/mup/docs/uguide/mugex101.gif differ
diff --git a/mup/docs/uguide/mugex11.gif b/mup/docs/uguide/mugex11.gif
new file mode 100644 (file)
index 0000000..04e7a16
Binary files /dev/null and b/mup/docs/uguide/mugex11.gif differ
diff --git a/mup/docs/uguide/mugex12.gif b/mup/docs/uguide/mugex12.gif
new file mode 100644 (file)
index 0000000..a7317ca
Binary files /dev/null and b/mup/docs/uguide/mugex12.gif differ
diff --git a/mup/docs/uguide/mugex13.gif b/mup/docs/uguide/mugex13.gif
new file mode 100644 (file)
index 0000000..497ba22
Binary files /dev/null and b/mup/docs/uguide/mugex13.gif differ
diff --git a/mup/docs/uguide/mugex14.gif b/mup/docs/uguide/mugex14.gif
new file mode 100644 (file)
index 0000000..572d27a
Binary files /dev/null and b/mup/docs/uguide/mugex14.gif differ
diff --git a/mup/docs/uguide/mugex15.gif b/mup/docs/uguide/mugex15.gif
new file mode 100644 (file)
index 0000000..1d87b78
Binary files /dev/null and b/mup/docs/uguide/mugex15.gif differ
diff --git a/mup/docs/uguide/mugex16.gif b/mup/docs/uguide/mugex16.gif
new file mode 100644 (file)
index 0000000..c5230c6
Binary files /dev/null and b/mup/docs/uguide/mugex16.gif differ
diff --git a/mup/docs/uguide/mugex17.gif b/mup/docs/uguide/mugex17.gif
new file mode 100644 (file)
index 0000000..3c31175
Binary files /dev/null and b/mup/docs/uguide/mugex17.gif differ
diff --git a/mup/docs/uguide/mugex18.gif b/mup/docs/uguide/mugex18.gif
new file mode 100644 (file)
index 0000000..4e088d8
Binary files /dev/null and b/mup/docs/uguide/mugex18.gif differ
diff --git a/mup/docs/uguide/mugex19.gif b/mup/docs/uguide/mugex19.gif
new file mode 100644 (file)
index 0000000..6d00e06
Binary files /dev/null and b/mup/docs/uguide/mugex19.gif differ
diff --git a/mup/docs/uguide/mugex2.gif b/mup/docs/uguide/mugex2.gif
new file mode 100644 (file)
index 0000000..2b11833
Binary files /dev/null and b/mup/docs/uguide/mugex2.gif differ
diff --git a/mup/docs/uguide/mugex20.gif b/mup/docs/uguide/mugex20.gif
new file mode 100644 (file)
index 0000000..26d095a
Binary files /dev/null and b/mup/docs/uguide/mugex20.gif differ
diff --git a/mup/docs/uguide/mugex21.gif b/mup/docs/uguide/mugex21.gif
new file mode 100644 (file)
index 0000000..a80ef39
Binary files /dev/null and b/mup/docs/uguide/mugex21.gif differ
diff --git a/mup/docs/uguide/mugex22.gif b/mup/docs/uguide/mugex22.gif
new file mode 100644 (file)
index 0000000..5a460c2
Binary files /dev/null and b/mup/docs/uguide/mugex22.gif differ
diff --git a/mup/docs/uguide/mugex23.gif b/mup/docs/uguide/mugex23.gif
new file mode 100644 (file)
index 0000000..c79f1c6
Binary files /dev/null and b/mup/docs/uguide/mugex23.gif differ
diff --git a/mup/docs/uguide/mugex24.gif b/mup/docs/uguide/mugex24.gif
new file mode 100644 (file)
index 0000000..f8ff821
Binary files /dev/null and b/mup/docs/uguide/mugex24.gif differ
diff --git a/mup/docs/uguide/mugex25.gif b/mup/docs/uguide/mugex25.gif
new file mode 100644 (file)
index 0000000..59e1b3c
Binary files /dev/null and b/mup/docs/uguide/mugex25.gif differ
diff --git a/mup/docs/uguide/mugex26.gif b/mup/docs/uguide/mugex26.gif
new file mode 100644 (file)
index 0000000..baf0d85
Binary files /dev/null and b/mup/docs/uguide/mugex26.gif differ
diff --git a/mup/docs/uguide/mugex27.gif b/mup/docs/uguide/mugex27.gif
new file mode 100644 (file)
index 0000000..fd3dd93
Binary files /dev/null and b/mup/docs/uguide/mugex27.gif differ
diff --git a/mup/docs/uguide/mugex28.gif b/mup/docs/uguide/mugex28.gif
new file mode 100644 (file)
index 0000000..206edd9
Binary files /dev/null and b/mup/docs/uguide/mugex28.gif differ
diff --git a/mup/docs/uguide/mugex29.gif b/mup/docs/uguide/mugex29.gif
new file mode 100644 (file)
index 0000000..b6ae0a8
Binary files /dev/null and b/mup/docs/uguide/mugex29.gif differ
diff --git a/mup/docs/uguide/mugex3.gif b/mup/docs/uguide/mugex3.gif
new file mode 100644 (file)
index 0000000..7d22267
Binary files /dev/null and b/mup/docs/uguide/mugex3.gif differ
diff --git a/mup/docs/uguide/mugex30.gif b/mup/docs/uguide/mugex30.gif
new file mode 100644 (file)
index 0000000..54bf03e
Binary files /dev/null and b/mup/docs/uguide/mugex30.gif differ
diff --git a/mup/docs/uguide/mugex31.gif b/mup/docs/uguide/mugex31.gif
new file mode 100644 (file)
index 0000000..8b714dd
Binary files /dev/null and b/mup/docs/uguide/mugex31.gif differ
diff --git a/mup/docs/uguide/mugex32.gif b/mup/docs/uguide/mugex32.gif
new file mode 100644 (file)
index 0000000..018356f
Binary files /dev/null and b/mup/docs/uguide/mugex32.gif differ
diff --git a/mup/docs/uguide/mugex33.gif b/mup/docs/uguide/mugex33.gif
new file mode 100644 (file)
index 0000000..c002a52
Binary files /dev/null and b/mup/docs/uguide/mugex33.gif differ
diff --git a/mup/docs/uguide/mugex34.gif b/mup/docs/uguide/mugex34.gif
new file mode 100644 (file)
index 0000000..21ffd3c
Binary files /dev/null and b/mup/docs/uguide/mugex34.gif differ
diff --git a/mup/docs/uguide/mugex35.gif b/mup/docs/uguide/mugex35.gif
new file mode 100644 (file)
index 0000000..84fba74
Binary files /dev/null and b/mup/docs/uguide/mugex35.gif differ
diff --git a/mup/docs/uguide/mugex36.gif b/mup/docs/uguide/mugex36.gif
new file mode 100644 (file)
index 0000000..147a891
Binary files /dev/null and b/mup/docs/uguide/mugex36.gif differ
diff --git a/mup/docs/uguide/mugex37.gif b/mup/docs/uguide/mugex37.gif
new file mode 100644 (file)
index 0000000..14e7cd6
Binary files /dev/null and b/mup/docs/uguide/mugex37.gif differ
diff --git a/mup/docs/uguide/mugex38.gif b/mup/docs/uguide/mugex38.gif
new file mode 100644 (file)
index 0000000..35eb394
Binary files /dev/null and b/mup/docs/uguide/mugex38.gif differ
diff --git a/mup/docs/uguide/mugex39.gif b/mup/docs/uguide/mugex39.gif
new file mode 100644 (file)
index 0000000..5dac9e1
Binary files /dev/null and b/mup/docs/uguide/mugex39.gif differ
diff --git a/mup/docs/uguide/mugex4.gif b/mup/docs/uguide/mugex4.gif
new file mode 100644 (file)
index 0000000..999df8f
Binary files /dev/null and b/mup/docs/uguide/mugex4.gif differ
diff --git a/mup/docs/uguide/mugex40.gif b/mup/docs/uguide/mugex40.gif
new file mode 100644 (file)
index 0000000..cbe8765
Binary files /dev/null and b/mup/docs/uguide/mugex40.gif differ
diff --git a/mup/docs/uguide/mugex41.gif b/mup/docs/uguide/mugex41.gif
new file mode 100644 (file)
index 0000000..cce5d00
Binary files /dev/null and b/mup/docs/uguide/mugex41.gif differ
diff --git a/mup/docs/uguide/mugex42.gif b/mup/docs/uguide/mugex42.gif
new file mode 100644 (file)
index 0000000..4e82014
Binary files /dev/null and b/mup/docs/uguide/mugex42.gif differ
diff --git a/mup/docs/uguide/mugex43.gif b/mup/docs/uguide/mugex43.gif
new file mode 100644 (file)
index 0000000..facfa4b
Binary files /dev/null and b/mup/docs/uguide/mugex43.gif differ
diff --git a/mup/docs/uguide/mugex44.gif b/mup/docs/uguide/mugex44.gif
new file mode 100644 (file)
index 0000000..dff64a1
Binary files /dev/null and b/mup/docs/uguide/mugex44.gif differ
diff --git a/mup/docs/uguide/mugex45.gif b/mup/docs/uguide/mugex45.gif
new file mode 100644 (file)
index 0000000..c4fa2d3
Binary files /dev/null and b/mup/docs/uguide/mugex45.gif differ
diff --git a/mup/docs/uguide/mugex46.gif b/mup/docs/uguide/mugex46.gif
new file mode 100644 (file)
index 0000000..d3c0a02
Binary files /dev/null and b/mup/docs/uguide/mugex46.gif differ
diff --git a/mup/docs/uguide/mugex47.gif b/mup/docs/uguide/mugex47.gif
new file mode 100644 (file)
index 0000000..4ee511c
Binary files /dev/null and b/mup/docs/uguide/mugex47.gif differ
diff --git a/mup/docs/uguide/mugex48.gif b/mup/docs/uguide/mugex48.gif
new file mode 100644 (file)
index 0000000..71f93a6
Binary files /dev/null and b/mup/docs/uguide/mugex48.gif differ
diff --git a/mup/docs/uguide/mugex49.gif b/mup/docs/uguide/mugex49.gif
new file mode 100644 (file)
index 0000000..714cd77
Binary files /dev/null and b/mup/docs/uguide/mugex49.gif differ
diff --git a/mup/docs/uguide/mugex5.gif b/mup/docs/uguide/mugex5.gif
new file mode 100644 (file)
index 0000000..c55796c
Binary files /dev/null and b/mup/docs/uguide/mugex5.gif differ
diff --git a/mup/docs/uguide/mugex50.gif b/mup/docs/uguide/mugex50.gif
new file mode 100644 (file)
index 0000000..8c4ee4e
Binary files /dev/null and b/mup/docs/uguide/mugex50.gif differ
diff --git a/mup/docs/uguide/mugex51.gif b/mup/docs/uguide/mugex51.gif
new file mode 100644 (file)
index 0000000..95019fa
Binary files /dev/null and b/mup/docs/uguide/mugex51.gif differ
diff --git a/mup/docs/uguide/mugex52.gif b/mup/docs/uguide/mugex52.gif
new file mode 100644 (file)
index 0000000..a7f0342
Binary files /dev/null and b/mup/docs/uguide/mugex52.gif differ
diff --git a/mup/docs/uguide/mugex53.gif b/mup/docs/uguide/mugex53.gif
new file mode 100644 (file)
index 0000000..a432951
Binary files /dev/null and b/mup/docs/uguide/mugex53.gif differ
diff --git a/mup/docs/uguide/mugex54.gif b/mup/docs/uguide/mugex54.gif
new file mode 100644 (file)
index 0000000..78862fa
Binary files /dev/null and b/mup/docs/uguide/mugex54.gif differ
diff --git a/mup/docs/uguide/mugex55.gif b/mup/docs/uguide/mugex55.gif
new file mode 100644 (file)
index 0000000..f1a59d9
Binary files /dev/null and b/mup/docs/uguide/mugex55.gif differ
diff --git a/mup/docs/uguide/mugex56.gif b/mup/docs/uguide/mugex56.gif
new file mode 100644 (file)
index 0000000..6445bd6
Binary files /dev/null and b/mup/docs/uguide/mugex56.gif differ
diff --git a/mup/docs/uguide/mugex57.gif b/mup/docs/uguide/mugex57.gif
new file mode 100644 (file)
index 0000000..de05080
Binary files /dev/null and b/mup/docs/uguide/mugex57.gif differ
diff --git a/mup/docs/uguide/mugex58.gif b/mup/docs/uguide/mugex58.gif
new file mode 100644 (file)
index 0000000..9dcd15c
Binary files /dev/null and b/mup/docs/uguide/mugex58.gif differ
diff --git a/mup/docs/uguide/mugex59.gif b/mup/docs/uguide/mugex59.gif
new file mode 100644 (file)
index 0000000..accb040
Binary files /dev/null and b/mup/docs/uguide/mugex59.gif differ
diff --git a/mup/docs/uguide/mugex6.gif b/mup/docs/uguide/mugex6.gif
new file mode 100644 (file)
index 0000000..8acd4c3
Binary files /dev/null and b/mup/docs/uguide/mugex6.gif differ
diff --git a/mup/docs/uguide/mugex60.gif b/mup/docs/uguide/mugex60.gif
new file mode 100644 (file)
index 0000000..a4c16b2
Binary files /dev/null and b/mup/docs/uguide/mugex60.gif differ
diff --git a/mup/docs/uguide/mugex61.gif b/mup/docs/uguide/mugex61.gif
new file mode 100644 (file)
index 0000000..2344c63
Binary files /dev/null and b/mup/docs/uguide/mugex61.gif differ
diff --git a/mup/docs/uguide/mugex62.gif b/mup/docs/uguide/mugex62.gif
new file mode 100644 (file)
index 0000000..044bbc3
Binary files /dev/null and b/mup/docs/uguide/mugex62.gif differ
diff --git a/mup/docs/uguide/mugex63.gif b/mup/docs/uguide/mugex63.gif
new file mode 100644 (file)
index 0000000..4e08e3d
Binary files /dev/null and b/mup/docs/uguide/mugex63.gif differ
diff --git a/mup/docs/uguide/mugex64.gif b/mup/docs/uguide/mugex64.gif
new file mode 100644 (file)
index 0000000..4b1de48
Binary files /dev/null and b/mup/docs/uguide/mugex64.gif differ
diff --git a/mup/docs/uguide/mugex65.gif b/mup/docs/uguide/mugex65.gif
new file mode 100644 (file)
index 0000000..17b0818
Binary files /dev/null and b/mup/docs/uguide/mugex65.gif differ
diff --git a/mup/docs/uguide/mugex66.gif b/mup/docs/uguide/mugex66.gif
new file mode 100644 (file)
index 0000000..c07a8d9
Binary files /dev/null and b/mup/docs/uguide/mugex66.gif differ
diff --git a/mup/docs/uguide/mugex67.gif b/mup/docs/uguide/mugex67.gif
new file mode 100644 (file)
index 0000000..aa7f5c0
Binary files /dev/null and b/mup/docs/uguide/mugex67.gif differ
diff --git a/mup/docs/uguide/mugex68.gif b/mup/docs/uguide/mugex68.gif
new file mode 100644 (file)
index 0000000..f32f6bf
Binary files /dev/null and b/mup/docs/uguide/mugex68.gif differ
diff --git a/mup/docs/uguide/mugex69.gif b/mup/docs/uguide/mugex69.gif
new file mode 100644 (file)
index 0000000..8291cde
Binary files /dev/null and b/mup/docs/uguide/mugex69.gif differ
diff --git a/mup/docs/uguide/mugex7.gif b/mup/docs/uguide/mugex7.gif
new file mode 100644 (file)
index 0000000..a4743db
Binary files /dev/null and b/mup/docs/uguide/mugex7.gif differ
diff --git a/mup/docs/uguide/mugex70.gif b/mup/docs/uguide/mugex70.gif
new file mode 100644 (file)
index 0000000..bb4e597
Binary files /dev/null and b/mup/docs/uguide/mugex70.gif differ
diff --git a/mup/docs/uguide/mugex71.gif b/mup/docs/uguide/mugex71.gif
new file mode 100644 (file)
index 0000000..db27d78
Binary files /dev/null and b/mup/docs/uguide/mugex71.gif differ
diff --git a/mup/docs/uguide/mugex72.gif b/mup/docs/uguide/mugex72.gif
new file mode 100644 (file)
index 0000000..cf5ed15
Binary files /dev/null and b/mup/docs/uguide/mugex72.gif differ
diff --git a/mup/docs/uguide/mugex73.gif b/mup/docs/uguide/mugex73.gif
new file mode 100644 (file)
index 0000000..116c464
Binary files /dev/null and b/mup/docs/uguide/mugex73.gif differ
diff --git a/mup/docs/uguide/mugex74.gif b/mup/docs/uguide/mugex74.gif
new file mode 100644 (file)
index 0000000..7cd9332
Binary files /dev/null and b/mup/docs/uguide/mugex74.gif differ
diff --git a/mup/docs/uguide/mugex75.gif b/mup/docs/uguide/mugex75.gif
new file mode 100644 (file)
index 0000000..de843fa
Binary files /dev/null and b/mup/docs/uguide/mugex75.gif differ
diff --git a/mup/docs/uguide/mugex76.gif b/mup/docs/uguide/mugex76.gif
new file mode 100644 (file)
index 0000000..ef18e30
Binary files /dev/null and b/mup/docs/uguide/mugex76.gif differ
diff --git a/mup/docs/uguide/mugex77.gif b/mup/docs/uguide/mugex77.gif
new file mode 100644 (file)
index 0000000..39a7a71
Binary files /dev/null and b/mup/docs/uguide/mugex77.gif differ
diff --git a/mup/docs/uguide/mugex78.gif b/mup/docs/uguide/mugex78.gif
new file mode 100644 (file)
index 0000000..1fa1521
Binary files /dev/null and b/mup/docs/uguide/mugex78.gif differ
diff --git a/mup/docs/uguide/mugex79.gif b/mup/docs/uguide/mugex79.gif
new file mode 100644 (file)
index 0000000..6d654b5
Binary files /dev/null and b/mup/docs/uguide/mugex79.gif differ
diff --git a/mup/docs/uguide/mugex8.gif b/mup/docs/uguide/mugex8.gif
new file mode 100644 (file)
index 0000000..7146ac6
Binary files /dev/null and b/mup/docs/uguide/mugex8.gif differ
diff --git a/mup/docs/uguide/mugex80.gif b/mup/docs/uguide/mugex80.gif
new file mode 100644 (file)
index 0000000..6b54ff7
Binary files /dev/null and b/mup/docs/uguide/mugex80.gif differ
diff --git a/mup/docs/uguide/mugex81.gif b/mup/docs/uguide/mugex81.gif
new file mode 100644 (file)
index 0000000..252382b
Binary files /dev/null and b/mup/docs/uguide/mugex81.gif differ
diff --git a/mup/docs/uguide/mugex82.gif b/mup/docs/uguide/mugex82.gif
new file mode 100644 (file)
index 0000000..23dcf7e
Binary files /dev/null and b/mup/docs/uguide/mugex82.gif differ
diff --git a/mup/docs/uguide/mugex83.gif b/mup/docs/uguide/mugex83.gif
new file mode 100644 (file)
index 0000000..404fcf4
Binary files /dev/null and b/mup/docs/uguide/mugex83.gif differ
diff --git a/mup/docs/uguide/mugex84.gif b/mup/docs/uguide/mugex84.gif
new file mode 100644 (file)
index 0000000..8c3b935
Binary files /dev/null and b/mup/docs/uguide/mugex84.gif differ
diff --git a/mup/docs/uguide/mugex85.gif b/mup/docs/uguide/mugex85.gif
new file mode 100644 (file)
index 0000000..d310dab
Binary files /dev/null and b/mup/docs/uguide/mugex85.gif differ
diff --git a/mup/docs/uguide/mugex86.gif b/mup/docs/uguide/mugex86.gif
new file mode 100644 (file)
index 0000000..0368a73
Binary files /dev/null and b/mup/docs/uguide/mugex86.gif differ
diff --git a/mup/docs/uguide/mugex87.gif b/mup/docs/uguide/mugex87.gif
new file mode 100644 (file)
index 0000000..3cea34f
Binary files /dev/null and b/mup/docs/uguide/mugex87.gif differ
diff --git a/mup/docs/uguide/mugex88.gif b/mup/docs/uguide/mugex88.gif
new file mode 100644 (file)
index 0000000..11dda78
Binary files /dev/null and b/mup/docs/uguide/mugex88.gif differ
diff --git a/mup/docs/uguide/mugex89.gif b/mup/docs/uguide/mugex89.gif
new file mode 100644 (file)
index 0000000..c528645
Binary files /dev/null and b/mup/docs/uguide/mugex89.gif differ
diff --git a/mup/docs/uguide/mugex9.gif b/mup/docs/uguide/mugex9.gif
new file mode 100644 (file)
index 0000000..788df31
Binary files /dev/null and b/mup/docs/uguide/mugex9.gif differ
diff --git a/mup/docs/uguide/mugex90.gif b/mup/docs/uguide/mugex90.gif
new file mode 100644 (file)
index 0000000..3ea7da1
Binary files /dev/null and b/mup/docs/uguide/mugex90.gif differ
diff --git a/mup/docs/uguide/mugex91.gif b/mup/docs/uguide/mugex91.gif
new file mode 100644 (file)
index 0000000..0a8da55
Binary files /dev/null and b/mup/docs/uguide/mugex91.gif differ
diff --git a/mup/docs/uguide/mugex92.gif b/mup/docs/uguide/mugex92.gif
new file mode 100644 (file)
index 0000000..326114d
Binary files /dev/null and b/mup/docs/uguide/mugex92.gif differ
diff --git a/mup/docs/uguide/mugex93.gif b/mup/docs/uguide/mugex93.gif
new file mode 100644 (file)
index 0000000..08d59f9
Binary files /dev/null and b/mup/docs/uguide/mugex93.gif differ
diff --git a/mup/docs/uguide/mugex94.gif b/mup/docs/uguide/mugex94.gif
new file mode 100644 (file)
index 0000000..7e41431
Binary files /dev/null and b/mup/docs/uguide/mugex94.gif differ
diff --git a/mup/docs/uguide/mugex95.gif b/mup/docs/uguide/mugex95.gif
new file mode 100644 (file)
index 0000000..758249f
Binary files /dev/null and b/mup/docs/uguide/mugex95.gif differ
diff --git a/mup/docs/uguide/mugex96.gif b/mup/docs/uguide/mugex96.gif
new file mode 100644 (file)
index 0000000..67b0082
Binary files /dev/null and b/mup/docs/uguide/mugex96.gif differ
diff --git a/mup/docs/uguide/mugex97.gif b/mup/docs/uguide/mugex97.gif
new file mode 100644 (file)
index 0000000..87b27f9
Binary files /dev/null and b/mup/docs/uguide/mugex97.gif differ
diff --git a/mup/docs/uguide/mugex98.gif b/mup/docs/uguide/mugex98.gif
new file mode 100644 (file)
index 0000000..b4930fb
Binary files /dev/null and b/mup/docs/uguide/mugex98.gif differ
diff --git a/mup/docs/uguide/mugex99.gif b/mup/docs/uguide/mugex99.gif
new file mode 100644 (file)
index 0000000..342d554
Binary files /dev/null and b/mup/docs/uguide/mugex99.gif differ
diff --git a/mup/docs/uguide/multirst.html b/mup/docs/uguide/multirst.html
new file mode 100644 (file)
index 0000000..6fcd571
--- /dev/null
@@ -0,0 +1,50 @@
+<HTML>
+<HEAD><TITLE>
+Multirests
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="bars.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="lyrics.html">next page --&gt;</A>
+</P>
+           
+<H2>
+Multirest
+</H2>
+<P>
+Multiple measure rests can be indicated using the &quot;multirest&quot; statement.
+It is followed by the number of measures of rest.
+The number must be greater than 1, and no larger than 1000.
+There must not be any note or lyric information specified for
+a multirest measure.
+Examples:
+<BR><PRE>
+multirest 15
+bar
+1: 2c;4;;
+bar
+1: 2.c;4r;
+bar
+multirest 5
+bar
+</PRE><BR>
+<IMG SRC="mugex40.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+See also
+<A HREF="cmdargs.html#coption">the -c command line option,</A>
+and
+<A HREF="param.html#restcomb">the restcombine parameter.</A>
+</P>
+<P>
+Normally, the number of measures of rest is printed, but
+it is possible to turn this off using
+<A HREF="param.html#prmultn">the printmultnum parameter.</A>
+An alternate notation can be specified using
+<A HREF="param.html#restsymm">the restsymmult parameter.</A>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="bars.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="lyrics.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/multsong.html b/mup/docs/uguide/multsong.html
new file mode 100644 (file)
index 0000000..66078f8
--- /dev/null
@@ -0,0 +1,82 @@
+<HTML>
+<HEAD><TITLE>
+Placing several songs on one page
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="tempochg.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="cadenza.html">next page --&gt;</A>
+</P>
+          
+<H2>
+Placing several songs on one page
+</H2>
+<P>
+Sometimes you may wish to print more than one song on the same page.
+While Mup considers all of its input to be a single song,
+it is possible to get the effect of separate songs.
+First of all, on the last bar line of first song, use &quot;hidechanges.&quot;
+That way, if the key or anything is
+different in the next song, Mup won't print the changes at the
+end of the first song. Then
+<A HREF="prnttext.html#block">use a "block"</A>
+for printing the titles
+for the second song.
+Here is an example:
+<BR><PRE>
+score
+       scoresep=10,14
+       label=&quot;&quot;
+header
+       title (18) &quot;Title for first song&quot;
+music
+1: c;d;e;f;
+bar
+1: f;e;d;c;
+bar
+1: c;d;e;f;
+bar
+1: f;d;2c;
+endbar
+
+// force time signature to be printed on next score
+// by changing the time, but only for an invisible measure
+score time=5/4n
+music
+1: ms;
+invisbar hidechanges
+
+// Force the block closer to next score,
+// so it will better match the spacing of
+// the title of the first song.
+score scoresep=6,6
+// print title for second song
+block
+title (30) &quot; &quot;   // Allow some extra room above title
+title (18) &quot;Title for second song&quot;
+
+score
+       // Set up for second song
+       time=4/4
+       key=1&amp;
+
+music
+1: d;e;2f;
+bar
+// Put score spacing back to original
+score scoresep=10,14
+music
+1: a;2g;4f;
+bar
+1: 2e;4c;d;
+bar
+1: 2g;f;
+endbar
+</PRE><BR>
+<IMG SRC="mugex96.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="tempochg.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="cadenza.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/muschar.gif b/mup/docs/uguide/muschar.gif
new file mode 100644 (file)
index 0000000..6e31f15
Binary files /dev/null and b/mup/docs/uguide/muschar.gif differ
diff --git a/mup/docs/uguide/music.html b/mup/docs/uguide/music.html
new file mode 100644 (file)
index 0000000..58de85d
--- /dev/null
@@ -0,0 +1,39 @@
+<HTML>
+<HEAD><TITLE>
+Mup music context
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="contexts.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="chordinp.html">next page --&gt;</A>
+</P>
+         
+<H1>
+BASIC STANDARD MUSIC NOTATION
+</H1>
+<P>
+Music data is given in the
+<A HREF="contexts.html">"music" context.</A>
+For each measure, there is usually
+one line of input for each voice.
+At the end of the measure, the kind of
+<A HREF="bars.html">bar line</A>
+to be used to end the measure is specified.
+This section describes the input for generating standard music notation.
+Mup can also generate
+<A HREF="tabstaff.html">tablature notation,</A>
+and that is covered in the next section.
+<BR>
+<A HREF="chordinp.html">Chords</A>
+<BR>
+<A HREF="bars.html">Bar lines</A>
+<BR>
+<A HREF="multirst.html">Multirests</A>
+<BR>
+<A HREF="lyrics.html">Lyrics</A>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="contexts.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="chordinp.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/muspaper.html b/mup/docs/uguide/muspaper.html
new file mode 100644 (file)
index 0000000..c7a474a
--- /dev/null
@@ -0,0 +1,65 @@
+<HTML>
+<HEAD><TITLE>
+Generating blank staff paper
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="heeltoe.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="pstools.html">next page --&gt;</A>
+</P>
+          
+<H2>
+Generating blank staff paper
+</H2>
+<P>
+It is possible to use Mup to generate
+blank music staff paper.
+You simply use an input file that contains
+<A HREF="chordinp.html#measdur">measure spaces,</A>
+each ending with an
+<A HREF="invisbar.html">invisbar.</A>
+You can control whether you want
+<A HREF="param.html#clef">clefs,</A>
+<A HREF="param.html#time">time signatures,</A>
+<A HREF="param.html#brace">braces,</A>
+etc., and can control the spacing of staffs using
+<A HREF="param.html#scoresep">the scoresep parameter.</A>
+Here is a simple input that will generate a page with 8 completely
+blank staffs.
+<BR><PRE>
+score
+       scoresep=9,100          // spread staffs out nicely
+       stafflines=5n           // don't print any clefs
+       label=&quot;&quot;              // make sure left edges line up both on first
+       label2=&quot;&quot;             //    and on subsequent lines
+       topmargin=1             // allow extra margin to write in header/footer
+       bottommargin=1
+       time=4/4n               // don't print any time signature
+music
+
+define SCORE
+       1: ms;
+       invisbar                // no bar line at the end of the staff
+@
+
+define SCORE_NEWSCORE
+       SCORE
+       newscore
+@
+
+// print 8 staffs, with newscore between each
+SCORE_NEWSCORE
+SCORE_NEWSCORE
+SCORE_NEWSCORE
+SCORE_NEWSCORE
+SCORE_NEWSCORE
+SCORE_NEWSCORE
+SCORE_NEWSCORE
+SCORE
+</PRE><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="heeltoe.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="pstools.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/mussym.html b/mup/docs/uguide/mussym.html
new file mode 100644 (file)
index 0000000..e8fdf3c
--- /dev/null
@@ -0,0 +1,51 @@
+<HTML>
+<HEAD><TITLE>
+Music symbols
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="textmark.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="phrase.html">next page --&gt;</A>
+</P>
+           
+<H2>
+Mussym
+</H2>
+<P>
+While it is possible to place musical symbols
+such as fermatas and coda signs using
+<A HREF="textmark.html">text statements,</A>
+it is perhaps a bit confusing, since music
+symbols are really not part of any particular font. So there is a &quot;mussym&quot;
+statement which can be used. The text strings after the colon must each
+consist of a single musical symbol whose name can be given without the
+usual \() wrapper. The following two lines produce identical results,
+but the second is perhaps a bit clearer:
+<BR><PRE>
+rom above 1: 1 &quot;\(ferm)&quot;;
+mussym above 1: 1 &quot;ferm&quot;;
+</PRE><BR>
+</P>
+<P>
+A duration is not allowed on mussym statements
+except in one special case--if the
+symbol is &quot;tr&quot; (trill). In that case, the duration tells Mup how long a
+wavy line to draw from the end of the &quot;tr&quot; symbol.
+<BR><PRE>
+1: 2e;g;
+mussym above 1: 1 &quot;tr&quot; til 2; 3 &quot;ferm&quot;;
+endbar
+</PRE><BR>
+<IMG SRC="mugex72.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+A size can optionally be specified, inside parentheses:
+<BR><PRE>
+mussym (15) above 2: &quot;turn&quot;;
+</PRE><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="textmark.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="phrase.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/newscore.html b/mup/docs/uguide/newscore.html
new file mode 100644 (file)
index 0000000..aaf66fa
--- /dev/null
@@ -0,0 +1,59 @@
+<HTML>
+<HEAD><TITLE>
+Newscore and newpage
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="linecurv.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="headfoot.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Newscore and newpage
+</H2>
+<P>
+Normally, Mup determines how many measures to put on each score and how many
+scores to put on each page. You can force Mup to move to the next score with
+the &quot;newscore&quot; statement, or to the next page with a &quot;newpage&quot; statement.
+Here is an example:
+<BR><PRE>
+1: c;d;e;f;
+bar
+1: e;f;g;;
+bar
+newscore   // go to next score
+1: 2c;;
+bar
+1: e;f;g;;
+bar
+newpage   // go to next page
+1: e;g;2c;
+bar
+</PRE><BR>
+</P>
+<P>
+You can temporarily change the indent for the new score
+by specifying &quot;leftmargin=<I>num</I>,&quot; where <I>num</I> is a floating point
+number of inches or centimeters (depending on the current setting of
+<A HREF="param.html#units">the units parameter.)</A>
+The new score will then be indented by that much, overriding the value
+of
+<A HREF="param.html#leftmar">the leftmargin parameter.</A>
+</P>
+<P>
+In a similar way, you can specify &quot;rightmargin=<I>num</I>,&quot; which
+will affect
+<A HREF="param.html#rightmar">the right margin</A>
+on the <B>previous</B> score. This might
+be used, for example, if you want a piece to end with a
+shorter than normal score.
+<BR><PRE>
+newscore leftmargin=1.2 rightmargin=2.7
+</PRE><BR>
+The equals sign is optional in these margin overrides.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="linecurv.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="headfoot.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/noteattr.html b/mup/docs/uguide/noteattr.html
new file mode 100644 (file)
index 0000000..d88e8d1
--- /dev/null
@@ -0,0 +1,196 @@
+<HTML>
+<HEAD><TITLE>
+Note attributes
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="chordinp.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="chrdattr.html">next page --&gt;</A>
+</P>
+         
+<H3>
+Note attributes
+</H3>
+<P>
+There are several optional attributes that can be specified for each note.
+Any or all of these may appear on any note in any order
+after the
+<A HREF="chordinp.html#letter">letter,</A>
+<A HREF="chordinp.html#acc">accidental,</A>
+and
+<A HREF="chordinp.html#oct">octave specifications.</A>
+They include:
+<UL>
+<LI>
+<A HREF="noteattr.html#small">small note head</A>
+<LI>
+<A HREF="noteattr.html#ntie">tie</A>
+<LI>
+<A HREF="noteattr.html#nslur">slurs</A>
+<LI>
+<A HREF="noteattr.html#shaped">headshape</A>
+<LI>
+<A HREF="noteattr.html#ntag">location tag</A>
+</UL>
+</P>
+<H4>
+Small note head
+</H4>
+<P>
+<A NAME="small">A note specification can be followed by a "?"</A>
+to indicate the note is to be printed with a small note head,
+rather than the normal
+size. (Note: if you have several notes in a chord and want all of them to
+be small,
+<A HREF="chrdattr.html#cue">the "cue" construct, described later,</A>
+may be preferable.)
+</P>
+<P>
+Examples:
+<BR><PRE>
+// print the &quot;e&quot; as a small note
+1: 1c e? g;
+bar
+
+// make the second note small
+1: f; ?; g; ;
+bar
+</PRE><BR>
+<IMG SRC="mugex12.gif" ALT="Picture of Mup output"><BR>
+</P>
+<H4>
+Note tie
+</H4>
+<P>
+<A NAME="ntie">A "~" can be used to indicate the note is to be tied</A>
+to the note of the same
+pitch in the following chord. That following chord need not be in the same
+measure, but it must contain a matching note.
+(Note: if a chord with several notes is to have all the notes tied
+to the following chord,
+<A HREF="ichdattr.html#tie">the "tie" construct</A>
+described later may be preferable.)
+The ~ may be preceded by the word 'dotted' or 'dashed' if you want
+a dotted or dashed tie; otherwise a normal, solid tie is drawn.
+The ~ may be followed by the word 'up' or 'down' to specify the
+direction for the curve's bulge. If neither is specified, Mup will
+determine an appropriate direction, so you only need to give a direction
+if you wish to override Mup's choice.
+</P>
+<P>
+Examples
+<BR><PRE>
+1: d~; 8; e~; ; f;
+bar
+
+// tie the g (which also happens
+// to be a &quot;small&quot; note)
+1: 2g+g?~; 4eg?;
+bar
+</PRE><BR>
+<IMG SRC="mugex13.gif" ALT="Picture of Mup output"><BR>
+</P>
+<H4>
+Slurs
+</H4>
+<P>
+<A NAME="nslur">A note can also be followed by a list of notes to be slurred to,</A>
+enclosed in angle brackets.
+A slur will be drawn from the note to each of the notes
+listed in the angle brackets. The notes inside the brackets
+are specified by a pitch and optional octave. No
+<A HREF="chordinp.html#acc">accidentals</A>
+are specified, even if the note to be slurred
+to has an accidental. Examples:
+<BR><PRE>
+// slur from c of first chord to e of second chord
+1: c&lt;e&gt;; e; f; g;
+bar
+
+// slur from c+ of first chord to a&amp; of second chord
+// and from c+ of first chord to d&amp;+ of second chord
+1: 2cc+&lt;ad+&gt;; a&amp;d&amp;+;
+bar
+</PRE><BR>
+<IMG SRC="mugex14.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+If there is only one note in the following chord, it isn't necessary to
+explicitly state it within the angle brackets; &quot;&lt;&gt;&quot; will suffice.
+<BR><PRE>
+// slur from c to d, and f to g
+1: c&lt;&gt;; d; f&lt;&gt;; g;
+bar
+</PRE><BR>
+<IMG SRC="mugex15.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+The &lt; may be preceded by the word 'dotted' or 'dashed' if you want
+a dotted or dashed slur, otherwise a normal, solid slur is drawn.
+The &gt; may be followed by the word 'up' or 'down' to specify the
+direction for the curve's bulge. If neither is specified, Mup will
+determine an appropriate direction, so you only need to give a direction
+if you wish to override Mup's choice.
+</P>
+<P>
+There are four special &quot;slurs&quot; which are really slides to/from an
+indefinite note. They are most commonly used on
+<A HREF="tabstaff.html">tablature staffs,</A>
+but are allowed on ordinary staffs too. 
+They are: &lt;/n&gt; &lt;\n&gt; &lt;n/&gt; and &lt;n\&gt; for sliding upward into the note,
+downward into the note, upward out from the note, and downward out from
+the note respectively. These have to be in angle brackets by themselves,
+so if you want to have both one of these slides and another slur on the
+same note, multiple sets of angle brackets must be used, as in
+<BR><PRE>
+1: 2c&lt;/n&gt;&lt;d&gt;;d;
+</PRE><BR>
+</P>
+<H4>
+Head shape
+</H4>
+<P>
+<A NAME="shaped">Sometimes you may want to mix head shapes on a single stem.</A>
+For example, you might want to use a diamond to designate a harmonic,
+with other notes in the same chord being normal shape.
+There is an entire
+<A HREF="shaped.html">section on head shapes,</A>
+so only a simple example is given here.
+To make a single note have a different head shape,
+use hs followed by the name of the shape in quotes.
+<BR><PRE>
+1: 2e e+ hs &quot;diam&quot;;g;
+</PRE><BR>
+</P>
+<H4>
+Note location tag
+</H4>
+<P>
+Finally, a
+<A HREF="tags.html">"location tag"</A>
+can be associated with a note. This would
+enable you to draw things relative to the note.
+<A NAME="ntag">A note location tag</A>
+is set by using an &quot;=&quot; followed by a name. The name can be either:
+<UL>
+<LI>
+a single lower case letter
+<LI>
+an underscore followed by one or more
+letters, numbers, and underscores in any combination.
+</UL>
+The name is arbitrary, and is used as
+a tag that can be referred to later. Examples:
+<BR><PRE>
+// associate tag p with note e&amp;
+3: 2c; e&amp; =p g;
+
+// associate tag _end with note f
+2: 1f =_end;
+</PRE><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="chordinp.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="chrdattr.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/octave.html b/mup/docs/uguide/octave.html
new file mode 100644 (file)
index 0000000..16f3ec4
--- /dev/null
@@ -0,0 +1,47 @@
+<HTML>
+<HEAD><TITLE>
+Octave marks
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="cres.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="pedal.html">next page --&gt;</A>
+</P>
+            
+<H2>
+Octave marks
+</H2>
+<P>
+Octave statements are used to mark notes that are to be played one or more
+octaves higher or lower than written.  An &quot;octave above&quot; statement is
+used to specify playing higher than written, or &quot;octave below&quot; for playing
+lower than written. Each item must include a begintime
+and a text string. The text string is most typically &quot;8va&quot;.
+It will always be printed in 12-point times italics font. If the octave
+shifting applies to more than a single chord, there should also be a
+duration specified, reaching to include the last affected note.  In this
+case, Mup will draw a dashed line to mark the span affected. Note that
+specifying the exact beat of a chord indicates the horizontal center of the
+chord, so if you want the dashed line to reach a bit past the note, it
+will be necessary to specify a duration slightly beyond the point of
+the last chord to be included. Examples:
+<BR><PRE>
+1: 2f;g;
+2: 2d+;g;
+3: 2g;ce;
+octave above 1: 2 &quot;8va&quot; til 1m + 1.3;
+bar
+1: 2a;c;
+2: 2f;e;
+3: 4f;;c;;
+octave below 2: 1 &quot;8va&quot;;
+octave below 3: 1 &quot;8va&quot; til 2.5; 3 &quot;15&quot; til 4.5;
+bar
+</PRE><BR>
+<IMG SRC="mugex76.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="cres.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="pedal.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/oddeven.html b/mup/docs/uguide/oddeven.html
new file mode 100644 (file)
index 0000000..32114bb
--- /dev/null
@@ -0,0 +1,62 @@
+<HTML>
+<HEAD><TITLE>
+Different margins for odd/even pages
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="mixtsig.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="tempochg.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Different margins for odd/even pages
+</H2>
+<P>
+Sometimes you may want to make margins different for odd and even pages,
+for example, if you want to put music in a ringed binder, and thus want to
+offset the printing on the pages to avoid the holes in the paper.
+While you can't do this directly, you can get the desired effect by using
+appropriate macros, and then printing the odd and even pages in two passes.
+</P>
+<P>
+In the Mup input file, put something like this:
+<BR><PRE>
+score
+       // if the WIDELEFT macro is set,
+       // make the left margin extra wide,
+       // otherwise if WIDERIGHT is set,
+       // make the right margin extra wide,
+       // otherwise make them equal.
+       ifdef WIDELEFT
+               leftmargin=1
+               rightmargin=0.5
+       else ifdef WIDERIGHT
+               leftmargin=0.5
+               rightmargin=1
+       else
+               leftmargin=0.75
+               rightmargin=0.75
+       endif endif
+</PRE><BR>
+</P>
+<P>
+Then when printing, print in two passes. First print the odd pages:
+<BR><PRE>
+mupprnt -oodd -DWIDELEFT file.mup
+</PRE><BR>
+Then turn the paper over and print the even pages:
+<BR><PRE>
+mupprnt -oeven -DWIDERIGHT file.mup
+</PRE><BR>
+</P>
+<P>
+This idea should work as long as the sum of the left and right margins are
+equal between the WIDELEFT and WIDERIGHT parts. Otherwise you may get
+different numbers of measures on each page in the two runs, and you'll
+end up missing or repeating measures.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="mixtsig.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="tempochg.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/param.html b/mup/docs/uguide/param.html
new file mode 100644 (file)
index 0000000..7e0e925
--- /dev/null
@@ -0,0 +1,2848 @@
+<HTML>
+<HEAD><TITLE>
+Mup Parameters
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="fontfile.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="debug.html">next page --&gt;</A>
+</P>
+            
+<H1>
+PARAMETERS
+</H1>
+<P>
+Parameters can be set in various contexts. All parameters
+have default values, so that you need to explicitly set them only if you
+want some value other than the default value. 
+</P>
+<P>
+Some parameters can be set only in the score context. Others can be set in
+either score or staff contexts. A few can be set in score, staff, or voice
+context. If a given parameter can be set in several
+<A HREF="contexts.html">contexts,</A>
+the value is that of the parameter at the
+most specific context in which it is set. For example, if Mup is working
+on musical data for voice 2 of staff 5, and it needs to
+look up the value of a parameter, it will first see if that parameter has
+been set in context &quot;voice 5 2&quot;.
+If so, it will use that value. If not,
+it will see if the parameter was set in context &quot;staff 5&quot;. If that has not
+been set either, it will use the value from the score context. The score
+context initially has all parameters set to their default values.
+There are a few parameters, mostly related to font and text size,
+that can also be set in
+<A HREF="headfoot.html">header, footer, and similiar contexts.</A>
+</P>
+<P>
+Parameters are set by the following syntax:
+<BR><PRE>
+<I>parameter_name</I><B>=</B><I>value</I>
+</PRE><BR>
+</P>
+<P>
+Several parameters can be set on a single line by separating them with
+a semicolon. For example:
+<BR><PRE>
+staffs=2 ; key=2&amp; ; time=2/4
+</PRE><BR>
+</P>
+<P>
+Parameters can be unset in staff or voice context using
+<BR><PRE>
+<B>unset</B><I> parameter_name</I>
+</PRE><BR>
+Unsetting a parameter in staff context will cause it
+to revert to its value in score context (unless overridden in voice context).
+Unsetting a parameter in voice context will cause it
+to revert to its value in staff context if that is set,
+otherwise to its value in score context.
+</P>
+<P>
+The parameters are listed below in alphabetical order. For each,
+the description includes the parameter's name,
+legal values, default value, and contexts in which the parameter can be
+set, along with an example of its usage.
+If there are other related parameters, they are referenced as well.
+</P>
+<H2>Index of parameters</H2>
+<A HREF="param.html#indexA">A</A> <A HREF="param.html#indexB">B</A> <A HREF="param.html#indexC">C</A> <A HREF="param.html#indexD">D</A> <A HREF="param.html#indexE">E</A> <A HREF="param.html#indexF">F</A> <A HREF="param.html#indexG">G</A> <A HREF="param.html#indexK">K</A> <A HREF="param.html#indexL">L</A> <A HREF="param.html#indexM">M</A> <A HREF="param.html#indexN">N</A> <A HREF="param.html#indexO">O</A> <A HREF="param.html#indexP">P</A> <A HREF="param.html#indexR">R</A> <A HREF="param.html#indexS">S</A> <A HREF="param.html#indexT">T</A> <A HREF="param.html#indexU">U</A> <A HREF="param.html#indexV">V</A> <A HREF="param.html#indexW">W</A> <H3><A NAME="indexA">A</A></H3><BR>
+<A HREF="param.html#aboveord">aboveorder</A><BR>
+<A HREF="param.html#addxpose">addtranspose</A><BR>
+<H3><A NAME="indexB">B</A></H3><BR>
+<A HREF="param.html#barstyle">barstyle</A><BR>
+<A HREF="param.html#beamslp">beamslope</A><BR>
+<A HREF="param.html#beamstyl">beamstyle</A><BR>
+<A HREF="param.html#beloword">beloworder</A><BR>
+<A HREF="param.html#betwnord">betweenorder</A><BR>
+<A HREF="param.html#botmar">bottommargin</A><BR>
+<A HREF="param.html#brace">brace</A><BR>
+<A HREF="param.html#bracket">bracket</A><BR>
+<H3><A NAME="indexC">C</A></H3><BR>
+<A HREF="param.html#canclkey">cancelkey</A><BR>
+<A HREF="param.html#chdist">chorddist</A><BR>
+<A HREF="param.html#clef">clef</A><BR>
+<A HREF="param.html#cresdist">crescdist</A><BR>
+<H3><A NAME="indexD">D</A></H3><BR>
+<A HREF="param.html#defoct">defoct</A><BR>
+<A HREF="param.html#dist">dist</A><BR>
+<A HREF="param.html#division">division</A><BR>
+<A HREF="param.html#dyndist">dyndist</A><BR>
+<H3><A NAME="indexE">E</A></H3><BR>
+<A HREF="param.html#endingst">endingstyle</A><BR>
+<H3><A NAME="indexF">F</A></H3><BR>
+<A HREF="param.html#firstpg">firstpage</A><BR>
+<A HREF="param.html#font">font</A><BR>
+<A HREF="param.html#fontfam">fontfamily</A><BR>
+<H3><A NAME="indexG">G</A></H3><BR>
+<A HREF="param.html#gridfret">gridfret</A><BR>
+<A HREF="param.html#gridend">gridsatend</A><BR>
+<A HREF="param.html#gridscl">gridscale</A><BR>
+<A HREF="param.html#gridused">gridswhereused</A><BR>
+<H3><A NAME="indexK">K</A></H3><BR>
+<A HREF="param.html#key">key</A><BR>
+<H3><A NAME="indexL">L</A></H3><BR>
+<A HREF="param.html#label">label</A><BR>
+<A HREF="param.html#label2">label2</A><BR>
+<A HREF="param.html#leftmar">leftmargin</A><BR>
+<A HREF="param.html#lyralign">lyricsalign</A><BR>
+<A HREF="param.html#lyrfont">lyricsfont</A><BR>
+<A HREF="param.html#lyrfam">lyricsfontfamily</A><BR>
+<A HREF="param.html#lyrsize">lyricssize</A><BR>
+<H3><A NAME="indexM">M</A></H3><BR>
+<A HREF="param.html#measnum">measnum</A><BR>
+<A HREF="param.html#mnumfont">measnumfont</A><BR>
+<A HREF="param.html#mnumfam">measnumfontfamily</A><BR>
+<A HREF="param.html#mnumsize">measnumsize</A><BR>
+<H3><A NAME="indexN">N</A></H3><BR>
+<A HREF="param.html#notehead">noteheads</A><BR>
+<A HREF="param.html#nummrpt">numbermrpt</A><BR>
+<H3><A NAME="indexO">O</A></H3><BR>
+<A HREF="param.html#ontheline">ontheline</A><BR>
+<H3><A NAME="indexP">P</A></H3><BR>
+<A HREF="param.html#packexp">packexp</A><BR>
+<A HREF="param.html#packfact">packfact</A><BR>
+<A HREF="param.html#pad">pad</A><BR>
+<A HREF="param.html#pgheight">pageheight</A><BR>
+<A HREF="param.html#pgsize">pagesize</A><BR>
+<A HREF="param.html#pgwidth">pagewidth</A><BR>
+<A HREF="param.html#panels">panelsperpage</A><BR>
+<A HREF="param.html#pedstyle">pedstyle</A><BR>
+<A HREF="param.html#prmultn">printmultnum</A><BR>
+<H3><A NAME="indexR">R</A></H3><BR>
+<A HREF="param.html#rehstyle">rehstyle</A><BR>
+<A HREF="param.html#release">release</A><BR>
+<A HREF="param.html#restcomb">restcombine</A><BR>
+<A HREF="param.html#restsymm">restsymmult</A><BR>
+<A HREF="param.html#rightmar">rightmargin</A><BR>
+<H3><A NAME="indexS">S</A></H3><BR>
+<A HREF="param.html#scale">scale</A><BR>
+<A HREF="param.html#scorepad">scorepad</A><BR>
+<A HREF="param.html#scoresep">scoresep</A><BR>
+<A HREF="param.html#size">size</A><BR>
+<A HREF="param.html#stlines">stafflines</A><BR>
+<A HREF="param.html#staffpad">staffpad</A><BR>
+<A HREF="param.html#staffs">staffs</A><BR>
+<A HREF="param.html#stscale">staffscale</A><BR>
+<A HREF="param.html#staffsep">staffsep</A><BR>
+<A HREF="param.html#stemlen">stemlen</A><BR>
+<A HREF="param.html#sshorten">stemshorten</A><BR>
+<A HREF="param.html#swing">swingunit</A><BR>
+<A HREF="param.html#sylpos">sylposition</A><BR>
+<H3><A NAME="indexT">T</A></H3><BR>
+<A HREF="param.html#tabwhite">tabwhitebox</A><BR>
+<A HREF="param.html#time">time</A><BR>
+<A HREF="param.html#timeunit">timeunit</A><BR>
+<A HREF="param.html#topmar">topmargin</A><BR>
+<A HREF="param.html#xpose">transpose</A><BR>
+<H3><A NAME="indexU">U</A></H3><BR>
+<A HREF="param.html#units">units</A><BR>
+<H3><A NAME="indexV">V</A></H3><BR>
+<A HREF="param.html#vcombine">vcombine</A><BR>
+<A HREF="param.html#visible">visible</A><BR>
+<A HREF="param.html#vscheme">vscheme</A><BR>
+<H3><A NAME="indexW">W</A></H3><BR>
+<A HREF="param.html#warn">warn</A><BR>
+
+<HR>
+<H2>
+<A NAME="aboveord">aboveorder</A>
+</H2><P>
+specify in what order to stack items that are printed above a staff.
+The value is a comma-separated list of all the types of things that
+can be printed above a staff. Items are stacked in the order listed,
+starting from just above the staff and working upward.
+If you want several types to be handled as a single
+category, with all types in the category
+having the same stacking priority, separate
+them with an ampersand rather than a comma. The ampersand cannot
+be used with lyrics, ending, or reh. The dyn category applies to
+crescendo and decrescendo marks (from &quot;&lt;&quot; and &quot;&gt;&quot; statements)
+as well as text with the dyn modifier.
+The chord category applies to text with chord, analysis, or figbass
+modifiers. The othertext category applies to rom, bold, ital, and
+boldital items that do not have a chord, analysis, figbass, or dyn modifier.
+If you omit any categories, they will be stacked last, in their default order.
+</P>
+<P><B>Value: </B>
+<A HREF="mussym.html">mussym,</A>
+<A HREF="octave.html">octave,</A>
+<A HREF="textmark.html#chordmod">dyn, othertext, chord,</A>
+<A HREF="lyrics.html">lyrics,</A>
+<A HREF="bars.html#endings">ending,</A>
+<A HREF="bars.html#reh">reh</A>
+</P>
+<P><B>Default value: </B>
+mussym, octave, dyn &amp; othertext &amp; chord, lyrics, ending, reh
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+aboveorder = mussym, lyrics, dyn, octave, othertext, chord, ending, reh
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#beloword">beloworder,</A>
+<A HREF="param.html#betwnord">betweenorder,</A>
+<A HREF="param.html#chdist">chorddist,</A>
+<A HREF="param.html#dist">dist,</A>
+<A HREF="param.html#dyndist">dyndist</A>
+</P>
+<HR>
+<H2>
+<A NAME="addxpose">addtranspose</A>
+</H2><P>
+specify by what additional interval to transpose the music data.
+There is another parameter called just
+<A HREF="param.html#xpose">transpose.</A>
+Typically you would use the transpose parameter to change the key of
+individual staffs (for transposing instruments), and then use the
+addtranspose parameter if you want to change the key of the entire score.
+But either of these parameters can be used either way.
+In any case, for each staff, and for the score, the values of
+transpose and addtranspose are &quot;added&quot; to find the transposition
+for that staff or score.
+The interval can be
+larger than an octave, but must be a valid interval (e.g., there is no
+such thing as a perfect 6th). It is an error to specify a transposition value
+which would result in a key signature with more than 7 flats or sharps.
+It is also an error if transposition would result in a note requiring a
+triple sharp or triple flat.
+</P>
+<P><B>Value: </B>
+the word &quot;up&quot; or &quot;down,&quot; followed by an interval and a whole number greater than 0.
+The interval is one of major, minor, augmented, diminished, or perfect.
+The intervals can be abbreviated to their first 3 letters (maj,
+min, aug, dim, or per).
+The
+<A HREF="trnspose.html">section on transposition</A>
+lists transposition intervals and gives further details.
+Depending on which key signature you are
+transposing from, some transposition intervals may not work because they
+result in more than 7 flats or sharps.
+</P>
+<P><B>Default value: </B>
+up perfect 1 (i.e., no transposition)
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Examples:</B><BR>
+addtranspose = down major 3
+<BR>
+addtranspose = up perfect 5
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#key">key,</A>
+<A HREF="param.html#xpose">transpose</A>
+</P>
+<HR>
+<H2>
+<A NAME="barstyle">barstyle</A>
+</H2><P>
+specifies which staffs are to have their bar lines connected together.
+When drawing bar lines, a continuous vertical line will be drawn from
+the top line of the top staff in a range to the bottom line of the bottom
+staff of the range.
+Any staff not listed will be barred by itself, with the bar line spanning
+only the height of the staff.
+</P>
+<P><B>Value: </B>
+a comma-separated list of staff numbers and/or ranges of staff numbers.
+Staff numbers can be from 1 to the value of the
+<A HREF="param.html#staffs">"staffs" parameter.</A>
+A range is a pair of numbers separated by a dash.
+A given staff number can be specified only once,
+and there can be no overlapping between ranges.
+</P>
+<P><B>Default value: </B>
+each visible staff barred individually
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+barstyle = 1-2, 5-8
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#staffs">staffs,</A>
+<A HREF="param.html#visible">visible</A>
+</P>
+<HR>
+<H2>
+<A NAME="beamslp">beamslope</A>
+</H2><P>
+allows you to control the slope of beams.
+Two values must be given, separated by a comma.
+Mup calculates an appropriate slope for beams by applying a linear
+regression algorithm that uses the positions of the note heads within
+the beam. The first value supplied for the beamslope parameter
+is a factor by which to multiply the default slope that Mup calculates.
+The minimum value of 0.0 would cause all beams to be horizontal,
+whereas the maximum value of 1.0 will use the slope Mup calculates.
+Intermediate values will yield beams that are less slanted than the
+default slope calculation. The second value given to the beamslope parameter
+is the maximum angle for the beam, in degrees.
+If the originally calculated value multiplied by the
+factor yields an angle of greater than this maximum angle,
+the maximum angle will be used.
+<A HREF="ichdattr.html#crossbm">Cross-staff beams that are between staffs</A>
+are allowed to have a slope up to 1.4 times the value
+of the slope of the maximum angle, since they face more constraints.
+The slope can be overridden on a particular beam by specifying a
+<A HREF="ichdattr.html#slope">slope as an interchord attribute</A>
+on the first chord of the beamed set.
+</P>
+<P><B>Value: </B>
+0.0 to 1.0 for the factor, and 0.0 to 45.0 for the maximum angle
+</P>
+<P><B>Default value: </B>
+1.0, 20.0
+</P>
+<P><B>Context: </B>
+score, staff, voice
+</P>
+<P><B>Example:</B><BR>
+beamslope=0.8,20
+</P>
+<HR>
+<H2>
+<A NAME="beamstyl">beamstyle</A>
+</H2><P>
+specifies how to beam eighth notes or shorter. It is specified
+as a list of time values. Any number of notes up to each time value
+will be beamed together. For example, in 4/4 time, with beamstyle=4,4,4,4
+each quarter note worth of shorter notes would be beamed together.
+However, beams would not span across beats. As another example, for an input
+of 4.; 8; 8; 4.; the two eighth notes
+would not be beamed together, because they span beats. If beamstyle
+had been specified as 4,2,4 then the eighth notes would be beamed.
+Normally, beams also end whenever a rest or space is encountered.
+However, if an &quot;r&quot; is placed at the end of the list of time values,
+Mup will beams across rests of less than quarter note duration.
+Similarly, if an &quot;s&quot; is placed at the end of the list,
+Mup will beam across spaces of less than quarter note duration.
+You can specify both r and s in either order.
+It is possible to specify subbeams, or secondary groupings within a beam,
+by enclosing a list of time values in parentheses. In this case,
+the outer beam extends for the sum of the values in the parentheses,
+while inner beams extend only for the individual values within the parentheses.
+For example, if you set
+beamstyle=(4,4),(4,4) and then have a measure that consists of all 16th notes,
+the first 8 notes would be connected by an outer beam, as would the last 8
+notes, but the second (inner) beams would cover only 4 notes each.
+The parentheses cannot be nested.
+It is possible to override this default beaming style within a specific
+measure. See the section on
+<A HREF="ichdattr.html#custbeam">Custom Beaming</A>
+for examples of how to obtain various kinds of beaming.
+The value of the beamstyle parameter is remembered for
+any later changes back to the same time signature.
+In other words, if you set the value of the
+<A HREF="param.html#time">time parameter</A>
+and the beamstyle parameter in the same context, then later set only
+the time, the beamstyle that you had set earlier
+will be used again.
+</P>
+<P><B>Value: </B>
+a comma-separated list of time values that add up to a measure. Time values
+are specified as 4 for a quarter note, 2 for half note, etc, and
+can be dotted if necessary, or an expression with added and/or subtracted
+times. The list can optionally be followed by an &quot;r&quot;
+to indicate beams should span rests.
+It can optionally be followed by &quot;s&quot; to indicate beams should span spaces.
+Two or more of the time values may be enclosed in parentheses, to indicate
+sub-groupings of inner (secondary) beams within outer (primary) beams.
+If the value is empty, automatic beaming is turned off.
+</P>
+<P><B>Default value: </B>
+no beams; each note of eighth or shorter duration is individually flagged.
+</P>
+<P><B>Context: </B>
+score, staff, and voice
+</P>
+<P><B>Examples:</B><BR>
+beamstyle = 4,4,4,4
+<BR>
+beamstyle = 2.
+<BR>
+beamstyle=4+16, 4+16
+<BR>
+beamstyle = 2, 2 rs   // beam across rests and spaces
+<BR>
+beamstyle = (4., 4., 4.)  // one outer beam per measure,
+<BR>
+             // with inner beams broken at each dotted quarter duration
+<BR>
+beamstyle =      // turn off beaming
+</P>
+<HR>
+<H2>
+<A NAME="beloword">beloworder</A>
+</H2><P>
+specify in what order to stack items that are printed below a staff.
+The value is a comma-separated list of all the types of things that
+can be printed below a staff. Items are stacked in the order listed,
+starting from just below the staff and working downward.
+If you want several types to be handled as a single
+category, with all types in the category
+having the same stacking priority, separate
+them with an ampersand rather than a comma. The ampersand cannot
+be used with lyrics or pedal. The dyn category applies to
+crescendo and decrescendo marks (from &quot;&lt;&quot; and &quot;&gt;&quot; statements)
+as well as text with the dyn modifier.
+The chord category applies to text with chord, analysis, or figbass
+modifiers. The othertext category applies to rom, bold, ital, and
+boldital items that do not have a chord, analysis, figbass, or dyn modifier.
+If you omit any categories, they will be stacked last, in their default order.
+</P>
+<P><B>Value: </B>
+<A HREF="mussym.html">mussym,</A>
+<A HREF="octave.html">octave,</A>
+<A HREF="textmark.html#chordmod">dyn, othertext, chord,</A>
+<A HREF="lyrics.html">lyrics,</A>
+<A HREF="pedal.html">pedal</A>
+</P>
+<P><B>Default value: </B>
+mussym, octave, dyn &amp; othertext &amp; chord, lyrics, pedal
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+beloworder = mussym, lyrics, dyn, octave, othertext, chord, pedal
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#aboveord">aboveorder,</A>
+<A HREF="param.html#betwnord">betweenorder,</A>
+<A HREF="param.html#chdist">chorddist,</A>
+<A HREF="param.html#dist">dist,</A>
+<A HREF="param.html#dyndist">dyndist</A>
+</P>
+<HR>
+<H2>
+<A NAME="betwnord">betweenorder</A>
+</H2><P>
+specify in what order to stack items that are printed between two staffs.
+The value is a comma-separated list of all the types of things that
+can be printed between staffs. Items are stacked in the order listed,
+starting from a baseline and working upward.
+If you want several types to be handled as a single
+category, with all types in the category
+having the same stacking priority, separate
+them with an ampersand rather than a comma. The ampersand cannot
+be used with lyrics. The dyn category applies to
+crescendo and decrescendo marks (from &quot;&lt;&quot; and &quot;&gt;&quot; statements)
+as well as text with the dyn modifier.
+The chord category applies to text with chord, analysis, or figbass
+modifiers. The othertext category applies to rom, bold, ital, and
+boldital items that do not have a chord, analysis, figbass, or dyn modifier.
+If you omit any categories, they will be stacked last, in their default order.
+</P>
+<P><B>Value: </B>
+<A HREF="mussym.html">mussym,</A>
+<A HREF="textmark.html#chordmod">dyn, othertext, chord,</A>
+<A HREF="lyrics.html">lyrics,</A>
+</P>
+<P><B>Default value: </B>
+mussym, dyn &amp; othertext &amp; chord, lyrics
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+betweenorder = mussym, lyrics, dyn &amp; othertext, chord
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#aboveord">aboveorder,</A>
+<A HREF="param.html#beloword">beloworder,</A>
+<A HREF="param.html#chdist">chorddist,</A>
+<A HREF="param.html#dist">dist,</A>
+<A HREF="param.html#dyndist">dyndist</A>
+</P>
+<HR>
+<H2>
+<A NAME="botmar">bottommargin</A>
+</H2><P>
+sets the amount of white space margin to put at the bottom of each page.
+It is specified in inches if the
+<A HREF="param.html#units">units parameter</A>
+is set to inches, or in centimeters if the units parameter is set to cm.
+This parameter can only be specified before any music or
+<A HREF="prnttext.html#block">block input.</A>
+Margins are unaffected by
+<A HREF="param.html#scale">the "scale" parameter.</A>
+The parameter name can be abbreviated to just &quot;botmargin&quot; if you wish.
+</P>
+<P><B>Value: </B>
+0.0 to pageheight minus 0.5 inches
+</P>
+<P><B>Default value: </B>
+0.5 inches
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+bottommargin = 0.8
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#leftmar">leftmargin,</A>
+<A HREF="param.html#rightmar">rightmargin,</A>
+<A HREF="param.html#topmar">topmargin</A>
+<A HREF="param.html#pgheight">pageheight</A>
+<A HREF="param.html#units">units</A>
+</P>
+<HR>
+<H2>
+<A NAME="brace">brace</A>
+</H2><P>
+specifies which staffs are to be grouped together with a brace to the left
+of the score. If there is a string given in parentheses, that string
+will be used as the label to print on the next score,
+left of the bracket at its vertical center.
+If there is a second string,
+that will be used as the label for succeeding scores.
+</P>
+<P><B>Value: </B>
+a comma-separated list of staffs and/or staff ranges, each optionally followed
+by one or two double-quoted strings enclosed in parentheses.
+If there are two strings, they are separated by a comma.
+Staff numbers can range from 1 to the value of
+<A HREF="param.html#staffs">the "staffs" parameter.</A>
+A given staff number can be specified only once,
+and there can be no overlapping between ranges.
+Giving no value will result in no braces on any staffs.
+</P>
+<P><B>Default value: </B>
+no staffs are grouped by braces.
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Examples:</B><BR>
+brace = 3-4
+<BR>
+brace = 1, 2-3, 4, 5-6
+<BR>
+brace = 1-2 (&quot;piano&quot;), 3 (&quot;cello&quot;)
+<BR>
+brace = 1-2 (&quot;Primo&quot;, &quot;I&quot;)
+<BR>
+brace =        // no braces at all (the default)
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#bracket">bracket,</A>
+<A HREF="param.html#label">label,</A>
+<A HREF="param.html#label2">label2,</A>
+<A HREF="param.html#staffs">staffs</A>
+</P>
+<HR>
+<H2>
+<A NAME="bracket">bracket</A>
+</H2><P>
+specifies which staffs are to be grouped together with a bracket to the left
+of the score. If there is a string given in parentheses, that string
+will be used as the label to print on the next score,
+left of the bracket at its vertical center.
+If there is a second string,
+that will be used as the label for succeeding scores.
+</P>
+<P><B>Value: </B>
+a comma-separated list of staffs and/or staff ranges, each optionally followed
+by one or two double-quoted strings enclosed in parentheses.
+If there are two strings, they are separated by a comma.
+Staff numbers can range from 1 to the value of
+<A HREF="param.html#staffs">the "staffs" parameter.</A>
+A bracket range can overlap another bracket range, as long as one range
+is a proper subset of the other.
+Giving no value will result in no brackets on any staffs.
+</P>
+<P><B>Default value: </B>
+no staffs are grouped by brackets.
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Examples:</B><BR>
+bracket = 6-7
+<BR>
+bracket = 17, 21-23
+<BR>
+bracket = 8-9 (&quot;SATB&quot;)
+<BR>
+bracket = 10-12 (&quot;Strings&quot;, &quot;Str&quot;)
+<BR>
+bracket =        // no brackets at all (the default)
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#brace">brace,</A>
+<A HREF="param.html#label">label,</A>
+<A HREF="param.html#label2">label2,</A>
+<A HREF="param.html#staffs">staffs</A>
+</P>
+<HR>
+<H2>
+<A NAME="canclkey">cancelkey</A>
+</H2><P>
+When set to <B>y</B>, when a key changes, any sharps or flats in the 
+previous key that are not part of the new key will be canceled by printing
+natural signs, before printing the new key signature. When
+set to <B>n</B>, the naturals will only be printed if the new key has no
+sharps or flats.
+</P>
+<P><B>Value: </B>
+<B>y</B> or <B>n</B>
+</P>
+<P><B>Default value: </B>
+n
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+cancelkey=y
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#key">key</A>
+</P>
+<HR>
+<H2>
+<A NAME="chdist">chorddist</A>
+</H2><P>
+sets minimum distance from staff to place chords. When
+chord marks are printed, they will be placed
+no closer to the staff than the value
+of this parameter. This can be used to reduce the ragged effect of having
+some chord marks much higher than others, because other things were in
+their way.
+If a specific chord mark has to be
+moved farther away than this parameter to avoid running into something,
+that will still happen,
+but any others will come out at the level specified by this parameter.
+This parameter may be overridden on specific items. The section on
+<A HREF="stuff.html">tempo, dynamic marks, ornaments, etc.</A>
+gives details on how to do this.
+</P>
+<P><B>Value: </B>
+a whole number between 0 and 50 inclusive, given in stepsizes.
+</P>
+<P><B>Default value: </B>
+3
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+chorddist = 4
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#dyndist">dyndist,</A>
+<A HREF="param.html#dist">dist,</A>
+<A HREF="param.html#scorepad">scorepad,</A>
+<A HREF="param.html#scoresep">scoresep</A>
+</P>
+<HR>
+<H2>
+<A NAME="clef">clef</A>
+</H2><P>
+sets the clef to use.
+Changing a clef may also change the default octave
+<A HREF="param.html#defoct">(see the "defoct" parameter below).</A>
+</P>
+<P><B>Value: </B>
+treble, treble8, 8treble, frenchviolin, soprano, mezzosoprano,
+alto, tenor, baritone or bass.
+The treble8 clef looks like a treble clef with an 8 below it,
+and refers to notes that are an octave lower than a normal treble clef.
+The 8treble clef looks like a treble clef with an 8 above it,
+and refers to notes that are an octave higher than a normal treble clef.
+If the
+<A HREF="param.html#stlines">stafflines parameter</A>
+includes the &quot;drum&quot;
+keyword, then the value of this clef parameter is
+only used for determining the placement of notes on the staff, with the
+drum (or &quot;neutral&quot;) clef actually printed.
+Clef can be changed in
+<A HREF="midmeas.html">the middle of a measure</A>
+using a construct like &lt;&lt;staff clef=bass&gt;&gt; before a note group.
+</P>
+<P><B>Default value: </B>
+treble
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+clef = alto
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#defoct">defoct,</A>
+<A HREF="param.html#stlines">stafflines</A>
+</P>
+<HR>
+<H2>
+<A NAME="cresdist">crescdist</A>
+</H2><P>
+This parameter is obsolete; it has been replaced by
+<A HREF="param.html#dyndist">the dyndist parameter.</A>
+</P>
+<HR>
+<H2>
+<A NAME="defoct">defoct</A>
+</H2><P>
+sets the default octave for any note 
+which does not have an explicit octave specified.
+An octave goes from C up to the next B, with octave 4 being the octave
+beginning on middle C.
+If the clef is changed on a staff, the default octave
+is changed to match the new clef.
+defoct can be changed in
+<A HREF="midmeas.html">the middle of a measure</A>
+using a construct like &lt;&lt;staff defoct=5&gt;&gt; before a note group.
+</P>
+<P><B>Value: </B>
+a number from 0 to 9 inclusive. Octave 4 is the octave beginning at middle C.
+</P>
+<P><B>Default value: </B>
+the octave containing the note represented by the middle line of the staff
+given the current
+<A HREF="param.html#clef">clef.</A>
+(Octave 5 for frenchviolin and 8treble;
+octave 4 for treble, soprano, mezzosoprano, and
+alto clefs; octave 3 for treble8, tenor, baritone and bass clefs).
+</P>
+<P><B>Context: </B>
+score, staff, voice
+</P>
+<P><B>Example:</B><BR>
+defoct = 3
+</P>
+<HR>
+<H2>
+<A NAME="dist">dist</A>
+</H2><P>
+sets minimum distance from staff to place
+<A HREF="textmark.html">rom, bold, ital, and boldital items,</A>
+and
+<A HREF="bars.html#reh">rehearsal marks.</A>
+When these items are printed,
+they will be placed no closer to the staff than the value
+of this parameter. This can be used to reduce the ragged effect of having
+some items much higher than others, because other things were in their way.
+If a specific item has to be
+moved farther away than this parameter to avoid running into something,
+that will still happen,
+but any others will come out at the level specified by this parameter.
+If an item is also a chord,
+<A HREF="param.html#chdist">the chorddist parameter</A>
+will be used instead of dist.
+This parameter may be overridden on specific items. The sections on
+<A HREF="stuff.html">tempo, dynamic marks, ornaments, etc.</A>
+and on
+<A HREF="bars.html#reh">rehearsal marks</A>
+give details on how to do this.
+</P>
+<P><B>Value: </B>
+a whole number between 0 and 50 inclusive, given in stepsizes.
+</P>
+<P><B>Default value: </B>
+2
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+dist = 6
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#chdist">chorddist,</A>
+<A HREF="param.html#dyndist">dyndist,</A>
+<A HREF="param.html#scorepad">scorepad,</A>
+<A HREF="param.html#scoresep">scoresep</A>
+</P>
+<HR>
+<H2>
+<A NAME="division">division</A>
+</H2><P>
+sets
+<A HREF="midi.html">MIDI</A>
+division (number of clock ticks per quarter note). This typically
+has a value of 192 or 384.
+This parameter can only be specified before any music or block input.
+</P>
+<P><B>Value: </B>
+1 to 1536
+</P>
+<P><B>Default value: </B>
+192
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+division = 384
+</P>
+<HR>
+<H2>
+<A NAME="dyndist">dyndist</A>
+</H2><P>
+sets minimum distance from staff to place
+<A HREF="cres.html">crescendo and decrescendo marks.</A>
+and text that is marked &quot;dyn.&quot;
+When these items are printed,
+they will be placed no closer to the staff than the value
+of this parameter. This can be used to reduce the ragged effect of having
+some items much higher than others, because other things were in their way.
+If a specific item has to be
+moved farther away than this parameter to avoid running into something,
+that will still happen,
+but any others will come out at the level specified by this parameter.
+This parameter may be overridden on specific items. The section on
+<A HREF="stuff.html">tempo, dynamic marks, ornaments, etc.</A>
+gives details on how to do this.
+</P>
+<P><B>Value: </B>
+a whole number between 0 and 50 inclusive, given in stepsizes.
+</P>
+<P><B>Default value: </B>
+2
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+dyndist = 4
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#chdist">chorddist,</A>
+<A HREF="param.html#dist">dist,</A>
+<A HREF="param.html#scorepad">scorepad,</A>
+<A HREF="param.html#scoresep">scoresep</A>
+</P>
+<HR>
+<H2>
+<A NAME="endingst">endingstyle</A>
+</H2><P>
+controls how
+<A HREF="bars.html#endings">first and second endings</A>
+are placed.
+This parameter also controls where
+<A HREF="param.html#measnum">measure numbers</A>
+and
+<A HREF="bars.html#reh">rehearsal marks are placed.</A>
+A value of &quot;top&quot; means that the endings and similar marks
+will be shown only above the top
+<A HREF="param.html#visible">visible staff.</A>
+A value of &quot;barred&quot;
+means these marks will be shown above each set of staffs
+that is barred together. Each staff that is barred individually will also
+have the ending shown above it.
+<A HREF="param.html#barstyle">(See the "barstyle" parameter above.)</A>
+A value of &quot;grouped&quot; means the marks
+will be shown above the top visible
+staff of each range of staffs that are joined by a
+<A HREF="param.html#brace">brace</A>
+or
+<A HREF="param.html#bracket">bracket.</A>
+In all cases, at least the top visible staff will
+have endings shown above it.
+</P>
+<P><B>Value: </B>
+top, barred, or grouped
+</P>
+<P><B>Default value: </B>
+top
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+endingstyle = grouped
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#barstyle">barstyle,</A>
+<A HREF="param.html#brace">brace,</A>
+<A HREF="param.html#bracket">bracket,</A>
+<A HREF="param.html#measnum">measnum,</A>
+<A HREF="param.html#rehstyle">rehstyle,</A>
+<A HREF="param.html#visible">visible</A>
+</P>
+<HR>
+<H2>
+<A NAME="firstpg">firstpage</A>
+</H2><P>
+specifies what to number the first page.
+This value can be overridden by the
+<A HREF="cmdargs.html#poption">-p command line option.</A>
+This parameter can only be set before any music or block input.
+</P>
+<P><B>Value: </B>
+1 to 5000
+</P>
+<P><B>Default value: </B>
+1
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+firstpage = 12
+</P>
+<HR>
+<H2>
+<A NAME="font">font</A>
+</H2><P>
+specifies which font to use for
+<A HREF="prnttext.html">print, left, right, center, and title statements,</A>
+and
+<A HREF="chrdattr.html#withlist">"with" lists (i.e., strings that are associated with a particular chord).</A>
+</P>
+<P><B>Value: </B>
+rom, ital, bold, or boldital
+</P>
+<P><B>Default value: </B>
+rom
+</P>
+<P><B>Context: </B>
+score, staff, header, footer, header2, footer2, top, bottom, top2, bottom2, block
+</P>
+<P><B>Example:</B><BR>
+font = boldital
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#fontfam">fontfamily,</A>
+<A HREF="param.html#lyrfont">lyricsfont,</A>
+<A HREF="param.html#lyrfam">lyricsfontfamily,</A>
+<A HREF="param.html#size">size</A>
+</P>
+<HR>
+<H2>
+<A NAME="fontfam">fontfamily</A>
+</H2><P>
+specifies what font family to use for
+<A HREF="prnttext.html">print, left, right, center, and title statements</A>
+and
+<A HREF="chrdattr.html#withlist">"with" lists (i.e., strings that are associated with a particular chord).</A>
+</P>
+<P><B>Value: </B>
+avantgarde, bookman, courier, helvetica, newcentury, palatino, times
+</P>
+<P><B>Default value: </B>
+times
+</P>
+<P><B>Context: </B>
+score, staff, header, footer, header2, footer2, top, bottom, top2, bottom2, block
+</P>
+<P><B>Example:</B><BR>
+fontfamily=palatino
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#font">font,</A>
+<A HREF="param.html#lyrfont">lyricsfont,</A>
+<A HREF="param.html#lyrfam">lyricsfontfamily</A>
+</P>
+<HR>
+<H2>
+<A NAME="gridfret">gridfret</A>
+</H2><P>
+specifies when to print fret numbers on grids.
+Normally, the top line of
+a grid represents the nut. However, if the fingering for a chord is rather
+far up the neck, it is customary to have the top line of the grid represent
+some other fret, and print a fret number and &quot;fr&quot; next to the grid,
+showing the actual fret of the rightmost fret mark. This parameter controls
+when Mup begins using this alternate format. Whenever all the frets of
+a chord are greater than or equal to
+the value specified for this parameter, and there are no strings marked &quot;o&quot;,
+the &quot;fr&quot; notation is used. If no value is set for this parameter,
+the grid will just be made as tall
+as necessary to accommodate the chord's frets.
+</P>
+<P><B>Value: </B>
+2 to 99, or not set
+</P>
+<P><B>Default value: </B>
+4
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+gridfret = 3
+<BR>
+gridfret =
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#gridend">gridsatend,</A>
+<A HREF="param.html#gridscl">gridscale,</A>
+<A HREF="param.html#gridused">gridswhereused,</A>
+</P>
+<HR>
+<H2>
+<A NAME="gridend">gridsatend</A>
+</H2><P>
+specifies whether to print guitar grids at the end of the song.
+If set to &quot;y&quot;
+grids for all of the chords used in the song will be printed.
+</P>
+<P><B>Value: </B>
+y or n
+</P>
+<P><B>Default value: </B>
+n
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+gridsatend = y
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#gridfret">gridfret,</A>
+<A HREF="param.html#gridscl">gridscale,</A>
+<A HREF="param.html#gridused">gridswhereused</A>
+</P>
+<HR>
+<H2>
+<A NAME="gridscl">gridscale</A>
+</H2><P>
+specifies how large to make grids, relative to their default size.
+For example, a value of 0.5 will make them 1/2 their default size.
+The default size for grids summarized at the end
+of the song
+<A HREF="param.html#gridend">(the gridsatend parameter)</A>
+is larger than the default size for those printed with the music
+<A HREF="param.html#gridused">(the gridswhereused parameter).</A>
+</P>
+<P><B>Value: </B>
+0.1 to 10.0
+</P>
+<P><B>Default value: </B>
+1.0
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+gridscale = 0.5
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#gridend">gridsatend,</A>
+<A HREF="param.html#gridfret">gridfret,</A>
+<A HREF="param.html#gridused">gridswhereused,</A>
+<A HREF="param.html#scale">scale,</A>
+<A HREF="param.html#stscale">staffscale</A>
+</P>
+<HR>
+<H2>
+<A NAME="gridused">gridswhereused</A>
+</H2><P>
+specifies whether to print guitar grids along with chords
+where they appear in the song. If set to &quot;y&quot; each
+<A HREF="textmark.html#chordmod">text item with the chord modifier</A>
+will have a grid printed below its name.
+</P>
+<P><B>Value: </B>
+y or n
+</P>
+<P><B>Default value: </B>
+n
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+gridswhereused = y
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#gridfret">gridfret,</A>
+<A HREF="param.html#gridend">gridsatend,</A>
+<A HREF="param.html#gridscl">gridscale</A>
+</P>
+<HR>
+<H2>
+<A NAME="key">key</A>
+</H2><P>
+sets the key signature. This can be specified either by giving the
+number of sharps (#) or flats (&amp;), or by giving the name of the key.
+</P>
+<P><B>Value: </B>
+If using the number of sharps/flats format, the value is
+a number from 0 to 7, followed by &quot;#&quot; or &quot;&amp;,&quot; optionally followed by &quot;major&quot;
+or &quot;minor.&quot; 0&amp; and 0# are equivalent.
+If using the name of the key, the value is a letter &quot;a&quot; through &quot;g,&quot;
+optionally followed by a &quot;#&quot; or &quot;&amp;,&quot; optionally followed by &quot;major&quot; or &quot;minor.&quot;
+The &quot;major&quot; and &quot;minor&quot; can be abbreviated to &quot;maj&quot; or &quot;min.&quot;
+The &quot;major&quot; or &quot;minor&quot; is used for
+<A HREF="midi.html">MIDI file</A>
+purposes, and is optional; if omitted, it defaults to major.
+If you wish to use a mode other than major or minor,
+you have to specify the number of sharps or flats.
+</P>
+<P><B>Default value: </B>
+c major
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+key = 3&amp;
+<BR>
+key = 6#
+<BR>
+key = c# minor
+<BR>
+key = d major
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#stlines">stafflines,</A>
+<A HREF="param.html#xpose">transpose,</A>
+<A HREF="param.html#addxpose">addtranspose</A>
+</P>
+<HR>
+<H2>
+<A NAME="label">label</A>
+</H2><P>
+specify a label to be printed to the left of the staff on the next
+score. If there is also a
+<A HREF="param.html#brace">brace</A>
+or
+<A HREF="param.html#bracket">bracket</A>
+label, that label will
+be to the left of this label.
+There is a
+<A HREF="param.html#label2">label2</A>
+parameter that is used on subsequent scores.
+In addition to being used for the very first score of a song,
+this label parameter might be used to clearly mark a change in instrumentation
+or voices for a particular staff. The label2 would typically be changed at
+the same time, giving a more abbreviated label. For example,
+you might set label=&quot;Tenor/Bass&quot; and label2=&quot;TB&quot;
+</P>
+<P><B>Value: </B>
+<A HREF="textstr.html">a text string</A>
+enclosed in double quotes.
+</P>
+<P><B>Default value: </B>
+enough spaces to produce an indent of 1/2 inch
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+label = &quot;oboe&quot;
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#brace">brace,</A>
+<A HREF="param.html#bracket">bracket,</A>
+<A HREF="param.html#label">label2</A>
+</P>
+<HR>
+<H2>
+<A NAME="label2">label2</A>
+</H2><P>
+specify a label to be printed to the left of the staff on all scores after
+the first. If there is also a
+<A HREF="param.html#brace">brace</A>
+or
+<A HREF="param.html#bracket">bracket</A>
+label, that label will be to the left of this label.
+If both the
+<A HREF="param.html#label">label</A>
+and label2 parameters are set at the same time,
+the label value will be used for the immediately
+following score, with the label2 value used for subsequent scores.
+If however, after the first score, only the label2 is changed,
+then the label2 value will be used on the immediately following score
+as well as subsequent scores.
+</P>
+<P><B>Value: </B>
+<A HREF="textstr.html">a text string</A>
+enclosed in double quotes
+</P>
+<P><B>Default value: </B>
+no label
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+label2 = &quot;Solo&quot;
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#brace">brace,</A>
+<A HREF="param.html#bracket">bracket,</A>
+<A HREF="param.html#label">label</A>
+</P>
+<HR>
+<H2>
+<A NAME="leftmar">leftmargin</A>
+</H2><P>
+sets the amount of white space margin to put at the left side of each page.
+It is specified in inches if the
+<A HREF="param.html#units">units parameter</A>
+is set to inches, or in centimeters if the units parameter is set to cm.
+This parameter can only be specified before any music or block input.
+Margins are unaffected by
+<A HREF="param.html#scale">the "scale" parameter.</A>
+</P>
+<P><B>Value: </B>
+0.0 to pagewidth minus 0.5 inches
+</P>
+<P><B>Default value: </B>
+0.5 inches
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+leftmargin = 0.3
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#botmar">bottommargin,</A>
+<A HREF="param.html#rightmar">rightmargin,</A>
+<A HREF="param.html#topmar">topmargin,</A>
+<A HREF="param.html#pgwidth">pagewidth,</A>
+<A HREF="param.html#units">units</A>
+</P>
+<HR>
+<H2>
+<A NAME="lyralign">lyricsalign</A>
+</H2><P>
+specifies how to align lyric syllables with chords. Its value is the
+proportion of each syllable to place to the left of the syllable's chord.
+Thus for example, a value of 0.0 causes
+the left edge of syllables to be aligned with
+the chords, whereas a value of 0.5 causes syllables to be centered with
+the chord, and 1.0 causes the right edge of the syllables to be aligned
+with the chord.
+</P>
+<P><B>Value: </B>
+0.0 to 1.0
+</P>
+<P><B>Default value: </B>
+0.25
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+lyricsalign = 0.1
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#sylpos">sylposition</A>
+</P>
+<HR>
+<H2>
+<A NAME="lyrfont">lyricsfont</A>
+</H2><P>
+sets which font to use for
+<A HREF="lyrics.html">lyrics.</A>
+</P>
+<P><B>Value: </B>
+rom, ital, bold, boldital
+</P>
+<P><B>Default value: </B>
+rom
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+lyricsfont = ital
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#font">font,</A>
+<A HREF="param.html#lyrsize">lyricssize</A>
+</P>
+<HR>
+<H2>
+<A NAME="lyrfam">lyricsfontfamily</A>
+</H2><P>
+specifies what font family to use for
+<A HREF="lyrics.html">lyrics.</A>
+</P>
+<P><B>Value: </B>
+avantgarde, bookman, courier, helvetica, newcentury, palatino, times
+</P>
+<P><B>Default value: </B>
+times
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+lyricsfontfamily=helvetica
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#font">font,</A>
+<A HREF="param.html#fontfam">fontfamily,</A>
+<A HREF="param.html#lyrfont">lyricsfont</A>
+</P>
+<HR>
+<H2>
+<A NAME="lyrsize">lyricssize</A>
+</H2><P>
+sets point size to use for
+<A HREF="lyrics.html">lyrics.</A>
+</P>
+<P><B>Value: </B>
+a number from 1 to 100
+</P>
+<P><B>Default value: </B>
+12
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+lyricssize = 10
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#lyrfont">lyricsfont,</A>
+<A HREF="param.html#lyrfam">lyricsfontfamily,</A>
+<A HREF="param.html#size">size</A>
+</P>
+<HR>
+<H2>
+<A NAME="measnum">measnum</A>
+</H2><P>
+specifies whether or not to print measure numbers.
+If set to &quot;y,&quot;
+the current measure number will be printed at the beginning of each score
+other than the first. The number will be printed above any scores that
+would receive ending marks
+<A HREF="param.html#endingst">(see "endingstyle" parameter).</A>
+If set to &quot;n,&quot; no measure numbers will be printed.
+This parameter does not affect
+<A HREF="bars.html#reh">rehearsal numbers, which are equal to measure numbers when "mnum" is used.</A>
+</P>
+<P><B>Value: </B>
+y or n
+</P>
+<P><B>Default value: </B>
+n
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+measnum = y
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#endingst">endingstyle,</A>
+<A HREF="param.html#mnumfont">measnumfont,</A>
+<A HREF="param.html#mnumfam">measnumfontfamily,</A>
+<A HREF="param.html#mnumsize">measnumsize,</A>
+<A HREF="param.html#rehstyle">rehstyle</A>
+</P>
+<HR>
+<H2>
+<A NAME="mnumfont">measnumfont</A>
+</H2><P>
+This specifies which font type to use for the automatic measure numbers,
+if they are turned on via the
+<A HREF="param.html#measnum">measnum parameter.</A>
+</P>
+<P><B>Value: </B>
+rom, ital, bold, or boldital
+</P>
+<P><B>Default value: </B>
+rom
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+measnumfont=boldital
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#measnum">measnum,</A>
+<A HREF="param.html#mnumfam">measnumfontfamily,</A>
+<A HREF="param.html#mnumsize">measnumsize</A>
+</P>
+<HR>
+<H2>
+<A NAME="mnumfam">measnumfontfamily</A>
+</H2><P>
+This specifies which font family to use for the automatic measure numbers,
+if they are turned on via the
+<A HREF="param.html#measnum">measnum parameter.</A>
+</P>
+<P><B>Value: </B>
+avantegarde, bookman, courier, helvetica, newcentry, palatino, or times
+</P>
+<P><B>Default value: </B>
+times
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+measnumfontfamily=helvetica
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#measnum">measnum,</A>
+<A HREF="param.html#mnumfont">measnumfont,</A>
+<A HREF="param.html#mnumsize">measnumsize</A>
+</P>
+<HR>
+<H2>
+<A NAME="mnumsize">measnumsize</A>
+</H2><P>
+This specifies what size to use for the automatic measure numbers,
+in points, if they are turned on via the
+<A HREF="param.html#measnum">measnum parameter.</A>
+</P>
+<P><B>Value: </B>
+1 to 100
+</P>
+<P><B>Default value: </B>
+11
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+measnumsize=15
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#measnum">measnum,</A>
+<A HREF="param.html#mnumfont">measnumfont,</A>
+<A HREF="param.html#mnumfam">measnumfontfamily</A>
+</P>
+<HR>
+<H2>
+<A NAME="notehead">noteheads</A>
+</H2><P>
+The noteheads parameter describes which note head shape(s)
+to use for each pitch in the scale.
+If you want to use the same shape for all pitches,
+as is the case with standard notation, the value is a string
+containing a single shape name (e.g., &quot;norm&quot; for standard notation).
+If you want to use different shapes for different pitches,
+the noteheads parameter value is a string containing a list of 7 shape names.
+They are listed in order starting from the &quot;tonic&quot;
+of the major key as indicated by the number of sharps or flats in the
+<A HREF="param.html#key">key signature.</A>
+There are 10 pre-defined head shapes:
+blank, diam, isostri, norm, pie, rect, righttri, semicirc, slash, and xnote.
+Additional head shapes can be defined in the
+<A HREF="shaped.html#hdshape">headshapes context.</A>
+See the examples below for the most common settings for
+this parameter. Head shape can be
+<A HREF="shaped.html#chord">overridden on an individual chord</A>
+by using [hs &quot;shapename&quot;]
+before the chord. It can also be
+<A HREF="shaped.html#note">overridden on an individual note</A>
+by putting hs &quot;shapename&quot; after the note.
+</P>
+<P><B>Value: </B>
+A string containing either 1 or 7 head shape names.
+</P>
+<P><B>Default value: </B>
+&quot;norm&quot;
+</P>
+<P><B>Context: </B>
+score, staff, voice
+</P>
+<P><B>Example:</B><BR>
+// This is the setting for the most common shaped note system using 4 shapes.
+<BR>
+noteheads = &quot;righttri norm rect righttri norm rect diam&quot;
+<BR>
+
+// This is the setting for a shaped notes system that uses 7 different shapes.
+<BR>
+noteheads = &quot;isostri semicirc diam righttri norm rect pie&quot;
+</P>
+<HR>
+<H2>
+<A NAME="nummrpt">numbermrpt</A>
+</H2><P>
+If set to 'y'
+<A HREF="chordinp.html#measdur">measure repeats</A>
+are numbered; if set to 'n' they aren't.
+</P>
+<P><B>Value: </B>
+y or n
+</P>
+<P><B>Default value: </B>
+y
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+numbermrpt = n
+</P>
+<HR>
+<H2>
+<A NAME="ontheline">ontheline</A>
+</H2><P>
+specifies whether notes for voices 1 and 2
+on a 1-line staff are to be placed on the line.
+If this is set to n, notes with stem up will be placed above the line
+and notes with stem down will be placed below the line, otherwise both
+will be placed on the line. For notes that don't have a stem, the rules
+are applied using the direction the stem would be if there were a stem.
+This parameter has no effect on
+<A HREF="param.html#stlines">5-line staffs</A>
+or
+<A HREF="tabstaff.html">tablature staffs.</A>
+Notes for voice 3 are always placed on the line on 1-line staffs,
+regardless of the value of this parameter.
+</P>
+<P><B>Value: </B>
+y or n
+</P>
+<P><B>Default value: </B>
+y
+</P>
+<P><B>Context: </B>
+score, staff, voice
+</P>
+<P><B>Example:</B><BR>
+ontheline=n
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#stlines">stafflines</A>
+</P>
+<HR>
+<H2>
+<A NAME="packexp">packexp</A>
+</H2><P>
+sets note expansion factor. This factor controls spacing of notes relative
+to their time values. If set to 1.0, Mup will try to give a half note twice
+as much space as a quarter note, a whole note twice as much as a half note,
+etc. If set to 0.0, a chord's time value will have no impact on its placement.
+Intermediate values will cause relative spacing
+between the two extremes. Note that individual chords may get more space
+than they would theoretically &quot;deserve&quot; if they happen to need extra space
+to accommodate accidentals, dots, etc.
+</P>
+<P><B>Value: </B>
+a number from 0.0 to 1.0 inclusive
+</P>
+<P><B>Default value: </B>
+0.8
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+packexp = 0.95
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#packfact">packfact,</A>
+<A HREF="param.html#pad">pad</A>
+</P>
+<HR>
+<H2>
+<A NAME="packfact">packfact</A>
+</H2><P>
+specifies how tightly to pack notes together on output. The smaller
+the value, the more tightly notes are packed together.
+</P>
+<P><B>Value: </B>
+a number from 0.0 to 10.0
+</P>
+<P><B>Default value: </B>
+1.0
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+packfact = 1.4
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#packexp">packexp,</A>
+<A HREF="param.html#pad">pad</A>
+</P>
+<HR>
+<H2>
+<A NAME="pad">pad</A>
+</H2><P>
+specifies the amount of padding to be added to notes.
+This can be used to control how tightly things are packed together.
+Especially if
+<A HREF="param.html#packexp">packexp</A>
+and
+<A HREF="param.html#packfact">packfact</A>
+are very small, notes can get placed very close together.
+This parameter can be used to always force a minimum amount of space
+between horizontally adjacent note groups.
+A value of zero means notes will be allowed to just touch.
+More positive values cause more space around notes.
+A negative value will let things
+actually overlap, so most people will probably never want to use a
+negative value, but the option is there if you want to do something unusual.
+This parameter works somewhat like
+<A HREF="chrdattr.html#pad">the "pad" value that can be specified for individual note groups,</A>
+except that it applies to all groups.
+</P>
+<P><B>Value: </B>
+a floating point number of stepsizes, -5.0 to 50.0
+</P>
+<P><B>Default value: </B>
+0.3333
+</P>
+<P><B>Context: </B>
+score, staff, voice
+</P>
+<P><B>Example:</B><BR>
+pad = 1.76
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#packexp">packexp,</A>
+<A HREF="param.html#packfact">packfact</A>
+</P>
+<HR>
+<H2>
+<A NAME="pgheight">pageheight</A>
+</H2><P>
+Set the page height. If the
+<A HREF="param.html#units">units parameter</A>
+is inches, the value of pageheight is given in inches,
+or if the units parameter is cm, it is given in centimeters.
+This parameter can only be specified before any music or block input.
+If the
+<A HREF="param.html#pgwidth">pagewidth</A>
+and pageheight parameters are set to values that match
+a standard paper size in landscape mode, the Mup output will be rotated
+to print properly in landscape mode.
+</P>
+<P><B>Value: </B>
+2.0 to 24.0 inches or 5.0 to 61.0 cm
+</P>
+<P><B>Default value: </B>
+11.0 inches
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+pageheight = 9
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#pgwidth">pagewidth,</A>
+<A HREF="param.html#botmar">bottommargin</A>
+<A HREF="param.html#topmar">topmargin,</A>
+<A HREF="param.html#units">units</A>
+</P>
+<HR>
+<H2>
+<A NAME="pgsize">pagesize</A>
+</H2><P>
+Set the page size. This is just an alternate way of specifying
+<A HREF="param.html#pgheight">pageheight</A>
+and
+<A HREF="param.html#pgwidth">pagewidth</A>
+using the common names for paper sizes rather than specifying in
+<A HREF="param.html#units">inches or cm.</A>
+An orientation (portrait or landscape) can also be specified;
+the default is portrait.
+This parameter can only be specified before any music or block input.
+</P>
+<P><B>Value: </B>
+letter, legal, flsa, halfletter, a4, a5, a6; optionally followed by
+portrait or landscape.
+</P>
+<P><B>Default value: </B>
+letter
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+pagesize = a4
+<BR>
+pagesize = legal landscape
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#pgheight">pageheight,</A>
+<A HREF="param.html#pgwidth">pagewidth,</A>
+<A HREF="param.html#panels">panelsperpage</A>
+</P>
+<HR>
+<H2>
+<A NAME="pgwidth">pagewidth</A>
+</H2><P>
+Set the page width. If the
+<A HREF="param.html#units">units parameter</A>
+is inches, the value of pagewidth is given in inches,
+or if the units parameter is cm, it is given in centimeters.
+This parameter can only be specified before any music or block input.
+If the pagewidth and
+<A HREF="param.html#pgheight">pageheight</A>
+parameters are set to values that match
+a standard paper size in landscape mode, the Mup output will be rotated
+to print properly in landscape mode.
+</P>
+<P><B>Value: </B>
+2.0 to 24.0 inches or 5.0 to 61.0 cm
+</P>
+<P><B>Default value: </B>
+8.5 inches
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+pagewidth = 6.5
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#pgheight">pageheight,</A>
+<A HREF="param.html#leftmar">leftmargin,</A>
+<A HREF="param.html#rightmar">rightmargin,</A>
+<A HREF="param.html#units">units</A>
+</P>
+<HR>
+<H2>
+<A NAME="panels">panelsperpage</A>
+</H2><P>
+Specifies how many pages of music to print on each physical page.
+This parameter can only be specified before any music or block input.
+Note that the
+<A HREF="param.html#pgheight">pageheight</A>
+and
+<A HREF="param.html#pgwidth">pagewidth</A>
+parameters still apply to the physical paper size viewed in portrait mode,
+even when the panelsperpage value causes the printing to be landscape mode,
+so you should continue to leave those set as you normally would.
+The
+<A HREF="cmdargs.html#ooption">-o command line option</A>
+may be useful for getting pages printed in desired order.
+For example, to make a 4-page booklet from a single sheet of paper
+folded in half, you can use panelsperpage=2, then use -o4,1 to print one side
+of the paper, and -o2,3 to print the other side.
+</P>
+<P><B>Value: </B>
+1 or 2
+</P>
+<P><B>Default value: </B>
+1
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+panelsperpage=2
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#pgheight">pageheight,</A>
+<A HREF="param.html#pgwidth">pagewidth</A>
+</P>
+<HR>
+<H2>
+<A NAME="pedstyle">pedstyle</A>
+</H2><P>
+Specifies whether to display
+<A HREF="pedal.html">piano pedal marks</A>
+with lines or with the word &quot;Ped&quot; and &quot;*&quot;.
+With the &quot;pedstar&quot; style, a &quot;bounce&quot; of the pedal is shown by a &quot;* Ped&quot;
+whereas with the &quot;alt pedstar&quot; style, only a &quot;Ped&quot; is printed.
+</P>
+<P><B>Value: </B>
+line, pedstar, or alt pedstar
+</P>
+<P><B>Default value: </B>
+line
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+pedstyle = pedstar
+</P>
+<HR>
+<H2>
+<A NAME="prmultn">printmultnum</A>
+</H2><P>
+If set to 'y'
+<A HREF="multirst.html">multirests</A>
+are labeled with the number of measures of rest they represent;
+if set to 'n' they aren't.
+This would allow you to print some other commentary in place of the
+number, print it in a different style, etc.
+</P>
+<P><B>Value: </B>
+y or n
+</P>
+<P><B>Default value: </B>
+y
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+printmultnum = n
+</P>
+<HR>
+<H2>
+<A NAME="rehstyle">rehstyle</A>
+</H2><P>
+Specifies whether to enclose
+<A HREF="bars.html#reh">rehearsal marks</A>
+inside box, inside a circle, or just as plain text.
+</P>
+<P><B>Value: </B>
+boxed, circled, or plain
+</P>
+<P><B>Default value: </B>
+boxed
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+rehstyle = circled
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#endingst">endingstyle</A>
+</P>
+<HR>
+<H2>
+<A NAME="release">release</A>
+</H2><P>
+Specifies how soon (in milliseconds) before the full time value of note
+to release the note when generating
+<A HREF="midi.html">MIDI output.</A>
+This controls how legato (smooth) the music is.
+A value of 0 will make it very legato. The larger the value, the
+more detached notes will be. This parameter specifies a
+maximum amount to shorten notes; a note will never be shortened
+to less than 75% of its full value.
+release can be changed in
+<A HREF="midmeas.html">the middle of a measure</A>
+using a construct like &lt;&lt;score release=50&gt;&gt; before a note group.
+</P>
+<P><B>Value: </B>
+0 to 500
+</P>
+<P><B>Default value: </B>
+20
+</P>
+<P><B>Context: </B>
+score, staff, voice
+</P>
+<P><B>Example:</B><BR>
+release = 40
+</P>
+<HR>
+<H2>
+<A NAME="restcomb">restcombine</A>
+</H2><P>
+If the given number of measures of rest occur in a row,
+they will be replaced by a
+<A HREF="multirst.html">multirest.</A>
+This parameter can be overridden by the
+-c command line option.
+See the
+<A HREF="cmdargs.html#coption">description of the -c option</A>
+for more complete information on how the combining is done.
+</P>
+<P><B>Value: </B>
+2 to 1000 or nothing
+</P>
+<P><B>Default value: </B>
+not set
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+restcombine = 5
+<BR>
+restcombine =    // turn off combining
+</P>
+<HR>
+<H2>
+<A NAME="restsymm">restsymmult</A>
+</H2><P>
+Multi-rests are normally drawn as a horizontal line on the middle line
+of the staff, with two vertical lines at the end. But there is an
+alternate notation style that uses rest symbols (whole, double whole,
+and quad whole) when the number of measures is short.
+If this parameter is set to y, that alternate style will be used for
+multirests of eight measures or less.
+</P>
+<P><B>Value: </B>
+y or n
+</P>
+<P><B>Default value: </B>
+n
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+restsymmult = y
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#prmultn">printmultnum</A>
+</P>
+<HR>
+<H2>
+<A NAME="rightmar">rightmargin</A>
+</H2><P>
+sets the amount of white space margin to put at the right side of each page.
+It is specified in inches if the
+<A HREF="param.html#units">units parameter</A>
+is set to inches, or in centimeters if the units parameter is set to cm.
+This parameter can only be specified before any music or block input.
+Margins are unaffected by
+<A HREF="param.html#scale">the "scale" parameter.</A>
+</P>
+<P><B>Value: </B>
+0.0 to pagewidth minus 0.5 inches
+</P>
+<P><B>Default value: </B>
+0.5 inches
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+rightmargin = 0.3
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#botmar">bottommargin,</A>
+<A HREF="param.html#leftmar">leftmargin,</A>
+<A HREF="param.html#topmar">topmargin,</A>
+<A HREF="param.html#pgwidth">pagewidth,</A>
+<A HREF="param.html#units">units</A>
+</P>
+<HR>
+<H2>
+<A NAME="scale">scale</A>
+</H2><P>
+Scale the printed output by the specified factor. For example,
+scale=2 prints everything twice as large as normal, while scale=0.5
+prints everything at half size.
+This parameter can only be specified before any music or block input.
+</P>
+<P><B>Value: </B>
+A number between 0.1 and 10.0
+</P>
+<P><B>Default value: </B>
+1.0
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+scale=0.95
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#packfact">packfact,</A>
+<A HREF="param.html#packexp">packexp,</A>
+<A HREF="param.html#stscale">staffscale</A>
+</P>
+<HR>
+<H2>
+<A NAME="scorepad">scorepad</A>
+</H2><P>
+sets the amount of padding (white space) to leave between scores,
+accounting for all the things that protrude from both scores.
+Either a single number, giving a minimum
+amount, or two numbers, giving a minimum and maximum,
+can be specified. They are specified in stepsizes.
+If only the minimum is specified, and it is larger than the default
+maximum of 2, the maximum will be adjusted to equal the minimum.
+Depending on the setting of the
+<A HREF="param.html#scoresep">scoresep parameter,</A>
+the maximum may be exceeded; see the description of
+scoresep for how these parameters interact to determine the placement
+of the scores.
+If a negative value is specified for scorepad, some overlap may occur,
+(subject to the interaction with scoresep).
+Specifying a negative value may be particularly useful when things
+protrude downward from the top score and upward from the bottom score,
+but at different places horizontally, such that it is actually safe
+to put the scores closer together without collision, even though Mup
+can't tell that it is safe.
+Note, however, that this overrides Mup's protection against real
+collisions, so this must be used with care to avoid undesired overlaps.
+</P>
+<P><B>Value: </B>
+one or two whole numbers, in the range from
+negative the height of the page and the height of a page, in stepsizes.
+If there are two numbers, they are separated by a comma, and the second
+must be greater than or equal to the first.
+</P>
+<P><B>Default value: </B>
+2,2
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+scorepad = 5
+<BR>
+scorepad = -1
+<BR>
+scorepad = 3,10
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#scoresep">scoresep,</A>
+<A HREF="param.html#staffpad">staffpad,</A>
+<A HREF="param.html#staffsep">staffsep</A>
+</P>
+<HR>
+<H2>
+<A NAME="scoresep">scoresep</A>
+</H2><P>
+sets how much space to leave between scores;
+i.e., between the bottom line of the
+bottom staff of one score and the top line of the top staff of the
+following score. Either a single number, giving a minimum
+amount, or two numbers, giving a minimum and maximum,
+can be specified. They are specified in stepsizes.
+If only the minimum is specified, and it is larger than the default
+maximum of 20, the maximum will be adjusted to equal the minimum.
+Depending on the setting of the
+<A HREF="param.html#scorepad">scorepad parameter,</A>
+the maximum may be exceeded.
+The parameters interact as follows in determining the layout of a page:
+As many scores are allocated to the page as will fit (or until
+<A HREF="newscore.html">a "newpage" command</A>
+is encountered).  Initially, they are packed together
+as tightly as they can be without violating
+the minimum values of scorepad and scoresep between any neighboring scores.
+Next, if there is extra space available at the bottom of the page,
+the scores are spread out, increasing the white space between them, but
+not increasing any beyond the maximum scorepad value.
+(Some may however already be beyond the maximum scorepad value, because
+the minimum scoresep value required it.)
+This spreading is done without regard for the maximum scoresep value.
+If any of the inter-score gaps start narrower than others
+(because of the minimum scoresep), they are increased first, in an
+attempt to even out the differences.
+If the maximum scorepad value is reached or exceeded between all the scores,
+and there is still extra space available at the bottom of the page,
+then the scores are spread out some more, increasing the white space between
+them, this time ignoring the scorepad values, but not increasing any
+beyond the maximum scoresep value.
+(Some may however already be beyond the maximum scoresep value, because
+of the previous steps.)
+If still not all the space is used up, it remains as extra space at the
+bottom of the page.
+</P>
+<P><B>Value: </B>
+one or two whole numbers, in the range from 6
+to the height of the page in stepsizes.
+If there are two numbers, they are separated by a comma, and the second
+must be greater than or equal to the first.
+</P>
+<P><B>Default value: </B>
+12,20 
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Examples:</B><BR>
+scoresep = 25
+<BR>
+scoresep = 9,15
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#scorepad">scorepad,</A>
+<A HREF="param.html#staffpad">staffpad,</A>
+<A HREF="param.html#staffsep">staffsep</A>
+</P>
+<HR>
+<H2>
+<A NAME="size">size</A>
+</H2><P>
+specifies what point size to use for text in
+<A HREF="prnttext.html">print, title, left, right, and center statements,</A>
+and
+<A HREF="chrdattr.html#withlist">"with" lists (i.e., strings that are associated with a particular chord).</A>
+</P>
+<P><B>Value: </B>
+a number from 1 to 100 inclusive
+</P>
+<P><B>Default value: </B>
+12
+</P>
+<P><B>Context: </B>
+score, staff, header, footer, header2, footer2, top, bottom, top2, bottom2, block
+</P>
+<P><B>Example:</B><BR>
+size = 9
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#font">font,</A>
+<A HREF="param.html#fontfam">fontfamily,</A>
+<A HREF="param.html#lyrsize">lyricssize</A>
+</P>
+<HR>
+<H2>
+<A NAME="stlines">stafflines</A>
+</H2><P>
+specifies how many lines to draw for the staff. Normally, there are 5 lines
+per staff, but a single line staff is sometimes used for percussion,
+and tablature staffs for various instruments
+may have different numbers of lines.
+Setting this parameter to 1 will produce a single line staff.
+The number of lines can be followed by &quot;n&quot; to indicate that
+<A HREF="param.html#clef">clef</A>
+and
+<A HREF="param.html#key">key signature</A>
+are not to be printed. The &quot;n&quot; also implies that accidentals are to
+be ignored and that notes are never to be transposed.
+If the number of lines is 1, the clef and
+key signature are never printed,
+regardless of whether or not you add the &quot;n,&quot; so the &quot;n&quot; is really only
+meaningful when used with 5. When stafflines=1, you can only have one note
+per chord, and the pitch of that note is irrelevant, except for
+<A HREF="midi.html">MIDI output.</A>
+Alternately, rather than specifying &quot;n&quot; you can specify &quot;drum&quot; which
+means to use the drum clef (also sometimes called the &quot;neutral&quot; clef).
+With the drum clef, no key signature is printed, accidentals are
+ignored, and notes are never transposed. The value used for the
+<A HREF="param.html#clef">clef parameter</A>
+is used to determine the pitch for placement of notes in this case,
+but the drum clef of two vertical lines is printed.
+For a tablature staff, rather than specifying a number of staff lines as the
+value, the keyword &quot;tab&quot; is used, optionally followed by a list of strings
+in parentheses. The strings are listed in order from the top line of the
+tablature staff to the bottom.
+Each item in the list has at least a string pitch, which is
+a letter from a to g, optionally followed by # or &amp;. If there is more than
+one string having the same letter/accidental, they are distinguished by
+adding one or more single quote marks (&quot;ticks&quot;). An octave number can also
+be specified.
+If the list of strings is omitted, standard guitar strings are used,
+which is tab( e5 b4 g4 d4 a3 e'3 ).
+Tablature can only be specified in staff context, not score or voice, and
+when a tablature staff is specified, the staff above it becomes a &quot;tabnote&quot;
+staff which is a normal 5-line staff containing music derived from the
+tablature staff.
+</P>
+<P><B>Value: </B>
+1 or 5, optionally followed by &quot;n&quot; or &quot;drum&quot;;
+or for tablature staff, the keyword &quot;tab&quot; optionally followed by a
+list of strings, in parentheses.
+Setting the stafflines parameter will also reinitialize other parameters:
+<A HREF="param.html#key">key,</A>
+<A HREF="param.html#xpose">transpose,</A>
+<A HREF="param.html#addxpose">addtranspose,</A>
+<A HREF="param.html#clef">clef,</A>
+<A HREF="param.html#beamstyl">beamstyle,</A>
+and
+<A HREF="param.html#defoct">defoct.</A>
+</P>
+<P><B>Default value: </B>
+5
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Examples:</B><BR>
+stafflines=1
+<BR>
+stafflines=5n
+<BR>
+stafflines = tab       // standard guitar tablature staff
+<BR>
+stafflines = tab ( g3 d3 a2 e2 )  // standard bass guitar
+<BR>
+stafflines = tab (d# g b3 g'3)
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#clef">clef,</A>
+<A HREF="param.html#key">key,</A>
+<A HREF="param.html#xpose">transpose,</A>
+<A HREF="param.html#addxpose">addtranspose</A>
+</P>
+<HR>
+<H2>
+<A NAME="staffpad">staffpad</A>
+</H2><P>
+sets the minimum amount of space to leave between staffs,
+accounting for all the things that protrude from both staffs.
+If a negative value is specified, some overlap may occur, although
+it will still be limited by the value of the
+<A HREF="param.html#staffsep">staffsep parameter.</A>
+Specifying a negative value may be particularly useful when things
+protrude downward from the top staff and upward from the bottom staff,
+but at different places horizontally, such that it is actually safe
+to put the staffs closer together without collision, even though Mup
+can't tell that it is safe.
+Note, however, that this overrides Mup's protection against real
+collisions, so this must be used with care to avoid undesired overlaps.
+</P>
+<P><B>Value: </B>
+a whole number between negative the height of the page
+and the height of a page, in stepsizes.
+</P>
+<P><B>Default value: </B>
+0
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+staffpad = -2
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#scorepad">scorepad,</A>
+<A HREF="param.html#scoresep">scoresep,</A>
+<A HREF="param.html#staffsep">staffsep</A>
+</P>
+<HR>
+<H2>
+<A NAME="staffs">staffs</A>
+</H2><P>
+specifies the number of staffs. It is possible that not all of these staffs
+will be printed (see
+<A HREF="param.html#visible">the "visible" parameter</A>
+below and
+<A HREF="cmdargs.html#soption">the -s command line argument).</A>
+Changing the number
+of staffs causes all parameters that had been
+set in staff and voice context to be set back to their default values.
+It is usually preferable to only set the staff parameter once at the beginning
+of a song, and use
+<A HREF="param.html#visible">the "visible" parameter</A>
+when you want to change which staffs are actually printed,
+rather than changing the number of staffs.
+</P>
+<P><B>Value: </B>
+a number between 1 and 40 inclusive.
+</P>
+<P><B>Default value: </B>
+1
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+staffs = 12
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#visible">visible</A>
+</P>
+<HR>
+<H2>
+<A NAME="stscale">staffscale</A>
+</H2><P>
+Specifies how to scale the size of a staff relative to the size of other
+staffs. A value of 1.0 yields the normal size, whereas 0.5 yields a staff
+that is half as high, and 2.0 one that is twice as high as normal,
+and so forth. This might be used, for example, for a piece written for
+two instruments, say piano and violin, where you want the piano part to
+be written in normal size, but want to show the violin part in smaller
+size, such that while the pianist will have the violin part available
+for reference, it won't take up a lot of space.
+Another possible use is to set staffscale in score context, to make
+all staff-related things a different size, but leave other things, like
+<A HREF="headfoot.html">headers and footers,</A>
+unaffected.
+</P>
+<P><B>Value: </B>
+0.1 to 10.0
+</P>
+<P><B>Default value: </B>
+1.0
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+staffscale=0.75
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#scale">scale</A>
+</P>
+<HR>
+<H2>
+<A NAME="staffsep">staffsep</A>
+</H2><P>
+specifies the minimum amount of space to leave between
+any two adjacent staffs within the same score. It is specified in stepsizes,
+and is measured from the bottom line of the staff above to the top line
+of the staff below. Staffs will be spread
+wider than this minimum if necessary to prevent things from colliding.
+</P>
+<P><B>Value: </B>
+a number from 6 to the height of the page in stepsizes
+</P>
+<P><B>Default value: </B>
+10
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+staffsep = 14
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#scorepad">scorepad,</A>
+<A HREF="param.html#scoresep">scoresep,</A>
+<A HREF="param.html#staffpad">staffpad</A>
+</P>
+<HR>
+<H2>
+<A NAME="stemlen">stemlen</A>
+</H2><P>
+Specifies how long stems should be, in stepsizes.
+This is for normal-sized chords; grace or cue size chords
+will gets stems that are 5/7 of this length.
+This length can be overridden on specific chords using
+<A HREF="chrdattr.html#stemlen">the len attribute in backets before the chord.</A>
+</P>
+<P><B>Value: </B>
+0.0 to 100.0
+</P>
+<P><B>Default value: </B>
+7.0
+</P>
+<P><B>Context: </B>
+score, staff, voice
+</P>
+<P><B>Example:</B><BR>
+stemlen = 0    // to make all notes stemless
+</P>
+<HR>
+<H2>
+<A NAME="sshorten">stemshorten</A>
+</H2><P>
+On beamed chords, Mup will sometimes shorten stems slightly.
+This parameter lets you control the maximum amount of shortening that
+will ever be done. It is specified in stepsizes.
+</P>
+<P><B>Value: </B>
+0.0 to 2.0
+</P>
+<P><B>Default value: </B>
+1.0
+</P>
+<P><B>Context: </B>
+score, staff, voice
+</P>
+<P><B>Example:</B><BR>
+stemshorten = 0             // never shorten any stems
+</P>
+<HR>
+<H2>
+<A NAME="swing">swingunit</A>
+</H2><P>
+This parameter only affects
+<A HREF="midi.html">MIDI output.</A>
+Some styles of music are often
+written in &quot;swing time,&quot; meaning the
+players are expected to play pairs of notes with the first twice
+as long as the second, even though they are written as if they were the
+same duration, or as if the first was three times as long as the second.
+The most common example would be where the written notation shows
+two eighth notes like 8;; or a dotted rhythm like 8.;16;
+but the musician &quot;knows&quot; that the composer really intended it
+to be played as if it were a triplet {4;8;}3;
+This parameter adjusts the Mup MIDI output
+to follow this performance convention.
+If this parameter is set,
+each measure is divided into segments of durations of &quot;swingunit,&quot; starting
+at the beginning. (Usually the
+<A HREF="param.html#time">time signature</A>
+divided by swingunit
+will be an integer, but if not, the last piece will be shorter.)
+Then within each segment, the time where one group ends
+and the next group starts will be
+altered in either of these two circumstances:
+(1) The current boundary time is halfway into a swingunit, and
+each group is at least half a swingunit long, or
+(2) The current boundary time is 3/4 of the way into a swingunit,
+and the first group is at least 3/4 of a swingunit long, and
+the second group is at least 1/4 of a swingunit long.   
+In both of these cases, the durations are altered so that the  
+meeting point is 2/3 of the way into the swingunit.
+</P>
+<P><B>Value: </B>
+A time value, like 2, 4, or 8, or not set to anything.
+It can be a dotted value like 2. or 16.. although dotted values
+are rarely likely to be useful.
+It can even be a time expression like 2.-32 although that is even
+less likely to be useful.
+</P>
+<P><B>Default value: </B>
+not set
+</P>
+<P><B>Context: </B>
+score, staff, voice
+</P>
+<P><B>Example:</B><BR>
+swingunit = 4
+<BR>
+swingunit =     // turn off swing
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#timeunit">timeunit</A>
+</P>
+<HR>
+<H2>
+<A NAME="sylpos">sylposition</A>
+</H2><P>
+A | can be used in lyrics at the beginning of a syllable (after
+anything in angle brackets) to indicate syllable alignment.
+This will override the
+<A HREF="param.html#lyralign">lyricsalign parameter,</A>
+and may be useful for aligning verse numbers or to make syllables at
+the beginning of poetic lines line up.
+If the | is not preceded by a number, the sylposition parameter specifies the
+default alignment value to use. It is the number of points (1 point
+is 1/72 of an inch) from the horizontal &quot;middle&quot; of the chord to place the
+left edge of the syllable. Negative values are to the left of the middle,
+positive to the right, so this value is usually negative.
+</P>
+<P><B>Value: </B>
+-100 to 100
+</P>
+<P><B>Default value: </B>
+-5
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+sylposition = -4
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#lyralign">lyricsalign</A>
+</P>
+<HR>
+<H2>
+<A NAME="tabwhite">tabwhitebox</A>
+</H2><P>
+says whether or not to put a small white box behind each fret number on
+<A HREF="tabstaff.html">tablature staffs.</A>
+This may make the music a little easier to read, since the staff lines
+won't be going through the middle of the fret numbers.
+</P>
+<P><B>Value: </B>
+<B>y</B> or <B>n</B>
+</P>
+<P><B>Default value: </B>
+n
+</P>
+<P><B>Context: </B>
+score, staff, voice
+</P>
+<P><B>Examples:</B><BR>
+tabwhitebox = y
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#stlines">stafflines</A>
+</P>
+<HR>
+<H2>
+<A NAME="time">time</A>
+</H2><P>
+sets the time signature. Music data for each measure is checked to ensure
+that the total time in the measure for each voice and verse
+adds up to exactly the time signature. Setting the time parameter will
+also reinitialize
+<A HREF="param.html#timeunit">the timeunit parameter</A>
+and
+<A HREF="param.html#beamstyl">the beamstyle parameter</A>
+to their most recent values for the same time signature
+(which would be their default values if they had never been explicitly
+set for this time signature).
+</P>
+<P><B>Value: </B>
+either a ratio of the form <I>N/D</I> or the word &quot;cut&quot; or &quot;common.&quot; If the ratio
+form is used, <I>N</I> must be between 1 and 99 inclusive,
+and <I>D</I> must be 1, 2, 4, 8, 16, 32, or 64.
+The numerator of the time signature can be the sum of several numbers,
+as in 3+4/4 or 2+3+2/2. You can also have several fractions added
+together, as in 3/4 + 4/4. It is also possible to provide &quot;alternating&quot;
+time signatures, where you list two (or more, although two is typical)
+time signatures separated by white space. Each measure then uses
+the next time signature in the list. For example, for
+3/4 4/4, the first measure would be in 3/4 time, the second measure in 4/4,
+the third back in 3/4, the fourth in 4/4, and so forth.
+It is possible to combine all the various complexities,
+with things like 3+4/8 + 2+3/4 4+3/4 although that would be very uncommon.
+The time signature can optionally be followed by the
+letter n to specify that the time signature is not to be printed.
+Or it can be followed by the letter y, which causes
+alternating time signatures to be treated differently.
+By default, the alternating signature are printed just once, as a list,
+and the performer has to remember
+that each subsequent measure has a different time signature.
+Using y forces Mup to print the appropriate time signature on each measure.
+</P>
+<P><B>Default value: </B>
+4/4
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Examples:</B><BR>
+time = 6/8
+<BR>
+time = cut
+<BR>
+time = 13/16n
+<BR>
+time = 2+3+4 / 8    // additive numerator
+<BR>
+time = 3/4 + 4/4    // fractions added together
+<BR>
+time = 4/4 3/4      // alternating 
+<BR>
+time = 3/4 6/8 y    // alternating, printing time sig on every measure
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#timeunit">timeunit</A>
+</P>
+<HR>
+<H2>
+<A NAME="timeunit">timeunit</A>
+</H2><P>
+sets the default time unit. If the first note of a measure has no time
+value specified, the value of the timeunit parameter will be used.
+If the
+<A HREF="param.html#time">time signature</A>
+is changed, the timeunit parameter reverts back
+to its previous value for that time signature, which defaults to the
+value of the denominator (bottom number) of the new time signature.
+</P>
+<P><B>Value: </B>
+1/4, 1/2, 1, 2, 4, 8, 16, 32, 64, 128, or 256
+representing quadruple whole, double whole, whole, half,
+quarter, eighth, sixteenth, thirty-second,
+sixty-fourth, 128th, or 256th,
+followed by zero or more dots. Each dot adds 50% of the previous note or dot
+to the time.
+It can also be a time expression, like 2+8 or 1-4+16.
+The time value must be less than or equal to
+the time signature.
+The timeunit value can be reinitialized indirectly by setting
+<A HREF="param.html#time">the time parameter.</A>
+Setting the time parameter will set the timeunit to the value
+used most recently for that time signature.
+</P>
+<P><B>Default value: </B>
+The denominator (bottom number) of the time signature
+</P>
+<P><B>Context: </B>
+score, staff, voice
+</P>
+<P><B>Examples:</B><BR>
+timeunit = 2
+<BR>
+timeunit = 4.
+<BR>
+timeunit = 2 + 8
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#swing">swingunit,</A>
+<A HREF="param.html#time">time</A>
+</P>
+<HR>
+<H2>
+<A NAME="topmar">topmargin</A>
+</H2><P>
+sets the amount of white space margin to put at the top of each page.
+It is specified in inches if the
+<A HREF="param.html#units">units parameter</A>
+is set to inches, or in centimeters if the units parameter is set to cm.
+This parameter can only be specified before any music or block input.
+Margins are unaffected by
+<A HREF="param.html#scale">the "scale" parameter.</A>
+</P>
+<P><B>Value: </B>
+0.0 to pageheight minus 0.5 inches
+</P>
+<P><B>Default value: </B>
+0.5 inches
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+topmargin = 0.8
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#botmar">bottommargin,</A>
+<A HREF="param.html#leftmar">leftmargin,</A>
+<A HREF="param.html#rightmar">rightmargin,</A>
+<A HREF="param.html#pgheight">pageheight,</A>
+<A HREF="param.html#units">units</A>
+</P>
+<HR>
+<H2>
+<A NAME="xpose">transpose</A>
+</H2><P>
+specify by what interval to transpose the music data.  The interval can be
+larger than an octave, but must be a valid interval (e.g., there is no
+such thing as a perfect 6th). It is an error to specify a transposition value
+which would result in a key signature with more than 7 flats or sharps.
+It is also an error if transposition would result in a note requiring a
+triple sharp or triple flat.
+</P>
+<P><B>Value: </B>
+the word &quot;up&quot; or &quot;down,&quot; followed by an interval and a whole number greater than 0.
+The interval is one of major, minor, augmented, diminished, or perfect.
+The intervals can be abbreviated to their first 3 letters (maj,
+min, aug, dim, or per).
+The
+<A HREF="trnspose.html">section on transposition</A>
+lists transposition intervals and gives further details.
+Depending on which key signature you are
+transposing from, some transposition intervals may not work because they
+result in more than 7 flats or sharps.
+There is also another parameter called
+<A HREF="param.html#addxpose">addtranspose.</A>
+Typically you would use the transpose parameter to change the key of
+individual staffs (for transposing instruments), and then use the
+addtranspose parameter if you want to change the key of the entire score.
+But either of these parameters can be used either way.
+In any case, for each staff, and for the score, the values of
+transpose and addtranspose are &quot;added&quot; to find the transposition
+for that staff or score.
+</P>
+<P><B>Default value: </B>
+up perfect 1 (i.e., no transposition)
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Examples:</B><BR>
+transpose = up minor 3
+<BR>
+transpose = down perfect 4
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#addxpose">addtranspose,</A>
+<A HREF="param.html#key">key</A>
+</P>
+<HR>
+<H2>
+<A NAME="units">units</A>
+</H2><P>
+Specifies whether margin and page size parameters are specified
+in inches or in centimeters.
+</P>
+<P><B>Value: </B>
+inches or cm
+</P>
+<P><B>Default value: </B>
+inches
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+units = cm
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#topmar">topmargin,</A>
+<A HREF="param.html#botmar">bottommargin</A>
+<A HREF="param.html#leftmar">leftmargin,</A>
+<A HREF="param.html#rightmar">rightmargin,</A>
+<A HREF="param.html#pgheight">pageheight,</A>
+<A HREF="param.html#pgwidth">pagewidth</A>
+</P>
+<HR>
+<H2>
+<A NAME="vcombine">vcombine</A>
+</H2><P>
+This parameter tells Mup to combine the specified
+voices onto a single stem whenever possible.
+One common use would be if you want multiple voices for
+<A HREF="midi.html">MIDI</A>
+purposes, but want them printed on the same stems.
+Another typical use would be to obtain a printing style common for hymns
+and certain other styles of music, where the two voices on each staff are
+printed on one common stem whenever possible, but when a note
+is shared between two voices, two opposing stems are used to make it clear the
+note is indeed shared.
+The value of this parameter is a list of voices plus an optional qualifier.
+The list format is like elsewhere for voices; common examples would be
+<TT>1,2</TT> or <TT>1-3</TT> or <TT>2-3</TT>.
+Order of voices is significant: sometimes Mup may have to choose between
+two possible combinations, so voices listed first get priority.
+The list of voices can be followed by a qualifier to specify what
+happens when voices overlap. If the qualifier is &quot;nooverlap,&quot;
+voices will only be combined if the bottom note of the higher voice
+is higher than the top note of the lower voice.
+(That is the typical value for getting the hymn style described above.)
+If the qualifier is &quot;shareone&quot; the bottom note of the top voice must be
+no lower than than top note of the lower voice for combining to occur.
+If the qualifier is &quot;overlap,&quot; combining will occur without regard for
+how the voices overlap. For the purpose of the qualifier, voice 1 is assumed
+to be the highest voice, voice 3 the middle voice, and voice 2 the lowest.
+If no qualifier is specified, the default is nooverlap. While the vcombine
+parameter is allowed to be used with any
+<A HREF="param.html#vscheme">vscheme parameter</A>
+value, using it with vscheme=1 is pointless, and only
+vscheme values of 2f and 3f are really appropriate.
+This parameters can be used with both voice-at-a-time and chord-at-a-time
+input styles. It has no effect on tablature or 1-line staffs.
+Note that there are various cases where combining will not be done, such
+as when time values or beamings are different in different voices, and cases
+where combining would cause information loss, such as when a shared note is
+tied in one voice but not another. In such cases,
+the usual non-combined format will be used.
+</P>
+<P><B>Value: </B>
+comma-separated list of voices or voice ranges, or nothing,
+optionally followed by nooverlap, shareone, or overlap.
+</P>
+<P><B>Default value: </B>
+not set
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+vcombine=3,1-2 shareone
+<BR>
+vcombine=   // turn off combining
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#vscheme">vscheme</A>
+</P>
+<HR>
+<H2>
+<A NAME="visible">visible</A>
+</H2><P>
+specifies whether a staff or voice is actually to be printed.
+This can be useful for
+printing a subset of a full score. The value is either y or n, for yes or no,
+or whereused. When whereused is specified,
+if a staff has no notes or lyrics or other associated things on an entire score,
+that staff is not printed. This might be used, for example,
+to save paper on an orchestral score by only printing staffs for
+instruments when they are actually playing.
+At least one staff must be visible at all times.
+When an individual voice is made invisible, but the other voice(s) on that staff
+remain visible, all the 
+<A HREF="stuff.html">tempo, dynamics, and similar marks</A>
+associated with the staff will still be printed, since Mup cannot know for sure
+whether you meant them to be associated with
+a particular voice or with the staff as a whole.
+When
+<A HREF="midi.html">MIDI output</A>
+is generated, this parameter controls whether the staff or voice
+is audible, so you can control which voices are played.
+<A HREF="cmdargs.html#soption">The -s command line argument can also be used</A>
+to control which staffs are printed or played.
+</P>
+<P><B>Value: </B>
+y, n, or whereused
+</P>
+<P><B>Default value: </B>
+y
+</P>
+<P><B>Context: </B>
+score, staff, voice
+</P>
+<P><B>Example:</B><BR>
+visible = n
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#brace">brace,</A>
+<A HREF="param.html#bracket">bracket,</A>
+<A HREF="param.html#endingst">endingstyle,</A>
+<A HREF="param.html#staffs">staffs</A>
+</P>
+<HR>
+<H2>
+<A NAME="vscheme">vscheme</A>
+</H2><P>
+sets voice scheme. A value of 1 means there is only a single voice on a
+staff. The direction of note stems will be determined based on how high
+or low the notes are on the staff. A value of 2o means there are two voices
+with &quot;opposing&quot; stems. In other words, the stems of voice 1 will always
+point upward, and the stems of voice 2 will always point downward,
+unless they are
+<A HREF="chrdattr.html#stemdir">explicitly forced</A>
+the other way. A
+value of 2f means there are two voices with &quot;free&quot; or &quot;floating&quot; stems.
+That means in places where there are notes or rests in both
+voices, stem directions will be as if 2o were set. However, if one of the
+voices has &quot;space&quot; where there are no notes or rests, the stem directions of the
+other voice will be determined as if there were only a single voice.
+2o is useful if you want to force stem directions a certain way. 2f is
+generally preferable when there are two voices only part of the time.
+The values 3o and 3f are like 2o and 2f except that a third voice is
+allowed. The third voice's stem defaults to up,
+but the direction can be changed at any chord. The
+<A HREF="chrdattr.html#stemdir">stem direction</A>
+remains in effect on subsequent chords of voice 3 until explicitly changed.
+While there can be voice crossings, in general voice 1 should be the &quot;top&quot;
+voice, voice 2 the &quot;bottom&quot; voice, and voice 3 the &quot;middle&quot; or &quot;extra&quot; voice.
+Mup does not use voice 3 when associating things like phrase marks and
+lyrics with chords.
+Setting vscheme to a different number of voices
+will reinitialize all voice level parameters for the
+affected staffs.
+</P>
+<P><B>Value: </B>
+1, 2o, 2f, 3o, or 3f
+</P>
+<P><B>Default value: </B>
+1
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+vscheme = 2f
+</P>
+<P><B>Related parameters: </B>
+<A HREF="param.html#vcombine">vcombine</A>
+</P>
+<HR>
+<H2>
+<A NAME="warn">warn</A>
+</H2><P>
+specifies whether to print warning messages or not.
+Normally, Mup will print warnings when it encounters input that
+it considers somewhat dubious. Sometimes, however, that input will really
+be what you want, so this parameter allows you to turn off warning messages.
+</P>
+<P><B>Value: </B>
+y or n
+</P>
+<P><B>Default value: </B>
+y
+</P>
+<P><B>Context: </B>
+score
+</P>
+<P><B>Example:</B><BR>
+warn = n
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="fontfile.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="debug.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/pedal.html b/mup/docs/uguide/pedal.html
new file mode 100644 (file)
index 0000000..44824c1
--- /dev/null
@@ -0,0 +1,50 @@
+<HTML>
+<HEAD><TITLE>
+Piano pedal marks
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="octave.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="roll.html">next page --&gt;</A>
+</P>
+             
+<H2>
+Piano pedal marks
+</H2>
+<P>
+Piano pedal marks are somewhat different than
+<A HREF="textmark.html">other similar Mup statements.</A>
+Rather than having begintime, text, and duration, each
+item is just a time offset value, plus an optional &quot;*&quot;. If no pedal mark
+is currently in progress, the first time offset value indicates where the
+pedal is depressed. Any subsequent pedal items on that staff will then
+indicate a &quot;blip&quot;--lifting and then immediately depressing the pedal
+(which is indicated on the printed music by a &quot;^&quot;), unless there is a &quot;*&quot;,
+in which case it means to lift the pedal and leave it up.
+</P>
+<P>
+Some examples may help:
+<BR><PRE>
+1: c;d;e;2.g;
+2: 1.ceg;
+// depress pedal on beat 1, release on 3
+pedal 2: 1; 3*;
+bar
+
+1: g;d;e;f;g;;
+2: 1.gdb-;
+// depress pedal on 2, release and depress
+// on 4, release on 6
+pedal below 2: 2; 4; 6*;
+bar
+</PRE><BR>
+<IMG SRC="mugex77.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+<A HREF="param.html#pedstyle">See also the "pedstyle" parameter.</A>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="octave.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="roll.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/phrase.html b/mup/docs/uguide/phrase.html
new file mode 100644 (file)
index 0000000..2c20466
--- /dev/null
@@ -0,0 +1,89 @@
+<HTML>
+<HEAD><TITLE>
+Phrase marks
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="mussym.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="cres.html">next page --&gt;</A>
+</P>
+             
+<H2>
+Phrase marks
+</H2>
+<P>
+If there is only one voice, specifying <I>place</I> for a phrase just tells
+Mup where to draw the phrase mark. If there are
+<A HREF="param.html#vscheme">two or more voices,</A>
+and a <I>place</I> is specified, &quot;above&quot;
+indicates to Mup that the phrase is associated with voice 1,
+and &quot;below&quot; indicates to Mup that the phrase is associated with voice 2.
+</P>
+<P>
+If no <I>place</I> is specified and there is only one voice with notes,
+Mup will decide which side would be better based on the musical data.
+This means the phrase mark may come out above or below.
+In the case where there are two voices and
+there are notes present in both voices, phrase marks will be drawn both
+above and below.
+</P>
+<P>
+Each phrase statement item must include a begintime and duration.
+A phrase mark must begin and end on a chord, so Mup first takes the begintime
+and duration and finds the chords nearest to each of them. It then draws a
+phrase mark between them, shaping it to be out of the way of other things as
+much as possible.
+It is possible to specify a &quot;grace back up&quot; on the begintime
+(a negative number in parentheses,
+specifying how many grace notes to back up),
+to make the phrase include leading grace notes.
+It is possible to &quot;nest&quot; phrase marks (i.e., have one phrase on a subset of
+the chords of another phrase).
+</P>
+<P>
+Some examples:
+<BR><PRE>
+staff 2
+  vscheme=2o
+
+music
+
+1: d;f;a;b;
+2,3 1: a;f;d;g;
+2 2: 4.c;8b-;4d;g; 
+phrase 1: 1 til 4;
+phrase above 2,3: 1 til 2; 3 til 4;
+phrase below 2: 2.5 til 1m + 1.5;
+bar
+1: b;c+;d+;e+;
+2,3 1: g;a;f;c;
+2 2: 4.e;8f;4b-;g;
+bar
+</PRE><BR>
+<IMG SRC="mugex73.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+Phrase marks are sometimes used on
+tablature staffs in conjunction with slides.
+<BR><PRE>
+score staffs=2
+staff 2 stafflines=tab
+music
+
+2: a3&lt;&gt;;a4;e4&lt;&gt;;e2;
+phrase above 2: 1 til 2; 3 til 4;
+bar
+</PRE><BR>
+<IMG SRC="mugex74.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+The word &quot;phrase&quot; can be preceded by a line type modifier: dotted or dashed.
+The dotted or dashed styles might be used for phrase marks
+that were added by an editor rather than the composer, or to show a phrase
+that doesn't apply to all verses.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="mussym.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="cres.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/pianored.html b/mup/docs/uguide/pianored.html
new file mode 100644 (file)
index 0000000..ce385e1
--- /dev/null
@@ -0,0 +1,73 @@
+<HTML>
+<HEAD><TITLE>
+Automatic piano reduction
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="verses.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="slashmrk.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Automatic piano reduction
+</H2>
+<P>
+Perhaps you'd like a 4-part vocal piece written on 4 separate staffs,
+as well as a piano reduction on two staffs with 2 voices.
+This could be done using:
+<BR><PRE>
+score
+   staffs=6
+   bracket=1-4
+   brace=5-6
+staff 3
+   clef=treble8
+staff 4
+   clef=bass
+staff 5
+   vscheme=2o
+   staffscale=0.75   // make piano staffs a little smaller
+staff 6
+   clef=bass
+   vscheme=2o
+   staffscale=0.75
+
+// Define macros to put each voice on its own staff
+// plus the appropriate staff/voice of the piano staffs.
+define S 1 1 &amp; 5 1: @  // soprano
+define A 2 1 &amp; 5 2: @  // alto
+define T 3 1 &amp; 6 1: @  // tenor
+define B 4 1 &amp; 6 2: @   // bass
+
+music
+S 2c+;;
+A 2f;e;
+T 2a;g;
+B 2c;;
+bar
+</PRE><BR>
+<IMG SRC="mugex98.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+This can also be done using
+<A HREF="altinp.html">chord-at-a-time input style:</A>
+<BR><PRE>
+// Define a macro to put each voice on its own staff
+// plus the appropriate staff/voice of the piano staffs.
+// This example assumes inputting notes from bottom to top.
+define M [ 4 1 &amp; 6 2; \
+           3 1 &amp; 6 1; \
+           2 1 &amp; 5 2; \
+           1 1 &amp; 5 1 ] :   @
+
+music
+
+M 2cafc+;cgec+;
+bar
+</PRE><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="verses.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="slashmrk.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/prnttext.html b/mup/docs/uguide/prnttext.html
new file mode 100644 (file)
index 0000000..2d0d3d9
--- /dev/null
@@ -0,0 +1,277 @@
+<HTML>
+<HEAD><TITLE>
+"Mup commands for printing text
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="tags.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="linecurv.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Printing commands
+</H2>
+<P>
+There are several commands for printing text.
+There are four commands that have similar formats,
+differing only in how they justify text.
+<BR><PRE>
+<B>print</B> <I>location</I> &quot;<I>text</I>&quot;
+<B>left</B> <I>location</I> &quot;<I>text</I>&quot;
+<B>right</B> <I>location</I> &quot;<I>text</I>&quot;
+<B>center</B> <I>location</I> &quot;<I>text</I>&quot;
+</PRE><BR>
+</P>
+<P>
+The <I>location</I> is optional. If the <I>location</I> is omitted, the &quot;print&quot;
+command will cause the <I>text</I> to be printed beginning at the current
+horizontal and vertical location. The other commands will cause the text to
+be placed vertically at the current vertical position, but left justified,
+right justified, or centered within the current margins of the page.
+</P>
+<P>
+The <I>location</I> can be specified using the special keyword of &quot;nl&quot;
+which means &quot;next line.&quot; This moves the current location to the beginning
+of the following line before placing the text. In other words, the current
+vertical position is moved downward by the height of the current text
+point size (or by as much as necessary
+if the string is taller than that). Then
+the <I>text</I> is printed on that line with the given justification style.
+</P>
+<P>
+The other way to specify a <I>location</I> is by using coordinates.
+The justification then takes place relative to the referenced location.
+For example, consider the following &quot;right&quot; command containing a reference
+to an absolute location:
+<BR><PRE>
+right (25, 4) &quot;something&quot;
+</PRE><BR>
+The y location given is 4. Since this is an absolute location with no location
+tags being referenced, this means the vertical position will be 4 stepsizes from
+the bottom of the page. The x location given is 25. Again, this is an
+absolute location, so the current horizontal position will be 25 stepsizes from
+the left edge of the page. Since right justification is indicated,
+the word &quot;something&quot; will be placed such that the right edge of the final &quot;g&quot;
+will be 25 stepsizes from the left edge of the page. If &quot;center&quot; had been
+specified, the middle of the word &quot;something&quot; would be at the 25 stepsize point.
+</P>
+<P>
+Here are some other examples:
+<BR><PRE>
+print &quot;Author unknown&quot;
+center nl &quot;subtitle&quot;
+left (h.x - 1.5, h.n + 2.3) &quot;Ad lib&quot;
+right (_fine.e + time 3, _note.n + 5) &quot;Duet&quot;
+</PRE><BR>
+</P>
+<P>
+Another type of print command
+is &quot;title.&quot; The full format of this command is:
+<BR><PRE>
+<B>title</B> <I>fontfamily font size  &quot;text1&quot;  &quot;text2&quot;  &quot;text3&quot;</I>
+</PRE><BR>
+However, only the word &quot;title&quot; and one quoted text string are required.
+The <I>fontfamily</I>, if specified, has one of the values valid for
+<A HREF="param.html#fontfam">the "fontfamily" parameter</A>
+(avantgarde, bookman, courier, helvetica,
+newcentury, palatino, or times). The default is the value of the &quot;fontfamily&quot;
+parameter.
+The <I>font</I>, if specified, has one of the values valid for the &quot;font&quot;
+parameter (rom, bold, ital, or boldital). If no <I>font</I> is specified
+the default is the value of
+<A HREF="param.html#font">the "font" parameter.</A>
+The optional <I>size</I> is a point size within parentheses.
+If not specified, the default is the value of
+<A HREF="param.html#size">the "size" parameter.</A>
+</P>
+<P>
+In all cases, the location will be like that obtained via the &quot;nl&quot;
+location to a print command. In other words, the title text string(s)
+will be printed on the line below the location that was current when the
+title command was encountered. If there is only one string given, it will
+be centered between the margins. If two strings are given, both will be
+printed on the same line, but the first will be left justified and the
+second will be right justified. If three strings are given, they will all
+be printed on the same line, with the first left justified, the second
+centered, and the last right justified.
+</P>
+<P>
+Some samples:
+<BR><PRE>
+title bold (12) &quot;Sonata 12&quot;
+title (18) &quot;Song Without Words&quot;
+title ital (12) &quot;Text: John Doe&quot; &quot;Tune: Jane Doe&quot;
+title &quot;Suite in C&quot; &quot;Trumpet I&quot; &quot;Waltz&quot;
+title    &quot;&quot;    &quot;A. Composer&quot;
+</PRE><BR>
+</P>
+<P>
+<A NAME="paragrph">The final command for printing text is</A>
+the &quot;paragraph&quot; command.
+This is used when you have a long section of text,
+and you would like it to automatically wrap around onto as many
+lines as necessary.
+You can specify whether you want the right margin to be &quot;justified&quot; or &quot;ragged.&quot;
+If you don't specify, the type of the previous paragraph is used.
+The default for the very first paragraph is to be justified.
+By default, the values of the
+<A HREF="param.html#fontfam">fontfamily,</A>
+<A HREF="param.html#font">font,</A>
+and
+<A HREF="param.html#size">size</A>
+parameters are used to determine the text style, but any or all of those
+parameters can be overridden on the paragraph command. The complete syntax is:
+<BR>
+ <I>justify_type</I> <B>paragraph</B> <I>fontfamily font</I> <B>(</B><I>size</I><B>) &quot;</B><I>string</I><B>&quot;</B>
+<BR>
+Only the keyword &quot;paragraph&quot; and the string are required.
+Here are some example paragraphs:
+<BR><PRE>
+paragraph &quot;This is an example of a paragraph. Since no justification
+type was specified, and this is the very first paragraph, the default
+(justified) is used. A paragraph will wrap around
+to as many lines as needed.
+An explicit newline is given at the end of this paragraph,
+to force a blank line between it and the following paragraph.\n&quot;
+
+ragged paragraph avantgarde ital (15) &quot;This paragraph
+is ragged rather than flush right. It is in a different font and size.
+Ragged paragraphs are split onto multiple lines if necessary,
+but they are not spread out to make lines go all the way to
+the right margin.&quot;
+
+justified paragraph (14) &quot;     Here is another paragraph.
+This one is justified.
+Only the size was specified for this paragraph; the font was not,
+so the current default will be used.
+Some spaces are included at the beginning of the paragraph text,
+to create an indented first line for the paragraph.&quot;
+
+paragraph &quot;Here is the final paragraph.
+Since no justification type was given,
+that of the previous paragraph (justified in this case) was used.
+A paragraph may be used for many things,
+such as describing how you want a piece to be performed,
+or a biography of the composer.&quot;
+</PRE><BR>
+<IMG SRC="mugex81.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+<A NAME="block">Sometimes you may want to mix</A>
+blocks of text with music.
+This can be done by specifying a &quot;block&quot; context. The block context
+will typically contain one or more &quot;paragraph&quot; commands, although any
+of the printing commands (paragraph, print, left, center, right, or title)
+can be used. The block can also contain changes in certain parameters, namely
+<A HREF="param.html#font">font,</A>
+<A HREF="param.html#size">size,</A>
+and
+<A HREF="param.html#fontfam">fontfamily,</A>
+which will affect the appearance of
+the following text. A block can also contain
+<A HREF="newscore.html">"newscore" or "newpage" commands.</A>
+Using &quot;newscore&quot; will cause vertical space to be added,
+as would be used to separate scores. The amount of space is affected
+by the
+<A HREF="param.html#scoresep">scoresep</A>
+and
+<A HREF="param.html#scorepad">scorepad</A>
+parameters. Using &quot;newpage&quot; will cause a new page to be started.
+If a newscore or newpage includes a &quot;leftmargin&quot; specification,
+that will alter the left margin on the block text that follows.
+A &quot;rightmargin&quot; specification will alter the right margin
+of the block text that precedes it.
+</P>
+<P>
+Here is an example of a block.
+<BR><PRE>
+block
+title bold &quot;Notation in Simple and Compound Meters&quot;
+title &quot;&quot;
+paragraph &quot;It is common for a person familiar
+with mathematics but not with music to assume
+that 3/4 and 6/8 time are equivalent,
+but that is not the case.
+In 3/4 time (which is known as simple triple meter),
+a measure containing 3 quarter notes
+would be notated like this:&quot;
+score time=3/4
+music
+1: c;;;
+bar
+block
+paragraph &quot;whereas in 6/8 time
+(which is compound duple meter),
+a measure with 3 quarter notes should be notated thus:&quot;
+score time=6/8
+music
+1: 4c;8~;;4;
+bar
+</PRE><BR>
+<IMG SRC="mugex82.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+The printing commands may occur in the
+<A HREF="headfoot.html">header, footer, header2, footer2, top, bottom, top2, bottom2,</A>
+<A HREF="prnttext.html#block">block,</A>
+and
+<A HREF="music.html">music</A>
+contexts.
+After each printing command,
+the current location is set to the right edge of the last character printed
+horizontally and at the baseline of the current line vertically.
+</P>
+<H2>
+Including raw PostScript
+</H2>
+<P>
+<A NAME="postscript">There is another command that looks a lot like the printing commands,</A>
+but gives you a way to insert raw PostScript into the Mup output.
+This might be used, for example,
+to include a picture or logo along with your music.
+The syntax is
+<BR><PRE>
+<B>postscript</B> <I>optional_location</I> <B>&quot;</B><I>raw PostScript</I><B>&quot;</B>
+</PRE><BR>
+As with the other print commands, if the location is omitted,
+the current location is used.
+</P>
+<P>
+The string is copied directly to the Mup output.
+You can use the usual \&quot; to embed a double quote in the string,
+but otherwise the string is copied exactly as it is,
+enclosed inside a PostScript save/restore.
+After the restore, the current location is reset back to where it
+was originally.
+</P>
+<P>
+Since the string is copied without any interpretation,
+Mup does not reserve any space on the page for the PostScript,
+and it is your responsibility to provide valid PostScript.
+The PostScript language is beyond the scope of this User's Guide;
+consult a book on PostScript if you need more information.
+</P>
+<P>
+As a simple example, you might include an Encapsulated PostScript file
+near the lower left corner of the current page using
+<BR><PRE>
+postscript &quot;50 50 translate (file.eps) run&quot;
+</PRE><BR>
+</P>
+<P>
+Or you could print a message in red italics
+near the bottom of the page like this:
+<BR><PRE>
+postscript (70, 20) &quot;
+              1 0 0 setrgbcolor
+              /NewCenturySchlbk-Italic findfont
+              16 scalefont setfont
+              (Photocopying prohibited) show
+              &quot;
+</PRE><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="tags.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="linecurv.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/pstools.html b/mup/docs/uguide/pstools.html
new file mode 100644 (file)
index 0000000..916037e
--- /dev/null
@@ -0,0 +1,40 @@
+<HTML>
+<HEAD><TITLE>
+Converting Mup files to other formats
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="muspaper.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="midi.html">next page --&gt;</A>
+</P>
+             
+<H2>
+Converting Mup files to other formats
+</H2>
+<P>
+Since Mup generates PostScript, almost any PostScript tool can be used
+on its output. In particular, the &quot;ps2pdf&quot; tool that comes with Ghostscript can
+convert Mup output to PDF format, and the &quot;ps2epsi&quot; tool, which also
+comes with Ghostscript, converts a PostScript file to an Encapsulated
+PostScript (EPS) file. Many text processing and graphics programs will
+let you import EPS files, so this can let you insert Mup output into
+some other document.
+</P>
+<P>
+There is a package called &quot;psutils&quot; available on most Linux archives,
+that contains various Postscript tools. These include &quot;psnup&quot; which lets
+you print multiple pages on one sheet of paper with more flexibility
+than Mup's
+<A HREF="param.html#panels">panelsperpage parameter,</A>
+and &quot;psselect&quot; which prints a subset of pages.
+</P>
+<P>
+You can check the
+<A HREF="http://www.arkkra.com/doc/userpgms.html">user donated programs page on Arkkra's web site</A>
+for other programs for processing Mup input or output.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="muspaper.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="midi.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/register.html b/mup/docs/uguide/register.html
new file mode 100644 (file)
index 0000000..dbec127
--- /dev/null
@@ -0,0 +1,39 @@
+<HTML>
+<HEAD>
+<TITLE>
+Mup shareware registration form
+</TITLE>
+</HEAD>
+<BODY>
+<TT><PRE>
+Mup is SHAREWARE.  You can try out a copy for free, but if you decide
+to keep and use it, you must register by filling out the form below
+and sending the form and cash, check, or money order to:
+                Arkkra Enterprises
+                P. O. Box 315
+                Warrenville, IL  60555    USA
+
+Name______________________________________________________________
+
+Address___________________________________________________________
+
+City_____________________________ State/Province__________________
+
+Zip code/Postal code_____________________ Country_________________
+
+Email address (please print clearly)______________________________
+
+How did you find out about Mup?___________________________________
+
+__________________________________________________________________
+
+___Linux  ___ Windows/MS-DOS  ___Mac  ___Other____________________
+
+Would you like to join the Mup users mailing list? ___ Yes  ___ No
+
+___ Mup Version 5.3 Registrations.........................$29 each
+                       (Illinois residents, add $2.18 sales tax)
+(For credit card payment, see http://www.arkkra.com/doc/credtcrd.html)
+</PRE></TT>
+</BODY>
+</HTML>
diff --git a/mup/docs/uguide/roll.html b/mup/docs/uguide/roll.html
new file mode 100644 (file)
index 0000000..11716b3
--- /dev/null
@@ -0,0 +1,81 @@
+<HTML>
+<HEAD><TITLE>
+Rolls
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="pedal.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="tags.html">next page --&gt;</A>
+</P>
+             
+<H2>
+Rolls
+</H2>
+<P>
+Rolls can be specified with the &quot;roll&quot; statement, which has a format:
+<BR><PRE>
+<B>roll</B> <I>staff voice</I> <B>:</B> <I>timeval</I><B>;</B>
+</PRE><BR>
+</P>
+<P>
+A simple example would be:
+<BR><PRE>
+roll 2 1: 3;
+</PRE><BR>
+which indicates that a roll is to be placed on the chord at count 3 of
+staff 2 voice 1.
+As usual, if the <I>voice</I> is omitted, voice 1 is assumed.
+</P>
+<P>
+Multiple rolls in a measure can be listed on a single statement if they are
+associated with the same voice. For example:
+<BR><PRE>
+1: ceg;dfa;egb;fac+;
+// rolls on 3 chords: on the first,
+// second, and third beats of the measure
+roll 1: 1;2;3;
+bar
+</PRE><BR>
+<IMG SRC="mugex78.gif" ALT="Picture of Mup output"><BR>
+would produce rolls on the chords on counts 1, 2, and 3.
+</P>
+<P>
+A roll can extend over several chords on different voices, or even
+different staffs. This is specified
+by giving the top and bottom staffs and voices, with the keyword &quot;to&quot;
+between them. For example:
+<BR><PRE>
+1: 4.r;8g+b+d++ tie;2;
+2-3: 4.ceg;8gbd+ tie;2;
+roll 1 1 to 3 1: 2.5;
+bar
+</PRE><BR>
+<IMG SRC="mugex79.gif" ALT="Picture of Mup output"><BR>
+The roll would extend from voice 1 of staff 1 to voice 1 of staff 3.
+</P>
+<P>
+If you wish the roll to be downward, the keyword &quot;down&quot; can be placed
+after &quot;roll.&quot; This will result in a downward arrow being drawn on the
+bottom end of the roll.
+<BR><PRE>
+score
+  vscheme=2o
+music
+1 1: c+e+g+;;;;
+1 2: ceg;;;;
+// downward roll on staff 1
+// on beats 2 and 4
+roll down 1 1 to 1 2: 2; 4;
+bar
+</PRE><BR>
+<IMG SRC="mugex80.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+You can also explicitly say &quot;up&quot; which will cause an upward arrow to be
+drawn at the top of the roll. If no direction is specified, no arrow is drawn.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="pedal.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="tags.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/running.html b/mup/docs/uguide/running.html
new file mode 100644 (file)
index 0000000..2d415d8
--- /dev/null
@@ -0,0 +1,90 @@
+<HTML>
+<HEAD><TITLE>
+Running Mup
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="basics.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="cmdargs.html">next page --&gt;</A>
+</P>
+          
+<H1>
+RUNNING MUP
+</H1>
+<P>
+There are two basic ways to run Mup: directly from a command line or via
+the Mupmate program. You can use either approach, or switch between them
+as you wish. The Mupmate program just
+provides a more menu-driven environment on top of the Mup program itself.
+</P>
+<P>
+You can create a Mup file using any ordinary text editor,
+and then run the Mup program on the file you created.
+On Windows, Notepad is a typical editor choice, and on Linux, editors like
+vim and emacs are commonly used, but pretty much any text editor (not
+word processor) can be used. Many people, however, prefer to be able to
+edit, display, and play from a single integrated and more graphical
+interface, and for them, a helper program called &quot;Mupmate&quot; is provided.
+The Mupmate program helps lead you through some of the steps,
+and you can easily access this User's Guide from its Help menu.
+</P>
+<H2>
+Mupmate
+</H2>
+<P>
+Mupmate is currently only supported on Windows and Linux.
+However, since the source code is
+available, and it is based on the cross-platform FLTK toolkit, it
+would probably be fairly easy to make it run on any system supported by FLTK.
+</P>
+<P>
+Once you have installed Mup and Mupmate on Windows, double clicking
+a .mup file in Windows explorer will run Mupmate on that file.
+Or, you can run Mupmate by going to the Start menu, and choosing
+Programs, then Arkkra, and then Mupmate.  If you would like an icon
+on the desktop, you can create one by right clicking the Mupmate choice
+in the Arkkra menu, choosing &quot;copy&quot;,
+right clicking somewhere on the desktop, and choosing &quot;paste&quot;.
+</P>
+<P>
+On Linux, you can just type the mupmate command in a terminal window,
+optionally followed by the name of a Mup input file. 
+Or you can add mupmate to your favorite window manager's menus.
+</P>
+<P>
+Mupmate provides five top level menus: File, Edit, Run, Config, and Help.
+The File menu provides commands for opening new files and saving the
+file you are working on, as well as exiting the program. The Edit menu
+provides the kinds of things you would expect in a editor: commands to find
+a pattern, or find and replace; to select text; to copy, cut, and paste;
+to go to a specific line; and to undo the previous operation, if you make
+a mistake or change you mind.
+The Run menu lets you set runtime options,
+and then run the Mup program on your input in various
+ways. You can either just generate a PostScript or MIDI file,
+or display the PostScript or play the MIDI.
+The Config menu lets you specify what application program you want
+to use to view PostScript files and which you want to use to play MIDI files,
+and well as specify locations for other Mup files. Mupmate will try to
+find reasonable default values, but you may want to check that they are
+what you want, and tweak them if they aren't.
+The Config menu also provides a way for you to fill in the Mup registration
+form if you wish to send in a paper form rather than registering online
+via credit card, as well as a place to entry the registration key you
+will receive once you have paid.
+The Help menu lets you browse this User's Guide, view some startup hints,
+or see the current version number of Mup and Mupmate.
+</P>
+<P>
+Mupmate does not directly provide a print facility. Almost any PostScript
+viewer already provides this ability, so you can simply select &quot;Display&quot;
+from the Run menu and use the viewer's print capabilities.
+Alternately you can use &quot;Write PostScript File&quot; from the Run menu
+to create a PostScript file that you can print as you would any other
+PostScript file.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="basics.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="cmdargs.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/shaped.html b/mup/docs/uguide/shaped.html
new file mode 100644 (file)
index 0000000..7a45842
--- /dev/null
@@ -0,0 +1,390 @@
+<HTML>
+<HEAD><TITLE>
+Shaped notes
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="tabstaff.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="textstr.html">next page --&gt;</A>
+</P>
+          
+<H1>
+SHAPED NOTES
+</H1>
+<P>
+If you intend to only use the usual system of note heads,
+you can skip over this section on shaped notes.
+If you wish to use less common note head shapes, like X-shaped notes,
+rather than normal note heads, or want &quot;shaped note&quot; music that is often used
+for &quot;Sacred Harp&quot; style music, sometimes also called &quot;fasola notation,&quot;
+then this section will explain how you can do that.
+</P>
+<H2>
+Headshapes context
+</H2>
+<P>
+<A NAME="hdshape">The headshapes context</A>
+is used in conjuction with the
+<A HREF="param.html#notehead">noteheads parameter</A>
+to determine what characters will be used when printing note heads.
+It is rarely necessary to include a headshapes context in your music,
+since Mup already has the most common values built in,
+so generally you just need to use the
+<A HREF="param.html#notehead">noteheads parameter</A>
+to access them. However, it is still important to understand
+what the headshapes context can contain,
+to understand how the builtin values work.
+</P>
+<P>
+The headshapes context defines, for
+a given head shape name, what specific note head characters
+to use for the notes of various durations.
+It contains one or more pairs of strings.
+The first string in the pair gives a name for a set of note head shapes.
+The second string contains a space-separated list of the names
+of 4 note head characters to use for that head shape name.
+The first shape in the list is used for quarter notes and shorter,
+the second for half notes,
+the third for whole notes, and the fourth for double whole notes.
+</P>
+<P>
+If an upside down version of the character is to be used for stem down notes,
+the name is prefixed by &quot;u?&quot; (The &quot;u&quot; stands for &quot;upside-down&quot; and the
+question mark is intended to be mnemonic for the fact
+that the upside down version
+will only be used part of the time, namely for stem-down notes.)
+</P>
+<P>
+As was mentioned above, the most common mappings are already built into Mup.
+Here is the list of the pre-defined values.
+Pay particular attention to the first string on each line,
+since those are the names you will use in the
+<A HREF="param.html#notehead">notehead parameter</A>
+and for
+<A HREF="shaped.html#chord">overriding chord</A>
+and
+<A HREF="shaped.html#note">note shapes.</A>
+<BR>
+<TABLE BORDER=4>
+<TR>
+<TD>&quot;norm&quot;</TD>      <TD>&quot;4n 2n 1n dblwhole&quot;</TD>
+</TR>
+<TR>
+<TD>&quot;x&quot;</TD> <TD>&quot;xnote diamond diamond dwhdiamond&quot;</TD>
+</TR>
+<TR>
+<TD>&quot;allx&quot;</TD>      <TD>&quot;xnote xnote xnote xnote&quot;</TD>
+</TR>
+<TR>
+<TD>&quot;diam&quot;</TD>      <TD>&quot;filldiamond diamond diamond dwhdiamond&quot;</TD>
+</TR>
+<TR>
+<TD>&quot;blank&quot;</TD>     <TD>&quot;blankhead blankhead blankhead blankhead&quot;</TD>
+</TR>
+<TR>
+<TD>&quot;righttri&quot;</TD>  <TD>&quot;u?fillrighttriangle u?righttriangle u?righttriangle u?dwhrighttriangle&quot;</TD>
+</TR>
+<TR>
+<TD>&quot;isostri&quot;</TD>   <TD>&quot;fillisostriangle isostriangle isostriangle dwhisostriangle&quot;</TD>
+</TR>
+<TR>
+<TD>&quot;rect&quot;</TD>      <TD>&quot;fillrectangle rectangle rectangle dwhrectangle&quot;</TD>
+</TR>
+<TR>
+<TD>&quot;pie&quot;</TD>       <TD>&quot;fillpiewedge piewedge piewedge dwhpiewedge&quot;</TD>
+</TR>
+<TR>
+<TD>&quot;semicirc&quot;</TD>  <TD>&quot;fillsemicircle semicircle semicircle dwhsemicircle&quot;</TD>
+</TR>
+<TR>
+<TD>&quot;slash&quot;</TD>     <TD>&quot;fillslashhead slashhead slashhead dwhslashhead&quot;</TD>
+</TR>
+<TR>
+<TD>&quot;allslash&quot;</TD>  <TD>&quot;fillslashhead fillslashhead fillslashhead fillslashhead&quot;</TD>
+</TR>
+</TABLE>
+
+</P>
+<P>
+You can redefine these or define new ones if you wish.
+The name (the first of the two strings in the pair)
+can be almost anything you want.
+The four names in the second string must be taken from the list of
+valid note head characters given below:
+<BR>
+<PRE>
+4n                  2n         1n      dblwhole
+filldiamond          diamond            dwhdiamond
+fillisostriangle     isostriangle       dwhisostriangle
+fillpiewedge         piewedge           dwhpiewedge
+fillrectangle        rectangle          dwhrectangle
+fillrighttriangle    righttriangle      dwhrighttriangle
+ufillrighttriangle   urighttriangle     udwhrighttriangle
+fillsemicircle       semicircle         dwhsemicircle
+fillslashhead        slashhead          dwhslashhead
+xnote
+blankhead
+</PRE>
+The righttriangle shape names can be prefixed by u? when
+used in the headshapes context, to indicate the upside down version of them should
+be used when the stem is down. Note that u? cannot be used on any other
+note head characters, since none of the others have a corresponding
+upside down version.
+</P>
+<P>
+As an example of how you could use the headshapes context,
+suppose you wished to use xnote for half notes and shorter,
+and diamond for longer notes.
+That is different than either of the builtin values &quot;x&quot; or &quot;allx&quot;
+but you could override one of them:
+<BR><PRE>
+headshapes
+       &quot;x&quot; &quot;xnote xnote diamond diamond&quot;
+</PRE><BR>
+</P>
+<P>
+The blankhead does not print any head at all, it just leaves space as if
+there were a note head. It might be used if for some reason you just want
+stems.
+</P>
+<H2>
+Noteheads parameter
+</H2>
+<P>
+<A HREF="param.html#notehead">The noteheads parameter</A>
+describes which note head shape to use for each pitch
+in the scale. It can be specified in score, staff, or voice contexts.
+If you want to use the same shape for all pitches,
+(as is the case with standard notation), only one shape name is specified.
+Thus the default value for this parameter is
+<BR><PRE>
+noteheads = &quot;norm&quot;
+</PRE><BR>
+</P>
+<P>
+If you want to use different shapes for different pitches,
+the noteheads value needs to be a string containing a list of 7 shape names.
+They are listed from the &quot;tonic&quot; of the major key up the scale,
+with the key based on the number of sharps or flats in the
+<A HREF="param.html#key">key signature.</A>
+The shape names must be from the list of pre-defined head shapes (norm,
+xnote, diam, blank, righttri, isostri, rect, pie, semicirc, slash),
+or names that you have given as the first in a pair of strings
+in the headshapes context.
+</P>
+<P>
+You can get the most common shaped note system using 4 shapes using:
+<BR><PRE>
+noteheads = &quot;righttri norm rect righttri norm rect diam&quot;
+</PRE><BR>
+There are several shaped notes systems using 7 different shapes.
+One such system is specified by:
+<BR><PRE>
+noteheads = &quot;isostri semicirc diam righttri norm rect pie&quot;
+</PRE><BR>
+</P>
+<P>
+Once the noteheads parameter is set,
+you specify your music just like you would for standard notation,
+but Mup will use the appropriate note heads based on your specifications.
+</P>
+<P>
+<BR><PRE>
+score
+   // Use a 7-shaped system.
+   noteheads = &quot;isostri semicirc diam righttri norm rect pie&quot;
+
+   // Noteheads are given in order for the major key,
+   // so we'll start out with an example in major.
+   key = d major
+
+music
+
+// Do a descending scale in D major
+1: d+;c+;b;a;
+bar
+
+1: g;f;e;d;
+dblbar
+
+score
+   // Now we switch to D minor, where the &quot;tonic&quot;
+   // will start at the rect and then wrap around.
+   key = d minor
+
+music
+
+// Do a descending scale in D minor
+1: d+;c+;b;a;
+bar
+
+1: g;f;e;d;
+bar
+</PRE><BR>
+<IMG SRC="mugex60.gif" ALT="Picture of Mup output"><BR>
+</P>
+<H2>
+Overriding chord note heads
+</H2>
+<P>
+<A NAME="chord">It is possible to override what note shape to use for a chord,</A>
+by giving &quot;hs&quot; followed by a head shape name from the headshapes context,
+inside square brackets.
+Thus
+<BR><PRE>
+       [hs &quot;righttri&quot;]
+</PRE><BR>
+would use the &quot;righttri&quot; headshape. The specific character to use would be
+based on the group's duration. In other words, if the chord was a
+quarter note or shorter, the &quot;fillrighttriangle&quot; note head would be used,
+but if the chord was a half or whole note, a &quot;righttriangle&quot; note head would be
+used, and a &quot;dwhrighttriangle&quot; would be used for a double whole note.
+</P>
+<P>
+The hs specification can be used along with other things that can go in the
+square brackets. For example,
+<BR><PRE>
+       [hs &quot;blank&quot;; len 0]
+</PRE><BR>
+would use blankheads and no stem, resulting in no chord being printed at all!
+</P>
+<H2>
+Overriding individual note heads
+</H2>
+<P>
+<A NAME="note">If you want to override the note head shape to be used for one specific</A>
+note in a chord, you use hs followed by the head shape name
+as a string after the note.
+<BR><PRE>
+1: cg e+ hs &quot;diam&quot;; f a hs &quot;x&quot; c+; 2ge+;
+bar
+</PRE><BR>
+<IMG SRC="mugex61.gif" ALT="Picture of Mup output"><BR>
+</P>
+<H2>
+Putting it all together to use shaped notes
+</H2>
+<P>
+In summary,
+note head shapes can be specified in five different places: per note,
+per chord, in voice context, in staff context, and in score context.
+When deciding what note head shape to use, Mup checks for specifications
+in that order, using the first it finds.
+</P>
+<P>
+Since fret numbers are used rather than note heads on
+<A HREF="tabstaff.html">tablature staffs,</A>
+the only head shape name that is allowed is &quot;allx.&quot;
+which is used for &quot;muffled&quot; notes.
+</P>
+<P>
+Here is a simple example of shaped notes, using the common 4-shape system.
+<BR><PRE>
+score
+       noteheads = &quot;righttri norm rect righttri norm rect diam&quot;
+       staffs=4
+       key=2#
+       bracket=1-4
+
+staff 3
+       clef=treble8
+staff 4
+       clef=bass
+music
+
+1: 2c+;4d+;e+;
+2: 2e;4a;f;
+3: 2e;4f;c;
+4: 2a-;4f-;a-;
+bar
+
+1: 1d+;
+2: 1f;
+3: 1d;
+4: 1d;
+endbar
+</PRE><BR>
+<IMG SRC="mugex62.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+Here is an example of using the same note head shape for all pitches,
+illustrating how the proper version--filled or open--of the note head
+is used, based on the note's duration.
+<BR><PRE>
+score
+       time=8/4
+       beamstyle=2,2,2,2
+
+music
+1: 8cf;;4;2;1;
+bar
+
+score noteheads=&quot;isostri&quot;
+music
+1: 4ec+;8;;2;1;
+bar
+
+score noteheads=&quot;rect&quot;
+music
+1: 1gc+;4;2;8;;
+bar
+
+score noteheads=&quot;pie&quot;
+music
+1: 8cf;;4;2;1;
+bar
+
+score noteheads=&quot;x&quot;
+music
+1: 4ec+;8;;2;1;
+bar
+
+score noteheads=&quot;slash&quot;
+music
+1: 1gc+;4;2;8;;
+bar
+</PRE><BR>
+<IMG SRC="mugex63.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+And finally, here is a somewhat silly example that demonstrates how
+you can use the various shaped notes features to get any kind of
+note head that Mup supports anywhere you want.
+<BR><PRE>
+headshapes
+       // Make some user-defined head shapes.
+       // These combinations don't really make sense;
+       // they are just to demonstrate what you can do.
+       &quot;reg&quot; &quot;4n 2n 2n 2n&quot;
+       &quot;other&quot; &quot;fillrectangle diamond isostriangle dblwhole&quot;
+
+score
+       // Set notesheads, using an arbitrary mixture of builtin
+       // and user-defined head shapes.
+       noteheads=&quot;norm reg other reg reg other righttri&quot;
+
+music
+
+1: c;d;2e;
+bar
+
+1: 2g;f;
+bar
+
+1: {b;a;g;}3;2c+;
+bar
+
+1: 1d;
+bar
+
+// do some shape overrides, both on group and note
+1: [ hs &quot;pie&quot; ]2ce; [hs &quot;isostri&quot;] c e g hs &quot;righttri&quot;; 
+endbar
+</PRE><BR>
+<IMG SRC="mugex64.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="tabstaff.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="textstr.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/sharehd.html b/mup/docs/uguide/sharehd.html
new file mode 100644 (file)
index 0000000..592c740
--- /dev/null
@@ -0,0 +1,25 @@
+<HTML>
+<HEAD><TITLE>
+Forcing shared noteheads
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="chant.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="mantup.html">next page --&gt;</A>
+</P>
+           
+<H2>
+Forcing shared noteheads
+</H2>
+<P>
+Mup will automatically share note heads when it can figure out it is safe
+and proper to do so. However, there may be some unusual cases where you would
+like to force the notes from two voices to share note heads even when Mup
+would not do that. That can be done by specifying a horizontal offset of zero,
+i.e., [ho 0], on one or both of the voices.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="chant.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="mantup.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/slashmrk.html b/mup/docs/uguide/slashmrk.html
new file mode 100644 (file)
index 0000000..0036924
--- /dev/null
@@ -0,0 +1,50 @@
+<HTML>
+<HEAD><TITLE>
+Diagonal slash marks
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="pianored.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="breathmk.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Diagonal slash marks
+</H2>
+<P>
+Sometimes, instead of a note or notes,
+a diagonal slash mark is printed on a staff.
+This is used for various purposes,
+such as strumming a chord (in a
+guitar part), or to mean that the previous beat should be
+repeated or
+that a note should be improvised.
+You can get slash marks for all notes by setting the
+<A HREF="param.html#notehead">noteheads parameter.</A>
+<BR><PRE>
+noteheads = &quot;allslash&quot;
+</PRE><BR>
+or if you want to use hollow slashes for half notes and longer
+<BR><PRE>
+noteheads = &quot;slash&quot;
+</PRE><BR>
+Usually such slash marks do not include a stem,
+so you may wish to also set
+<BR><PRE>
+stemlen=0
+</PRE><BR>
+</P>
+<P>
+If you just want specific chords to be slashes, you can use the
+chord head shape override:
+<BR><PRE>
+1: b;[ hs &quot;allslash&quot;; len 0 ]... ;;;
+bar
+</PRE><BR>
+<IMG SRC="mugex99.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="pianored.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="breathmk.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/stuff.html b/mup/docs/uguide/stuff.html
new file mode 100644 (file)
index 0000000..57bb1d4
--- /dev/null
@@ -0,0 +1,293 @@
+<HTML>
+<HEAD><TITLE>
+"Tempo, dynamic marks, ornaments, etc."
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="textstr.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="textmark.html">next page --&gt;</A>
+</P>
+         
+<H1>
+TEMPO, DYNAMIC MARKS, ORNAMENTS, ETC.
+</H1>
+<H2>
+General information
+</H2>
+<P>
+There are a number of symbols and other markings that appear frequently
+in music, which are normally associated with a particular time or place in the
+composition. There are several classes of such symbols, all of which are
+handled by Mup in a somewhat similar fashion. The general format of these
+statements is:
+<BR><PRE>
+<I>mark_type place staff(s) distance : begintime text duration;</I>
+</PRE><BR>
+</P>
+<P>
+The <I>mark_type</I> can be any of the following:
+<PRE>
+Mark_type        Meaning
+
+rom        text in roman font
+ital       text in italic font
+bold       text in bold font
+boldital   text in bold-italic font
+mussym     music symbol (fermata, coda sign, etc.)
+phrase     phrase mark
+&lt;          crescendo &quot;hairpin&quot;
+&gt;          decrescendo &quot;hairpin&quot;
+octave     play 1 or more octaves higher or lower
+pedal      piano pedal marks
+</PRE>
+</P>
+<P>
+The <I>place</I> is as for
+<A HREF="lyrics.html">lyrics:</A>
+above, below, or between.
+There are some restrictions, as summarized below:
+<PRE>
+                       place allowed
+mark_type   above   below   between   default
+
+rom          yes     yes      yes      above
+bold         yes     yes      yes      above
+ital         yes     yes      yes      above
+boldital     yes     yes      yes      above
+mussym       yes     yes      yes      above
+phrase       yes     yes       no     varies
+&lt;            yes     yes      yes      above
+&gt;            yes     yes      yes      above
+octave       yes     yes       no       none
+pedal         no     yes       no      below
+</PRE>
+</P>
+<P>
+<A HREF="octave.html">Octave marks</A>
+must include a <I>place</I> of above or below.
+For all the other mark_types, the <I>place</I> is optional. For
+<A HREF="phrase.html">phrase,</A>
+if <I>place</I> is not specified, Mup determines it
+on a case-by-case basis depending on the location of the notes. 
+</P>
+<P>
+As with musical data or lyrics, the <I>staff</I> can be a single
+number or may include lists and ranges. In the case of &quot;between&quot;,
+staff numbers must be in pairs, separated by an &quot;&amp;&quot;, with the second
+staff number one greater than the first.
+</P>
+<P>
+The <I>staff</I> can also be specified by the keyword &quot;all,&quot; in which
+case the mark will be placed above the top visible staff or below the
+bottom visible staff. 
+</P>
+<P>
+Here are some examples:
+<BR><PRE>
+rom 3:
+boldital below 1:
+&lt; between 3&amp;4:
+pedal below 2:
+octave above 3:
+phrase 3,4:
+mussym above 2-3, 5:
+ital between 1&amp;2, 3&amp;4:
+</PRE><BR>
+</P>
+<P>
+<A NAME="dist">The</A>
+<I>distance</I> is optional. It is specified by the keyword &quot;dist&quot; followed
+by a number. This number overrides the
+<A HREF="param.html#dist">dist,</A>
+<A HREF="param.html#chdist">chorddist,</A>
+or
+<A HREF="param.html#dyndist">dyndist</A>
+parameter value that would normally apply, and is given in stepsizes.
+If the number is followed by a ! the items will be placed at exactly that
+distance from the edge of the staff,
+without regard for anything they might overwrite.
+Otherwise the normal rules apply: the dist is a minimum value, and items
+may be placed farther away than this to avoid colliding with other things.
+If the ! is used, the number is allowed to be negative,
+which allows you to place items inside the staff.
+A dist cannot be specified with pedal, phrase, or between.
+<BR><PRE>
+score
+       dist=2
+music
+
+rom above 1: 1 &quot;normal dist&quot;;
+rom above 1 dist 4: 2 &quot;dist 4&quot;;              // higher than usual
+rom above 1 dist 0! : 3 &quot;forced 0&quot;;  // lower than normal
+mussym above 1 dist -2! : 4.5 &quot;rr&quot;;  // forced down into staff
+1: c;;;;
+endbar
+</PRE><BR>
+<IMG SRC="mugex67.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+After the colon comes one or more items to be printed. Each item contains
+at least a begintime specification. Some may also contain a
+<A HREF="textstr.html">text string</A>
+and/or
+a duration. Each item ends with a semicolon. A newline ends the list of items.
+</P>
+<P>
+The begintime describes where in time the item should be printed. It is
+a number ranging from 0 to the numerator (top number)
+of the
+<A HREF="param.html#time">time signature</A>
+plus one.
+0 refers to the bar line at the beginning of the current measure, 1 refers
+to the first beat of the measure, 2 to the second beat, etc., with the
+maximum value referring to the bar line which ends the measure. A &quot;beat&quot;
+is whatever time value is given by the denominator (bottom number)
+of the time signature.
+For example, in 4/4 or 3/4 time, a beat is a quarter note, whereas in 6/8
+or 9/8 time, a beat is an eighth note. Fractional values can be specified
+using a decimal number. Thus 1.5 is halfway between beats 1 and 2,
+while 2.66 is about 2/3 of the way between beats 2 and 3.
+For
+<A HREF="param.html#time">time signatures</A>
+that are the addition of two or more fractions, like 4/4 + 3/8,
+a &quot;beat&quot; is given by the largest denominator.
+</P>
+<P>
+Since grace notes effectively take zero time, special notation is used
+to place something relative to a grace note. The <I>begintime</I> can be
+followed by a number of grace notes to &quot;back up&quot; from the beat.
+The number is a negative number enclosed in parentheses.
+</P>
+<P>
+The beat time value can optionally be followed by
+<A NAME="stepoff">an offset, in stepsizes.</A>
+This offset is a number in square brackets.
+The number must begin with a + or - sign.
+It can optionally include a decimal point and fractional part.
+A negative offset will cause the item to
+be moved to the left, while a positive offset will cause it
+to be moved to the right.
+This offset is used as a final adjustment after all the other placement
+has been done. A common use for this would be if you want to place something
+slightly before the beginning of the first measure of a song. You could
+then specify something like:
+<BR><PRE>
+rom above all: 0 [-3.5] &quot;Allegro&quot;;
+</PRE><BR>
+which would place the &quot;Allegro&quot; 3.5 stepsizes left of the beginning
+of the measure.
+</P>
+<P>
+The grace note back up, if any, must occur before the
+stepsize offset, if any.
+For example:
+<BR><PRE>
+1: c; [grace] 8d; []e; []f; 2.g;
+ital above 1: 2(-3)[+1] &quot;cresc.&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex68.gif" ALT="Picture of Mup output"><BR>
+would find the chord at or closest to count 2,
+and back up 3 grace notes from there, then move right by 1 stepsize.
+</P>
+<P>
+For items that include a duration, the duration tells the ending point of
+the item. A duration is specified by:
+<BR><PRE>
+<B>til</B> <I>M</I><B>m</B> + <I>N</I>
+</PRE><BR>
+where <I>M</I> is a number of
+<A HREF="bars.html">bar lines</A>
+to cross, and <I>N</I> is a number of additional beats.
+If either of them is 0, it can be omitted,
+but at least one of them must be non-zero.
+Here are some examples:
+<BR><PRE>
+til 3  // until beat 3 of current measure
+til 1m+2   // until beat 2 of next measure
+til 1m   // until next bar line
+</PRE><BR>
+</P>
+<P>
+Whether the text and duration are allowed or required depends on the mark_type,
+as summarized below:
+<PRE>
+mark_type    text            duration
+
+rom        required          optional
+bold       required          optional
+ital       required          optional
+boldital   required          optional
+mussym     required      allowed on tr only
+phrase    not allowed        required
+&lt;         not allowed        required
+&gt;         not allowed        required
+octave     required          optional
+pedal     * or nothing     not allowed
+</PRE>
+</P>
+<P>
+If there are several items, such that they have to be stacked on top
+of each other, all items of a particular class are placed from top to bottom
+according to input order. The classes are done in the order
+shown in the table below, unless the order is overridden by
+the
+<A HREF="param.html#aboveord">aboveorder,</A>
+<A HREF="param.html#beloword">beloworder,</A>
+or
+<A HREF="param.html#betwnord">betweenorder</A>
+parameters.
+<PRE>
+above  (from bottom up)
+   phrase
+   mussym
+   octave
+   rom bold ital boldital &lt; &gt;
+   lyrics
+   endings
+   rehearsal marks
+
+below  (from top down)
+   phrase
+   mussym
+   octave
+   rom bold ital boldital &lt; &gt;
+   lyrics
+   pedal
+
+between        (from bottom up)
+   mussym
+   rom bold ital boldital &lt; &gt;
+   lyrics
+</PRE>
+</P>
+<P>
+For example, for the above items, all phrases will be placed as close to the
+staff as possible, then mussym items above them, then octave marks above
+them, etc. However, if there are several mussym items that belong at the
+same horizontal position, the first one entered in the input will be printed
+above the second, the second one entered will be printed above the third, etc.
+All of the &quot;above all&quot; items of a given class will be above the
+items of that class for the top visible staff,
+and all &quot;below all&quot; items of a given class will be below the
+items of that class for the bottom visible staff.
+<BR>
+<A HREF="textmark.html">Text</A>
+<BR>
+<A HREF="mussym.html">Music symbols</A>
+<BR>
+<A HREF="phrase.html">Phrase marks</A>
+<BR>
+<A HREF="cres.html">Crescendo and decrescendo marks</A>
+<BR>
+<A HREF="octave.html">Octave marks</A>
+<BR>
+<A HREF="pedal.html">Piano pedal marks</A>
+<BR>
+<A HREF="roll.html">Rolls</A>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="textstr.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="textmark.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/tabstaff.html b/mup/docs/uguide/tabstaff.html
new file mode 100644 (file)
index 0000000..b3f8d64
--- /dev/null
@@ -0,0 +1,394 @@
+<HTML>
+<HEAD><TITLE>
+Tablature notation
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="lyrics.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="shaped.html">next page --&gt;</A>
+</P>
+           
+<H1>
+TABLATURE NOTATION
+</H1>
+<P>
+Mup can print tablature staffs. Tablature notation is commonly used for
+guitar and several other instruments. Mup supports tablature for 1 to 9
+strings.
+</P>
+<P>
+Mup will automatically create a normal 5-line staff above each tablature
+staff, giving the equivalant music on that staff.
+This staff will be referred to as the &quot;tabnote
+staff.&quot; Normally, you will input music just for the tablature staff, and
+the tabnote staff will be derived from that. However, for any given measure,
+you can explicitly input music for a tabnote staff,
+which will turn off the automatic
+translation for that measure. If you only want either the tab or tabnote
+staff to be printed, you can mark the other one as invisible
+<A HREF="param.html#visible">(see the "visible" parameter).</A>
+You should specify the appropriate
+<A HREF="param.html#clef">clef</A>
+and
+<A HREF="param.html#key">key signature</A>
+for the tabnote staff, so that Mup can make the best derivation.
+</P>
+<H2>
+Specifying a tablature staff
+</H2>
+<P>
+To set up a tablature staff, you use the
+<A HREF="param.html#stlines">stafflines parameter.</A>
+To get a standard 6-line guitar tablature staff, you can just say
+<BR><PRE>
+score
+       staffs=2
+staff 2
+       stafflines = tab
+</PRE><BR>
+There are 2 staffs, because there is both the tablature staff and the
+automatically generated tabnote staff. The tablature staff is always
+immediately below the corresponding tabnote staff.
+Setting the
+<A HREF="param.html#stlines">stafflines parameter</A>
+to &quot;tab&quot; marks staff 2 as a tablature staff.
+</P>
+<P>
+If you want tablature for an instrument other than a 6-string guitar with
+standard tuning, you specify
+the pitches of the strings from top to bottom
+within parentheses after the &quot;tab.&quot; For example:
+<BR><PRE>
+stafflines = tab (e a d&amp; g)
+</PRE><BR>
+would define some instrument that had 4 strings, with the string on the
+top line of tablature staff being an e string, the next a, the next d flat,
+and the bottom g.
+As shown in the example, pitches can include a # or &amp; if necessary.
+Strings are assumed to be in octave 4 unless otherwise marked.
+You can specify a different octave by specifying an
+<A HREF="chordinp.html#oct">octave number</A>
+after the
+string's pitch (using either an absolute octave number or pluses or minuses).
+If the instrument
+has more than one string with the same pitch
+(even if they are in different octaves),
+they must be distinguished by adding one or more ' marks after the
+pitch. The tablature definition for standard guitar is
+<BR><PRE>
+stafflines = tab (e5 b g d a3 e'3)
+</PRE><BR>
+This specifies that the top string on the staff is e in octave 5.
+The next three strings
+are in the default octave of 4, and the last two strings are in octave 3.
+Since there are two different strings with pitch letter of e, the lower e is
+marked as e'. Note that the octaves given are how they
+should be printed on the tabnote staff. A standard guitar actually sounds
+an octave lower than written. If you just use &quot;stafflines = tab&quot; without
+specifying any strings, Mup not only assumes the standard guitar layout,
+and prints in the appropriate octave,
+<A NAME="autotran">but it also automatically</A>
+<A HREF="trnspose.html">transposes</A>
+the
+<A HREF="midi.html">MIDI output</A>
+to the actual pitches an octave lower. If you specify
+strings explicitly, you will have to specify the octaves and any
+desired MIDI transposition values yourself. Stated another way,
+<BR><PRE>
+score
+       staffs = 2
+staff 2
+       stafflines = tab
+</PRE><BR>
+is equivalent to
+<BR><PRE>
+score
+       staffs=2
+staff 2
+       stafflines = tab (e5 b g d a3 e'3)
+staff 1
+       ifdef MIDI transpose = down perfect 8 endif
+</PRE><BR>
+Note from this last example that MIDI is taken from the tabnote staff,
+not the tablature staff, so MIDI directives should be placed with the
+tabnote staff.
+</P>
+<P>
+Mup should be able to handle almost any instrument with up to 9 strings.
+Several strings can have the same pitch; you just need to distinguish
+them with ' marks.
+The strings must be listed in whatever order the strings are to appear
+on the tablature staff.
+As another example,
+<BR><PRE>
+stafflines = tab (g3 d3 a2 e2)
+</PRE><BR>
+would define a standard bass guitar. Note that a bass guitar also sounds
+an octave lower than written, so it should be transposed for MIDI purposes.
+</P>
+<H2>
+Music input on tablature staffs
+</H2>
+<P>
+Input of tablature is similar to that on regular staffs. Each note in a
+chord is specified by a string and a
+fret.
+So fret 3 on the g string
+is designated by g3 or fret 0 on the e' string is designated by e'0.
+If your open string pitch includes an accidental, that would be included
+as well, so if you had an instrument with an f# string and wanted to
+play the 6th fret on that string, it would be f#6.
+Fret numbers can range from 0 to 99.
+If you want fret numbers to be placed inside parentheses,
+put parentheses
+around them in the input.
+You can also put both the string and fret within a set of parentheses,
+in which case, the note generated on the tabnote staff will have parentheses
+around it.
+Here are some examples of chords:
+<BR><PRE>
+2: d4; d5a3; b0 d(5); e2(b3)g2;
+bar
+</PRE><BR>
+<IMG SRC="mugex53.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+<A HREF="chordinp.html#duration">Time values</A>
+are specified just like on non-tablature staffs: a number
+optionally followed by one or more dots (like 4 or 8..),
+or a list of such numbers added together (like 2+8),
+preceding the chord pitches. Tablature staffs follow the same
+rules as non-tablature staffs for using time values from the previous
+chord if no time value is specified on the current chord. Similarly,
+if no notes are specified for a chord, the same notes used in the previous
+chord are reused. As an example:
+<BR><PRE>
+2: 4.e5; ;8;b2;
+bar
+</PRE><BR>
+<IMG SRC="mugex54.gif" ALT="Picture of Mup output"><BR>
+Since nothing is specified for the second chord, both time value (dotted
+quarter) and note (e string fret 5) are copied from the first chord.
+The third chord in the measure has only a time value
+(an eighth note) so the note (string/fret) is repeated.
+The final chord has only a note,
+so the previous time value is used.
+</P>
+<P>
+Rests and spaces can be specified with r and s, just like on non-tablature
+staffs. They result in nothing being printed on the tablature staff, and
+rest or space being printed on the tabnote staff.
+</P>
+<H2>
+Chord attributes
+</H2>
+<P>
+Any chord on a tablature staff can be preceded by a list of
+<A HREF="chrdattr.html#chstyle">chord attributes</A>
+in brackets, just like with non-tablature staffs. If you want a chord to be
+printed with X (for a muffled string) rather than a fret number,
+use [xnote].
+In this case, the fret number will be used only to determine where to put
+the X on the tabnote staff, and what note to use for
+<A HREF="midi.html">MIDI.</A>
+Using [diam]
+will have no affect on the tablature staff, but will cause
+diamond notes to be used on the tabnote staff.
+Using [grace] or [cue] will cause the fret numbers to printed in a smaller
+size, and the corresponding notes on the tabnote staff to be printed
+in a smaller size. Using [slash <I>N</I>]
+will cause <I>N</I> slashes to be printed below the chord on the tablature
+staff, as well as
+<A HREF="chrdattr.html#slashes">slashes</A>
+on the corresponding chord on the tabnote staff.
+You can use the other chord attributes (with, pad, and =tag) just
+like on a non-tablature staff.
+</P>
+<H2>
+Ties
+</H2>
+<P>
+From an input point of view,
+<A HREF="noteattr.html#ntie">ties</A>
+work much the same on tablature staffs as on other staffs.
+On output, tie marks on tablature staffs are normally not printed,
+and the frets are not printed on the tied-to chord. If a tie goes across
+to a new score, the frets are printed, but in parentheses, to indicate the
+chord is really just the continuation of a tie.
+</P>
+<H2>
+Slides
+</H2>
+<P>
+In Mup input,
+slides are shown with &lt;&gt;, rather like
+<A HREF="noteattr.html#nslur">slurs</A>
+on non-tablature staffs.
+There is a special variation used for slides that come from nowhere in
+particular or go to nowhere in particular.
+These are shown with &lt;\n&gt;, &lt;/n&gt;, &lt;n\&gt;, or &lt;n/&gt;.
+A slide is indicated on output on tablature staffs
+as a slanted line between 2 fret numbers on a string.
+On tabnote staffs, they as drawn as a slanted line between 2 notes.
+See the examples below:
+<BR><PRE>
+2: a5&lt;&gt;; a6; d3&lt;&gt;; d2;
+bar
+
+2: b4&lt;/n&gt;; e3&lt;\n&gt;; a2&lt;n/&gt;; e'5&lt;n\&gt;;
+bar
+</PRE><BR>
+<IMG SRC="mugex55.gif" ALT="Picture of Mup output"><BR>
+</P>
+<H2>
+Bends
+</H2>
+<P>
+A bend (stretching a string to make it sound higher than normal)
+is specified on tablature staffs
+by putting a text string after the string. The
+text string can be the word &quot;full&quot; or a number and/or fraction.
+Some examples:
+<BR><PRE>
+2: e4 &quot;full&quot;; e &quot;1/2&quot;; 2e &quot;1 1/2&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex56.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+If you want to bend back down to having no bend (a release),
+the text string specifying
+the bend is just an empty string of &quot;&quot;.
+Note that if both a fret and bend other than &quot;&quot; are specified,
+<A NAME="prebend">this indicates a prebend,</A>
+whereas if only a bend is specified, this indicates a normal bend.
+</P>
+<P>
+Bends need not be an integer number of half steps, but if you specify a bend
+that falls between half steps, when it is used on the tabnote
+staff, the bend is rounded to the nearest half step, or rounded downward
+if it is exactly in the middle of a half step.
+When possible, bends of 1/4 step or less are shown on the tabnote staff
+by a small curve rather than by a separate note.
+</P>
+<P>
+You can specify bends on more than one string at once, but a continuation
+bend (bending to a new distance without replucking the string) is only
+allowed on a single string at a time. Here are some examples:
+<BR><PRE>
+2: g0b2e'0; e' &quot;1/2&quot; g &quot;full&quot; b &quot;3/4&quot;; e' &quot;&quot;; a2;
+bar
+
+2: a &quot;1/2&quot;; a &quot;full&quot;; a &quot;1/2&quot;; a &quot;&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex57.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+If you have more than one voice on a tablature staff,
+bends on other than the top voice may collide with other voices in some
+cases, and if there are bends from more than one voice simultaneously,
+they may collide.
+</P>
+<P>
+On non-tablature staffs, bends are specified with a ^ symbol followed
+by the note to bend to. The note to bend to is specified by letter and
+optional octave (accidentals are not specified). If you want just a small
+bend (1/4 step), this is specified by ^/. For example:
+<BR><PRE>
+1: e ^f; f; b ^c5; c#5;
+bar
+
+1: d+^e+ g^a; e+a; g ^/; c ^/ c+^/;
+bar
+</PRE><BR>
+<IMG SRC="mugex58.gif" ALT="Picture of Mup output"><BR>
+</P>
+<H2>
+Miscellaneous
+</H2>
+<P>
+Note attributes of ~ for tie, ? for a small note, and = for a tag work the
+same on tablatures staffs as on non-tablature staffs.
+</P>
+<P>
+If bm, ebm, or esbm are given on tablature staffs they are
+transferred to the tabnote staff and used for
+<A HREF="ichdattr.html#custbeam">custom beaming</A>
+there.
+<A HREF="chrdattr.html#withlist">Items in "with" lists inside [ ]</A>
+are also copied to the tabnote staff.
+In general, unless otherwise specified here,
+if you want items such as
+<A HREF="stuff.html">tempo and dynamic marks</A>
+to appear on both tablature and tabnote staff, you
+have to specify them for both staffs.
+</P>
+<P>
+The
+<A HREF="ichdattr.html#alt">"alt" inter-chord attribute</A>
+is not allowed on tablature staffs.
+</P>
+<P>
+When there is a tablature staff, the
+<A HREF="midi.html">MIDI</A>
+is actually generated from the
+tabnote staff. There are some limitations.
+Currently, no MIDI pitch bends are generated; slides and
+bends are instantaneous rather than gradual.
+</P>
+<P>
+If a
+capo is being used, it probably better to declare a
+<A HREF="trnspose.html">transposition</A>
+of the tabnote staff rather than declaring the strings to be different
+notes. This is because most people would rather think of the original
+string letters when entering the tab staff information; and if you decide to
+put the capo on a different fret later,
+you only have to change the &quot;transpose&quot; line.
+<A HREF="tabstaff.html#autotran">The automatic MIDI octave tranposition for standard guitar</A>
+will also then still apply, on top of your transposition.
+</P>
+<P>
+If you specify an
+<A HREF="octave.html">octave mark</A>
+(discussed in a later section)
+on a tabnote staff, the derived music will be printed with the notes
+raised or lowered the appropriate number of octaves to correspond to the given
+octave mark interval.
+</P>
+<P>
+Since ties are not printed on tablature staff, and input notation for
+tablature slides is like what is used for slurs on ordinary staffs, if
+you want a curved line like a tie or slur on a tablature or tabnote staff,
+you have to use a phrase mark. See the section on
+<A HREF="phrase.html">phrase marks</A>
+for more details.
+</P>
+<P>
+The chord-at-a-time input style can also be used for tablature.
+The staffs being mapped to from a single input line must either be
+all tablature or all non-tablature, however.
+<BR><PRE>
+score
+       staffs=4
+       brace=1-2, 3-4
+       tabwhitebox=y
+staff 2
+       stafflines=tab
+staff 4
+       stafflines=tab
+music
+
+// The first two notes in each chord go to staff 2,
+// and the last two go to staff 4.
+[ 2; 2; 4; 4] : a2d0 g0b3; e'0a2 g0e0; 2 e'0d2 b0e3; 
+bar
+</PRE><BR>
+<IMG SRC="mugex59.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="lyrics.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="shaped.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/tags.html b/mup/docs/uguide/tags.html
new file mode 100644 (file)
index 0000000..0a52157
--- /dev/null
@@ -0,0 +1,224 @@
+<HTML>
+<HEAD><TITLE>
+Location Tags
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="roll.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="prnttext.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Location tags
+</H2>
+<P>
+A location tag is associated with a
+<A HREF="noteattr.html#ntag">note,</A>
+<A HREF="chrdattr.html#ctag">chord,</A>
+or
+<A HREF="bars.html#btag">barline.</A>
+It can then be referenced in order to place a second object, like a comment
+or dotted line, relative to the first object.
+</P>
+<P>
+A tag name can be either a single lower case letter, or an underscore
+folowed by one or more letters, digits, or underscores.
+Each location tag is really a collection of six values,
+namely the north, south, east,
+west, x, and y values of the tagged object. These are referenced by giving
+the tag name followed by a dot, followed by the letter n, s, e, w, x, or y.
+For example:
+<BR><PRE>
+c.n    // north of tag c
+_xyz.e // east of tag _xyz
+x.x    // x coordinate of tag x
+</PRE><BR>
+</P>
+<P>
+The n, s, e, and w values describe the smallest rectangle that will
+completely enclose the object being tagged.
+The north refers to the top of the object, the south to the bottom, the
+west to the left edge, and the east the right edge. The x and y values
+correspond to the &quot;center&quot; coordinate of the object. This is not necessarily
+the geometric center, but more of a &quot;logical center.&quot; In the case of a tag
+associated with an individual note, it is the geometric center of the note head.
+However, on tags associated with a chord, the x is at the center line of 
+note heads that are on the &quot;normal&quot; side of the stem. (Normally, when a stem
+is up, notes are put on the left side of the stem, and when the stem is
+down they are placed on the right side. However, when two notes adjacent
+on the staff have to be printed in a single chord, one has to be moved to the
+opposite side.) The y of a chord is always the middle line of the staff
+containing the chord. The x of a bar line is its geometric center. The y
+of a bar line is the center line of the top visible staff.
+</P>
+<P>
+Tag names can be re-used. The value of a tag will always be its most
+recent definition.
+</P>
+<P>
+There are also several &quot;pre-defined&quot; tags. They are:
+<DL>
+<DT>
+_page
+<DD>
+the entire page
+<DT>
+_win
+<DD>
+the available part of the page
+<DT>
+_cur
+<DD>
+the current location
+</DL>
+</P>
+<P>
+The _page tag refers to the entire page.
+The x and y values of _page are at the geometric center of the page.
+This tag is
+seldom useful, but is provided in case you want to force something to
+a specific place on a page.
+</P>
+<P>
+<A NAME="wintag">The _win tag</A>
+refers to the area of the page available for printing.
+The name comes from the idea that it provides a view, as if through a window,
+of a portion of the page. Its precise meaning depends upon the current
+context.
+In header, footer, top, bottom,
+header2, footer2,  top2, bottom2, and block contexts,
+it refers to the area of the
+page taken up by the corresponding element. In music context, it refers
+to the area of the page that remains after excluding the margins and the
+header, footer, top and bottom for the page.
+There is no way to access location tags in any other
+contexts, so _win (and all other location tags)
+are meaningless in other contexts.
+</P>
+<P>
+The _cur tag refers to the current location on the page. This is a single
+point, such that east and west values are the same as x, and north and
+south values are the same as y. It is only useful immediately
+after a command that explicitly sets the current location, that is, after
+a printing command or line or curve command. Since Mup places musical
+data in an arbitrary order, trying to use _cur at other times is likely
+to cause output at a seemingly random place.
+</P>
+<P>
+Location tags can be referenced by a number of commands, including those
+for
+<A HREF="prnttext.html">printing text,</A>
+or
+<A HREF="linecurv.html">drawing lines or curves.</A>
+In the simplest case, two
+tag references are given in parentheses. The first tag
+must refer to a horizontal direction (the &quot;x&quot; direction for mathematicians),
+namely a tag with a w, e, or x after the dot. The second tag is then a
+vertical tag, having n, s, or y. For example:
+<BR><PRE>
+(g.x, g.y)     // x and y of tag &quot;g&quot;
+(_tag.w, _item.n)   // west of tag &quot;_tag&quot; and
+                   // north of tag &quot;_item&quot;
+</PRE><BR>
+The first example refers to the x,y coordinate of tag &quot;g&quot;. The second item
+refers to two different tags. The point referenced has its horizontal
+location aligned with
+the west side of the object having the tag &quot;_tag,&quot; while its vertical
+position is in line with the north side of the object having the tag &quot;_item&quot;.
+In other words, if a line were drawn along the west side of the object
+tagged with &quot;_tag&quot; and another line were drawn along the top edge of the
+object with tag &quot;_item&quot;, the point where those two lines crossed would be
+the point referenced.
+</P>
+<P>
+Frequently, you may want to place something relative to a tagged object.
+You can add offsets in both the x and y dimensions. These offsets are given
+in stepsizes.
+As was mentioned earlier, a stepsize is half the distance between two staff
+lines.
+<BR><PRE>
+(g.x + 4.5, g.y + 4.5)
+</PRE><BR>
+refers to the point 4.5 stepsizes to the right and above the point (g.x, g.y).
+Adding an offset moves to the right in the horizontal direction and
+upward in the vertical direction. You can also subtract an offset:
+<BR><PRE>
+(k.w - 1.3, m.n - 2)
+</PRE><BR>
+refers to a point 1.3 stepsizes to the left of the
+west edge of k and 2 stepsizes below the top of m.
+</P>
+<P>
+In the horizontal direction, offsets can be given in terms of &quot;time&quot;. This
+is specified by using the keyword &quot;time&quot; followed by a number of beats.
+As an example, suppose we have the tag reference:
+<BR><PRE>
+(q.x + time 1, q.y + 2)
+</PRE><BR>
+If the
+<A HREF="param.html#time">time signature</A>
+is 4/4 and tag &quot;q&quot; happens
+to be associated with a half note, this tag reference
+would refer to a point halfway between that note and the following chord,
+since it includes an offset of a quarter note. If &quot;q&quot; had been associated
+with a whole note, the point would be only 1/4 of the way between the
+note and the following chord. Since notes are placed based on various
+constraints and aesthetic considerations, the actual distance will vary
+depending on which tag is referenced.
+</P>
+<P>
+In the case of a
+<A HREF="bars.html#btag">tag associated with a bar line,</A>
+the time to distance mapping
+is done based on the distance between the bar (at count &quot;0&quot;) and the first
+chord in the measure (at count &quot;1&quot;). So, for example, in 4/4 time, a reference
+to a bar line tag + time 0.5 would indicate a place halfway between the bar
+line and the first chord, whereas tag + time 0.25 would be one fourth of the
+way.
+</P>
+<P>
+The mapping of time to distance is done based only on the note, rest, or bar
+line associated with the tag. For example, if the tag is associated with a
+quarter note, and the distance between that note and the next was 0.5 inches,
+specifying  &quot;+ time 2&quot; (a half note) would mean 1.0 inch to the right, or
+specifying &quot;- time 2&quot; would mean 1.0 inch to the left, even if the notes to
+the left or right happened to be spread somewhat differently than 0.5 inches
+per quarter note. Thus it is usually advisable not to specify a time offset 
+greater than the time value of the note or rest associated with the tag,
+nor to subtract a time value. Stated another way, when specifying the X
+portion of a coordinate using a time offset, it is best to use a location tag
+based on whichever note, rest, or bar is immediately to the left of the
+X location you are trying to specify.
+</P>
+<P>
+The various kinds of offsets can be combined.
+<BR><PRE>
+( _pp + 1.2 - time 3.5, _zz + 2)
+</PRE><BR>
+</P>
+<P>
+At least one of the three possible items--tag, stepsize offset, or
+time offset--must be specified for each direction. Only one
+tag is allowed for each direction. If no tag is specified, the reference
+becomes an absolute reference, giving an exact page location. For example:
+<BR><PRE>
+(10, 20)
+</PRE><BR>
+is 10 stepsizes from the left edge and 20 stepsizes
+above the bottom of the page.
+Time offsets are not allowed on absolute references, and must follow the tag
+reference.
+</P>
+<P>
+It is possible to specify multiple offsets of the same type, although
+this is rarely, if ever, useful. Thus the following are equivalent:
+<BR><PRE>
+( f.x + 1 - 0.5 + time 1 - time 0.5, f.s + .3 - .1)
+( f.x + 0.5 + time 0.5, f.s + .2)
+</PRE><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="roll.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="prnttext.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/tempochg.html b/mup/docs/uguide/tempochg.html
new file mode 100644 (file)
index 0000000..e94ab8c
--- /dev/null
@@ -0,0 +1,68 @@
+<HTML>
+<HEAD><TITLE>
+Marking complicated tempo changes
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="oddeven.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="multsong.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Marking complicated tempo changes
+</H2>
+<P>
+Sometimes you may wish to indicate tempo changes by showing 2 note
+values with an equals sign between them. For simple cases, this is
+fairly straightforward, but if you want to include beamed notes or a triplet,
+a little more work is required. Another use of this notation is to
+show that the music is to be played in &quot;swing time,&quot; as in this example,
+which has two ordinary eight notes on one side of the equals sign,
+and a triplet made up of a quarter and eighth note on the other:
+<BR><PRE>
+score 
+       // This example assumes &quot;size&quot; is set to 15
+       size=15
+       beamstyle=4,4
+
+music
+
+// set a location tag 
+1: [=c] 8c+;a;g;f;
+
+// set X and Y to where the first note will be placed
+define X c.x - 3 @
+define Y c.y + 5 @
+
+// print &quot;straight 8ths = triplet quarter plus 8th&quot;
+
+// print the basic notes and equal sign
+print (X, Y) &quot;\(smup4n)  \(smup4n)  = \(smup4n)  \(smup8n)&quot;
+
+// print the beam between the straight 8th notes
+wide line (X + 2.1, Y + 5.5) to (X + 7.2, Y + 5.5)
+
+// now do the triplet bracket
+line (X + 14.7, Y + 7.0)  to (X + 17.6, Y + 7.0) // horz left top segment
+line (X + 19.4, Y + 7.0)  to (X + 22.5, Y + 7.0) // horz right top segment
+line (X + 14.7, Y + 7.05) to (X + 14.7, Y + 5.3) // vert left side segment
+line (X + 22.5, Y + 7.05) to (X + 22.5, Y + 5.3) // vert right side segment
+
+// print the 3 in the middle of the bracket
+print (X + 17.9, Y + 6.1) &quot;\s(8)\f(TI)3&quot;     // the 3 for the triplet
+
+bar
+</PRE><BR>
+<IMG SRC="mugex95.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+Note that if you want a piece to be played in swing time,
+you may also want to set the
+<A HREF="param.html#swing">swingunit parameter,</A>
+which will make the MIDI output use swing time.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="oddeven.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="multsong.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/textmark.html b/mup/docs/uguide/textmark.html
new file mode 100644 (file)
index 0000000..0b744be
--- /dev/null
@@ -0,0 +1,233 @@
+<HTML>
+<HEAD><TITLE>
+Mup Text Marks
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="stuff.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="mussym.html">next page --&gt;</A>
+</P>
+           
+<H2>
+Text
+</H2>
+<P>
+The four forms of Mup text statements
+(rom, bold, ital, and boldital) operate identically except for the font
+which is used.
+</P>
+<P>
+The text statements can have several additional qualifiers. The first is a
+fontfamily, given before the font. It can have any of the values of
+<A HREF="param.html#fontfam">the "fontfamily" parameter</A>
+(avantgarde, bookman, courier, helvetica,
+newcentury, palatino, or times), with the default being the value of
+the &quot;fontfamily&quot; parameter.
+</P>
+<P>
+The next optional qualifier is a
+point size, given in parentheses after the font type of rom, bold, etc.
+If this is omitted, the size is obtained from
+<A HREF="param.html#size">the "size" parameter</A>
+for the given staff, or for the score if the staff is specified by &quot;all.&quot;
+</P>
+<H3>
+Chord, analysis, figured bass, and dynamics
+</H3>
+<P>
+<A NAME="chordmod">The final optional qualifier specifies special treatment of the text.</A>
+The qualifier can be &quot;chord&quot;, &quot;analysis&quot;, &quot;figbass&quot;, or &quot;dyn&quot;.
+The &quot;chord&quot; modifier is typically used for marking chords that might be
+played by a guitar or other instrument. The &quot;analysis&quot; modifier is
+typically used when marking harmonic analysis like &quot;IV&quot; or &quot;vii&quot;.
+The &quot;figbass&quot; modifier is for figured bass notation.
+For all three, distance from the staff is affected by
+<A HREF="param.html#chdist">the "chorddist" parameter.</A>
+The &quot;dyn&quot; modifier is to mark the text as something that specifies
+dynamics. Mup only uses it when deciding where to place the text;
+something marked &quot;dyn&quot; will be treated like crescendo
+and decrescendo &quot;hairpins.&quot;
+The default <I>place</I> for chord and dyn is above, whereas the default
+for the others is below.
+</P>
+<P>
+The text strings used with these chord, analysis, or figbass modifiers can
+contain any characters, but
+characters that indicate accidentals (&quot;#&quot;, &quot;&amp;&quot;, &quot;x&quot;, &quot;&amp;&amp;&quot;, and &quot;n&quot;)
+are translated to the appropriate music character, while &quot;o&quot;, &quot;o/&quot;,
+and &quot;^&quot; are translated to &quot;\(dim)&quot;, &quot;\(halfdim)&quot;, and &quot;\(triangle)&quot;
+respectively. However, with &quot;chord,&quot; the
+translation of &quot;n&quot; to natural sign is not done, so you have to
+use \(nat) if you want a natural sign. This is because a literal letter n
+tends to occur more often in chords than natural signs.
+</P>
+<P>
+If you want to turn off the translation, to treat one of these characters
+literally, you can precede it with two backslashes.
+Thus, for example, &quot;\\&amp;&quot; would yield a literal ampersand rather than
+a flat symbol.
+</P>
+<P>
+If the
+<A HREF="param.html#xpose">transpose</A>
+or
+<A HREF="param.html#addxpose">addtranspose</A>
+parameters are set, chords are transposed to match the new key:
+the letters &quot;A&quot; through &quot;G&quot;
+and any following accidentals will be transposed appropriately.
+The accidental can be either something like &quot;#&quot; or &quot;&amp;&quot; or any of the special
+<A HREF="textstr.html#symlist">music characters</A>
+for accidentals (\(sharp), \(flat), etc.).
+If the staff is specified as &quot;all,&quot; the score transposition value is used.
+Transposition has no effect on analysis or figbass.
+</P>
+<P>
+In figbass, the string starts out in piled mode, which means that
+each space in the input string will cause a new line on output, and,
+unless you specify other alignment, each line will be aligned on
+the last digit in the line. Also, the meanings of
+/ and \/ are reversed from the normal meaning. This is done since
+drawing a slash through a number is very common in
+figured bass, so you can just use a / to indicate this,
+but if you really want a real slash,
+you can still get one by entering \/.
+</P>
+<P>
+With all three special qualifiers, the usual meanings
+of : and \: are reversed. This is
+because piling is very common in these strings, so it's handier to just
+put a : to indicate this, and for those rare cases when you want a
+literal colon, you can still get one by entering a \:.
+</P>
+<P>
+Here is an example showing chord, analysis, and figbass:
+<BR><PRE>
+1: egc+;dgb;dfa;dgb;
+bold chord above 1: 1 &quot;C&quot;; 2 &quot;G&quot;; 3 &quot;Dm&quot;; 4 &quot;G&quot;;
+rom analysis below 1: 1 &quot;I&quot;; 2 &quot;V&quot;; 3 &quot;ii&quot;; 4 &quot;V&quot;;
+bar
+
+1: egc+;dgb;df#a;dgb;
+rom figbass below 1: 1 &quot;6 3&quot;; 2 &quot;6 4&quot;; 3 &quot;3/&quot;; 4 &quot;6 4&quot;;
+bar
+
+1: 1cegb;
+rom chord above 1: 1 &quot;C^7&quot;;
+bar
+1: 1ce&amp;g&amp;b&amp;;
+rom chord above 1: 1 &quot;Co/&quot;;
+bar
+1: 1ce&amp;g&amp;b&amp;&amp;;
+rom chord above 1: 1 &quot;Co:7&quot;;
+bar
+1: 1e&amp;g&amp;b&amp;;
+rom chord above 1: 1 &quot;E&amp;m&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex69.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+If a music symbol occurs inside an ital or boldital string,
+<A NAME="italmus">the music symbol will automatically be made italics,</A>
+to match the rest of the string.
+</P>
+<P>
+It is possible to supply a duration on text statements. When this is done,
+Mup will draw a dashed line from the end of the text to the
+end of the duration.
+This may be useful if you want to indicate how long
+an action such as an accelerando or crescendo is to last.
+If the last character of the string is a &quot;~&quot;, 
+a wavy line will be drawn instead of a dashed line.
+If the last character of the string is an underscore, an underscore
+line will be drawn.
+</P>
+<P>
+Here are some examples of text:
+<BR><PRE>
+1: e;g;b;d+;
+2: 2e;b-;
+rom (12) above 1: 0 &quot;Andante ( \(smup4n) = 88 )&quot;;
+boldital (12) below 1: 1 &quot;mf&quot;; 3.5 &quot;mp&quot;;
+newcentury bold (12) chord above 1: 1 &quot;E&amp;7&quot;; 3 &quot;B&amp;9&quot;;
+ital between 1&amp;2: 2 &quot;rit.&quot;;
+palatino ital below 2: 2 &quot;cresc.&quot; til 1m+2;
+bar
+1: 1egc+;
+2: 1c;
+bold (12) chord above 1: 1 &quot;Cm&quot;;
+bar
+</PRE><BR>
+<IMG SRC="mugex70.gif" ALT="Picture of Mup output"><BR>
+</P>
+<H2>
+Grids
+</H2>
+<P>
+<A NAME="grids">If the</A>
+<A HREF="param.html#gridused">gridswhereused parameter</A>
+is set to &quot;y&quot; chords will also have a grid printed.
+For this to work, a grid with the same name as the chord must be
+defined in &quot;grids&quot; context elsewhere in the input file.
+</P>
+<P>
+The grids context contains lines each consisting of two text strings.
+The first is the name of the chord, matching the name you want to
+use in printing text with the &quot;chord&quot; qualifier. The second describes
+the fret pattern for that chord. It is a space-separated list, with
+each list element being either a fret number from 1 to 99, which will result in
+a dot being printed at that fret, or an &quot;o&quot; or &quot;x&quot;
+which will result in a circle or x respectively being printed above the
+grid, or a &quot;-&quot; in which case no mark at all will be made.
+The fret pattern may also contain an open and closing
+parenthesis to mark where a curve is to be drawn, indicating the use
+of a single finger to span several strings. For example:
+<BR><PRE>
+score
+      gridswhereused=y
+      gridfret=3
+grids
+      &quot;C&quot;     &quot; -  3  2  o  1  o &quot;
+      &quot;C5&quot;     &quot; -  3  x  o  1  3 &quot;
+      &quot;Em&quot;     &quot; o  2  2  o  o  o &quot;
+      &quot;A&amp;&quot;     &quot;(4  6  6  5  4  4)&quot;
+      &quot;A11&quot;    &quot; -  o  o  o  o  o &quot;
+music
+
+rom chord 1: 1 &quot;C&quot;; 2 &quot;C5&quot;; 3 &quot;Em&quot;;
+1: 2c;e;
+bar
+
+rom chord 1: 1 &quot;A&amp;&quot;; 3 &quot;A11&quot;;
+1: 2a&amp;;an;
+bar
+</PRE><BR>
+<IMG SRC="mugex71.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+If
+<A HREF="param.html#xpose">transposition</A>
+is in effect,
+the chord names in the grids context have to match the transposed names.
+So, for example, if you use an &quot;A&quot; chord in a chord statement, then
+transpose the staff up a major second, Mup will look for and use the grid
+definition called &quot;B&quot; to match the transposed chord name.
+</P>
+<P>
+If you supply more than one grid definition for the same chord name,
+Mup uses the last one. This allows you to easily
+<A HREF="include.html">"include" a file</A>
+of standard chords, but override a few of them with a special fingering for a
+particular song. If you really want to use more than one fingering in
+different places in the same song for the same chord name, you need to make
+the names look different, so Mup will treat them as different chords.
+One way to do this would be to put a space and backspace in the name.
+So, for example, &quot;Am&quot; and &quot;Am \b&quot; would count as separate chords and could
+have different grid definitions, but the chord names would still look
+the same on output.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="stuff.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="mussym.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/textstr.html b/mup/docs/uguide/textstr.html
new file mode 100644 (file)
index 0000000..00b5952
--- /dev/null
@@ -0,0 +1,495 @@
+<HTML>
+<HEAD><TITLE>
+Text Strings
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="shaped.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="stuff.html">next page --&gt;</A>
+</P>
+            
+<H1>
+TEXT STRINGS
+</H1>
+<P>
+Text strings are used in many different ways.
+A text string is enclosed in double quotes,
+and can contain any combination of letters, numbers, spaces,
+and punctuation.
+It can contain a \n to indicate a newline or \b to indicate a backspace,
+but otherwise cannot contain tabs or other
+control characters. If you want a double quote mark inside a string, it
+has to be preceded by a backslash, to indicate it is not ending the string:
+<BR><PRE>
+&quot;A \&quot;word\&quot; in quotes&quot;
+</PRE><BR>
+</P>
+<P>
+If you want an actual backslash in a string, it must be entered as two
+backslashes.
+</P>
+<P>
+<A NAME="strcat">You can concatenate strings with a + sign. Thus the following are equivalent:</A>
+<BR><PRE>
+&quot;this is a string&quot;
+&quot;this is &quot; + &quot;a string&quot;
+</PRE><BR>
+</P>
+<H2>
+Special characters
+</H2>
+<P>
+<A NAME="symlist">A string can also contain special</A>
+music characters.
+These are specified
+by \(<I>xxx</I>), where the <I>xxx</I> is a code from the following table:
+</P>
+<H3>
+Clef
+</H3>
+<PRE>
+gclef       G clef (treble clef)
+fclef       F clef (bass clef)
+cclef       C clef (used for alto clef, tenor clef, etc.)
+</PRE>
+<H3>
+Time Signature
+</H3>
+<PRE>
+com         common time
+cut         cut time
+</PRE>
+<H3>
+Accidentals
+</H3>
+<PRE>
+flat        flat
+dblflat     double flat
+sharp       sharp
+dblsharp    double sharp
+nat         natural
+</PRE>
+<H3>
+Notes
+</H3>
+<PRE>
+dn2n        half note with stem down
+dn4n        quarter note with stem down
+dn8n        eighth note with stem down
+dn16n       16th note with stem down
+dn32n       32nd note with stem down
+dn64n       64th note with stem down
+dn128n      128th note with stem down
+dn256n      256th note with stem down
+up2n        half note with stem up
+up4n        quarter note with stem up
+up8n        eighth note with stem up
+up16n       16th note with stem up
+up32n       32nd note with stem up
+up64n       64th note with stem up
+up128n      128th note with stem up
+up256n      256th note with stem up
+upflag      upward flag
+dnflag      downward flag
+</PRE>
+<H3>
+Noteheads
+</H3>
+<PRE>
+4n                   quarter (and shorter) note head
+2n                   half note head
+1n                   whole note
+dblwhole             double whole note
+xnote                X-shaped note head
+diamond              open diamond-shaped note head
+filldiamond          filled diamond-shaped note head
+dwhdiamond           double whole diamond-shaped note
+isostriangle         open isosceles triangle notehead
+fillisostriangle     filled isosceles triangle notehead
+dwhisostriangle      double whole isosceles triangle notehead
+piewedge             open piewedge notehead
+fillpiewedge         filled piewedge notehead
+dwhpiewedge          double whole piewedge notehead
+rectangle            open rectangle notehead
+fillrectangle        filled rectangle notehead
+dwhrectangle         double whole rectangle notehead
+righttriangle        open right triangle notehead
+fillrighttriangle    filled right triangle notehead
+dwhrighttriangle     double whole right triangle notehead
+urighttriangle       upside-down open right triangle notehead
+ufillrighttriangle   upside-down filled right triangle notehead
+udwhrighttriangle    upside-down double whole right triangle notehead
+semicircle           open semicircle notehead
+fillsemicircle       filled semicircle notehead
+dwhsemicircle        double whole semicircle notehead
+slashhead            open slash notehead
+fillslashhead        filled slash notehead
+dwhslashhead         double whole slash notehead
+blankhead            blank notehead
+</PRE>
+<H3>
+Rests
+</H3>
+<PRE>
+qwhrest     quadruple whole rest
+dwhrest     double whole rest
+1rest       whole rest
+2rest       half rest
+4rest       quarter rest
+8rest       eighth rest
+16rest      sixteenth rest
+32rest      thirty-second rest
+64rest      sixty-fourth rest
+128rest     128th rest
+256rest     256th rest
+</PRE>
+<H3>
+Pedal
+</H3>
+<PRE>
+begped      begin pedal mark
+endped      end pedal mark
+pedal       pedal up/down mark
+</PRE>
+<H3>
+Ornaments
+</H3>
+<PRE>
+tr          trill
+mor         mordent
+invmor      inverted mordent
+turn        turn
+invturn     inverted turn
+</PRE>
+<H3>
+Miscellaneous
+</H3>
+<PRE>
+ferm        fermata
+uferm       upside-down fermata
+acc_gt      accent like a greater-than sign
+acc_hat     accent like a &quot;hat&quot; or ^ (circumflex or &quot;up-arrow&quot;)
+acc_uhat    accent like an upside down hat
+leg         legato mark
+dot         dot
+wedge       wedge
+uwedge      upside-down wedge
+sign        sign for D. S.
+coda        coda mark
+upbow       up bow
+dnbow       down bow
+rr          &quot;railroad tracks&quot; or caesura (2 slanted lines sometimes put
+            at the top of a staff to indicate the end of a musical thought)
+measrpt     measure repeat
+copyright   C-in-circle copyright symbol
+dim         diminished
+halfdim     half diminished
+triangle    triangle
+</PRE>
+<BR>
+<IMG SRC="muschar.gif" ALT="music characters">
+<BR>
+<P>
+Any of these music character names can be prefixed by &quot;sm&quot; to indicate a
+smaller version of the character. For example, &quot;smup4n&quot; is a small quarter
+note, as might be used for a &quot;cue&quot; note.
+Small music characters are 0.65 times as big as regular characters.
+</P>
+<P>
+<A NAME="special">Various non-ASCII characters</A>
+can be included in text strings. If you have a non-United States keyboard
+which can produce characters listed in the table below
+from the &quot;Latin-1&quot; alphabet, you can simply type them into strings as
+you normally would. If you want a character that your keyboard does not
+support, you can put them in strings
+by using their names in a manner similar to the music characters.
+For example, you can include an 'a' with an acute accent on it in
+a string by using \(aacute), or an upside down question mark
+using \(questiondown). Many characters have shorthand names too.
+For example, \(a') is a shorter name for 'a' with an acute accent.
+The full names of the special characters and their shorthand names, if any,
+are given in the following table:
+<PRE>
+ full name   shorthand         full name   shorthand
+------------------------------------------------------
+exclamdown                   questiondown
+sterling                     yen
+cent                         quotedblbase
+quotedblleft    &#96;&#96;           quotedblright       &#180;&#180;
+guillemotleft   &lt;&lt;           guillemotright       &gt;&gt;
+guilsinglleft                guilsinglright
+dagger                       daggerdbl
+grave                        acute
+macron                       breve
+dotaccent                    dieresis
+ring                         cedilla
+hungarumlaut                 ogonek
+caron                        emdash
+AE                           ae
+ordfeminine                  ordmasculine
+Lslash          L/           lslash              l/
+Oslash          O/           oslash              o/
+OE                           oe
+dotlessi                     germandbls          ss
+Aacute          A&#180;           aacute              a&#180;
+Acircumflex     A^           acircumflex         a^
+Adieresis       A:           adieresis           a:
+Agrave          A&#96;           agrave              a&#96;
+Aring           Ao           aring               ao
+Atilde          A~           atilde              a~
+Ccedilla        C,           ccedilla            c,
+Eacute          E&#180;           eacute              e&#180;
+Ecircumflex     E^           ecircumflex         e^
+Edieresis       E:           edieresis           e:
+Egrave          E&#96;           egrave              e&#96;
+Iacute          I&#180;           iacute              i&#180;
+Icircumflex     I^           icircumflex         i^
+Idieresis       i:           idieresis           i:
+Igrave          I&#96;           igrave              i&#96;
+Ntilde          N~           ntilde              n~
+Oacute          O&#180;           oacute              o&#180;
+Ocircumflex     O^           ocircumflex         o^
+Odieresis       O:           odieresis           o:
+Ograve          O&#96;           ograve              o&#96;
+Otilde          O~           otilde              o~
+Scaron          Sv           scaron              sv
+Uacute          U&#180;           uacute              u&#180;
+Ucircumflex     U^           ucircumflex         u^
+Udieresis       U:           udieresis           u:
+Ugrave          U&#96;           ugrave              u&#96;
+Ydieresis       Y:           ydieresis           y:
+Zcaron          Zv           zcaron              Zv
+bullet
+</PRE>
+</P>
+<P>
+<A NAME="space">There is one additional special characters,</A>
+specified by \(space).
+This character appears as a normal space on output, but is not treated
+like a space when Mup is looking for word or syllable boundaries.
+The most common use for this is probably in
+<A HREF="lyrics.html">lyrics</A>
+when you want several words to be sung on a single note.
+Another use would be in cases where Mup would normally split up a long
+string between words in order to avoid running off the edge of a page,
+but you want to prevent that split.
+</P>
+<H2>
+Font and size changes
+</H2>
+<P>
+Strings can also contain special codes to indicate changes in font or size.
+The font codes begin with \f, and
+can either be spelled out, as in the first column of
+the table below, or as the abbreviations given in the second column.
+<PRE>
+       Code              Abbr        Meaning
+
+\f(avantgarde rom)      \f(AR)  Avant Garde roman font
+\f(avantgarde bold)     \f(AB)  Avant Garde bold font
+\f(avantgarde ital)     \f(AI)  Avant Garde italic font
+\f(avantgarde boldital) \f(AX)  Avant Garde bold-italic font
+
+\f(bookman rom)         \f(BR)  Bookman roman font
+\f(bookman bold)        \f(BB)  Bookman bold font
+\f(bookman ital)        \f(BI)  Bookman italic font
+\f(bookman boldital)    \f(BX)  Bookman bold-italic font
+
+\f(courier rom)         \f(CR)  Courier roman font
+\f(courier bold)        \f(CB)  Courier bold font
+\f(courier ital)        \f(CI)  Courier italic font
+\f(courier boldital)    \f(CX)  Courier bold-italic font
+
+\f(helvetica rom)       \f(HR)  Helvetica* roman font
+\f(helvetica bold)      \f(HB)  Helvetica bold font
+\f(helvetica ital)      \f(HI)  Helvetica italic font
+\f(helvetica boldital)  \f(HX)  Helvetica bold-italic font
+
+\f(newcentury rom)      \f(NR)  New Century roman font
+\f(newcentury bold)     \f(NB)  New Century bold font
+\f(newcentury ital)     \f(NI)  New Century italic font
+\f(newcentury boldital) \f(NX)  New Century bold-italic
+
+\f(palatino rom)        \f(PR)  Palatino roman font
+\f(palatino bold)       \f(PB)  Palatino bold font
+\f(palatino ital)       \f(PI)  Palatino italic font
+\f(palatino boldital)   \f(PX)  Palatino bold-italic font
+
+\f(times rom)           \f(TR)  Times* roman font
+\f(times bold)          \f(TB)  Times bold font
+\f(times ital)          \f(TI)  Times italic font
+\f(times boldital)      \f(TX)  Times bold-italic font
+
+\f(previous)            \f(PV)  previous font
+</PRE>
+Some of the
+<A HREF="textstr.html#special">special characters</A>
+look better in some fonts than others.  We have found that
+some PostScript interpreters unfortunately don't always
+implement all the special characters in all fonts.
+</P>
+<P>
+If you need a font other than those Mup supports directly,
+it is possible to override Mup's builtin fonts with other fonts.
+This is described later in the
+<A HREF="fontfile.html">section on "Installing other fonts."</A>
+</P>
+<P>
+<A NAME="size">The point size can also be changed. (A "point" is about 1/72 of an inch.)</A>
+<PRE>
+   Code                   Meaning
+
+\s(<I>N)</I>    change to point size <I>N</I>
+\s(+<I>N)</I>   increase point size by <I>N</I> points
+\s(-<I>N)</I>   decrease point size by <I>N</I> points
+\s(PV) or \s(previous) revert to previous size
+
+</PRE>
+The point size can range from 1 to 100. A font or size change will last until
+changed or until the end of the string. Any subsequent strings will begin
+with default font and size values, except in the case of
+<A HREF="lyrics.html">lyrics,</A>
+where font and size information is maintained separately
+for each staff and verse, and carried forward from measure to measure, and
+<A HREF="bars.html#reh">rehearsal marks,</A>
+where the information is also carried forward.
+The default values can be set as
+<A HREF="param.html">described in the "Parameters" section. The</A>
+<A HREF="textstr.html#symlist">music symbols</A>
+are affected by size changes.
+If a music symbol follows italics or bolditalics characters, it will be
+made italics to match.
+</P>
+<P>
+Here are some examples of strings:
+<BR><PRE>
+&quot;hello&quot;
+&quot;( \(up2n) = 100 )&quot;
+&quot;\f(TB)this will be bold. \f(TI)this will be italics&quot;
+&quot;A \f(TX)\s(+12)BIG\f(PV)\s(-12) word&quot;
+&quot;\f(newcentury boldital)Allegro&quot;
+</PRE><BR>
+</P>
+<H2>
+Horizontal and vertical motion
+</H2>
+<P>
+It is also possible to specify a string that takes up more than one line,
+by putting a &quot;\n&quot; where you want to move to a new line. The place where
+this is most likely to be useful is for
+<A HREF="param.html#label">staff labels,</A>
+which you may want
+to make multi-line, to keep them from becoming excessively wide.
+For example:
+<BR><PRE>
+&quot;Violins\nI&amp;II&quot;
+</PRE><BR>
+</P>
+<P>
+A &quot;\b&quot; can be used to specify a backspace. This might be useful for
+adding underlines to text.
+If you wish to use letters with diacritical marks,
+you will probably want to use the
+<A HREF="textstr.html#special">special characters,</A>
+described earlier in this section,
+rather than trying to construct them using the plain letter,
+a backspace, and the mark.
+</P>
+<P>
+You are not allowed to back up to before the beginning of a line.
+Note that in all fonts except Courier,
+different characters have different widths, so
+using backspaces can be a bit tricky. For example, underlining a 5-letter
+word might require more than 5 underscores, if the characters in the word
+are wider than an underscore character. In general, it works better to
+enter an entire string, then backspace to add underscoring or accents, rather
+than doing them along the way. For example, &quot;My\b\b___&quot; will line up
+much better than &quot;M\b_y\b_&quot;.
+</P>
+<P>
+<A NAME="vert">Vertical motion within a string</A>
+can be specified using &quot;\v(<I>N</I>)&quot;
+where <I>N</I> is some percentage of the current font height.
+The distance may be negative for downward motion
+or positive for upward motion, ranging from -100 to 100.
+This might be used for creating superscripts and subscripts, although
+the next section describes an alternate way of doing that which is
+usually better. It might also be used just to line something up differently
+than Mup normally would.
+You cannot put newlines (with \n) in the same string with vertical
+motion.
+</P>
+<H2>
+Piled text, for superscripts, subscripts, etc.
+</H2>
+<P>
+It is also possible to &quot;pile up&quot; lines of text in a string.
+Some common uses of this could be for superscripts and subscripts or for
+figured bass notation.
+Some facilities to specifically deal with
+<A HREF="textmark.html#chordmod">figured bass</A>
+will be described in a later section, but
+here we describe the general-purpose constructs for piling text. 
+A \: is used to indicate the beginning of piling. Any subsequent
+instances of \: in the same string will alternately turn piling off and on.
+When a pile is begun, the text size is automatically made smaller, and
+the text baseline is moved up, so that the first line of piled text is
+like a superscript, and the next like a subscript. If there are additional
+lines, they are placed below the subscript.
+By default, the lines in a pile are placed such that the last digit
+in each line all line up, or if there is no digit, the last character.
+However, you can force different alignment.
+A \| will force alignment at that point, or a \^ will force alignment
+at the center of the following character. A maximum of one alignment marker
+can be specified on each line of a pile.
+You cannot put newlines (with \n) in the same string with piling.
+A new line of the pile is started at each &lt;space&gt; character in the input string.
+If you want an actual literal space inside a piled line, it must be
+preceded with a backslash. As an example:
+<BR><PRE>
+&quot;Text\:superscript subscript\: back to normal.&quot;;
+&quot;This pile \:has\ literal spaces\ in\ it.&quot;;
+&quot;This pile \:h\^as align\|ment spec\^ified.&quot;;
+</PRE><BR>
+<IMG SRC="mugex65.gif" ALT="Picture of Mup output"><BR>
+</P>
+<H2>
+Slash through number
+</H2>
+<P>
+Another thing which is common in figured bass notation
+is to draw a slash through a number. Again, the section on
+<A HREF="textmark.html#chordmod">figured bass</A>
+will describe how to do that inside figured bass,
+but it is possible to put a slash through a number elsewhere by
+placing a backslashed slash after a number, like this:
+<BR><PRE>
+       &quot;6\/&quot;
+       &quot;10\/&quot;
+</PRE><BR>
+</P>
+<H2>
+Boxed or circled text
+</H2>
+<P>
+<A NAME="boxed">You can cause the text to be</A>
+printed inside a box by placing a \[ at
+the beginning of the string and a \] at the end of the string.
+Similarly you can cause text to be placed inside a circle (or ellipse
+for strings that are wide) by placing a \{ at
+the beginning of the string and a \} at the end of the string.
+Boxed or circled text are not allowed in
+<A HREF="lyrics.html">lyrics.</A>
+<BR><PRE>
+ &quot;\[This is in a box\]&quot;
+ &quot;\{This is in an ellipse\}&quot;
+</PRE><BR>
+<IMG SRC="mugex66.gif" ALT="Picture of Mup output"><BR>
+<HR>
+* Times is a trademark and Helvetica is a registered trademark of Allied Corporation.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="shaped.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="stuff.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/trnspose.html b/mup/docs/uguide/trnspose.html
new file mode 100644 (file)
index 0000000..5d23ebd
--- /dev/null
@@ -0,0 +1,139 @@
+<HTML>
+<HEAD><TITLE>
+Transposition
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="cadenza.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="verses.html">next page --&gt;</A>
+</P>
+           
+<H2>
+Transposition
+</H2>
+<P>
+The
+<A HREF="param.html#xpose">transpose</A>
+and
+<A HREF="param.html#addxpose">addtranspose</A>
+parameters
+can be used to transpose the pitches for a staff or the whole score.
+The following table shows what transposition values to use for different
+intervals.
+<TABLE BORDER=4>
+<TR>
+<TD><B>halfsteps</B></TD>      <TD><B>tranposition</B></TD>    <TD><B>alternate transposition</B></TD>
+</TR>
+<TR>
+<TD>0</TD>     <TD>perfect 1</TD>      <TD>diminished 2</TD>
+</TR>
+<TR>
+<TD>1</TD>     <TD>augmented 1</TD>    <TD>minor 2</TD>
+</TR>
+<TR>
+<TD>2</TD>     <TD>major 2</TD>        <TD>diminished 3</TD>
+</TR>
+<TR>
+<TD>3</TD>     <TD>augmented 2</TD>    <TD>minor 3</TD>
+</TR>
+<TR>
+<TD>4</TD>     <TD>major 3</TD>        <TD>diminished 4</TD>
+</TR>
+<TR>
+<TD>5</TD>     <TD>augmented 3</TD>    <TD>perfect 4</TD>
+</TR>
+<TR>
+<TD>6</TD>     <TD>augmented 4</TD>    <TD>diminished 5</TD>
+</TR>
+<TR>
+<TD>7</TD>     <TD>perfect 5</TD>      <TD>diminished 6</TD>
+</TR>
+<TR>
+<TD>8</TD>     <TD>augmented 5</TD>    <TD>minor 6</TD>
+</TR>
+<TR>
+<TD>9</TD>     <TD>major 6</TD>        <TD>diminished 7</TD>
+</TR>
+<TR>
+<TD>10</TD>    <TD>augmented 6</TD>    <TD>minor 7</TD>
+</TR>
+<TR>
+<TD>11</TD>    <TD>major 7</TD>        <TD>diminished 8</TD>
+</TR>
+</TABLE>
+
+</P>
+<P>
+This table continues in a similar way for intervals beyond an octave.
+For each number of halfsteps you want to transpose, there
+is more than one way the
+<A HREF="param.html#xpose">transpose</A>
+and
+<A HREF="param.html#addxpose">addtranspose</A>
+parameters can be
+specified, as shown by this table.  This allows to you control
+whether a sharp key or a flat key is to be used in cases where there is
+a choice.  For example, if the key signature has three sharps, and you
+want to transpose up two halfsteps, you could say either
+<BR><PRE>
+       transpose = up maj 2
+</PRE><BR>
+or
+<BR><PRE>
+       transpose = up dim 3
+</PRE><BR>
+The first will result in a key of five sharps, and the second will
+result in seven flats.  These are equivalent keys; in major for
+example, they are B and C flat, which are the same note.  It is up to
+you to choose the way you would like it to be printed.
+But no key is allowed to have more than seven sharps or flats, so in
+most cases only one of the ways will result in a valid key, and the
+other way will result in an error message.
+</P>
+<P>
+The transpose and addtranspose parameters are allowed
+in score and staff contexts, so they can
+be set to different values on different staffs, and on the score as a whole.
+This is useful for printing scores where some of the instruments are
+transposing instruments (like B-flat clarinet).
+You can set the transpose parameter on specific staffs to appropriate
+values for the transposing instruments. Then if you decide you want to
+move the entire score to a new key, you can set the addtranspose parameter
+in score context.
+You can enter all the music at true pitch, but print the score and/or
+the individual parts with the correct transposition.
+</P>
+<P>
+Another use for setting different transposition values is the following
+trick, useful in guitar music for printing both the real chords and chords
+for capo.
+Say, for example, you have a song that is in B flat, but the guitar is
+to use a capo on the third fret, and play in the key of G.
+You could define the following macro to print both versions of a chord,
+the capo version above the real version:
+<BR><PRE>
+define CHORD(COUNT, NAME)
+
+       bold chord all: COUNT `NAME`;     // chord for capo
+       ital(8) chord 1: COUNT `NAME`;    // real chord
+@
+</PRE><BR>
+Then, set these transpositions:
+<BR><PRE>
+score   transpose = down minor 3       // transpose score for capo
+staff 1 transpose = up perfect 1       // override score transposition
+</PRE><BR>
+and similarly for any other staffs.
+Then, wherever you want to print a chord, say (for example)
+<BR><PRE>
+CHORD(3,Dm)
+</PRE><BR>
+This will print both versions of the chord above count 3 of the measure.
+For the top chord it will transpose this to Bm, the capo chord.
+For the bottom chord it will leave it as Dm, the real chord.
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="cadenza.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="verses.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/tuplets.html b/mup/docs/uguide/tuplets.html
new file mode 100644 (file)
index 0000000..bfe8819
--- /dev/null
@@ -0,0 +1,98 @@
+<HTML>
+<HEAD><TITLE>
+Tuplets
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="ichdattr.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="altinp.html">next page --&gt;</A>
+</P>
+           
+<H3>
+Tuplets
+</H3>
+<P>
+Tuplets are specified by giving a list of chords within curly braces.
+The ending brace is optionally followed by a side (&quot;above&quot; or &quot;below&quot;).
+This is followed by a number or pair of numbers, and a semicolon.
+</P>
+<P>
+The &quot;side&quot; tells Mup whether to print the tuplet number and bracket above
+or below the chords. It only applies on voice 1 or 2
+when the other voice (1 or 2) is nonexistent or a space.
+If there are at least two voices, the number and bracket
+will always be put above on voice 1 and below on voice 2.
+You can always force the side on voice 3.
+If you don't specify a side for a tuplet,
+Mup will choose the side that seems best.
+</P>
+<P>
+The first number is the number that should be printed with the tuplet.
+If it is followed by an &quot;n&quot; the number (and bracket) will not actually be
+printed.
+If it is followed by a &quot;y&quot; the number and bracket will always be printed,
+unless there is only a single chord in the tuplet, in which case only
+the number will be printed.
+If it is followed by &quot;num&quot; the number will always be printed,
+but the bracket will never be printed.
+If none of those modifiers are are specified,
+the number will always be printed, but
+the bracket will be omitted in cases where all the notes in the tuplet
+are beamed together and the beam does not include any notes not in the tuplet.
+</P>
+<P>
+The second number, if any, is separated from the first by a comma,
+and tells the time unit that the tuplet is to
+take up. This number can be dotted if necessary.
+It can also be a time expression, like 2+8,
+although that is very rarely likely to be useful.
+If no second number is given, the default is to fit in the next shorter
+un-dotted note. For example, three eighth notes would be fitted into
+the time of a quarter note, or five eighth notes would be fitted into the
+time of a half note.
+</P>
+<P>
+Occasionally in music, as a shorthand,
+a single note or chord is printed with a tuplet number to
+indicate the note or chord is to be repeated several times as a tuplet.
+Mup will allow this; simply use a tuplet with only one chord, and add
+one or more
+<A HREF="chrdattr.html#slashes">slashes.</A>
+</P>
+<P>
+Here are some examples of tuplets:
+<BR><PRE>
+// This has a triplet, where 3 eighth
+// notes take as much time as a
+// normal quarter note.
+1: { 8ce; df; eg;}3; 4fa;
+bar
+
+// This has a dublet, in which 2 quarter notes
+// take the time of a normal dotted quarter
+1: { 4f; g; } 2, 4.;8a;
+bar
+
+// A quarter note and eighth note that
+// make up a triplet the length of a
+// normal quarter note,
+// with the 3 printed above the notes
+1: { 4c+; 8b; } above 3; 4c+;
+bar
+
+// A septuplet in the time of a half note
+// with the &quot;7&quot; printed below the notes
+1: { 8c; b-; c; e; d; f; a; } below 7;
+bar
+
+// single chord tuplet
+1:  { [slash 1] 4.ceg;}3; 4;
+bar
+</PRE><BR>
+<IMG SRC="mugex30.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="ichdattr.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="altinp.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/utilpgms.html b/mup/docs/uguide/utilpgms.html
new file mode 100644 (file)
index 0000000..7175d02
--- /dev/null
@@ -0,0 +1,112 @@
+<HTML>
+<HEAD><TITLE>
+Mup Utilities for displaying and printing output
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="cmdargs.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="gensyn.html">next page --&gt;</A>
+</P>
+           
+<H2>
+Mupdisp and Mupprnt utility programs
+</H2>
+<P>
+If you are using Ghostscript, but prefer to not use Mupmate,
+there are two utility programs included with
+Mup for displaying and printing music.
+<BR><PRE>
+mupdisp <I>Mup_options myfile</I>
+</PRE><BR>
+will display music to your screen, while
+<BR><PRE>
+mupprnt <I>Mup_options myfile</I>
+</PRE><BR>
+will print the output to your printer.
+See the installation instructions for more details on configuring the
+Mupprnt program for your printer.
+</P>
+<P>
+The <I>Mup_options</I> can be any of the options listed in the
+section on
+<A HREF="cmdargs.html">"Command line arguments"</A>
+except -C, -E, -f, -F, -m, -M, -r, or -v, which don't
+send PostScript output to the standard output.
+</P>
+<P>
+The Mupdisp program allows you to view pages in any order, with either a
+version small enough to fit on your screen or a near-actual-size version
+that you can scroll if it doesn't fit on your screen.
+Mupdisp will run under MS-DOS/Windows or will run under
+UNIX with TERM of AT386, linux, or xterm (under X windows). 
+</P>
+<P>
+Mupdisp begins in partial page mode,
+which displays output at approximately actual size (depending
+on the size of your monitor). In this mode, it is possible that
+not all of the page fits on the
+screen, so the scrolling commands can be used to move up and down to view
+different parts of the page. In full page mode, a small version of the
+entire page is displayed.  This is useful
+for seeing overall page layout, but is generally too small to see much detail.
+This mode is now somewhat of a relic of the days when screens were typically
+much smaller than they are today, and is thus becoming less useful.
+</P>
+<P>
+Once the music has been drawn on the screen, you can enter various commands
+to view different pages or parts of the current page.
+The commands are:
+<DL>
+<DT><I>num</I> &lt;Enter&gt;
+<DD>
+Go to page number <I>num</I>.
+<DT>+ or &lt;space&gt; or &lt;control-E&gt; or &lt;control-F&gt;
+<DD>
+move forward on the page by about 1/8 of an inch
+(partial page mode only)
+<DT>- or &lt;backspace&gt; or &lt;control-Y&gt; or &lt;control-B&gt;
+<DD>
+move backward on the page by about 1/8 of an inch
+(partial page mode only)
+<DT>b or &lt;control-U&gt; or &lt;control-P&gt;
+<DD>
+move backward on the page by about an inch
+(partial page mode only)
+<DT>f or &lt;Enter&gt; or &lt;control-D&gt; or &lt;control-N&gt;
+<DD>
+move forward on the page by about an inch
+(partial page mode only)
+<DT>h or ?
+<DD>
+display help screen
+<DT>m
+<DD>
+toggle between partial page and full page modes.
+<DT>n
+<DD>
+go to next page
+<DT>p
+<DD>
+go to previous page
+<DT>q or ZZ
+<DD>
+quit
+<DT>r
+<DD>
+Repaint the page (useful for exiting help page)
+</DL>
+</P>
+<P>
+When in X windows, the mouse can be used for scrolling. The left button scrolls
+downward like the f command, while the right button scrolls backwards like
+the b command.
+<HR>
+UNIX is a registered trademark of X/Open Company Limited
+<BR>
+MS-DOS and Windows are registered trademarks of Microsoft Corporation
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="cmdargs.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="gensyn.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/uguide/verses.html b/mup/docs/uguide/verses.html
new file mode 100644 (file)
index 0000000..2e571d1
--- /dev/null
@@ -0,0 +1,73 @@
+<HTML>
+<HEAD><TITLE>
+Placing verses below the scores
+</TITLE></HEAD>
+<BODY>
+<P>
+&nbsp;&nbsp;&nbsp;<A HREF="trnspose.html">&lt;-- previous page</A>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="pianored.html">next page --&gt;</A>
+</P>
+         
+<H2>
+Placing verses below the scores
+</H2>
+<P>
+Sometimes, particularly with songs that have a lot of verses,
+you may want to put some verses of lyrics as blocks of
+text below the music. Probably the easiest way to do this
+is using &quot;print&quot; or &quot;paragraph&quot; statements inside
+<A HREF="prnttext.html#block">a "block."</A>
+<BR><PRE>
+block
+print (_win.w + 30, _win.n - 15) &quot;2.   &quot;
+print &quot;\
+Here is the first line
+and the second line
+and the third line.
+&quot;
+print (_win.w + 90, _win.n - 15) &quot;3.   &quot;
+print &quot;\
+Here is another verse's first line
+and its second line
+and its third line.
+&quot;
+</PRE><BR>
+</P>
+<P>
+You may need to use a little trial-and-error to determine the
+coordinates to use on the print statements,
+but you only have to determine one coordinate per verse,
+and with a bit of practice it gets easier to find the right values.
+Since the &quot;print&quot; statement is being used, the font and size will be
+determined by the
+<A HREF="param.html#size">size parameter</A>
+and
+<A HREF="param.html#font">font parameter,</A>
+rather than by
+<A HREF="param.html#lyrsize">lyricssize</A>
+and
+<A HREF="param.html#lyrfont">lyricsfont.</A>
+</P>
+<P>
+If you also want chords symbols with these verses,
+you can do that too. It is easiest if you use Courier font,
+as shown in the example below, since its constant-width characters
+make it easy to line things up. If you use a proportional-width font,
+you will have to determine how to place the chords by trial and error.
+<BR><PRE>
+print (_win.w + 50, _win.n - 35) &quot;3.   &quot;
+print &quot;\f(CR)\
+C            D7    G7
+This is the first line
+C       F
+of the next verse
+B\(smflat)
+of the song.
+&quot;
+</PRE><BR>
+</P>
+<HR><P>
+&nbsp;&nbsp;&nbsp;<A HREF="trnspose.html">&lt;-- previous page</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Table of Contents</A>&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="pianored.html">next page --&gt;</A>
+</P>
+</BODY></HTML>
diff --git a/mup/docs/whatsnew.html b/mup/docs/whatsnew.html
new file mode 100644 (file)
index 0000000..f86b101
--- /dev/null
@@ -0,0 +1,700 @@
+<HTML>
+<HEAD>
+<TITLE>New Mup Features</TITLE>
+</HEAD>
+<BODY>
+<H1>New Mup Features</H1>
+<H2>New Features in Mup Version 5.3</H2>
+<P>
+Version 5.3 is primarily focused on ease of use enhancements.
+The largest item is the additional of a companion program, called Mupmate,
+that provides an interface for editing, displaying, and playing Mup files
+with the kinds of menus and windows that many people are used to. 
+The Help menu will take you right to the
+<A HREF="uguide/index.html">Mup User's Guide,</A>
+which has also had improvements made.
+If you are a user who prefers the command line interface that Mup
+has always had, don't worry; we like to use that too,
+and have no intention of dropping support for it.
+</P>
+<P>
+Windows users now only need to
+<A HREF="obtain.html#windows">download a single file</A>
+and execute it to
+install everything (although you still need to get and install GSview and
+Ghostscript separately, if you want to use that for viewing the PostScript
+files). Other users can also just download a single file that contains
+both program and documentation.
+</P>
+<P>
+Other new features in 5.3 include:
+<UL>
+<LI>
+Error and warning messages have been enhanced to show you the text
+of the line of input where the problem was found.
+<LI>
+There is a new
+<A HREF="uguide/param.html#pgsize">pagesize parameter</A>
+that lets you specify paper size by common names like letter or a4,
+as an alternate to specifying
+<A HREF="uguide/param.html#pgheight">pageheight</A> and
+<A HREF="uguide/param.html#pgheight">pagewidth</A> in
+<A HREF="uguide/param.html#units">inches or cm.</A>
+<LI>
+There is a new
+<A HREF="uguide/param.html#vcombine">vcombine parameter,</A> that lets
+you enter notes on separate voices, yet have them printed on a common stem
+when possible. Typical uses are:
+<UL>
+<LI>
+To have separate
+<A HREF="uguide/midi.html">MIDI</A> tracks for different voices, yet have the
+voices printed on common stems.
+<LI>
+For a style of printing where a single
+stem is used for the two voices on a staff except when the voices share a
+common note, when two opposing stems are printed.
+</UL>
+<LI>
+The
+<A HREF="uguide/param.html#scorepad">scorepad parameter</A> now accepts an
+optional maximum value, in addition to the minimum value.
+</UL>
+</P>
+<H2>New Features in Mup Version 5.2</H2>
+<P>
+<UL>
+<LI>
+There is now a 
+<A HREF="uguide/ifclause.html">generalized 'if' clause'</A> that is
+much more flexible and powerful than the simple
+<A HREF="uguide/macros.html">ifdef and ifndef.</A>
+These provide capabilities somewhat similar to the preprocessors for
+the C and C++ languages.
+<LI>
+Complicated
+<A HREF="uguide/param.html#time">time signatures</A> are now supported.
+This includes a numerator with two or more numbers added together,
+like 3+4 / 4, or two or more fractions added together, like 3/4 + 3/8.
+Alternating time signatures, such as when a piece continuously
+switches between 3/4 and 6/8, are also supported.
+<LI>
+The
+<A HREF="uguide/param.html#beamstyl">beamstyle</A>
+and
+<A HREF="uguide/param.html#timeunit">timeunit</A>
+parameter values associated with a
+<A HREF="uguide/param.html#time">time signature</A>
+are now remembered, so that if you later change back to the same time signature,
+you don't have to also set the beamstyle and timeunit at the same time;
+the value used previously for that time signature will be
+restored automatically.
+(Note that if you have existing Mup files that rely on the old behavior,
+they may need small modifications, but that should be rare.)
+<LI>
+It is now possible to
+<A HREF="uguide/chrdattr.html#stemdir">force stem direction</A>on voices 1 and 2
+even when the other voice is not space.
+<LI>
+Improvements have been made to how the
+angle for beams is calculated.
+The &quot;best&quot; angle for a beam is sometimes somewhat subjective,
+but in general, these changes will result in more
+cases where beams are horizontal or less sloped,
+<LI>
+There are also additional ways you can control beams:
+A new
+<A HREF="uguide/ichdattr.html#slope">slope interchord attribute</A>
+lets you force a specific slope.
+The new
+<A HREF="uguide/param.html#sshorten">stemshorten parameter</A>
+lets you determine how much a chord's stem
+is allowed to be shortened when it is beamed.
+And the existing
+<A HREF="uguide/chrdattr.html#stemlen">len chord attribute</A>
+can now be set for
+just one end of a beamed set of chords as an alternative to
+setting it at both ends.
+<LI>
+<A HREF="uguide/index.html">The HTML version of the Mup User's Guide</A>
+now includes 'next page' and 'previous page' links on each page.
+</UL>
+</P>
+<H2>New Features in Mup Version 5.1</H2>
+<P>
+<UL>
+<LI>
+You may specify <A HREF="uguide/chordinp.html#duration">a time value that is the
+summation of several time values.</A> This can be used to obtain
+<A HREF="uguide/param.html#beamstyl">beaming</A>,
+<A HREF="uguide/lyrics.html">lyrics</A>, or
+<A HREF="uguide/tuplets.html">tuplets</A> with durations that
+cannot be represented with a single time value, like a half note plus
+an eighth note. It also gives an alternate way to specify
+<A HREF="uguide/ichdattr.html#tie">chord ties.</A>
+<LI>
+<A HREF="uguide/crossst.html">Cross-staff stems</A> are now supported.
+<LI>
+You can now explicitly specify a direction of &quot;up&quot; on
+<A HREF="uguide/roll.html">rolls</A> to get an upward arrow drawn at the
+top of the roll. (Before, only a downward roll would get an arrow.)
+<LI>
+Mup will now allow you to
+<A HREF="uguide/param.html#beamstyl">beam across spaces</A> as well
+as rests.
+<LI>
+There is a new
+<A HREF="uguide/param.html#restsymm">restsymmult parameter.</A>
+Setting it to y will cause Mup to use an alternate style for
+multirests of eight measures or less, which uses rest symbols.
+<LI>
+There is a new string sequence that will be replaced by
+<A HREF="uguide/headfoot.html#pagenum">the page number of the last page.</A>
+This may useful to be able to automatically get output
+like &quot;Page 2 of 4 pages.&quot;
+<LI>
+There is a new option for printing of
+<A HREF="uguide/tuplets.html">tuplet</A> numbers,
+where the number is always printed, but the bracket is never printed.
+<LI>
+If you want to have the same
+<A HREF="uguide/lyrics.html">lyrics</A>
+above some staffs and below others,
+it is now possible to specify that on a single input line,
+rather than requiring two.
+<LI>
+Improvements have been made to how voice 3 is placed,
+which will often eliminate the need to manually specify a
+<A HREF="uguide/chrdattr.html#hoffset">horizontal offset.</A>
+</UL>
+</P>
+<H2>New Features in Mup Version 5.0</H2>
+<P>
+<UL>
+<LI>
+Mup now supports the
+<A HREF="uguide/shaped.html">shaped notes</A>
+often used in &quot;Sacred
+Harp&quot; music, also sometimes called &quot;fasola&quot; notation.
+New note head characters are available for the most common system of 4 shapes,
+as well as a system with 7 shapes.
+As part of this feature, there is a new
+<A HREF="uguide/shaped.html#hdshape">headshape context</A>
+and a new
+<A HREF="uguide/param.html#notehead">noteheads parameter</A>
+that lets you define what shapes will be used for notes.
+<LI>
+Note head shapes can also be specified on
+<A HREF="uguide/shaped.html#chord">specific chords</A>
+or
+<A HREF="uguide/shaped.html#note">a specific note within a chord.</A>
+This makes it possible to do things like have both normal
+and X-shaped notes on the same stem.
+<LI>
+There are new &quot;slash&quot;
+<A HREF="uguide/shaped.html">note heads,</A>
+often used to indicate
+repeated chords, and a new &quot;blankhead&quot; note head, that can be
+used if you just want a stem without any note head.
+<LI>
+There is a new
+<A HREF="uguide/param.html#stemlen">stemlen parameter</A>
+that lets you set the default stem length. A common use for this would
+be to set this parameter to 0.0,
+to not have any stems at all (sometimes used for chant).
+<LI>
+It is now possible to change the
+<A HREF="uguide/param.html#clef">clef,</A>
+<A HREF="uguide/param.html#defoct">defoct,</A>
+and
+<A HREF="uguide/param.html#release">release</A>
+parameters in the
+<A HREF="uguide/midmeas.html">middle of a measure.</A>
+<LI>
+You can now include
+<A HREF="uguide/prnttext.html#postscript">raw PostScript</A>
+in the input to the copied to the output. This could be used,
+for example, to include a picture or logo with your music.
+<LI>
+In addition to the old way of specifying
+<A HREF="uguide/param.html#key">key signature,</A>
+by stating the number of sharps or flats,
+it is now possible to specify the key by name, as in &quot;a major&quot;
+or &quot;c# minor.&quot;
+<LI>
+There is a new
+<A HREF="uguide/param.html#swing">swingunit parameter.</A>
+Some styles of music are often written with straight eighth notes
+or dotted-eighth-sixteeen notations, but where the players &quot;know&quot;
+that the composer really wants the music played
+with the first note in each pair twice as long as the second,
+as if it were a quarter-eighth triplet.
+This parameter will make Mup's MIDI output automatically follow that kind of
+performance convention.
+<LI>
+It is possible to
+<A HREF="uguide/bars.html#setreh">set the rehearsal letter or number</A>
+to a specific value, to override the automatic incrementing.
+This might be especially useful when there are multiple songs or movements
+in a single Mup file.
+</UL>
+</P>
+<H2>New Features in Mup Version 4.6</H2>
+<P>
+<UL>
+<LI>
+There are new
+<A HREF="uguide/headfoot.html">top, bottom, top2, and bottom2 contexts</A>
+that let you define a second layer of headers and footers. These new
+contexts can be changed multiple times in a file, so you can use different
+headings and footing for different songs or movements within a file.
+<LI>
+There is a new
+<A HREF="uguide/prnttext.html#block">&quot;block&quot; context,</A>
+that lets you place blocks of text in your musical scores.
+<LI>
+There is a new
+<A HREF="uguide/prnttext.html#paragrph">paragraph</A> command for printing
+long sections of text that you would like to have automatically wrapped
+around unto as many lines as needed. The right margin can be justified
+or ragged.
+<LI>
+For Linux, in addition to being available in tar.gz format, Mup files are now
+<A HREF="obtain.html#linux">available in rpm package format,</A>
+for very quick-and-easy installation.  The
+MS-DOS/Windows Mup files are now available as
+<A HREF="obtain.html#windows">self-extracting zip files,</A>
+so you don't need to have
+an unzip program to unpack them.
+<LI>
+The
+<A HREF="uguide/param.html#visible">visible parameter</A>
+now accepts a value of &quot;whereused.&quot;
+With this value, when a staff has no notes on an entire score,
+that staff is not printed. This might be used, for example,
+to save paper on an orchestral score by only printing staffs for
+instruments when they are actually playing.
+<LI>
+There are new parameters
+<A HREF="uguide/param.html#mnumfont">measnumfont,</A>
+<A HREF="uguide/param.html#mnumfam">measnumfontfamily,</A>
+and
+<A HREF="uguide/param.html#mnumsize">measnumsize,</A>
+to control the appearance of
+<A HREF="uguide/param.html#measnum">automatic measure numbers.</A>
+<LI>
+It is now possible to
+<A HREF="uguide/param.html">unset parameters</A>
+in voice or staff context, to make them revert to their values
+in the next more general context where they are set (staff or score).
+<LI>
+When a repeatstart gets moved to the beginning of a score, sometimes
+you'd like the bar line at the end of the previous score to be a double
+bar rather than single bar. It is now possible to
+<A HREF="uguide/bars.html">specify that.</A>
+<LI>
+There is a new
+<A HREF="uguide/cmdargs.html#Foption">-F option</A>
+that is like the -f option, except it derives the name of the output
+file based on the name of the input file, rather than you needing to
+specify an output file name.
+<LI>
+The Mup input file name is given in the PostScript output file,
+so that PostScript viewer programs like gv can use it in their window title.
+<LI>
+There is now a
+<A HREF="maillist.html">majordomo mailing list available for
+registered Mup users.</A> This is a forum for talking with other Mup users,
+to discuss questions and tips on using Mup.
+</UL>
+</P>
+<H2>New Features in Mup Version 4.5</H2>
+<P>
+<UL>
+<LI>
+There is a new
+<A HREF="uguide/cmdargs.html#xoption">-x option</A>
+that lets you extract a portion of a song. This can be
+especially useful for MIDI, where you might want
+to listen to just a few measures
+in the middle or end of a piece. But it also works in printing mode,
+so you can print just an excerpt of a piece.
+<LI>
+It is now possible to specify &quot;subbeams,&quot; both with
+<A HREF="uguide/ichdattr.html#custbeam">custom beaming</A> and via the
+<A HREF="uguide/param.html#beamstyl">beamstyle parameter.</A>
+This can be used when there are a lot of very short notes,
+and you want to subdivide the beam groupings.
+<LI>
+The drawing of phrase marks, ties, and slurs has been re-implemented to
+produce more aesthetically pleasing curves.
+<LI>
+There is a new special character,
+<A HREF="uguide/textstr.html#space">called \(space),</A>
+which is printed like
+a normal space on output, but which is not treated like a space when Mup is
+looking for word or syllable boundaries. The most common use for this would
+probably be on
+<A HREF="uguide/lyrics.html">chant lyrics,</A>
+where you want several words to be sung to the same note.
+It might also be useful in cases where Mup would normally split a long
+string at a word boundary to avoid running off the edge of a page,
+but for some reason you want to prevent that splitting.
+<LI>
+It is possible to
+<A HREF="uguide/linecurv.html">print a text string centered above a line.</A>
+This is likely to be the most useful for printing &quot;gliss.&quot; by a wavy
+line for a glissando, but it can be used on any kind of line.
+<LI>
+There are some new <a HREF="userpgms.html">user-donated files,</A>
+including a Windows installer, and Mup syntax files for nedit and vim.
+</UL>
+</P>
+<H2>New Features in Mup Version 4.4</H2>
+<P>
+<UL>
+<LI>
+Many of the changes in this release were to make Mup conform more closely with
+established guidelines or rules for musical notation.
+This mainly involved small adjustments to cosmetic details, like
+how accidentals and dots are placed.
+For mid-score clef changes, the clef is now placed before the barline,
+as it should be, rather than after.
+There is also an improved algorithm for determining where to
+end the underscores on lyrics.
+<LI>
+The use of labels, both
+<A HREF="uguide/param.html#label">labels associated with individual staffs</A>
+and labels associated with staffs grouped by
+<A HREF="uguide/param.html#brace">braces</A> or
+<A HREF="uguide/param.html#bracket">brackets</A>,
+has been made more flexible.
+It used to be that the &quot;label&quot; was only used on
+the very first score, with &quot;label2&quot; used on all subsequent scores.
+Thus resetting label after the beginning really had no effect.
+Now, however, whenever a new label is specified, that label will be used for the
+next score, going back to label2 for subsequent scores.
+As an example, this might be useful if staff 1 was used for just soprano
+at the beginning of the song,
+so you wanted label=&quot;Soprano&quot; and label2=&quot;S&quot;
+for that portion, but later soprano and alto share the staff, so you would
+like label=&quot;Soprano/alto&quot; to clearly point out the change, but then
+revert to just &quot;SA&quot; on subsequent staffs, to conserve space.
+<LI>
+You can specify a bulge direction for
+<A HREF="uguide/noteattr.html#ntie">note ties,</A>
+<A HREF="uguide/noteattr.html#nslur">note slurs,</A>
+<A HREF="uguide/ichdattr.html#tie">chord ties,</A> and
+<A HREF="uguide/ichdattr.html#slur">chord slurs,</A>
+if you wish to override Mup's choice of direction.
+<LI>
+You can now use \s(PV) or \s(previous) in a text string to return to
+the previous
+<A HREF="uguide/textstr.html#size">size.</A>
+<LI>
+The
+<A HREF="uguide/param.html#clef">8treble clef</A> is now supported.
+This is like the treble8 clef, except the 8 is printed above the G clef
+rather than below it, to show notes that sound an octave <I>higher</I> than
+a normal treble clef.
+<LI>
+<A HREF="uguide/phrase.html">Phrase marks</A> can now have
+an optional line type modifier of dotted or dashed.
+</UL>
+</P>
+<H2>New Features in Mup Version 4.3</H2>
+<P>
+<UL>
+<LI>
+There is a new
+<A HREF="uguide/param.html#rehstyle">rehstyle parameter</A>
+that controls whether rehearsal marks are boxed, circled, or plain.
+<LI>
+It is no longer necessary to specify verse numbers for
+<A HREF="uguide/lyrics.html">lyrics</A>
+(unless you want to skip a verse). If not specified, each
+succeeding set of lyrics for a given staff and place defaults
+to having a verse number one more than the previous verse.
+<LI>
+There is a new way to
+<A HREF="uguide/param.html#sylpos">force the position of individual lyrics syllables</A>
+that is particularly useful for ensuring that verse numbers or the
+beginnings of poetic lines align consistently on all verses.
+<LI>
+There are new
+<A HREF="uguide/cmdargs.html#Eoption">-E and -C options</A>
+that let you see how macros expand, which can help you in debugging
+very complex macros.
+<LI>
+There is a new
+<A HREF="uguide/param.html#staffpad">staffpad parameter</A>,
+and the value of the 
+<A HREF="uguide/param.html#scorepad">scorepad parameter</A>
+can now be negative. Using negative values for these can let you
+jam staffs or scores closer together in cases where 
+Mup is spacing them wider apart than is really necessary.
+<LI>
+It is now possible to have more than one voice on
+<A HREF="uguide/tabstaff.html">tablature staffs</A>
+just like on non-tablature.
+<LI>
+It is now possible to
+<A HREF="uguide/newscore.html">temporarily override margins</A>
+on a particular score. This can let you indent one score differently
+than the others, or end a piece with a shorter-than-normal score.
+<LI>
+There is now an &quot;alt pedstar&quot; value for the
+<A HREF="uguide/param.html#pedstyle">pedstyle parameter</A>
+This is like the &quot;pedstar&quot; value
+except that when there is a pedal &quot;bounce,&quot;
+only a &quot;Ped&quot; is printed, rather than a &quot;* Ped.&quot;
+<LI>
+There is a new
+<A HREF="userpgms.html">user-donated program</A> called
+<A HREF="ftp://ftp.arkkra.com/pub/dos/user.pgms/winmup11.zip">Winmup</A>
+which provides a Windows front-end for the MS-DOS version of Mup. The 
+<A HREF="ftp://ftp.arkkra.com/pub/dos/user.pgms/winmup11src.zip">Visual Basic source
+code for Winmup</A> is also available.
+<LI>
+Several miscellaneous changes were made to improve the quality of
+printed output and to improve portability.
+Current Mup users may find the layout of some songs may change
+somewhat when they upgrade.
+</UL>
+</P>
+<H2>New Features in Mup Version 4.2</H2>
+<P>
+<UL>
+<LI>
+A <A HREF="uguide/param.html#vscheme">third voice per staff</A>
+is now supported.
+<LI>
+It is now possible to
+<A HREF="uguide/chrdattr.html#hoffset">adjust the horizontal placement of notes.</A>
+<LI>
+It is now possible to
+<A HREF="uguide/param.html#beamstyl">beam across rests.</A>
+<LI>
+The optional
+<A HREF="uguide/param.html#measnum">automatic measure numbers
+at the beginnings of scores</A> are now printed in a larger size.
+<LI>
+<A HREF="uguide/altinp.html">The chord-at-a-time input style</A>
+has been made more versatile. Previously,
+if a voice was mentioned in a pattern, that voice could not be used for
+voice-at-a-time input style in that measure, even if the pattern was
+never actually used. Now the restriction only applies if the pattern is
+actually used.
+<LI>
+Strings can be printed
+<A HREF="uguide/textstr.html#boxed">enclosed in a circle or elipse.</A>
+<LI>
+There is a new
+<A HREF="uguide/param.html#beamslp">beamslope parameter</A>
+that controls the maximum tilt for beams.
+<LI>
+There is a new
+<A HREF="uguide/param.html#pad">pad parameter</A>
+that provides an additional way to control how close together
+note groups are placed horizontally.
+<LI>
+There is a new
+<A HREF="uguide/midi.html">MIDI "port" keyword.</A>
+This can let you assign different tracks to different ports on
+multi-port MIDI devices, allowing for more than 16 channels.
+<LI>
+The minimum values for the
+<A HREF="uguide/param.html#scoresep">scoresep</A> and
+<A HREF="uguide/param.html#staffsep">staffsep</A> parameters
+can now be set as low as 6, rather than the previous minimum of 9.
+</UL>
+</P>
+<H2>New Features in Mup Version 4.1</H2>
+<P>
+<UL>
+<LI>
+<A HREF="uguide/textmark.html#grids">Guitar grids</A> can now be
+printed, either
+<A HREF="uguide/param.html#gridused">where they are used in the music,</A>
+or
+<A HREF="uguide/param.html#gridend">summarized at the end of a song.</A>
+There is also a
+<A HREF="userpgms.html">library of pre-defined grids</A>
+that you can
+<A HREF="uguide/include.html">&quot;include&quot;</A> in your music.
+<LI>
+<A HREF="uguide/textstr.html#special">Non-ASCII characters from the Latin-1 alphabet</A> can now be typed directly
+into strings in Mup input, rather than needing to be specified by name.
+Shortcut names have also been added for guillemots.
+<LI>
+The maximum
+<A HREF="uguide/param.html#staffs">number of staffs</A> has been raised to 40.
+<LI>
+The
+<A HREF="uguide/param.html#stlines">stafflines</A>
+and
+<A HREF="uguide/param.html#stscale">staffscale</A>
+parameters can now be changed at any bar line rather than only at the
+beginning of a song. Changing either of them forces a new score.
+<LI>
+The <A HREF="uguide/param.html#staffsep">staffsep</A>
+parameter can now be set on a per-staff basis, rather than just
+for the score as a whole.
+<LI>
+There are new parameters that allow you to control the order that items
+<A HREF="uguide/param.html#aboveord">above,</A>
+<A HREF="uguide/param.html#beloword">below,</A>
+and
+<A HREF="uguide/param.html#betwnord">between</A>
+staffs are stacked.
+<LI>
+It is now possible to
+<A HREF="uguide/param.html#nummrpt">
+turn off the automatic numbering of measure repeats</A>
+and the
+<A HREF="uguide/param.html#prmultn">
+printing of multirest numbers.</A>
+<LI>
+It is now possible to
+<A HREF="uguide/chrdattr.html#dist">specify the vertical placement of a rest character,</A>
+if you want to override Mup's automatic placement.
+<LI>
+It is now possible to
+<A HREF="uguide/textstr.html#strcat">concatenate strings.</A>
+This is likely to be most useful in
+<A HREF="uguide/macros.html">macros,</A>
+but can be used anywhere strings are used.
+<LI>
+There is a new
+<A HREF="uguide/param.html#firstpg">firstpage parameter,</A>
+which is similar to the
+<A HREF="uguide/cmdargs.html#poption">-p command line option,</A>
+for setting the first page number.
+<LI>
+There is a new
+<A HREF="uguide/param.html#restcomb">restcombine parameter,</A>
+which is similar to the
+<A HREF="uguide/cmdargs.html#coption">-c command line option,</A>
+for automatically combining a sequences of rest measures into
+<A HREF="uguide/multirst.html">multirests.</A>
+<LI>
+Music symbols that occur inside ital or boldital strings will
+<A HREF="uguide/textmark.html#italmus">automatically be made italics</A>
+to match the string.
+<LI>
+It is possible to
+<A HREF="uguide/lyrics.html#centered">vertically center lyrics.</A>
+This is useful when there is a refrain with identical words for all
+verses, and you only want it printed once.
+<LI>
+It is now allowed to have a
+<A HREF="uguide/param.html#brace">brace</A>
+to the left of
+<A HREF="uguide/param.html#bracket">brackets,</A>
+to group a subset of staffs.
+(Previously, only brackets were allowed to be nested that way.)
+</UL>
+</P>
+<H2>New Features in Mup Version 4.0</H2>
+<P>
+<UL>
+<LI>
+There is now an
+<A HREF="uguide/altinp.html">alternate input style,</A>
+in which you can enter music a chord at a time rather than a voice at
+a time. For certain kinds of music, this may be more natural,
+and allow you to enter music more quickly.
+<A HREF="uguide/chordinp.html">The previous input style</A>
+has also been made more flexible, such that it
+is now possible to specify that one line of input will go to voice 1
+on one staff or set of staffs and voice 2 on another staff or set of staffs.
+These enhancements make it easier to do things like input a vocal score and
+<A HREF="uguide/pianored.html">automatically get a piano reduction.</A>
+<LI>
+It is now possible to
+<A HREF="uguide/macros.html#quoting">transform a parameter passed
+to a macro into a string.</A>
+If you are a C programmer, you will find this works somewhat
+like the # operator of ANSI C preprocessor macros. If you're not a
+C programmer, suffice it to say that this allows Mup macros to be used
+to do things they couldn't do before.
+<LI>
+There is a new special bar type, called
+<A HREF="uguide/bars.html#restart">restart</A>, that lets you
+end the current set of staffs and begin a new set of staffs on the same
+line, as is sometimes done for a short coda.
+<LI>
+The symbols for accidentals (like # and &amp;) are now translated to
+their corresponding musical symbols everywhere in
+<A HREF="uguide/textmark.html#chordmod">chords,</A>
+rather than only if they immediately follow the letters A through G.
+You can, however, turn off this automatic translation
+for individual cases where you want them to be treated literally.
+<LI>
+<A HREF="uguide/chordinp.html#duration">Quadruple whole rests</A> are supported.
+<LI>
+It is possible to force a
+<A HREF="uguide/chordinp.html#measdur">measure rest</A>
+to be shown with a rest symbol other than the whole rest symbol
+that is usually used.
+<LI>
+There is a new
+<A HREF="uguide/param.html#addxpose">addtranspose parameter</A>. This
+enables you to use the 
+<A HREF="uguide/param.html#xpose">transpose parameter</A> to change
+the transposition on specific staffs for transposing instruments,
+then use addtranpose to transpose the entire score into a new key.
+<LI>
+There is a new
+<A HREF="uguide/param.html#warn">warn parameter</A> which allows you
+to control whether warning messages are printed or not.
+<LI>
+There is a new
+<A HREF="uguide/param.html#ontheline">ontheline parameter</A>. This
+allows you to control whether notes on 1-line staffs are printed above, below,
+or on the line.
+<LI>
+The
+<A HREF="uguide/param.html#dist">dist,</A>
+<A HREF="uguide/param.html#chdist">chorddist,</A>
+and
+<A HREF="uguide/param.html#cresdist">crescdist</A>
+parameters can be
+<A HREF="uguide/stuff.html#dist">overridden on individual items.</A>
+A dist override can also be specified on
+<A HREF="uguide/bars.html#reh">rehearsal marks.</A>
+Each dist override can also include a modifier
+to force items to a specific place,
+even if they then overwrite other items that Mup would normally avoid.
+<LI>
+There is a new
+<A HREF="uguide/cmdargs.html#moption">-M option</A> which is like the
+-m option, except the name of the MIDI file is derived from the Mup
+input file name, rather than requiring you to supply a name.
+<LI>
+If a given input file name does not exist, Mup will try appending .mup
+to the name and attempt to open that file.
+<LI>
+It is now possible to specify an
+<A HREF="uguide/chordinp.html#restspc">uncollapseable space</A>.
+This may be useful when drawing "slash" marks and at other times.
+<LI>
+There is a new
+<A HREF="userpgms.html">user-donated program</A> called midi2mup, which
+is a Perl script that can convert a MIDI file to Mup input.
+<LI>
+The uguide gives examples of how to
+<A HREF="uguide/verses.html">places verses as text blocks below the scores.</A>
+</UL>
+</P>
+<H2>Coming Attractions</H2>
+<P>
+We're always interested in hearing about what features you would
+like to see in the next version of Mup.
+What features we add will depend on your input, so
+please send us a note at
+<A HREF="mailto:support@arkkra.com">support@arkkra.com.</A>
+</P>
+<!-- add link to home page -->
+</BODY>
+</HTML>
diff --git a/mup/docs/whatsnew.txt b/mup/docs/whatsnew.txt
new file mode 100644 (file)
index 0000000..797bcdf
--- /dev/null
@@ -0,0 +1,556 @@
+
+                             New Mup Features
+
+       1.  New Mup Features
+
+       1.1  New Features in Mup Version 5.3
+
+       Version 5.3 is primarily focused on ease of use
+       enhancements.  The largest item is the additional of a
+       companion program, called Mupmate, that provides an
+       interface for editing, displaying, and playing Mup files
+       with the kinds of menus and windows that many people are
+       used to. The Help menu will take you right to the Mup User's
+       Guide, which has also had improvements made.  If you are a
+       user who prefers the command line interface that Mup has
+       always had, don't worry; we like to use that too, and have
+       no intention of dropping support for it.
+
+       Windows users now only need to download a single file and
+       execute it to install everything (although you still need to
+       get and install GSview and Ghostscript separately, if you
+       want to use that for viewing the PostScript files). Other
+       users can also just download a single file that contains
+       both program and documentation.
+
+       Other new features in 5.3 include:
+
+          - Error and warning messages have been enhanced to show
+            you the text of the line of input where the problem was
+            found.
+
+          - There is a new pagesize parameter that lets you specify
+            paper size by common names like letter or a4, as an
+            alternate to specifying pageheight and pagewidth in
+            inches or cm.
+
+          - There is a new vcombine parameter, that lets you enter
+            notes on separate voices, yet have them printed on a
+            common stem when possible. Typical uses are:
+
+               - To have separate MIDI tracks for different voices,
+                 yet have the voices printed on common stems.
+
+               - For a style of printing where a single stem is
+                 used for the two voices on a staff except when the
+                 voices share a common note, when two opposing
+                 stems are printed.
+
+          - The scorepad parameter now accepts an optional maximum
+            value, in addition to the minimum value.
+
+       1.2  New Features in Mup Version 5.2
+
+          - There is now a generalized 'if' clause' that is much
+            more flexible and powerful than the simple ifdef and
+            ifndef.  These provide capabilities somewhat similar to
+            the preprocessors for the C and C++ languages.
+
+          - Complicated time signatures are now supported.  This
+            includes a numerator with two or more numbers added
+            together, like 3+4 / 4, or two or more fractions added
+            together, like 3/4 + 3/8.  Alternating time signatures,
+            such as when a piece continuously switches between 3/4
+            and 6/8, are also supported.
+
+          - The beamstyle and timeunit parameter values associated
+            with a time signature are now remembered, so that if
+            you later change back to the same time signature, you
+            don't have to also set the beamstyle and timeunit at
+            the same time; the value used previously for that time
+            signature will be restored automatically.  (Note that
+            if you have existing Mup files that rely on the old
+            behavior, they may need small modifications, but that
+            should be rare.)
+
+          - It is now possible to force stem direction on voices 1
+            and 2 even when the other voice is not space.
+
+          - Improvements have been made to how the angle for beams
+            is calculated.  The "best" angle for a beam is
+            sometimes somewhat subjective, but in general, these
+            changes will result in more cases where beams are
+            horizontal or less sloped,
+
+          - There are also additional ways you can control beams:
+            A new slope interchord attribute lets you force a
+            specific slope.  The new stemshorten parameter lets you
+            determine how much a chord's stem is allowed to be
+            shortened when it is beamed.  And the existing len
+            chord attribute can now be set for just one end of a
+            beamed set of chords as an alternative to setting it at
+            both ends.
+
+          - The HTML version of the Mup User's Guide now includes
+            'next page' and 'previous page' links on each page.
+
+       1.3  New Features in Mup Version 5.1
+
+          - You may specify a time value that is the summation of
+            several time values.  This can be used to obtain
+            beaming, lyrics, or tuplets with durations that cannot
+            be represented with a single time value, like a half
+            note plus an eighth note. It also gives an alternate
+            way to specify chord ties.
+
+          - Cross-staff stems are now supported.
+
+          - You can now explicitly specify a direction of "up" on
+            rolls to get an upward arrow drawn at the top of the
+            roll. (Before, only a downward roll would get an
+            arrow.)
+
+          - Mup will now allow you to beam across spaces as well as
+            rests.
+
+          - There is a new restsymmult parameter.  Setting it to y
+            will cause Mup to use an alternate style for multirests
+            of eight measures or less, which uses rest symbols.
+
+          - There is a new string sequence that will be replaced by
+            the page number of the last page.  This may useful to
+            be able to automatically get output like "Page 2 of 4
+            pages."
+
+          - There is a new option for printing of tuplet numbers,
+            where the number is always printed, but the bracket is
+            never printed.
+
+          - If you want to have the same lyrics above some staffs
+            and below others, it is now possible to specify that on
+            a single input line, rather than requiring two.
+
+          - Improvements have been made to how voice 3 is placed,
+            which will often eliminate the need to manually specify
+            a horizontal offset.
+
+       1.4  New Features in Mup Version 5.0
+
+          - Mup now supports the shaped notes often used in "Sacred
+            Harp" music, also sometimes called "fasola" notation.
+            New note head characters are available for the most
+            common system of 4 shapes, as well as a system with 7
+            shapes.  As part of this feature, there is a new
+            headshape context and a new noteheads parameter that
+            lets you define what shapes will be used for notes.
+
+          - Note head shapes can also be specified on specific
+            chords or a specific note within a chord.  This makes
+            it possible to do things like have both normal and X-
+            shaped notes on the same stem.
+
+          - There are new "slash" note heads, often used to
+            indicate repeated chords, and a new "blankhead" note
+            head, that can be used if you just want a stem without
+            any note head.
+
+          - There is a new stemlen parameter that lets you set the
+            default stem length. A common use for this would be to
+            set this parameter to 0.0, to not have any stems at all
+            (sometimes used for chant).
+
+          - It is now possible to change the clef, defoct, and
+            release parameters in the middle of a measure.
+
+          - You can now include raw PostScript in the input to the
+            copied to the output. This could be used, for example,
+            to include a picture or logo with your music.
+
+          - In addition to the old way of specifying key signature,
+            by stating the number of sharps or flats, it is now
+            possible to specify the key by name, as in "a major" or
+            "c# minor."
+
+          - There is a new swingunit parameter.  Some styles of
+            music are often written with straight eighth notes or
+            dotted-eighth-sixteeen notations, but where the players
+            "know" that the composer really wants the music played
+            with the first note in each pair twice as long as the
+            second, as if it were a quarter-eighth triplet.  This
+            parameter will make Mup's MIDI output automatically
+            follow that kind of performance convention.
+
+          - It is possible to set the rehearsal letter or number to
+            a specific value, to override the automatic
+            incrementing.  This might be especially useful when
+            there are multiple songs or movements in a single Mup
+            file.
+
+       1.5  New Features in Mup Version 4.6
+
+          - There are new top, bottom, top2, and bottom2 contexts
+            that let you define a second layer of headers and
+            footers. These new contexts can be changed multiple
+            times in a file, so you can use different headings and
+            footing for different songs or movements within a file.
+
+          - There is a new "block" context, that lets you place
+            blocks of text in your musical scores.
+
+          - There is a new paragraph command for printing long
+            sections of text that you would like to have
+            automatically wrapped around unto as many lines as
+            needed. The right margin can be justified or ragged.
+
+          - For Linux, in addition to being available in tar.gz
+            format, Mup files are now available in rpm package
+            format, for very quick-and-easy installation.  The MS-
+            DOS/Windows Mup files are now available as self-
+            extracting zip files, so you don't need to have an
+            unzip program to unpack them.
+
+          - The visible parameter now accepts a value of
+            "whereused."  With this value, when a staff has no
+            notes on an entire score, that staff is not printed.
+            This might be used, for example, to save paper on an
+            orchestral score by only printing staffs for
+            instruments when they are actually playing.
+
+          - There are new parameters measnumfont,
+            measnumfontfamily, and measnumsize, to control the
+            appearance of automatic measure numbers.
+
+          - It is now possible to unset parameters in voice or
+            staff context, to make them revert to their values in
+            the next more general context where they are set (staff
+            or score).
+
+          - When a repeatstart gets moved to the beginning of a
+            score, sometimes you'd like the bar line at the end of
+            the previous score to be a double bar rather than
+            single bar. It is now possible to specify that.
+
+          - There is a new -F option that is like the -f option,
+            except it derives the name of the output file based on
+            the name of the input file, rather than you needing to
+            specify an output file name.
+
+          - The Mup input file name is given in the PostScript
+            output file, so that PostScript viewer programs like gv
+            can use it in their window title.
+
+          - There is now a majordomo mailing list available for
+            registered Mup users.  This is a forum for talking with
+            other Mup users, to discuss questions and tips on using
+            Mup.
+
+       1.6  New Features in Mup Version 4.5
+
+          - There is a new -x option that lets you extract a
+            portion of a song. This can be especially useful for
+            MIDI, where you might want to listen to just a few
+            measures in the middle or end of a piece. But it also
+            works in printing mode, so you can print just an
+            excerpt of a piece.
+
+          - It is now possible to specify "subbeams," both with
+            custom beaming and via the beamstyle parameter.  This
+            can be used when there are a lot of very short notes,
+            and you want to subdivide the beam groupings.
+
+          - The drawing of phrase marks, ties, and slurs has been
+            re-implemented to produce more aesthetically pleasing
+            curves.
+
+          - There is a new special character, called \(space),
+            which is printed like a normal space on output, but
+            which is not treated like a space when Mup is looking
+            for word or syllable boundaries. The most common use
+            for this would probably be on chant lyrics, where you
+            want several words to be sung to the same note.  It
+            might also be useful in cases where Mup would normally
+            split a long string at a word boundary to avoid running
+            off the edge of a page, but for some reason you want to
+            prevent that splitting.
+
+          - It is possible to print a text string centered above a
+            line.  This is likely to be the most useful for
+            printing "gliss." by a wavy line for a glissando, but
+            it can be used on any kind of line.
+
+          - There are some new user-donated files, including a
+            Windows installer, and Mup syntax files for nedit and
+            vim.
+
+       1.7  New Features in Mup Version 4.4
+
+          - Many of the changes in this release were to make Mup
+            conform more closely with established guidelines or
+            rules for musical notation.  This mainly involved small
+            adjustments to cosmetic details, like how accidentals
+            and dots are placed.  For mid-score clef changes, the
+            clef is now placed before the barline, as it should be,
+            rather than after.  There is also an improved algorithm
+            for determining where to end the underscores on lyrics.
+
+          - The use of labels, both labels associated with
+            individual staffs and labels associated with staffs
+            grouped by braces or brackets, has been made more
+            flexible.  It used to be that the "label" was only used
+            on the very first score, with "label2" used on all
+            subsequent scores.  Thus resetting label after the
+            beginning really had no effect.  Now, however, whenever
+            a new label is specified, that label will be used for
+            the next score, going back to label2 for subsequent
+            scores.  As an example, this might be useful if staff 1
+            was used for just soprano at the beginning of the song,
+            so you wanted label="Soprano" and label2="S" for that
+            portion, but later soprano and alto share the staff, so
+            you would like label="Soprano/alto" to clearly point
+            out the change, but then revert to just "SA" on
+            subsequent staffs, to conserve space.
+
+          - You can specify a bulge direction for note ties, note
+            slurs, chord ties, and chord slurs, if you wish to
+            override Mup's choice of direction.
+
+          - You can now use \s(PV) or \s(previous) in a text string
+            to return to the previous size.
+
+          - The 8treble clef is now supported.  This is like the
+            treble8 clef, except the 8 is printed above the G clef
+            rather than below it, to show notes that sound an
+            octave <I>higher</I> than a normal treble clef.
+
+          - Phrase marks can now have an optional line type
+            modifier of dotted or dashed.
+
+       1.8  New Features in Mup Version 4.3
+
+          - There is a new rehstyle parameter that controls whether
+            rehearsal marks are boxed, circled, or plain.
+
+          - It is no longer necessary to specify verse numbers for
+            lyrics (unless you want to skip a verse). If not
+            specified, each succeeding set of lyrics for a given
+            staff and place defaults to having a verse number one
+            more than the previous verse.
+
+          - There is a new way to force the position of individual
+            lyrics syllables that is particularly useful for
+            ensuring that verse numbers or the beginnings of poetic
+            lines align consistently on all verses.
+
+          - There are new -E and -C options that let you see how
+            macros expand, which can help you in debugging very
+            complex macros.
+
+          - There is a new staffpad parameter, and the value of the
+            scorepad parameter can now be negative. Using negative
+            values for these can let you jam staffs or scores
+            closer together in cases where Mup is spacing them
+            wider apart than is really necessary.
+
+          - It is now possible to have more than one voice on
+            tablature staffs just like on non-tablature.
+
+          - It is now possible to temporarily override margins on a
+            particular score. This can let you indent one score
+            differently than the others, or end a piece with a
+            shorter-than-normal score.
+
+          - There is now an "alt pedstar" value for the pedstyle
+            parameter This is like the "pedstar" value except that
+            when there is a pedal "bounce," only a "Ped" is
+            printed, rather than a "* Ped."
+
+          - There is a new user-donated program called Winmup which
+            provides a Windows front-end for the MS-DOS version of
+            Mup. The Visual Basic source code for Winmup is also
+            available.
+
+          - Several miscellaneous changes were made to improve the
+            quality of printed output and to improve portability.
+            Current Mup users may find the layout of some songs may
+            change somewhat when they upgrade.
+
+       1.9  New Features in Mup Version 4.2
+
+          - A third voice per staff is now supported.
+
+          - It is now possible to adjust the horizontal placement
+            of notes.
+
+          - It is now possible to beam across rests.
+
+          - The optional automatic measure numbers at the
+            beginnings of scores are now printed in a larger size.
+
+          - The chord-at-a-time input style has been made more
+            versatile. Previously, if a voice was mentioned in a
+            pattern, that voice could not be used for voice-at-a-
+            time input style in that measure, even if the pattern
+            was never actually used. Now the restriction only
+            applies if the pattern is actually used.
+
+          - Strings can be printed enclosed in a circle or elipse.
+
+          - There is a new beamslope parameter that controls the
+            maximum tilt for beams.
+
+          - There is a new pad parameter that provides an
+            additional way to control how close together note
+            groups are placed horizontally.
+
+          - There is a new MIDI "port" keyword.  This can let you
+            assign different tracks to different ports on multi-
+            port MIDI devices, allowing for more than 16 channels.
+
+          - The minimum values for the scoresep and staffsep
+            parameters can now be set as low as 6, rather than the
+            previous minimum of 9.
+
+       1.10  New Features in Mup Version 4.1
+
+          - Guitar grids can now be printed, either where they are
+            used in the music, or summarized at the end of a song.
+            There is also a library of pre-defined grids that you
+            can "include" in your music.
+
+          - Non-ASCII characters from the Latin-1 alphabet can now
+            be typed directly into strings in Mup input, rather
+            than needing to be specified by name.  Shortcut names
+            have also been added for guillemots.
+
+          - The maximum number of staffs has been raised to 40.
+
+          - The stafflines and staffscale parameters can now be
+            changed at any bar line rather than only at the
+            beginning of a song. Changing either of them forces a
+            new score.
+
+          - The staffsep parameter can now be set on a per-staff
+            basis, rather than just for the score as a whole.
+
+          - There are new parameters that allow you to control the
+            order that items above, below, and between staffs are
+            stacked.
+
+          - It is now possible to turn off the automatic numbering
+            of measure repeats and the printing of multirest
+            numbers.
+
+          - It is now possible to specify the vertical placement of
+            a rest character, if you want to override Mup's
+            automatic placement.
+
+          - It is now possible to concatenate strings.  This is
+            likely to be most useful in macros, but can be used
+            anywhere strings are used.
+
+          - There is a new firstpage parameter, which is similar to
+            the -p command line option, for setting the first page
+            number.
+
+          - There is a new restcombine parameter, which is similar
+            to the -c command line option, for automatically
+            combining a sequences of rest measures into multirests.
+
+          - Music symbols that occur inside ital or boldital
+            strings will automatically be made italics to match the
+            string.
+
+          - It is possible to vertically center lyrics.  This is
+            useful when there is a refrain with identical words for
+            all verses, and you only want it printed once.
+
+          - It is now allowed to have a brace to the left of
+            brackets, to group a subset of staffs.  (Previously,
+            only brackets were allowed to be nested that way.)
+
+       1.11  New Features in Mup Version 4.0
+
+          - There is now an alternate input style, in which you can
+            enter music a chord at a time rather than a voice at a
+            time. For certain kinds of music, this may be more
+            natural, and allow you to enter music more quickly.
+            The previous input style has also been made more
+            flexible, such that it is now possible to specify that
+            one line of input will go to voice 1 on one staff or
+            set of staffs and voice 2 on another staff or set of
+            staffs.  These enhancements make it easier to do things
+            like input a vocal score and automatically get a piano
+            reduction.
+
+          - It is now possible to transform a parameter passed to a
+            macro into a string.  If you are a C programmer, you
+            will find this works somewhat like the # operator of
+            ANSI C preprocessor macros. If you're not a C
+            programmer, suffice it to say that this allows Mup
+            macros to be used to do things they couldn't do before.
+
+          - There is a new special bar type, called restart, that
+            lets you end the current set of staffs and begin a new
+            set of staffs on the same line, as is sometimes done
+            for a short coda.
+
+          - The symbols for accidentals (like # and &) are now
+            translated to their corresponding musical symbols
+            everywhere in chords, rather than only if they
+            immediately follow the letters A through G.  You can,
+            however, turn off this automatic translation for
+            individual cases where you want them to be treated
+            literally.
+
+          - Quadruple whole rests are supported.
+
+          - It is possible to force a measure rest to be shown with
+            a rest symbol other than the whole rest symbol that is
+            usually used.
+
+          - There is a new addtranspose parameter. This enables you
+            to use the transpose parameter to change the
+            transposition on specific staffs for transposing
+            instruments, then use addtranpose to transpose the
+            entire score into a new key.
+
+          - There is a new warn parameter which allows you to
+            control whether warning messages are printed or not.
+
+          - There is a new ontheline parameter. This allows you to
+            control whether notes on 1-line staffs are printed
+            above, below, or on the line.
+
+          - The dist, chorddist, and crescdist parameters can be
+            overridden on individual items.  A dist override can
+            also be specified on rehearsal marks.  Each dist
+            override can also include a modifier to force items to
+            a specific place, even if they then overwrite other
+            items that Mup would normally avoid.
+
+          - There is a new -M option which is like the -m option,
+            except the name of the MIDI file is derived from the
+            Mup input file name, rather than requiring you to
+            supply a name.
+
+          - If a given input file name does not exist, Mup will try
+            appending .mup to the name and attempt to open that
+            file.
+
+          - It is now possible to specify an uncollapseable space.
+            This may be useful when drawing "slash" marks and at
+            other times.
+
+          - There is a new user-donated program called midi2mup,
+            which is a Perl script that can convert a MIDI file to
+            Mup input.
+
+          - The uguide gives examples of how to places verses as
+            text blocks below the scores.
+
+       1.12  Coming Attractions
+
+       We're always interested in hearing about what features you
+       would like to see in the next version of Mup.  What features
+       we add will depend on your input, so please send us a note
+       at support@arkkra.com.
diff --git a/mup/makefile b/mup/makefile
new file mode 100644 (file)
index 0000000..8acf0d6
--- /dev/null
@@ -0,0 +1,222 @@
+
+# Makefile for Mup (and auxiliary programs mupdisp, mkmupfnt, and mupmate).
+# This is not an optimal makefile; instead it tries to be very simple,
+# and easy to understand, so it can be easily modified, if needed.
+
+# On most Linux/Unix type systems, just doing
+#      make install
+# as root will probably work.
+# (You really only need to be root to copy the products into
+# the system directories. If you change PREFIX
+# to point to some other writeable area, you wouldn't need to be root.)
+# If you only want the Mup program itself, you can do
+#      make mup/mup
+# The other programs are optional:
+# - mupdisp runs Mup and then runs GhostScript on the result.
+#   You can run Mup directly, and use gv, GSview, ghostview or any other
+#   PostScript viewer on the Mup output, as an alternative to mupdisp.
+# - mkmupfnt is only needed if you want to use fonts beyond the basic
+#   standard PostScript fonts.
+# - mupmate is a graphical user interface front end for Mup.
+#   It is not needed if you intend to only use Mup via command line interface.
+
+# The mupdisp and mupmate programs require X libraries and headers (www.x.org).
+# The mupmate program requires FLTK libraries and headers (www.fltk.org).
+
+# If you want mupdisp to support Linux console mode, make sure you have
+# the svgalib package installed, then find the two commented-out lines below
+# related to Linux console support, and uncomment them.
+
+
+# Lines you might conceivably want to change have comments by them,
+# explaining how you might want to change them.
+# Any line without any comment by it is very unlikely to ever need changing.
+
+#-----------------------------------------------------------------------
+
+# These define where to put the Mup products.
+# You could change this to /usr/local or your own space if you like.
+PREFIX = /usr
+BINDIR = $(PREFIX)/bin
+MANDIR = $(PREFIX)/man/man1
+DOCDIR = $(PREFIX)/share/doc/packages/mup
+
+# This is the name of your C compiler.
+# cc would be another common choice.
+CCOMPILER = gcc
+
+# This is the name of your C++ compiler.
+# CC would be another common choice.
+CPPCOMPILER = g++
+
+# -O option turns on optimization for most C compilers.
+# You can add other options, if you like, as appropriate for your C compiler.
+# Another common addition would be -g to get debugging information.
+CFLAGS = -O
+
+# You can change this if your X libraries and headers are somewhere else
+# (like /usr/X11R6).
+X_LOCATION = /usr/X11
+
+# The FLTK header files are under $(FLTK_INCLUDE)/FL
+FLTK_INCLUDE = $(X_LOCATION)/include
+
+# You can use fltk_jpeg or jpeg library, whichever you have
+JPEGLIB = fltk_jpeg
+
+# You can use fltk_png or png library, whichever you have
+PNGLIB = fltk_png
+
+# You can use fltk_z or z library, whichever you have
+ZLIB = fltk_z
+
+#-----------------------------------------------------------------------
+
+MUP_SRC =  \
+       mup/abshorz.c \
+       mup/absvert.c \
+       mup/assign.c \
+       mup/beaming.c \
+       mup/beamstem.c \
+       mup/brac.c \
+       mup/charinfo.c \
+       mup/check.c \
+       mup/debug.c \
+       mup/errors.c \
+       mup/extchtbl.c \
+       mup/font.c \
+       mup/fontdata.c \
+       mup/globals.c \
+       mup/grpsyl.c \
+       mup/ifgram.c \
+       mup/lex.c \
+       mup/locvar.c \
+       mup/lyrics.c \
+       mup/macros.c \
+       mup/main.c \
+       mup/mainlist.c \
+       mup/map.c \
+       mup/midi.c \
+       mup/midiutil.c \
+       mup/mkchords.c \
+       mup/muschtbl.c \
+       mup/nxtstrch.c \
+       mup/parstssv.c \
+       mup/parstuff.c \
+       mup/phrase.c \
+       mup/plutils.c \
+       mup/print.c \
+       mup/prntdata.c \
+       mup/prntmisc.c \
+       mup/prnttab.c \
+       mup/prolog.c \
+       mup/range.c \
+       mup/rational.c \
+       mup/relvert.c \
+       mup/restsyl.c \
+       mup/roll.c \
+       mup/setgrps.c \
+       mup/setnotes.c \
+       mup/ssv.c \
+       mup/stuff.c \
+       mup/symtbl.c \
+       mup/tie.c \
+       mup/trantab.c \
+       mup/trnspose.c \
+       mup/undrscre.c \
+       mup/utils.c \
+       mup/ytab.c
+
+MUP_HDRS = \
+       mup/defines.h \
+       mup/extchar.h \
+       mup/globals.h \
+       mup/muschar.h \
+       mup/rational.h \
+       mup/ssvused.h \
+       mup/structs.h \
+       mup/ytab.h
+
+MUPDISP_SRC = \
+       mupdisp/at386.c \
+       mupdisp/do_cmd.c \
+       mupdisp/dos.c \
+       mupdisp/genfile.c \
+       mupdisp/init.c \
+       mupdisp/linvga.c \
+       mupdisp/mupdisp.c \
+       mupdisp/xterm.c
+
+MUPDISP_HDRS = mupdisp/dispttyp.h mupdisp/mupdisp.h
+
+MUPDISP_BITMAPS = mupdisp/help.bm mupdisp/waitmsg.bm
+
+MKMUPFNT_SRC = mkmupfnt/mkmupfnt.c
+
+MUPMATE_SRC = \
+       mupmate/Config.C \
+       mupmate/Edit.C \
+       mupmate/File.C \
+       mupmate/Help.C \
+       mupmate/Main.C \
+       mupmate/Preferences.C \
+       mupmate/Run.C \
+       mupmate/utils.C \
+       mupmate/license.C \
+       mupmate/regform.C \
+       mupmate/template.C
+
+MUPMATE_HDRS = \
+       mupmate/Config.H \
+       mupmate/Edit.H \
+       mupmate/File.H \
+       mupmate/Help.H \
+       mupmate/Main.H \
+       mupmate/Preferences.H \
+       mupmate/Run.H \
+       mupmate/utils.H \
+       mupmate/globals.H \
+       mupmate/resource.h
+
+MUPMATE_OTHER_FILES = \
+       mupmate/mup32.xpm
+#---------------------------------------------------------------
+
+all: mup/mup mupdisp/mupdisp mkmupfnt/mkmupfnt mupmate/mupmate
+
+mup/mup: $(MUP_HDRS) $(MUP_SRC)
+       $(CCOMPILER) $(CFLAGS) -o $@ $(MUP_SRC) -lm
+
+mupdisp/mupdisp: $(MUPDISP_HDRS) $(MUPDISP_BITMAPS) $(MUPDISP_SRC)
+       $(CCOMPILER) $(CFLAGS) -L$(X_LOCATION)/lib -o $@ -DNO_VGA_LIB $(MUPDISP_SRC) -lX11
+       # For Linux console mode support, comment out the previous line
+       # and uncomment the following line
+       # $(CCOMPILER) $(CFLAGS) -L$(X_LOCATION)/lib -o $@ $(MUPDISP_SRC) -lvga -lX11 -lm
+
+mkmupfnt/mkmupfnt: $(MKMUPFNT_SRC)
+       $(CCOMPILER) $(CFLAGS) -o $@ $(MKMUPFNT_SRC)
+
+mupmate/mupmate: $(MUPMATE_SRC) $(MUPMATE_HDRS) $(MUPMATE_OTHER_FILES)
+       $(CPPCOMPILER) $(CFLAGS) -o $@ $(MUPMATE_SRC) \
+       -I$(FLTK_INCLUDE) -Imup -L$(X_LOCATION)/lib \
+       -lfltk -lfltk_images -lXext -lX11 -lXpm \
+       -l$(JPEGLIB) -l$(PNGLIB) -l$(ZLIB) -lm
+
+install:       all
+       mkdir -p $(BINDIR) $(MANDIR) $(DOCDIR)/uguide
+       cp mup/mup $(BINDIR)/mup
+       cp mkmupfnt/mkmupfnt $(BINDIR)/mkmupfnt
+       cp mupdisp/mupdisp $(BINDIR)/mupdisp
+       # For Linux console mode support, uncomment the following line
+       # chown root $(BINDIR)/mupdisp ; chmod 4755 $(BINDIR)/mupdisp
+       cp mupmate/mupmate $(BINDIR)/mupmate
+       cp mupprnt $(BINDIR)/mupprnt
+       cp docs/*.1 $(MANDIR)
+       cp docs/README* docs/*.txt docs/*.ps docs/*.mup $(DOCDIR)
+       cp docs/uguide/* $(DOCDIR)/uguide
+
+clean:
+       rm -f mup/*.o mupdisp/*.o mkmupfnt/*.o mupmate/*.o
+
+clobber:       clean
+       rm -f mup/mup mupdisp/mupdisp mkmupfnt/mkmupfnt mupmate/mupmate
diff --git a/mup/mkmupfnt/mkmupfnt.c b/mup/mkmupfnt/mkmupfnt.c
new file mode 100644 (file)
index 0000000..a481e40
--- /dev/null
@@ -0,0 +1,436 @@
+char Copyright[] =
+       "Copyright (c) 1999, 2000 by Arkkra Enterprises\nAll rights reserved\n\n";
+
+/* This program generates a Mup fontfile, that will let you override a
+ * Mup font with one of your own. It is done in C rather than with
+ * a "shell script" to be portable to systems without a Unix-like shell.
+ * See the "usage_message" for how to invoke this program.
+ * It creates a PostScript program to print each character in the font
+ * and print out its width, height, and ascent.
+ * It runs Ghostscript on that program.
+ */
+
+#ifdef __DJGPP__
+#define __DOS__
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#ifdef __DOS__
+#include <process.h>
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#endif
+
+#ifdef O_BINARY
+#define READ_FLAGS (O_RDONLY | O_BINARY)
+#define WRITE_FLAGS (O_WRONLY | O_BINARY | O_CREAT | O_TRUNC)
+#else
+#define READ_FLAGS (O_RDONLY)
+#define WRITE_FLAGS (O_WRONLY | O_CREAT | O_TRUNC)
+#endif
+
+/* temp file used for PostScript program */
+char *PS_script_file = "mkmupfnt.ps";
+#ifdef __DOS__
+char *GS_output = "mkmupfnt.tmp";
+#endif
+
+char Version[] = "5.3";
+
+void usage(char *program_name);
+void verify_valid_Mup_name(char *Mup_name);
+int name_matches(char *namelist[], char *name, int namelength);
+void run_Ghostscript(char *PostScript_name, char *Mup_name);
+char * make_string(char *first_part, char *second_part);
+void generate_PostScript_program(char *PS_file);
+void cleanup(int exitcode);
+
+int
+main(int argc, char **argv)
+{
+       char *PostScript_name;
+       char *Mup_name;
+       char *outfile;
+
+       fprintf(stderr, "%s Version %s\n%s", argv[0], Version, Copyright);
+
+       if (argc < 4 || argc > 5) {
+               usage(argv[0]);
+       }
+
+       PostScript_name = argv[1];
+       Mup_name = argv[2];
+       outfile = argv[3];
+
+       verify_valid_Mup_name(Mup_name);
+
+       if ((freopen(outfile, "w", stdout)) == (FILE *) 0) {
+               fprintf(stderr, "Can't open '%s'\n", outfile);
+               exit(1);
+       }
+
+       /* Generate a PostScript program to run, and redirect that program
+        * into Ghostscript. */
+       generate_PostScript_program(argc == 5 ? argv[4] : (char *) 0);
+       if ((freopen(PS_script_file, "r", stdin)) == (FILE *) 0) {
+               fprintf(stderr, "Can't open '%s'\n", PS_script_file);
+               cleanup(1);
+       }
+       run_Ghostscript(PostScript_name, Mup_name);
+
+       /* If there is a PostScript file to add to the output, copy that */
+       if (argc == 5) {
+               int file;
+               int n;
+               char buff[BUFSIZ];
+
+               if ((file = open(argv[4], READ_FLAGS)) < 0) {
+                       fprintf(stderr, "Can't open '%s'\n", argv[4]);
+                       cleanup(1);
+               }
+               while ((n = read(file, buff, BUFSIZ)) > 0) {
+                       write(1, buff, n);
+               }
+               close(file);
+       }
+
+       cleanup(0);
+       /* This line is not reached, since cleanup() exits,
+        * but some compilers complain if function doesn't have a
+        * return or exit, so the return is here to appease them. */
+       return(0);
+}
+
+
+char *usage_message =
+       "PostScript_font_name Mup_font_name outfile [file]\n\n"
+       " Generates a fontfile for Mup to use, to override a Mup font.\n"
+       " Arguments are:\n\n"
+       "    PostScript_font_name   the name of the font you want to add to Mup,\n"
+       "                                  like 'Helvetica-Narrow'\n\n"
+       "    Mup_font_name          the name of the Mup font you want to replace,\n"
+       "                                  like 'HR' or 'helvetica rom'\n\n"
+       "    outfile                the generated Mup fontfile\n\n"
+       "    file                   can contain PostScript to be added to Mup prolog,\n"
+       "                                  if needed to use the font.\n";
+
+void
+usage(char *program_name)
+{
+       fprintf(stderr, "usage: %s %s", program_name, usage_message);
+       exit(1);
+}
+
+/* verify Mup font name is a valid one, give error and exit if not */
+
+char *family_names[] = {
+       "avantegarde",
+       "bookman",
+       "courier",
+       "helvetica",
+       "newcentury",
+       "palatino",
+       "times",
+       (char *) 0
+};
+
+char *font_names[] = {
+       "rom",
+       "bold",
+       "ital",
+       "boldital",
+       (char *) 0
+};
+
+void
+verify_valid_Mup_name(char *Mup_name)
+{
+       char *space_loc;
+
+       if (strlen(Mup_name) == 2 && strchr("ABCHNPT", Mup_name[0])
+                                       && strchr("RBIX", Mup_name[1]) ) {
+               /* name is okay, an abbreviated name */
+               return;
+       }
+
+       /* check long names */
+       if ((space_loc = strchr(Mup_name, ' ')) != 0 &&
+               name_matches(family_names, Mup_name, space_loc - Mup_name) &&
+               name_matches(font_names, space_loc + 1, strlen(space_loc + 1))) {
+               return;
+       }
+
+       fprintf(stderr, "'%s' is not a valid Mup font name\n", Mup_name);
+       exit(1);
+}
+
+/* verify name given matches one on the list of valid names */
+
+int
+name_matches(char *namelist[], char *name, int namelength)
+{
+       int i;
+
+       for (i = 0; namelist[i] != (char *) 0; i++) {
+               if (strncmp(namelist[i], name, namelength) == 0 &&
+                                       namelength == strlen(namelist[i])) {
+                       /* matches */
+                       return(1);
+               }
+       }
+       return(0);
+}
+
+/* Run Ghostscript to write width/ascent/descent information for all
+ * characters. */
+
+void
+run_Ghostscript(char *PostScript_name, char *Mup_name)
+{
+       char *  PS_option;
+       char *  Mup_option;
+#ifdef __DOS__
+       char *  output_option;
+       int     ret;
+#endif
+       int status;
+
+       /* pass the arguments on to Ghostscript */
+       PS_option = make_string("-sPostScript_name=", PostScript_name);
+       Mup_option = make_string("-sMup_name=", Mup_name);
+#ifdef __DOS__
+       /* use temp file as a /dev/null */
+       output_option = make_string("-sOutputFile=", GS_output);
+
+       if ((ret = spawnlp(P_WAIT, "gs386", "gs386", "-sDEVICE=bit",
+                               "-dQUIET", output_option, Mup_option,
+                               PS_option, "-", (char *) 0)) != 0) {
+               /* try just plain 'gs' */
+               ret = spawnlp(P_WAIT, "gs", "gs", "-sDEVICE=bit",
+                               "-dQUIET", output_option, Mup_option,
+                               PS_option, "-", (char *) 0);
+       }
+       unlink(GS_output);
+       if (ret != 0) {
+               fprintf(stderr, "failed to execute gs\n");
+               cleanup(1);
+       }
+#else
+       switch (fork()) {
+       case 0:
+               execlp("gs", "gs", "-sDEVICE=bit", "-dQUIET",
+                       "-sOutputFile=/dev/null", Mup_option,
+                       PS_option, "-", (char *) 0);
+               /* FALL THROUGH */
+       case -1:
+               fprintf(stderr, "failed to execute gs\n");
+               cleanup(1);
+       default:
+               wait( &status);
+               if (status != 0) {
+                       fprintf(stderr, "Ghostscript failed\n");
+                       cleanup(1);
+               }
+       }
+#endif
+}
+
+/* given two strings, get enough space to concatenate them,
+ * write them into the malloc-ed string, and return it. */
+
+char *
+make_string(char *first_part, char *second_part)
+{
+       char *new_string;
+
+       if ((new_string = (char *) malloc(strlen(first_part)
+                                       + strlen(second_part) + 1)) == 0) {
+               fprintf(stderr, "malloc failed\n");
+               cleanup(1);
+       }
+       sprintf(new_string, "%s%s", first_part, second_part);
+       return(new_string);
+}
+
+/* This is the PostScript program that actually extracts the
+ * font size information. It is included here and generated as needed,
+ * so that this can be a standalone program, and not have to search
+ * for another file in order to run. In Unix, we could just pipe this
+ * directly into Ghostscript, but on systems that don't have pipes,
+ * a temp file would need to be used, so we do it that way everywhere
+ * for consistency.
+ */
+
+char *PostScript_program =
+"%% This PostScript program generates a fontfile for use by Mup.\n"
+"% PostScript_name and Mup_name must be defined as strings\n"
+"% when this is called.\n"
+"% PostScript_name is the font you want to add to Mup, while\n"
+"% Mup_name is name of the Mup font you want to replace.\n"
+"% So, for example, if you want to replace the Mup Helvetica roman\n"
+"% font with the PostScript Helvetica-Narrow font, these strings would be\n"
+"% (Helvetica-Narrow) and (helvetica rom).\n"
+"% These can be passed in using the Ghostscript -s option.\n"
+"\n"
+"1 setflat             % make bounding box very accurate\n"
+"\n"
+"/buff 50 string def   % number to string conversion buffer\n"
+"/character 1 string def       % buffer for a character to get the bbox of\n"
+"\n"
+"%------------------------------------------------------------------\n"
+"\n"
+"\n"
+"% Usage\n"
+"%     given a one-character string in \"character\",\n"
+"%     outputs its width in 1/1000ths of an inch\n"
+"\n"
+"/getwidth {\n"
+"      % get width of character\n"
+"      character stringwidth\n"
+"\n"
+"      % convert x to 1/1000th of an inch\n"
+"      pop 1000 mul 72 div round cvi\n"
+"\n"
+"      % print results\n"
+"      buff cvs (\\t) print print\n"
+"} def\n"
+"\n"
+"%-----------------------------------\n"
+"% Usage\n"
+"%     given a one-character string in \"character\",\n"
+"%     outputs its height in 1/1000ths of an inch\n"
+"\n"
+"/getheight {\n"
+"      % place character at (100, 100) and get its pathbbox\n"
+"      newpath\n"
+"      100 100 moveto\n"
+"      character true charpath flattenpath pathbbox\n"
+"\n"
+"      % save the top and bottom y coordinates of the bbox\n"
+"      /top exch def pop\n"
+"      /bot exch def pop\n"
+"\n"
+"      % if bot is above the baseline, the height is (top - baseline)\n"
+"       % otherwise it is (top - bot)\n"
+"      bot 100 gt { top 100 sub } { top bot sub } ifelse\n"
+"\n"
+"      % space is special, use 9 points for height\n"
+"      character ( ) eq { 9 add } if\n"
+"\n"
+"      % add 2 point of padding, one for top and one for bottom white space,\n"
+"      % and convert to 1/1000ths of an inch\n"
+"      2 add 1000 mul 72 div round cvi\n"
+"\n"
+"      % print the results\n"
+"      buff cvs (\\t) print print\n"
+"} def\n"
+"\n"
+"%----------------------------------\n"
+"% Usage\n"
+"%     given a one-character string in \"character\",\n"
+"%     outputs its ascent in 1/1000ths of an inch\n"
+"\n"
+"/getascent {\n"
+"      % place character at (100, 100) and get its pathbbox\n"
+"      newpath\n"
+"      100 100 moveto\n"
+"      character true charpath flattenpath pathbbox\n"
+"\n"
+"      % save the top y coordinate of the bbox\n"
+"      /top exch def pop pop pop\n"
+"\n"
+"      % ascent is top minus baseline\n"
+"      top 100 sub\n"
+"\n"
+"      % space is special, use 6.8 points for ascent\n"
+"      character ( ) eq { 6.8 add } if\n"
+"\n"
+"      % add 1 point of padding and convert to 1/1000ths of an inch\n"
+"      1 add 1000 mul 72 div round cvi\n"
+"\n"
+"      % print results\n"
+"      buff cvs (\\t) print print\n"
+"} def\n"
+"\n"
+"\n"
+"%-----------------------------------\n"
+"\n"
+"% generate width, height an ascent for a font.\n"
+"% Usage:\n"
+"%     fname mupfname do_a_font\n"
+"\n"
+"/do_a_font {\n"
+"      % save arguments for later use\n"
+"      /mupfname exch def\n"
+"      /fname exch def\n"
+"\n"
+"      % Outut heading\n"
+"      (# This is a Mup font file\\n) print\n"
+"      (Mup font name: ) print mupfname print (\\n) print\n"
+"      (PostScript font name: ) print fname buff cvs print (\\n) print\n"
+"      (Size data:\\n) print\n"
+"\n"
+"      % Set up to use the desired font\n"
+"      fname findfont\n"
+"      12 scalefont setfont\n"
+"\n"
+"      % Mup uses ASCII character codes from 32 through 126\n"
+"      32 1 126 {\n"
+"              dup buff cvs print\n"
+"              /val exch def character 0 val put\n"
+"              getwidth\n"
+"              getheight\n"
+"              getascent\n"
+"              (\\t# ') print character print ('\\n) print\n"
+"      } for\n"
+"\n"
+"      (PostScript:\\n) print\n"
+"} def\n"
+"\n"
+"%-----------------------------------\n"
+"\n"
+"% generate the output\n"
+"PostScript_name cvn Mup_name do_a_font\n"
+"\n"
+"quit\n";
+
+void
+generate_PostScript_program(char *PS_file)
+{
+       int file;
+       int length;
+
+       if ((file = open(PS_script_file, WRITE_FLAGS, 0644)) < 0) {
+               fprintf(stderr, "Can't generate '%s'\n", PS_script_file);
+               exit(1);
+       }
+
+       /* If user gave a PostScript file, that probably implements the
+        * font, so include that in the script */
+       if (PS_file != (char *) 0) {
+               write(file, "(", 1);
+               write(file, PS_file, strlen(PS_file));
+               write(file, ") run\n", 6);
+       }
+
+       length = strlen(PostScript_program);
+       if (write(file, PostScript_program, length) != length) {
+               fprintf(stderr, "generation of PostScript program failed\n");
+               cleanup(1);
+       }
+       close(file);
+}
+
+/* remove the temp file and exit */
+void
+cleanup(int exitcode)
+{
+       unlink(PS_script_file);
+       exit(exitcode);
+}
diff --git a/mup/mup/abshorz.c b/mup/mup/abshorz.c
new file mode 100644 (file)
index 0000000..8d157db
--- /dev/null
@@ -0,0 +1,3446 @@
+/* Copyright (c) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ * Name:       abshorz.c
+ *
+ * Description:        This file contains functions for setting absolute
+ *             horizontal coordinates.
+ */
+
+#include <string.h>
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+static void barclefsigs P((void));
+static int barwithssv P((struct MAINLL *mainll_p));
+static void setclefsigwid P((struct MAINLL *mainll_p, struct CHHEAD *chhead_p));
+static void abschunk P((struct MAINLL *mainll_p, struct MAINLL *end_p));
+static void tryabs P((struct MAINLL *mainll_p, double scale, int *scores_p,
+               short measinscore[]));
+static int endchunk P((struct MAINLL *mainll_p));
+static double adjust_measwid4mrpt P((double oldmeaswid, struct CHORD *ch_p));
+static void fillclefsig P((struct CLEFSIG *clefsig_p, struct MAINLL *feed_p));
+static struct MAINLL *trymeasure P((struct MAINLL *mainll_p, double scale,
+               float *measwidth_p, float *adjust_p, int *ressv_p));
+static void setabs P((struct MAINLL *start_p, int scores, short measinscore[]));
+static void chkrestart P((struct MAINLL *start_p, struct MAINLL *end_p));
+static void setabsscore P((struct MAINLL *start_p, struct MAINLL *end_p));
+static void setabschord P((struct CHORD *ch_p, double nomx));
+static double effwidth P((struct CHORD *ch_p));
+static double bardiff P((struct MAINLL *mainll_p, struct MAINLL *end_p));
+static void fixfullmeas P((struct CHORD *ch_p, double x));
+static void restore_grpsyl_west P((void));
+static void setipw P((void));
+static void setipwgrpsyl P((struct MAINLL *mainll_p, struct GRPSYL *gs_p));
+static void setipwchord P((struct MAINLL *mainll_p));
+static void fixendings P((void));
+static void fixreh P((void));
+static void clrinhprint P((void));
+static int hidestaffs P((struct MAINLL *mainll_p, struct MAINLL *ml2_p));
+static int silent P((struct MAINLL *mainll_p, struct MAINLL *ml2_p, int s,
+               int *ressv_p));
+static int getmultinum P((struct MAINLL *mll_p));
+
+/*
+ * Depending on which type of clefsig, get its full width, or its effective
+ * width.  The latter is for user requested ones, which may overlap notes.
+ */
+#define EFF_WIDCLEFSIG(clefsig_p) \
+       ((clefsig_p)->clefsize == DFLT_SIZE ? width_clefsig(clefsig_p) : \
+       (clefsig_p)->effwidth)
+
+/*
+ * Define the padding after a clefsig.  It's greater when there's a pseudobar,
+ * because we need to allow room for carry-in ties/slurs.
+ */
+#define CSP(clefsig_p) (((clefsig_p)->bar_p == 0 ? 2.0 : 9.0) * STDPAD)
+\f
+/*
+ * Name:        abshorz()
+ *
+ * Abstract:    Set absolute horizontal coordinates of everything.
+ *
+ * Returns:     void
+ *
+ * Description: This function inserts the initial FEED of the piece.  Then, for
+ *             each section of the piece delimited by FEEDs (initial one and
+ *             user-requested ones), it breaks it into the necessary number
+ *             of scores (inserting more FEEDs), and sets all the horizontal
+ *             absolute coordinates.  Finally, it does some fix-up work.
+ */
+
+void
+abshorz()
+
+{
+       struct MAINLL *mainll_p;        /* point at any MAINLL member */
+       struct MAINLL *ml2_p;           /* point at another MAINLL member */
+       struct MAINLL *mainfeed_p;      /* point at MAINLL containing a FEED */
+       struct MAINLL *end_p;           /* point to end of a chunk of MAINLL */
+       int gotbar;                     /* found a bar in this chunk */
+
+
+       debug(16, "abshorz");
+       ml2_p = 0;              /* prevent useless 'used before set' warning */
+
+       /*
+        * The parse phase put any user-requested score feeds in the main
+        * linked list.  We must now insert a FEED before the first measure,
+        * unless the user already requested one there (unlikely!).  Later
+        * we'll add more as needed.
+        */
+       for (mainll_p = Mainllhc_p;
+            mainll_p != 0 && mainll_p->str == S_SSV;
+            mainll_p = mainll_p->next)
+               ;       /* skip by all initial SSVs */
+
+       if (mainll_p == 0)
+               pfatal("main linked list has nothing but SSVs");
+
+       if (mainll_p->str != S_FEED) {
+               mainfeed_p = newMAINLLstruct(S_FEED, 0);
+               insertMAINLL(mainfeed_p, mainll_p->prev);
+       }
+
+       /* whenever a CLEFSIG is needed after a bar line, put one there */
+       barclefsigs();
+
+       /*
+        * Find each section of the main linked list, delimited by FEEDs.
+        * For each such section, call abschunk() to set the absolute
+        * horizontal coords for things in that chunk.  At the end of each
+        * chunk, back up to avoid including SSVs/PRHEADs/LINEs/CURVEs which
+        * might follow the last measure of the chunk.  If a chunk contains no
+        * bar lines (like if there was a useless scorefeed at the end),
+        * don't call abschunk().
+        */
+       /* skip anything before first FEED first */
+       for (mainll_p = Mainllhc_p; mainll_p->str != S_FEED;
+                       mainll_p = mainll_p->next)
+               ;
+       for (;;) {
+               gotbar = NO;
+               for (end_p = mainll_p->next;
+                    end_p != 0 && end_p->str != S_FEED;
+                    ml2_p = end_p, end_p = end_p->next) {
+
+                       if (end_p->str == S_BAR)
+                               gotbar = YES;
+               }
+
+               if (gotbar == NO) {
+                       /*
+                        * If end_p is 0, this must be the end of the MLL, and
+                        * there was a final feed after all the music data.
+                        * There is no need to process this chunk.
+                        */
+                       if (end_p == 0)
+                               break;
+                       /*
+                        * This chunk must contain a BLOCKHEAD.  There is no
+                        * need to process it.  Set the absolute horizontal
+                        * coords.  Then point mainll_p at the FEED at the end
+                        * of the chunk, and go to the next loop.
+                        */
+                       mainll_p->u.feed_p->c[AW] = eff_leftmargin(mainll_p);
+                       mainll_p->u.feed_p->c[AE] = PGWIDTH -
+                                       eff_rightmargin(end_p);
+                       mainll_p->u.feed_p->c[AX] = (mainll_p->u.feed_p->c[AW]
+                                       + mainll_p->u.feed_p->c[AE]) / 2.0;
+                       mainll_p = end_p;
+                       continue;
+               }
+
+               while (ml2_p->str == S_SSV || ml2_p->str == S_PRHEAD ||
+                               ml2_p->str == S_LINE || ml2_p->str == S_CURVE)
+                       ml2_p = ml2_p->prev;
+               abschunk(mainll_p, ml2_p->next);
+               if (end_p == 0)
+                       break;
+               mainll_p = end_p;
+       }
+
+       /* restore west boundaries of GRPSYLs that have associated clefs */
+       restore_grpsyl_west();
+
+       /* set inches per whole ( c[INCHPERWHOLE] ) in the relevant structs */
+       setipw();
+
+       /* move endings that start at end of score to the next score */
+       fixendings();
+
+       /* move rehearsal marks at end of a score to the next score */
+       fixreh();
+
+       /* clear the inhibitprint flag on tablature staffs when appropriate */
+       clrinhprint();
+}
+\f
+/*
+ * Name:        barclefsigs()
+ *
+ * Abstract:    Put a CLEFSIG after each bar line that requires one.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through the main linked list, applying
+ *             SSVs as it goes.  Whenever an SSV changes clef, key, or time,
+ *             it inserts a CLEFSIG into the list to show what will need to
+ *             be printed at that point.  It also inserts one after any bar
+ *             that is a restart.
+ */
+
+static void
+barclefsigs()
+
+{
+       struct MAINLL *mainll_p;        /* point at items in main linked list*/
+       struct MAINLL *maincs_p;        /* point at MAINLL with CLEFSIG */
+       struct MAINLL *mll_p;           /* point along MLL */
+       struct CLEFSIG *clefsig_p;      /* point at CLEFSIG being filled in */
+       struct BAR *bar_p;              /* point at the bar */
+       struct CHHEAD *chhead_p;        /* point at the latest CHHEAD seen */
+       struct TIMEDSSV *tssv_p;        /* point along timed SSV list */
+       struct GRPSYL *gs_p;            /* point at a group */
+       int oldstaffs;                  /* no. of staffs before SSVs */
+       int oldvis[MAXSTAFFS + 1];      /* visibility of staffs before SSVs */
+       int oldclef[MAXSTAFFS + 1];     /* clefs before SSVs */
+       int newclef[MAXSTAFFS + 1];     /* clefs after SSVs */
+       int premidclef[MAXSTAFFS + 1];  /* clefs before applying midmeas SSVs*/
+       int oldkey[MAXSTAFFS + 1];      /* effective keys before SSVs */
+       int newkey[MAXSTAFFS + 1];      /* effective keys after SSVs */
+       int oldnorm[MAXSTAFFS + 1];     /* is staff "normal" (5 line, nontab)?*/
+       int newnorm[MAXSTAFFS + 1];     /* is staff "normal" (5 line, nontab)?*/
+       char oldtimerep[MAXTSLEN];      /* time sig before SSVs */
+       int oldclefsequal, oldkeysequal;/* were they equal on all staffs? */
+       int newclefsequal, newkeysequal;/* are they equal on all staffs? */
+       int gottimedssv;                /* were there any timed SSVs? */
+       int vidx;                       /* voice index */
+       int lastclef;                   /* last clef printed */
+       RATIONAL offset;                /* offset of a group in a measure */
+       RATIONAL lastclefoffset;        /* offset of last midmeasure clef */
+       int timechg;                    /* did they change time sig info? */
+       int change;                     /* did they change clefs/keys/time? */
+       register int s;                 /* staff number */
+
+
+       debug(16, "barclefsigs");
+       initstructs();                  /* clean out old SSV info */
+
+       /* apply any SSVs that come before the first measure */
+       mainll_p = Mainllhc_p;
+       while (mainll_p != 0 && mainll_p->str == S_SSV) {
+               asgnssv(mainll_p->u.ssv_p);
+               mainll_p = mainll_p->next;
+       }
+
+       chhead_p = 0;           /* keep lint happy; will be set before used */
+
+       /*
+        * Loop once for each bar line in the piece that has SSV(s) after it,
+        * or is a RESTART.  Whenever this occurs, insert a CLEFSIG after them
+        * if required.  RESTART always requires it.
+        */
+       for (;;) {
+               /*
+                * Find the next bar that is either followed by an SSV or has
+                * timed SSVs for the preceding measure or is a restart.  These
+                * are the cases where a CLEFSIG may be needed.  If we hit the
+                * end of the MLL, break out.
+                */
+               while (mainll_p != 0 && ! (mainll_p->str == S_BAR &&
+                               (barwithssv(mainll_p) == YES ||
+                               mainll_p->u.bar_p->timedssv_p != 0 ||
+                               mainll_p->u.bar_p->bartype == RESTART))) {
+                       switch (mainll_p->str) {
+                       case S_CHHEAD:
+                               /* remember the last chhead */
+                               chhead_p = mainll_p->u.chhead_p;
+                               break;
+                       case S_SSV:
+                               /* apply SSVs */
+                               asgnssv(mainll_p->u.ssv_p);
+                               break;
+                       }
+                       mainll_p = mainll_p->next;
+               }
+               if (mainll_p == 0) {
+                       break;
+               }
+               bar_p = mainll_p->u.bar_p;
+
+               /*
+                * If there were timed SSVs in the measure just ended, we need
+                * to make sure that any clef changes requested actually got
+                * printed before some GRPSYL.  If the clef was changed on one
+                * staff by <<score clef = whatever>>, some other staff may be
+                * affected and yet not have a GRPSYL after that point before
+                * which the clef can be printed.  In that case, we want to
+                * generate a CLEFSIG at this bar line, to print it.
+                */
+               tssv_p = bar_p->timedssv_p;
+               gottimedssv = tssv_p != 0;      /* remember if we had any */
+               if (gottimedssv) {
+                       /* get clef state before the timed SSVs */
+                       for (s = 1; s <= Score.staffs; s++) {
+                               premidclef[s] = svpath(s, CLEF)->clef;
+                       }
+                       /* assign the timed SSVs */
+                       for ( ; tssv_p != 0; tssv_p = tssv_p->next) {
+                               asgnssv(&tssv_p->ssv);
+                       }
+               }
+
+               /*
+                * Save the current number of staffs, whether they are visible,
+                * and all clefs and effective keys in case the SSVs coming
+                * up will change some of these things.  Also, save the timesig
+                * info so we can check if it changed (it is settable only in
+                * the score).
+                * Set oldnorm according to whether the staff is "normal",
+                * capable of having a clef or key sig.
+                * Set oldclefsequal and oldkeysequal according to whether all
+                * staffs have the same values for clef and key.
+                */
+               oldclefsequal = oldkeysequal = YES;
+               for (s = 1; s <= Score.staffs; s++) {
+                       oldvis[s] = svpath(s, VISIBLE)->visible;
+                       oldclef[s] = svpath(s, CLEF)->clef;
+                       oldkey[s] = eff_key(s);
+                       oldnorm[s] = svpath(s, STAFFLINES)->stafflines == 5 &&
+                                    svpath(s, STAFFLINES)->printclef == YES &&
+                                       ! is_tab_staff(s) ? YES : NO;
+                       if (s > 1 && oldclef[s - 1] != oldclef[s])
+                               oldclefsequal = NO;
+                       if (s > 1 && oldkey[s - 1] != oldkey[s])
+                               oldkeysequal = NO;
+               }
+               oldstaffs = Score.staffs;
+               strcpy(oldtimerep, Score.timerep);
+
+               /* see if clefs need printing due to timed SSVs */
+               if (gottimedssv) {
+                       /* check this on every staff */
+                       for (s = 1; s <= Score.staffs; s++) {
+                               /* find this staff's MLL structure */
+                               for (mll_p = mainll_p; mll_p->str != S_STAFF ||
+                                    mll_p->u.staff_p->staffno != s;
+                                    mll_p = mll_p->prev) {
+                                       ;
+                               }
+                               /* don't force clefsig for an invisible staff*/
+                               if (mll_p->u.staff_p->visible == NO) {
+                                       continue;
+                               }
+                               /*
+                                * Find last clef that was printed for this
+                                * measure.  Start with the value of the clef
+                                * at the previous bar (before any midmeasure
+                                * clefs).  Then update with the ones that were
+                                * printed midmeasure, until we have the last.
+                                */
+                               lastclef = premidclef[s];
+                               lastclefoffset = rneg(One);
+                               for (vidx = 0; vidx < MAXVOICES; vidx++) {
+                                       /* look down this voice */
+                                       offset = Zero;
+                                       for (gs_p = mll_p->u.staff_p->groups_p[
+                                       vidx]; gs_p != 0; gs_p = gs_p->next) {
+                                               if (gs_p->clef != NOCLEF &&
+                                               GT(offset, lastclefoffset)) {
+                                                       lastclef = gs_p->clef;
+                                                       lastclefoffset = offset;
+                                               }
+                                               offset = radd(offset,
+                                                       gs_p->fulltime);
+                                       }
+                               }
+                               /*
+                                * Set the oldclef to the last one printed.
+                                * Then later code will create a CLEFSIG, if
+                                * necessary.
+                                */
+                               oldclef[s] = lastclef;
+                       }
+               }
+
+               /*
+                * Loop through this set of SSV(s), applying them.  If we hit
+                * the end of the main linked list, break out.  We don't want
+                * to put a CLEFSIG after the last bar line, regardless of
+                * whether it changed anything.
+                */
+               mainll_p = mainll_p->next;
+               while (mainll_p != 0 && mainll_p->str == S_SSV) {
+                       asgnssv(mainll_p->u.ssv_p);
+                       mainll_p = mainll_p->next;
+               }
+               /* Retain mainll_p for later; loop onwards using mll_p.  Need */
+               /* to keep looking for SSVs in case there is a block here. */
+               mll_p = mainll_p;
+               while (mll_p != 0 && (mll_p->str == S_SSV ||
+                                     mll_p->str == S_FEED ||
+                                     mll_p->str == S_BLOCKHEAD)) {
+                       if (mll_p->str == S_SSV) {
+                               asgnssv(mll_p->u.ssv_p);
+                       }
+                       mll_p = mll_p->next;
+               }
+               if (mainll_p == 0)
+                       break;
+
+
+               /*
+                * Get the new clefs and effective keys.
+                * Again, find out if the clefs and keys are equal on all
+                * staffs.
+                */
+               newclefsequal = newkeysequal = YES;
+               for (s = 1; s <= Score.staffs; s++) {
+                       newclef[s] = svpath(s, CLEF)->clef;
+                       newkey[s] = eff_key(s);
+                       newnorm[s] = svpath(s, STAFFLINES)->stafflines == 5 &&
+                                    svpath(s, STAFFLINES)->printclef == YES &&
+                                       ! is_tab_staff(s) ? YES : NO;
+                       if (s > 1 && newclef[s - 1] != newclef[s])
+                               newclefsequal = NO;
+                       if (s > 1 && newkey[s - 1] != newkey[s])
+                               newkeysequal = NO;
+               }
+
+               /* first check if any time sig info changed */
+               if (strcmp(Score.timerep, oldtimerep) != 0)
+                       timechg = YES;
+               else
+                       timechg = NO;
+
+               /*
+                * If the bar was a restart, we treat it as if it were at the
+                * start of a score.  That is, we always print the clefs and
+                * key signatures.  The clefs are full size, and no naturals
+                * are printed.  Print the time signature only if it changed.
+                */
+               if (bar_p->bartype == RESTART) {
+                       /*
+                        * We always require a CLEFSIG.  Allocate one and put
+                        * it between where we are now and the preceding
+                        * structure.
+                        */
+                       maincs_p = newMAINLLstruct(S_CLEFSIG, 0);
+                       insertMAINLL(maincs_p, mainll_p->prev);
+                       clefsig_p = maincs_p->u.clefsig_p;
+
+                       clefsig_p->clefsize = DFLT_SIZE;        /* full size */
+                       clefsig_p->multinum = getmultinum(maincs_p);
+
+                       /*
+                        * Note: If the number of staffs is changing here, the
+                        * following might not be right.  But it doesn't
+                        * matter, because in that case this CLEFSIG will be
+                        * thrown away later anyway.
+                        */
+                       for (s = 1; s <= oldstaffs; s++) {
+                               /* draw nothing if this staff is not "normal" */
+                               if (oldnorm[s] == NO || newnorm[s] == NO)
+                                       continue;
+                               clefsig_p->prclef[s] = YES;
+                               clefsig_p->sharps[s] = newkey[s];
+                       }
+
+                       /* print the time signature if it changed */
+                       clefsig_p->prtimesig = timechg;
+
+                       continue;
+               }
+
+               /*
+                * When the number of staffs changes, special rules apply.
+                * Handle this situation and continue.
+                */
+               if (oldstaffs != Score.staffs) {
+                       /*
+                        * Identify the cases where no clefsig is needed, and
+                        * continue.  This is when time didn't change, and no
+                        * clefs or keys are to be printed.  Clefs are to be
+                        * printed only when all the old staffs had the same
+                        * clef, all the new ones had the same clef, and the
+                        * old and new clefs are different.  The analogous rule
+                        * holds for keys.  This is because, when the number of
+                        * staffs changes, we can't really tell which old staff
+                        * corresponds to which new staff (if any), so it's
+                        * silly to print a clef or key change on any.
+                        */
+                       if (timechg == NO &&
+                                       (oldclefsequal == NO ||
+                                        newclefsequal == NO ||
+                                        oldclef[1] == newclef[1]) &&
+                                       (oldkeysequal == NO ||
+                                        newkeysequal == NO ||
+                                        oldkey[1] == newkey[1])) {
+                               /* no CLEFSIG needed here */
+                               continue;
+                       }
+
+                       /*
+                        * Something changed that requires a CLEFSIG.  Allocate
+                        * one and put it between where we are now and the
+                        * preceding structure, the last SSV we applied.
+                        */
+                       maincs_p = newMAINLLstruct(S_CLEFSIG, 0);
+                       insertMAINLL(maincs_p, mainll_p->prev);
+                       clefsig_p = maincs_p->u.clefsig_p;
+
+                       /* any clefs to be printed should be small size */
+                       clefsig_p->clefsize = SMALLSIZE;
+                       clefsig_p->multinum = getmultinum(maincs_p);
+
+                       /*
+                        * Since the number of staffs is changing, there will
+                        * be a scorefeed here, and this CLEFSIG will be at the
+                        * end of the first score.  Every old staff will have
+                        * the same info printed by the CLEFSIG, except that
+                        * clef and key never exist on "abnormal" staffs. Check
+                        * against staff 1 since we know that has to exist on
+                        * both sides.  It doesn't hurt to mark even invisible
+                        * ones.
+                        */
+                       for (s = 1; s <= oldstaffs; s++) {
+
+                               /* draw nothing if this staff is not "normal" */
+                               if (oldnorm[s] == NO || newnorm[s] == NO)
+                                       continue;
+                               /*
+                                * Draw the new clef if the clefs on each score
+                                * are consistent and they changed.
+                                */
+                               if (oldclefsequal && newclefsequal &&
+                                               oldclef[1] != newclef[1])
+                                       clefsig_p->prclef[s] = YES;
+
+                               /*
+                                * Draw the new key if the keys on each score
+                                * are consistent and they changed.  See below
+                                * for a more detailed explanation.
+                                */
+                               if (oldkeysequal && newkeysequal &&
+                                               oldkey[1] != newkey[1]) {
+                                       clefsig_p->sharps[s] = newkey[1];
+
+                                       if (newkey[1] == 0) {
+                                               clefsig_p->naturals[s] =
+                                                               oldkey[1];
+                                       } else if (svpath(s, CANCELKEY)->
+                                                       cancelkey == YES) {
+                                               if (oldkey[1] * newkey[1] < 0) {
+                                                       /* 1 has #s, 1 has &s */
+                                                       clefsig_p->naturals[s] =
+                                                               oldkey[1];
+                                               } else if (abs(oldkey[1]) >
+                                                               abs(newkey[1])){
+                                                       /* new has fewer accs*/
+                                                       clefsig_p->naturals[s] =
+                                                       oldkey[1] - newkey[1];
+                                               }
+                                       }
+                               }
+                       }
+
+                       /* print the time signature if it changed */
+                       if (timechg == YES)
+                               clefsig_p->prtimesig = YES;
+
+                       /* set clefsig's effective width */
+                       setclefsigwid(maincs_p, chhead_p);
+
+                       continue;
+               }
+
+
+               change = timechg;
+
+               /* see if anything else requiring a CLEFSIG changed */
+               for (s = 1; s <= oldstaffs; s++) {
+                       if (oldvis[s] == NO ||
+                           svpath(s, VISIBLE)->visible == NO)
+                               continue;
+                       if (oldclef[s] != newclef[s])
+                               change = YES;
+                       if (oldkey[s] != newkey[s])
+                               change = YES;
+                       if (change == YES)
+                               break;  /* don't waste any more time looping */
+               }
+               if (change == NO)
+                       continue;       /* no visible time, key, clef changed*/
+
+               /*
+                * If we get here, it means either the clef, effective key, or
+                * time changed on some visible staff.  Allocate a CLEFSIG and
+                * put it between where we are now and the preceding structure,
+                * which is the last SSV we applied.
+                */
+               maincs_p = newMAINLLstruct(S_CLEFSIG, 0);
+               insertMAINLL(maincs_p, mainll_p->prev);
+               clefsig_p = maincs_p->u.clefsig_p;
+
+               /* any clefs to be printed should be small size */
+               clefsig_p->clefsize = SMALLSIZE;
+               clefsig_p->multinum = getmultinum(maincs_p);
+
+               /*
+                * Loop through the staffs, marking in the CLEFSIG what should
+                * be drawn.
+                */
+               for (s = 1; s <= Score.staffs; s++) {
+                       /* draw nothing if this staff is invisible */
+                       if (oldvis[s] == NO)
+                               continue;
+
+                       /* draw nothing if this staff is not "normal" */
+                       if (oldnorm[s] == NO || newnorm[s] == NO)
+                               continue;
+
+                       /* draw the new clef if the clef changed */
+                       if (oldclef[s] != newclef[s])
+                               clefsig_p->prclef[s] = YES;
+
+                       /*
+                        * If the effective key changed, draw the new key
+                        * signature.  But if the new key has 0 sharps, we
+                        * should draw naturals in the shape of the old key
+                        * signature.  And if cancelkey is set, and a sharp key
+                        * is changing to a flat key or vice versa, or the
+                        * number of sharps or flats is being reduced, we need
+                        * enough naturals to cancel the ones being removed.
+                        */
+                       if (oldkey[s] != newkey[s]) {
+                               clefsig_p->sharps[s] = newkey[s];
+                               if (newkey[s] == 0) {
+                                       clefsig_p->naturals[s] = oldkey[s];
+                               } else if (svpath(s, CANCELKEY)->
+                                               cancelkey == YES) {
+                                       if (oldkey[s] * newkey[s] < 0) {
+                                               /* 1 has sharps, 1 has flats */
+                                               clefsig_p->naturals[s] =
+                                                       oldkey[s];
+                                       } else if (abs(oldkey[s]) >
+                                                       abs(newkey[s])) {
+                                               /* new has fewer accidentals */
+                                               clefsig_p->naturals[s] =
+                                                       oldkey[s] - newkey[s];
+                                       }
+                               }
+                       }
+               }
+
+               /*
+                * Finally, print the time signature if it changed.
+                */
+               if (timechg == YES)
+                       clefsig_p->prtimesig = YES;
+
+               /* set clefsig's effective width, and widestclef */
+               setclefsigwid(maincs_p, chhead_p);
+       }
+}
+\f
+/*
+ * Name:        barwithssv()
+ *
+ * Abstract:    Is this bar followed by SSV(s), ignoring FEEDs and BLOCKHEADs?
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function is called with the MLL structure for a BAR.
+ *             Ignoring the possible presence of FEEDs and BLOCKHEADs, return
+ *             YES if the next structure is an SSV.
+ */
+
+static int
+barwithssv(mainll_p)
+
+struct MAINLL *mainll_p;       /* for the BAR */
+
+{
+       struct MAINLL *mll_p;           /* loop after the BAR */
+
+
+       for (mll_p = mainll_p->next; mll_p != 0; mll_p = mll_p->next) {
+               switch (mll_p->str) {
+               case S_SSV:
+                       return (YES);
+               case S_FEED:
+               case S_BLOCKHEAD:
+                       break;          /* ignore these, keep looking */
+               default:
+                       return (NO);
+               }
+       }
+
+       return (NO);            /* hit end of MLL */
+}
+\f
+/*
+ * Name:        setclefsigwid()
+ *
+ * Abstract:    Set effective width and widest clef of a user requested clefsig.
+ *
+ * Returns:     void
+ *
+ * Description: This function is called with a user-requested clefsig.  If it
+ *             contains clefs, they should be printed before the bar line.  If
+ *             we are lucky, part or all of the clef's widths can overlap notes
+ *             on other staffs.  The effective width is the full width minus
+ *             the amount that can overlap.  This function sets the effective
+ *             width of the clefsig, and the widest clef that it contains.  We
+ *             need to do this now, because we need to use the pseudo absolute
+ *             coords set by relxchord() before they are overwritten later in
+ *             abshorz.c.
+ */
+
+static void
+setclefsigwid(mainll_p, chhead_p)
+
+struct MAINLL *mainll_p;       /* point at the given clefsig's MLL struct */
+struct CHHEAD *chhead_p;       /* point at the preceding chhead */
+
+{
+       struct MAINLL *m2_p;            /* another pointer down the MLL */
+       struct CLEFSIG *clefsig_p;      /* point at a clefsig */
+       struct CHORD *ch_p;             /* point at a chord */
+       struct STAFF *staff_p;          /* point at a staff */
+       struct GRPSYL *gs_p;            /* point at a group in a voice */
+       struct GRPSYL *gs2_p;           /* point at a group in a chord */
+       float lasteast;                 /* phony AE of last chord in measure */
+       float size;                     /* to be used for clef */
+       float clefspace;                /* space needed for printing clefs */
+       float clefwid;                  /* width of a clef */
+       float widestclef;               /* width of the widest to be printed */
+       float staffscale;               /* scale for a staff */
+       float gap;                      /* between last group & last chord */
+       int staffno;                    /* staff number, 1 to MAXSTAFFS */
+       int clef;                       /* clef type */
+       int v;                          /* voice number, 0 to 2 */
+
+
+       debug(16, "setclefsigwid");
+
+       clefsig_p = mainll_p->u.clefsig_p;      /* convenient pointer */
+
+       /*
+        * Although relxchord() overlaps chords in various ways, it does not
+        * overlap the last chord in the measure with anything following.
+        * And it sets phony absolute coordinates for each chord, based on
+        * pretending that everything is packed as tight as possible.  So, as
+        * the rightmost coord of all groups, we can use the AE of the last
+        * chord of the measure just ended.
+        */
+       for (ch_p = chhead_p->ch_p; ch_p->ch_p != 0; ch_p = ch_p->ch_p)
+               ;
+       lasteast = ch_p->c[AE];
+
+       /*
+        * Init the amount of space needed for clefs to be printed.  We start
+        * at zero, and whenever a clef is to be printed, we find out how much
+        * of it can't be overlapped; and clefspace keeps track of the maximum
+        * of these for all staffs.
+        */
+       clefspace = 0.0;
+
+       widestclef = 0.0;       /* max width of any clef to be printed */
+
+       size = 3.0/4.0 * DFLT_SIZE;     /* small size clefs */
+
+       /*
+        * Loop backwards through the preceding measure, looking for visible
+        * staffs to process.
+        */
+       for (m2_p = mainll_p; m2_p->str != S_CHHEAD; m2_p = m2_p->prev) {
+
+               if (m2_p->str != S_STAFF || m2_p->u.staff_p->visible == NO)
+                       continue;
+
+               staff_p = m2_p->u.staff_p;
+               staffno = staff_p->staffno;
+
+               /* if no clef, it doesn't need any space */
+               if (clefsig_p->prclef[staffno] == NO)
+                       continue;
+
+               /* find width of this clef, including padding */
+               clef = svpath(staffno, CLEF)->clef;
+               staffscale = svpath(staffno, STAFFSCALE)->staffscale;
+               clefwid = (clefwidth(clef, YES) + CLEFPAD) * staffscale;
+
+               /* remember biggest clef width */
+               if (clefwid > widestclef)
+                       widestclef = clefwid;
+
+               /* loop through all voices on this staff */
+               for (v = 0; v < MAXVOICES; v++) {
+
+                       /* find last group in this voice */
+                       gs_p = staff_p->groups_p[v];
+                       if (gs_p == 0)
+                               continue;
+                       for ( ; gs_p->next != 0; gs_p = gs_p->next)
+                               ;
+
+                       /*
+                        * Find out what chord this group belongs to, by
+                        * searching down the GRPSYL list hanging off each
+                        * chord in this measure.
+                        */
+                       for (ch_p = chhead_p->ch_p; ch_p != 0;
+                                       ch_p = ch_p->ch_p) {
+                               for (gs2_p = ch_p->gs_p; gs2_p != 0;
+                                               gs2_p = gs2_p->gs_p) {
+                                       /* if found, or after the right staff*/
+                                       if (gs2_p == gs_p || gs2_p->staffno >
+                                                            gs_p->staffno)
+                                               break;
+                               }
+
+                               /*
+                                * If we found it, find the gap between this
+                                * group's AE and the last chord's.  If the
+                                * amount of the clef's width that does not fit
+                                * in that gap is the greatest so far, save it.
+                                */
+                               if (gs2_p == gs_p) {
+                                       gap = lasteast -
+                                               (ch_p->c[AX] + gs_p->c[RE]);
+
+                                       if (clefwid - gap > clefspace)
+                                               clefspace = clefwid - gap;
+
+                                       break;  /* look no more */
+                               }
+                       }
+               } /* loop through voices on a staff */
+       } /* loop through staffs */
+
+       clefsig_p->widestclef = widestclef;
+
+       /* (effective width) = (real width) - (what can overlap) */
+       clefsig_p->effwidth = width_clefsig(clefsig_p) -
+                       (widestclef - clefspace);
+}
+\f
+/*
+ * Name:        abschunk()
+ *
+ * Abstract:    Set the absolute horz. coords of everything in one chunk.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given a chunk of the piece, which is
+ *             delimited by FEEDs.  It estimates how many inches should
+ *             be allocated to each whole note of time.  Then it calls
+ *             tryabs() repeatedly, trying to find a scale factor that
+ *             will avoid having the last score be too empty.  Finally,
+ *             it calls setabs() to set the absolute horizontal coordinates
+ *             of everything in the chunk.
+ */
+
+static void
+abschunk(start_p, end_p)
+
+struct MAINLL *start_p;                /* FEED at start of chunk of MAINLL */
+struct MAINLL *end_p;          /* points after last struct in chunk (or 0) */
+
+{
+       float totwidth;         /* total minimal width of this chunk */
+       float totpseudodur;     /* total pseudodur of measures in this chunk */
+       struct MAINLL *mainll_p;/* point at items in main linked list*/
+       struct CHORD *ch_p;     /* point at a chord */
+       short *measinscore;     /* malloc'ed array; bars in each score */
+       float packfact;         /* as it was at the start of this score */
+       float lowscale;         /* small guess at inches per whole */
+       float highscale;        /* large guess at inches per whole */
+       float midscale;         /* average of low and high scale */
+       float measwidth;        /* width of a measure */
+       int numbars;            /* number of measures in this chunk */
+       int scores;             /* number of scores needed for this chunk */
+       int reqscores;          /* the number of score required */
+       int trial;              /* trial number for getting correct scale */
+
+
+       debug(16, "abschunk file=%s line=%d", start_p->inputfile,
+                       start_p->inputlineno);
+
+       /*
+        * For our first estimate of how wide to make everything, we need to
+        * add up the total minimal width and total elapsed time.
+        */
+       /* must apply all SSVs from start, to get the right time sig */
+       initstructs();                  /* clean out old SSV info */
+       for (mainll_p = Mainllhc_p; mainll_p != start_p;
+                       mainll_p = mainll_p->next) {
+               if (mainll_p->str == S_SSV)
+                       asgnssv(mainll_p->u.ssv_p);
+       }
+
+       packfact = Score.packfact;      /* use current value (start of score) */
+       totwidth = 0;           /* start totals at 0 */
+       totpseudodur = 0;
+       numbars = 0;
+
+       /* loop through chunk, adding up width and time */
+       for ( ; mainll_p != end_p; mainll_p = mainll_p->next) {
+
+               switch (mainll_p->str) {
+               case S_SSV:
+                       /* assign to keep time sig accurate */
+                       asgnssv(mainll_p->u.ssv_p);
+                       break;
+
+               case S_CHHEAD:
+                       /*
+                        * Add in the minimum widths of all chords in the
+                        * measure, and add up the pseudoduration.  There are
+                        * special things done for mrpt: 1) if all staff(s)
+                        * have mrpt, we don't want them to "deserve" as much
+                        * space as an mr, so reduce their pseudodur; 2) the
+                        * minimum width of the measure must be made wide
+                        * enough to contain the symbol.  Also, allow room
+                        * for any midmeasure clefs.  (This will happen
+                        * automatically, because the group boundaries still
+                        * include their preceding midmeasure clefs at this
+                        * point.)
+                        */
+                       measwidth = 0;
+                       ch_p = mainll_p->u.chhead_p->ch_p;
+                       if (ABSDIFF(ch_p->width, TEMPMRPTWIDTH) < 0.001) {
+                               /* the 0.001 is to allow for roundoff error */
+                               ch_p->pseudodur *= 0.5;
+                       }
+                       for ( ; ch_p != 0; ch_p = ch_p->ch_p) {
+                               measwidth += ch_p->width;
+                               /* only count time if there is a real width */
+                               /* (nonspace, or "us", or padded "s") */
+                               if (ch_p->width != 0)
+                                       totpseudodur += ch_p->pseudodur;
+                       }
+                       /* add this measure into the total */
+                       totwidth += adjust_measwid4mrpt(measwidth,
+                                       mainll_p->u.chhead_p->ch_p);
+                       break;
+
+               case S_CLEFSIG:
+                       /* width of clef/key/time to print when changing */
+                       totwidth += EFF_WIDCLEFSIG(mainll_p->u.clefsig_p) +
+                                       CSP(mainll_p->u.clefsig_p);
+                       break;
+
+               case S_BAR:
+                       /* add width of bar line, and incr no. of bars */
+                       totwidth += width_barline(mainll_p->u.bar_p);
+                       numbars++;
+                       break;
+               }
+       }
+
+       /*
+        * Allocate the measinscore array.  We need an element for each score
+        * that this chunk will be broken up into.  We don't yet know how
+        * many that will be.  So allocate enough for the worst case, where
+        * each measure is so wide that it has to go on a separate score.
+        */
+       MALLOCA(short, measinscore, numbars + 1);
+
+       /*
+        * Our first trial is to allow "packfact" times the minimal
+        * width we have just added up, partly to allow for the stuff at the
+        * start of each score (more CLEFSIGs to be inserted after we know
+        * where the FEEDs are going to be), and partly so things can spread
+        * out nicely.
+        */
+       lowscale = packfact * totwidth / totpseudodur;
+       tryabs(start_p, lowscale, &scores, measinscore);
+
+       /*
+        * If the whole chunk fits on one score, just set the absolute coords
+        * for this score and get out.
+        */
+       if (scores == 1) {
+               setabs(start_p, scores, measinscore);
+               FREE(measinscore);
+               return;
+       }
+
+       /*
+        * However many scores tryabs() says were needed, that is what we will
+        * require.  But it's likely that the last score is far from filled up.
+        * It would look bad to just spread out the stuff in the last score.
+        * We want to "balance the load".
+        *
+        * So make up a new scale (highscale) which would probably force us to
+        * use an additional score.  Then loop, binary searching, to find a
+        * value for scale almost as big as possible without forcing a new
+        * score.
+        */
+       reqscores = scores;
+       highscale = 3.0 * lowscale;
+       for (trial = 0; trial < 12; trial++) {
+               midscale = (lowscale + highscale) / 2;
+               tryabs(start_p, midscale, &scores, measinscore);
+               if (scores > reqscores) {
+                       highscale = midscale;
+               } else { /* must be equal, can never be less */
+                       lowscale = midscale;
+               }
+       }
+       /*
+        * If the last one we tried is not a good one, we have to run tryabs
+        * again to reset the scores array properly.
+        */
+       if (midscale != lowscale) {
+               tryabs(start_p, lowscale, &scores, measinscore);
+       }
+
+       setabs(start_p, scores, measinscore);
+
+       FREE(measinscore);
+}
+\f
+/*
+ * Name:        tryabs()
+ *
+ * Abstract:    Given trial scale, find how many scores are needed, etc.
+ *
+ * Returns:     void
+ *
+ * Description: This function, given a proposed scale factor for a chunk
+ *             delimited by FEEDs, figures out how many measures would
+ *             fit on each score.
+ */
+
+static void
+tryabs(start_p, scale, scores_p, measinscore)
+
+struct MAINLL *start_p;                /* FEED at start of chunk of MAINLL */
+double scale;                  /* inches per "whole" unit of time */
+int *scores_p;                 /* return number of scores needed */
+short measinscore[];           /* return number of measures in each score */
+
+{
+       struct MAINLL *mainll_p;/* points along main linked list */
+       struct MAINLL *new_p;   /* points at first struct in new measure */
+       struct MAINLL *ml2_p;   /* another general pointer into MAINLL */
+       struct MAINLL *prevfeed_p;/* where previous FEED is or would go */
+       float remwidth;         /* width remaining on this score */
+       float userdelta;        /* (user right margin) - (normal right margin)*/
+       int atend;              /* are we at the end of the chunk? */
+       struct CLEFSIG clefsig; /* temporary CLEFSIG for start of each score */
+       struct BAR bar;         /* temp BAR; may be need by the above CLEFSIG*/
+       float measwidth;        /* width needed by one measure */
+       float adjust;           /* bar line adjust if last measure in score */
+       int ressv;              /* do we have to re-initstructs() and re-SSV?*/
+
+
+       debug(32, "tryabs file=%s line=%d scale=%f", start_p->inputfile,
+                       start_p->inputlineno, (float)scale);
+       /* must apply all SSVs from start, to get the right clef/key/time; */
+       setssvstate(start_p);
+
+       mainll_p = start_p;
+
+       /*
+        * Set up for beginning of first score in this chunk.
+        * Find out how much width is available, allowing for
+        * margins and stuff to the left (labels, etc.).
+        */
+       *scores_p = 0;                  /* no scores yet */
+       /* left margin may have user override; for now, assume right doesn't */
+       remwidth = PGWIDTH - eff_rightmargin((struct MAINLL *)0)
+                               - eff_leftmargin(start_p);
+       remwidth -= width_left_of_score(start_p);
+       measinscore[0] = 0;
+
+       /*
+        * If the user overrode the right margin at the end of this chunk, we
+        * need to know the difference between what they requested and what the
+        * normal value is.  If they didn't, userdelta will be zero.
+        */
+       userdelta = eff_rightmargin(start_p->next) -
+                   eff_rightmargin((struct MAINLL *)0);
+
+       prevfeed_p = start_p;   /* init previous FEED to the start of chunk */
+
+       /*
+        * We need to set up a provisional CLEFSIG containing what would need
+        * to be printed at the start of this new score.  We can't put it in
+        * the real MAINLL yet, since this function is just trying a
+        * possibility, and cannot alter MAINLL for real.  Set a pointer to
+        * a bar, which in real life would be allocated by fillclefsig.
+        * Subtract the clefsig's width from what we have left to work with.
+        */
+       (void)memset((char *)&clefsig, 0, sizeof(clefsig));
+       (void)memset((char *)&bar, 0, sizeof(bar));
+       clefsig.bar_p = &bar;
+       fillclefsig(&clefsig, mainll_p);
+       remwidth -= width_clefsig(&clefsig) + CSP(&clefsig);
+
+       /* loop through chunk, once per measure, finding where FEEDs would go*/
+       for (;;) {
+               /* get width of this measure, and where next one starts */
+               new_p = trymeasure(mainll_p, scale, &measwidth, &adjust,&ressv);
+
+               atend = endchunk(new_p);        /* last measure of chunk? */
+
+               if (!atend && (measwidth - adjust) <= remwidth ||
+                    atend && (measwidth - adjust) <= remwidth - userdelta ||
+                    measinscore[*scores_p] == 0) {
+                       /*
+                        * There is room for this measure on this score, or
+                        * there are no measures here yet so we better force
+                        * this one onto there.  We'll fail later if this
+                        * in fact cannot fit.
+                        * Subtract its width from what's left on this score,
+                        * and increment the number of measures on it.  Point
+                        * at the next measure.
+                        */
+                       remwidth -= measwidth;
+                       measinscore[*scores_p]++;
+                       mainll_p = new_p;
+
+                       /* if we are at the end, inc no. of scores & return */
+                       if (atend) {
+                               (*scores_p)++;
+                               return;
+                       }
+               } else {
+                       /*
+                        * There is not room for this measure on this score.
+                        * Increment the number of scores needed.
+                        */
+                       (*scores_p)++;
+
+                       /*
+                        * If this last measure ended with SSV(s) after the
+                        * bar line that would cause a CLEFSIG, we need to
+                        * undo the change so that the new score will start
+                        * with the old info.  Sadly, we'll have to init
+                        * the SSVs and apply them over from the beginning.
+                        */
+                       if (ressv) {
+                               setssvstate(mainll_p);
+                       }
+
+                       /*
+                        * Find out how much width is available, allowing for
+                        * margins and stuff to the left (labels, etc.).
+                        * For now, assume this is not the last score, so no
+                        * user margin override.
+                        */
+                       remwidth = PGWIDTH - eff_rightmargin((struct MAINLL *)0)
+                                        - eff_leftmargin((struct MAINLL *)0);
+                       remwidth -= pwidth_left_of_score(mainll_p, prevfeed_p);
+
+                       prevfeed_p = mainll_p;  /* where feed would go */
+
+                       /*
+                        * We need to set up a provisional CLEFSIG containing
+                        * what would need to be printed at the start of this
+                        * new score.  We can't put it in the real MAINLL yet,
+                        * since this function is just trying a possibility,
+                        * and cannot alter MAINLL for real.  In case a repeat
+                        * start is going to be needed, have a bar pointer
+                        * ready.  Subtract the clefsig's width from what we
+                        * have left to work with.
+                        */
+                       (void)memset((char *)&clefsig, 0, sizeof(clefsig));
+                       (void)memset((char *)&bar, 0, sizeof(bar));
+                       clefsig.bar_p = &bar;
+                       fillclefsig(&clefsig, mainll_p);
+                       remwidth -= width_clefsig(&clefsig) + CSP(&clefsig);
+                       measinscore[*scores_p] = 0; /* no bars here yet */
+
+                       /*
+                        * If the measure we just figured is too wide for the
+                        * new score we are about to begin, it must be that
+                        * we are just padding things too much.  (If there
+                        * really is too much stuff in the measure, we'll fail
+                        * later.)  So assume we'll cram in it anyway, set up
+                        * 0 width remaining, and prepare for next measure.
+                        * We have to reapply the SSVs we removed above, since
+                        * we won't be calling trymeasure() again for that
+                        * measure.
+                        *
+                        * If the measure fits, don't do any of this.  Just let
+                        * trymeasure figure the same one over again, next
+                        * time around.
+                        */
+                       if (!atend && measwidth > remwidth ||
+                            atend && measwidth > remwidth - userdelta) {
+                               if (ressv) {
+                                       for (ml2_p = mainll_p; ml2_p != new_p;
+                                                       ml2_p = ml2_p->next) {
+                                               if (ml2_p->str == S_SSV)
+                                                       asgnssv(ml2_p->u.ssv_p);
+                                       }
+                               }
+                               remwidth = 0;
+                               measinscore[*scores_p] = 1;
+                               mainll_p = new_p;
+
+                               /* if at the end, fix no. of scores & ret */
+                               if (atend) {
+                                       (*scores_p)++;
+                                       return;
+                               }
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        endchunk()
+ *
+ * Abstract:    Is this MLL item near the end of a chunk?
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function, given a main linked list structure, finds out
+ *             whether there is nothing left in this chunk of the MLL other
+ *             than possibly SSVs/PRHEADs/LINEs/CURVEs.  The very end of a
+ *             chunk is determined by the end of the MLL, or the FEED that
+ *             begins the next chunk.
+ */
+
+static int
+endchunk(mainll_p)
+
+struct MAINLL *mainll_p;       /* points into the MAINLL */
+
+{
+       /* loop past any SSVs or PRHEADs */
+       while (mainll_p != 0 && (mainll_p->str == S_SSV ||
+                                mainll_p->str == S_PRHEAD ||
+                                mainll_p->str == S_LINE ||
+                                mainll_p->str == S_CURVE))
+               mainll_p = mainll_p->next;
+
+       /* if we hit the end or a FEED, we found the end of this chunk */
+       if (mainll_p == 0 || mainll_p->str == S_FEED)
+               return (YES);
+       return (NO);
+}
+\f
+/*
+ * Name:        adjust_measwid4mrpt()
+ *
+ * Abstract:    If the measure contains a mrpt, adjust the measure's width.
+ *
+ * Returns:     the new (possibly increased) measure width
+ *
+ * Description: This function, given the supposed width of a measure and the
+ *             first chord of the measure, looks to see if there is an mrpt
+ *             in the measure.  If so, it enlarges the chord(s) in the measure
+ *             if necessary, to make sure there's enough room for the symbol.
+ */
+
+static double
+adjust_measwid4mrpt(oldmeaswid, ch_p)
+
+double oldmeaswid;     /* old measure width */
+struct CHORD *ch_p;    /* points at a chord, should be first chord in meas */
+
+{
+       int gotmrpt;            /* is there an mrpt? */
+       struct GRPSYL *gs_p;    /* point down list of GRPSYLs in chord */
+       float newmeaswid;       /* possible new measure width */
+       float thismrpt;         /* space needed by one mrpt and its padding */
+       float increase;         /* how much bigger must we make the measure? */
+
+
+       /*
+        * Scan down the first chord and see if any groups have an mrpt.
+        */
+       gotmrpt = NO;
+       newmeaswid = 0.0;
+       for (gs_p = ch_p->gs_p; gs_p != 0; gs_p = gs_p->gs_p) {
+               if (is_mrpt(gs_p)) {
+                       gotmrpt = YES;
+                       /* get width of this mrpt + its padding, if any */
+                       thismrpt = width(FONT_MUSIC, DFLT_SIZE, C_MEASRPT) *
+                               svpath(gs_p->staffno, STAFFSCALE)->staffscale +
+                               gs_p->padding;
+                       if (thismrpt > newmeaswid) {
+                               newmeaswid = thismrpt;
+                       }
+               }
+       }
+
+       if (gotmrpt == NO)
+               return (oldmeaswid);    /* no mrpt, return original width */
+
+       /* if measure is already wider than all mrpts, return unchanged */
+       if (oldmeaswid >= newmeaswid)
+               return (oldmeaswid);
+
+       /*
+        * Some staff(s) have mrpts, and the existing chord(s) add up to
+        * narrower than the width of an mrpt.  It's really rare that this
+        * could happen if there is only one chord.  So we will handle it by
+        * forcing the first chord to be wider, rather than allocating the
+        * extra amongst all the chords.
+        */
+       if (ABSDIFF(ch_p->width, TEMPMRPTWIDTH) < 0.001) {
+               /* first chord is all mrpt, so no other chords exist; */
+               /* the 0.001 is to allow for roundoff error */
+               ch_p->c[RE] = newmeaswid / 2.0;
+               ch_p->c[RW] = -newmeaswid / 2.0;
+               ch_p->width = newmeaswid;
+       } else {
+               /* add extra to the right side of the first chord */
+               increase = newmeaswid - oldmeaswid;
+               ch_p->c[RE] += increase;
+               ch_p->width += increase;
+       }
+
+       return (newmeaswid);
+}
+\f
+/*
+ * Name:        fillclefsig()
+ *
+ * Abstract:    Fill the CLEFSIG for after a FEED.
+ *
+ * Returns:     void
+ *
+ * Description: This function, given an empty CLEFSIG structure and a pointer
+ *             to a FEED structure in the MAINLL, fills the CLEFSIG according
+ *             to what should be printed.  If called from tryabs() (bar_p !=
+ *             0), the bar will be set to REPEATSTART if need be, based on the
+ *             type of the preceding bar.  If called from setabs() (bar_p ==
+ *             0), the same will be done, if need be, after allocating a BAR
+ *             and setting the pointer to it.  In one bizarre case, abschunk()
+ *             calls here directly, and this is treated the same as tryabs();
+ *             bar_p != 0.
+ */
+
+static void
+fillclefsig(clefsig_p, feed_p)
+
+struct CLEFSIG *clefsig_p;     /* points at empty clefsig to be filled in */
+struct MAINLL *feed_p;         /* points at a FEED in the MAINLL */
+
+{
+       struct MAINLL *mainll_p;/* points along the MAINLL */
+       struct BAR *realbar_p;  /* point at bar before this feed */
+       float barpad;           /* padding on that bar */
+       int s;                  /* staff number */
+
+
+       /*
+        * On every visible staff, the clef and key signature are to
+        * be printed.
+        */
+       for (s = 1; s <= Score.staffs; s++) {
+               if (svpath(s, VISIBLE)->visible == NO)
+                       continue;       /* invisible */
+               clefsig_p->prclef[s] = YES;
+               clefsig_p->sharps[s] = eff_key(s);
+       }
+
+       /* clefs to be printed should be regular size */
+       clefsig_p->clefsize = DFLT_SIZE;
+
+       /*
+        * The time signature is to be printed on the first score, or if
+        * it just changed.  Search back to see if there was a CLEFSIG just
+        * before this FEED where the time changed, or if this is the first
+        * measure.
+        */
+       for (mainll_p = feed_p->prev; mainll_p != 0 &&
+                       mainll_p->str != S_BAR && mainll_p->str != S_CLEFSIG;
+                       mainll_p = mainll_p->prev)
+               ;
+
+       /* see chkrestart() for explanation of the bar_p->c[AY] part of this */
+       if (mainll_p == 0 ||
+                       mainll_p->str == S_CLEFSIG &&
+                               mainll_p->u.clefsig_p->prtimesig == YES ||
+                       mainll_p->str == S_BAR &&
+                               mainll_p->u.bar_p->c[AY] > 0.0)
+               clefsig_p->prtimesig = YES;
+
+       /*
+        * If the preceding BAR (if any) was a REPEATSTART or REPEATBOTH, it
+        * has to be "split up".  Search back to find this bar.
+        */
+       for (mainll_p = feed_p->prev; mainll_p != 0 && mainll_p->str != S_BAR;
+                       mainll_p = mainll_p->prev)
+               ;
+
+       if (clefsig_p->bar_p != 0) {
+               /*
+                * tryabs() called us.  If there is a preceding bar, and it is
+                * REPEATSTART or REPEATBOTH, it would have to be "split", and
+                * our pseudo bar must be made a REPEATSTART.  Otherwise, the
+                * the pseudo bar should be INVISBAR since nothing really
+                * should be printed there.  Since tryabs() called us, we can't
+                * tamper with the preceding (real) bar.  That's okay; the
+                * change would just make that bar slightly narrower, so
+                * things will still fit on that score.
+                */
+               if (mainll_p != 0 &&
+                               (mainll_p->u.bar_p->bartype == REPEATSTART ||
+                                mainll_p->u.bar_p->bartype == REPEATBOTH)) {
+                       clefsig_p->bar_p->bartype = REPEATSTART;
+               } else {
+                       clefsig_p->bar_p->bartype = INVISBAR;
+               }
+       } else {
+               /*
+                * setabs() called us, so we must allocate a pseudo bar and
+                * point the clefsig at it.  The same splitting rules apply as
+                * for tryabs(), except since we're now doing it for real, we
+                * have to really alter the preceding bar's bar type in those
+                * cases.  This preceding bar's AW and AX must also be
+                * adjusted, since the bar is now going to be narrower than it
+                * was before.
+                */
+               CALLOC(BAR, clefsig_p->bar_p, 1);
+
+               if (mainll_p != 0 &&
+                               (mainll_p->u.bar_p->bartype == REPEATSTART ||
+                                mainll_p->u.bar_p->bartype == REPEATBOTH)) {
+
+                       realbar_p = mainll_p->u.bar_p;
+                       realbar_p->bartype = realbar_p->bartype == REPEATSTART ?
+                                       realbar_p->precbartype : REPEATEND;
+                       realbar_p->c[AW] = realbar_p->c[AE] - 
+                                       width_barline(realbar_p);
+                       /* to get AX, temporarily set padding to 0; find the */
+                       /* width of the resulting nonpadded bar, and subtract*/
+                       /* half of that from AE; then restore padding */
+                       barpad = realbar_p->padding;
+                       realbar_p->padding = 0;
+                       realbar_p->c[AX] = realbar_p->c[AE] -
+                                       width_barline(realbar_p) / 2;
+                       realbar_p->padding = barpad;
+                       clefsig_p->bar_p->bartype = REPEATSTART;
+               } else {
+                       clefsig_p->bar_p->bartype = INVISBAR;
+               }
+       }
+}
+\f
+/*
+ * Name:        trymeasure()
+ *
+ * Abstract:    Find trial width of a measure.
+ *
+ * Returns:     Pointer to the first MAINLL structure of the next measure,
+ *             or 0 if we hit the end of MAINLL.
+ *
+ * Description: This function, given a pointer to the first MAINLL structure
+ *             in a measure (or the FEED preceding), finds and fills in the
+ *             width of the measure.
+ */
+
+static struct MAINLL *
+trymeasure(mainll_p, scale, measwidth_p, adjust_p, ressv_p)
+
+struct MAINLL *mainll_p;       /* points first thing in meas, or FEED */
+double scale;                  /* inches per "whole" unit of time */
+float *measwidth_p;            /* width of measure to be filled in */
+float *adjust_p;               /* bar line adjust, to be filled in; if last
+                                * meas in score, bar shouldn't be padded on
+                                * right, so subtract this for measwidth */
+int *ressv_p;                  /* did we apply a CLEFSIG-causing SSV? */
+
+{
+       struct CHORD *ch_p;     /* point at a chord */
+       struct TIMEDSSV *tssv_p;/* point along timed SSV list */
+       float idealwidth;       /* the width a chord should be, based on time*/
+
+
+       if (mainll_p == 0)
+               pfatal("invalid mainll_p argument (0) to trymeasure");
+
+       *ressv_p = NO;          /* assume no SSVs for now */
+
+       /* every measure has one CHHEAD; find it */
+       while (mainll_p != 0 && mainll_p->str != S_CHHEAD)
+               mainll_p = mainll_p->next;
+       if (mainll_p == 0)
+               pfatal("missing CHHEAD near end of main linked list");
+
+       *measwidth_p = 0;
+
+       /*
+        * For each chord, find out how much width it "deserves",
+        * based on its pseudodur.  But if it requires more space
+        * than that, give it what it needs.  Accumulate in *measwidth_p.
+        */
+       for (ch_p = mainll_p->u.chhead_p->ch_p; ch_p != 0;
+                               ch_p = ch_p->ch_p) {
+
+               idealwidth = scale * ch_p->pseudodur;
+               /* but a chord of all compressible, nonpadded spaces */
+               /*  deserves no width */
+               if (ch_p->width == 0)
+                       idealwidth = 0;
+               *measwidth_p += MAX(idealwidth, ch_p->width);
+       }
+
+       /*
+        * Find the bar line and add in its width.
+        */
+       while (mainll_p->str != S_BAR)
+               mainll_p = mainll_p->next;
+       *measwidth_p += width_barline(mainll_p->u.bar_p);
+
+       /* apply any timed SSVs */
+       for (tssv_p = mainll_p->u.bar_p->timedssv_p; tssv_p != 0;
+                       tssv_p = tssv_p->next) {
+               asgnssv(&tssv_p->ssv);
+               *ressv_p = YES;         /* remember we've assigned SSVs */
+       }
+
+       /* need this in case this will be the last measure in the score */
+       *adjust_p = eos_bar_adjust(mainll_p->u.bar_p);
+
+       mainll_p = mainll_p->next;      /* point after bar line */
+       /* if end of MAINLL or next measure is starting up, return now */
+       if (mainll_p == 0 || (mainll_p->str != S_SSV &&
+                             mainll_p->str != S_CLEFSIG))
+               return (mainll_p);
+
+       /* apply any SSVs at this point */
+       while (mainll_p != 0 && mainll_p->str == S_SSV) {
+               asgnssv(mainll_p->u.ssv_p);
+               mainll_p = mainll_p->next;
+               *ressv_p = YES;         /* remember we've assigned SSVs */
+       }
+
+       if (mainll_p != 0 && mainll_p->str == S_CLEFSIG) {
+               *measwidth_p += EFF_WIDCLEFSIG(mainll_p->u.clefsig_p) +
+                               CSP(mainll_p->u.clefsig_p);
+               mainll_p = mainll_p->next;
+       }
+
+       return (mainll_p);
+}
+\f
+/*
+ * Name:        setabs()
+ *
+ * Abstract:    Sets horizontal absolute coordinates for one chunk.
+ *
+ * Returns:     void
+ *
+ * Description: This function, given a chunk of the piece delimited by FEEDs,
+ *             and the number of measures to be put on each score, loops
+ *             through the scores, inserting FEEDs between them, and calling
+ *             setabsscore() to set the horizontal absolute coordinates.
+ */
+
+static void
+setabs(start_p, scores, measinscore)
+
+struct MAINLL *start_p;                /* FEED at start of chunk of MAINLL */
+int scores;                    /* number of scores this chunk needs */
+short measinscore[];           /* number of measures in each score */
+
+{
+       struct MAINLL *mainll_p;/* points along main linked list */
+       struct MAINLL *ml2_p;   /* another general pointer into MAINLL */
+       int score;              /* score number, 0 to scores-1 */
+       int n;                  /* loop counter */
+
+
+       debug(16, "setabs file=%s line=%d scores=%d", start_p->inputfile,
+                       start_p->inputlineno, scores);
+       /* must apply all SSVs from start, to get the right clef/key/time; */
+       setssvstate(start_p);
+
+       /* point at first item in first measure of chunk (skip initial FEED) */
+       mainll_p = start_p->next;
+
+       for (score = 0; score < scores; score++) {
+               /* the first score already has a FEED; insert if later score */
+               if (score != 0) {
+                       ml2_p = newMAINLLstruct(S_FEED, 0);
+                       insertMAINLL(ml2_p, mainll_p->prev);
+               }
+               mainll_p = mainll_p->prev;      /* point at the FEED */
+
+               /*
+                * Insert CLEFSIG following the FEED, and fill as needed.
+                * fillclefsig() will also allocate a BAR, and point the
+                * clefsig at it.  If the previous bar line was a REPEATSTART
+                * or REPEATBOTH, it will set REPEATSTART in the new pseudo
+                * BAR, and alter the preceding bar as necessary.
+                */
+               ml2_p = newMAINLLstruct(S_CLEFSIG, 0);
+               insertMAINLL(ml2_p, mainll_p);
+               fillclefsig(ml2_p->u.clefsig_p, mainll_p);
+               ml2_p->u.clefsig_p->multinum = getmultinum(ml2_p);
+
+               /*
+                * Find end of score by searching forward the correct number
+                * of measures.  Each measure begins with a CHHEAD, and a block
+                * begins with a BLOCKHEAD, so stop at either of these.  Call
+                * a subroutine to process this score.
+                */
+               ml2_p = ml2_p->next;            /* point at CHHEAD */
+               for (n = 0; n < measinscore[score]; n++) {
+                       do {
+                               ml2_p = ml2_p->next;
+                       } while (ml2_p != 0 && ml2_p->str != S_CHHEAD &&
+                                              ml2_p->str != S_BLOCKHEAD);
+               }
+               chkrestart(mainll_p, ml2_p);
+               if (hidestaffs(mainll_p, ml2_p) == YES) {
+                       /* if we had to force any staffs invisible, we have to
+                        * reapply SSVs so that the new ones we inserted take
+                        * effect */
+                       setssvstate(start_p);
+               }
+               setabsscore(mainll_p, ml2_p);
+               mainll_p = ml2_p;
+       }
+}
+\f
+/*
+ * Name:        chkrestart()
+ *
+ * Abstract:    Check for restart bars and remove if necessary.
+ *
+ * Returns:     void
+ *
+ * Description: This function, given one score's worth of input, checks for
+ *             restart bars.  These are used for making a gap in the score.
+ *             So when they are the first or last bar in a score, they don't
+ *             make sense, and should be removed.  Well, not simply removed;
+ *             various things need to be done to the main linked list.
+ */
+
+static void
+chkrestart(start_p, end_p)
+
+struct MAINLL *start_p;                /* point at the initial FEED of this score */
+struct MAINLL *end_p;          /* point after the last thing on this score */
+
+{
+       struct MAINLL *mainll_p;/* points along main linked list */
+       struct MAINLL *m2_p;    /* another pointer along main linked list */
+       int s;                  /* staff number */
+
+
+       /* find first bar on this score; there has to be at least one */
+       for (mainll_p = start_p; mainll_p->str != S_BAR;
+                       mainll_p = mainll_p->next)
+               ;
+
+       if (mainll_p->u.bar_p->bartype == RESTART) {
+               /*
+                * The first bar on the score is a restart.  So the score would
+                * start with whitespace followed by the restart bar, which
+                * would look bad.  So make the restart into an invisbar (which
+                * eliminates the whitespace).  A little negative padding is
+                * needed to make things line up.  Clean out the beginning of
+                * score clefsig so that nothing prints there.  The former
+                * restart's clefsig will print at the start of the line as if
+                * it were the beginning of line clefsig.
+                */
+               mainll_p->u.bar_p->bartype = INVISBAR;
+               mainll_p->u.bar_p->padding = -0.12;
+
+               start_p->next->u.clefsig_p->prtimesig = NO;
+               for (s = 1; s <= MAXSTAFFS; s++) {
+                       start_p->next->u.clefsig_p->prclef[s] = NO;
+                       start_p->next->u.clefsig_p->sharps[s] = 0;
+                       /* no need to zap the naturals, already 0 */
+               }
+       }
+
+       /* find the last bar on this score */
+       m2_p = 0;       /* keep lint happy */
+       for ( ; mainll_p != end_p; mainll_p = mainll_p->next) {
+               if (mainll_p->str == S_BAR)
+                       m2_p = mainll_p;
+       }
+
+       if (m2_p->u.bar_p->bartype == RESTART) {
+               /*
+                * The last bar on the score is a restart.  So the score would
+                * end with whitespace followed by a clefsig, which would look
+                * bad.  So make the restart into an invisbar (which eliminates
+                * the whitespace) and remove the clefsig from the MLL, since
+                * we don't want to show those things at a restart.  The next
+                * score will now be like a restart.
+                */
+               m2_p->u.bar_p->bartype = INVISBAR;
+               m2_p->u.bar_p->padding = 0;
+
+               mainll_p = m2_p;        /* remember bar */
+
+               /* find the clefsig; defensive check for end of MLL */
+               for ( ; m2_p != 0 && m2_p->str != S_CLEFSIG; m2_p = m2_p->next)
+                       ;
+               if (m2_p == 0)
+                       pfatal("the last bar in the piece is a restart");
+
+               /*
+                * When it comes time to create the coming feed and clefsig,
+                * that clefsig's value for prtimesig depends on the one in the
+                * clefsig we are about to remove.  So as a special kluge, if
+                * that value is YES, set the bar's AY to a positive number.
+                * It will get overwritten in absvert.c.
+                */
+               if (m2_p->u.clefsig_p->prtimesig == YES) {
+                       mainll_p->u.bar_p->c[AY] = 1.0;
+               }
+
+               m2_p->prev->next = m2_p->next;
+               m2_p->next->prev = m2_p->prev;
+               FREE(m2_p->u.clefsig_p);
+               FREE(m2_p);
+       }
+}
+\f
+/*
+ * Name:        setabsscore()
+ *
+ * Abstract:    Sets horizontal absolute coordinates for one score.
+ *
+ * Returns:     void
+ *
+ * Description: This function, given one score's worth of input, decides how
+ *             to space everything horizontally to look pleasing, and then
+ *             sets the horizontal absolute coordinates.
+ */
+
+static void
+setabsscore(start_p, end_p)
+
+struct MAINLL *start_p;                /* point at the initial FEED of this score */
+struct MAINLL *end_p;          /* point after the last thing on this score */
+
+{
+       struct MAINLL *mainll_p;/* points along main linked list */
+       struct MAINLL *m2_p;    /* another pointer along main linked list */
+       struct CHORD *ch_p;     /* point at a chord */
+       struct CHORD *firstch_p;/* point at first chord in a measure */
+       struct BAR *bar_p;      /* convenient pointer at a clefsig's bar */
+       struct MAINLL *mm_p;    /* another pointer along MLL */
+       struct MAINLL *lastbarmll_p; /* remember the last bar in the score */
+       struct CLEFSIG *clefsig_p; /* point at a clefsig */
+       struct TIMEDSSV *tssv_p;/* point along a timed SSV list */
+       float prevbarae;        /* remember previous bar's AE */
+       float wid;              /* temp variable, width of something */
+       float eff_right;        /* effective right margin */
+       float scorewidth;       /* total width allowed for the score */
+       float totwidth;         /* total minimum width */
+       float totwhole;         /* total equivalent whole notes of time */
+       float chw;              /* total minimum width of chords */
+       float notespace;        /* space for chords */
+       float nnotespace;       /* space for expandable chords */
+       float ntotwhole;        /* total equiv wholes for expandables */
+       float inchpwhole;       /* inches each whole note should have */
+       float expanded;         /* width of something after expansion */
+       float absx;             /* absolute x coordinate */
+       float leftx, rightx;    /* start and end positions of a measure */
+       float eff;              /* effective width */
+       int toowide;            /* number of chords wider than they deserve */
+       int ntoowide;           /* new no. of chords wider than deserved */
+
+
+       debug(32, "setabsscore file=%s line=%d",
+               start_p->inputfile, start_p->inputlineno);
+       firstch_p = 0;          /* keep lint happy; will be set before used */
+       prevbarae = 0.0;        /* keep lint happy; will be set before used */
+       lastbarmll_p = 0;       /* keep lint happy; will be set before used */
+
+       /*
+        * Get total available width on this score.
+        */
+       if (end_p == 0) {
+               /* find last feed or last bar, whichever comes last */
+               for (m2_p = Mainlltc_p; m2_p->str != S_FEED && 
+                               m2_p->str != S_BAR; m2_p = m2_p->prev)
+                       ;
+               if (m2_p->str == S_FEED) {
+                       /* a feed after the last bar; use it */
+                       eff_right = eff_rightmargin(m2_p);
+               } else {
+                       /* no feed after the last bar */
+                       eff_right = eff_rightmargin((struct MAINLL *)0);
+               }
+       } else {
+               /*
+                * end_p must be the chhead of the following measure.  Its prev
+                * may be a user FEED.  (The CLEFSIG which should be between
+                * them has not been inserted yet.)
+                */
+               if (end_p->prev->str == S_FEED) {
+                       /* it is a feed, so use it */
+                       eff_right = eff_rightmargin(end_p->prev);
+               } else {
+                       /* no feed */
+                       eff_right = eff_rightmargin((struct MAINLL *)0);
+               }
+       }
+
+       scorewidth = PGWIDTH - eff_right - eff_leftmargin(start_p);
+       scorewidth -= width_left_of_score(start_p);
+
+       /*
+        * Accumulate the total minimum width, total pseudodur in equivalent
+        * wholes, and the total minimum width needed by chords.
+        */
+       totwidth = 0;
+       totwhole = 0;
+       chw = 0;
+       for (mainll_p = start_p; mainll_p != end_p; mainll_p = mainll_p->next){
+               switch (mainll_p->str) {
+
+               case S_SSV:
+                       /* assign to keep time sig accurate */
+                       asgnssv(mainll_p->u.ssv_p);
+                       break;
+
+               case S_CHHEAD:
+                       /*
+                        * Add in min widths & time of all chords in measure.
+                        * Skip any leading space chords in determining first.
+                        * (Actually, only compressible, nonpadded spaces.)
+                        * The west part of the first chord is considered part
+                        * a fixed width.  The "effwidth" of a chord is its
+                        * east part plus the west part of the next chord, if
+                        * any.
+                        */
+                       for (ch_p = mainll_p->u.chhead_p->ch_p; ch_p != 0 &&
+                                    ch_p->width == 0; ch_p = ch_p->ch_p)
+                               ;
+                       if (ch_p == 0)
+                               break;
+                       totwidth -= ch_p->c[RW];        /* first nonspace */
+                       for ( ; ch_p != 0; ch_p = ch_p->ch_p) {
+                               totwidth += effwidth(ch_p);
+                               chw += effwidth(ch_p);
+
+                               /* count time only if not a chord of */
+                               /*  compressible, nonpadded spaces */
+                               if (ch_p->width != 0)
+                                       totwhole += ch_p->pseudodur;
+                       }
+                       break;
+
+               case S_CLEFSIG:
+                       /*
+                        * If this clefsig is the last thing on this score
+                        * (except possibly the FEED that starts the next chunk)
+                        * find the preceding bar line.  If that bar has
+                        * hidechanges set, it means that we are not to print
+                        * this clefsig.
+                        */
+                       if (mainll_p->next == end_p ||
+                           mainll_p->next->str == S_FEED) {
+                               for (m2_p = mainll_p; m2_p->str != S_BAR;
+                                               m2_p = m2_p->prev)
+                                       ;
+                               if (m2_p->u.bar_p->hidechanges) {
+                                       mainll_p->u.clefsig_p->hide = YES;
+                                       mainll_p->u.clefsig_p->effwidth = 0.0;
+                               }
+                       }
+
+                       /* width of clef/key/time/repeatstart when needed */
+                       totwidth += EFF_WIDCLEFSIG(mainll_p->u.clefsig_p);
+                       /* pad clefsig, unless it's the last thing on score */
+                       if (mainll_p->next != end_p &&
+                           mainll_p->next->str != S_FEED)
+                               totwidth += CSP(mainll_p->u.clefsig_p);
+                       break;
+
+               case S_BAR:
+                       /* bar's width */
+                       totwidth += width_barline(mainll_p->u.bar_p) +
+                                       mainll_p->u.bar_p->padding;
+                       /* apply any timed SSVs */
+                       for (tssv_p = mainll_p->u.bar_p->timedssv_p;
+                                       tssv_p != 0; tssv_p = tssv_p->next) {
+                               asgnssv(&tssv_p->ssv);
+                       }
+                       lastbarmll_p = mainll_p;
+                       break;
+               }
+       }
+
+       /*
+        * If the last bar is truly at the end of the line, it doesn't need its
+        * full width, because there is no padding after it.  But when there is
+        * a visible clefsig with time or sig there, the bar is not at the end.
+        */
+       for (mm_p = lastbarmll_p; mm_p != 0; mm_p = mm_p->next) {
+               if (mm_p->str == S_STAFF || mm_p->str == S_CLEFSIG) {
+                       break;
+               }
+       }
+       if (mm_p == 0 || mm_p->str != S_CLEFSIG ||
+                               mm_p->u.clefsig_p->hide == YES) {
+               /* no visible clefsig; get rid of padding */
+               totwidth -= eos_bar_adjust(lastbarmll_p->u.bar_p);
+       } else {
+               /* If there is a clefsig, but it has hidechanges,
+                * or it has no time sigature or any key signatures,
+                * it needs to be moved to the edge of the score. */
+               if (mm_p->u.clefsig_p->prtimesig == NO) {
+                       int s;
+                       for (s = 1; s <= MAXSTAFFS; s++) {
+                               if ((mm_p->u.clefsig_p->sharps[s] != 0 ||
+                                    mm_p->u.clefsig_p->naturals[s] != 0) &&
+                                    svpath(s, VISIBLE)->visible == YES) {
+                                       break;
+                               }
+                       }
+                       if (s > MAXSTAFFS) {
+                               totwidth -= eos_bar_adjust(
+                                               lastbarmll_p->u.bar_p);
+                       }
+               }
+       }
+
+       /* fail if even the minimum size for everything doesn't fit */
+       if (totwidth > scorewidth) {
+               if (Score.units == INCHES) {
+                       l_ufatal(start_p->inputfile, start_p->inputlineno,
+                                       "too much (%f inches) to put in score",
+                                       totwidth * Score.scale_factor);
+               } else {
+                       l_ufatal(start_p->inputfile, start_p->inputlineno,
+                                       "too much (%f cm) to put in score",
+                                       totwidth * Score.scale_factor *
+                                       CMPERINCH);
+               }
+       }
+
+       /*
+        * Only chords are allowed to expand when there is extra space;
+        * other items have a fixed width.  To find how much space is
+        * available for chords, take the total screen width minus the
+        * space needed by the fixed-size things.
+        */
+       notespace = scorewidth - (totwidth - chw);
+
+       /*
+        * Some chords' "effwidths" are already wider than what they deserve
+        * based on their pseudodur.  Let them keep that minimum size.  We
+        * will consider their size as fixed and allocate the remaining
+        * space among chords that deserve more.  Remove the too-wide (and
+        * just right) chords from the totals.  This has to be done
+        * repeatedly, since after each iteration the number of inches
+        * deserved by each remaining chord shrinks.  Leave the loop when
+        * it is found that all remaining chords deserve to expand.
+        */
+       ntotwhole = totwhole;   /* initially assume all may be expandable */
+       nnotespace = notespace;
+       ntoowide = 0;
+       do {
+               /*
+                * If there are no notes in this score, totwhole will already
+                * be 0 on the first loop iteration, and there is nothing that
+                * can expand.  Each measure will be very small, just the width
+                * of the bar line and its padding, and the rightmost bar line
+                * won't be at the right edge of the score.  This is usually a
+                * useless situation; but if invisbars are used, and "newscore"
+                * every measure, it provides a way to print blank music paper.
+                *
+                * inchpwhole won't ever get used, but we set it to something
+                * arbitrary in case lint cares.  Then break out of this loop.
+                */
+               if (totwhole == 0.0) {
+                       inchpwhole = 1.0;
+                       break;
+               }
+               /*
+                * Find how much space each whole note worth of chords
+                * deserves, allocating proportionally.  Consider just the
+                * ones not known to be too big already.
+                */
+               inchpwhole = nnotespace / ntotwhole;
+
+               /* start with all chords' time and space */
+               ntotwhole = totwhole;
+               nnotespace = notespace;
+
+               toowide = ntoowide;     /* remember how many last time */
+               ntoowide = 0;
+
+               /* remove from consideration ones that are too big already */
+               for (mainll_p = start_p; mainll_p != end_p;
+                                       mainll_p = mainll_p->next) {
+
+                       if (mainll_p->str == S_CHHEAD) {
+                               /* loop through all chords doing this */
+                               for (ch_p = mainll_p->u.chhead_p->ch_p;
+                                               ch_p != 0; ch_p = ch_p->ch_p) {
+                                       if (effwidth(ch_p) >=
+                                       ch_p->pseudodur * inchpwhole) {
+                                               ntotwhole -= ch_p->pseudodur;
+                                               nnotespace -= effwidth(ch_p);
+                                               ntoowide++;
+                                       }
+                               }
+                       }
+               }
+
+               /*
+                * In the (rare) case where nothing is now expandable (every-
+                * thing is packed perfectly tightly), we should break out now.
+                * The "<" is defensive.
+                */
+               if (ntotwhole <= 0)
+                       break;
+
+       } while (ntoowide > toowide);
+
+       /*
+        * Now inchpwhole is the number of inches that should be given to each
+        * whole note worth of chords that deserve to be wider than their
+        * minimum.  Allocate width proportionally to these chords.
+        */
+       for (mainll_p = start_p; mainll_p != end_p; mainll_p = mainll_p->next){
+               if (mainll_p->str == S_CHHEAD) {
+                       for (ch_p = mainll_p->u.chhead_p->ch_p;
+                                       ch_p != 0; ch_p = ch_p->ch_p) {
+
+                               /* normal case (proportional) */
+                               expanded = ch_p->pseudodur * inchpwhole;
+
+                               /* special case to fix space interaction */
+
+                               /* but a chord of all compressible, */
+                               /*  nonpadded spaces deserves no width */
+                               if (ch_p->width == 0)
+                                       expanded = 0;
+
+                               /* get min dist needed from our X to next's X */
+                               eff = effwidth(ch_p);
+
+                               /* the dist we'll really have from X to X */
+                               ch_p->fullwidth = MAX(eff, expanded);
+                       }
+               }
+       }
+
+       /*
+        * Now that we know everything's width, set all absolute horizontal
+        * coordinates for this score.  The absx variable keeps track of
+        * where we are, working from left to right.  At all times, keep
+        * track of the start and end of each measure (leftx and rightx)
+        * and the first chord in it, so we can reposition measure rests.
+        */
+       /* first reset SSVs to how they were at start of this score */
+       setssvstate(start_p);
+
+       start_p->u.feed_p->c[AW] = eff_leftmargin(start_p);
+       start_p->u.feed_p->c[AE] = PGWIDTH - eff_right;
+       absx = eff_leftmargin(start_p) + width_left_of_score(start_p);
+       start_p->u.feed_p->c[AX] = absx;
+       leftx = 0.0;            /* prevent useless 'used before set' warning */
+
+       for (mainll_p = start_p; mainll_p != end_p; mainll_p = mainll_p->next) {
+               switch (mainll_p->str) {
+               case S_SSV:
+                       /* assign to keep time sig accurate */
+                       asgnssv(mainll_p->u.ssv_p);
+                       break;
+
+               case S_CLEFSIG:
+                       clefsig_p = mainll_p->u.clefsig_p;
+
+                       /* this kind partly already handled by preceding bar */
+                       if (clefsig_p->clefsize == SMALLSIZE &&
+                                       clefsig_p->hide == NO) {
+                               /* absx points at AE of barline, so add width*/
+                               /* of clef excluding any clef space */
+                               absx += width_clefsig(clefsig_p) -
+                                               clefsig_p->widestclef +
+                                               CSP(clefsig_p);
+                               leftx = absx;
+                               break;
+                       }
+
+                       /* "beginning of line" or "restart" clefsig */
+                       clefsig_p->wclefsiga = absx;
+                       if (clefsig_p->hide == NO) {
+                               absx += width_clefsig(clefsig_p) +
+                                               CSP(clefsig_p);
+                       }
+                       bar_p = clefsig_p->bar_p;
+                       if (bar_p != 0) {
+                               /* clefsig has a pseudo bar in it; set coords*/
+                               bar_p->c[AE] = absx;
+                               bar_p->c[AW] = absx - width_barline(bar_p);
+                               bar_p->c[AX] = (bar_p->c[AW] + absx) / 2;
+
+                               /* remember the AE of this pseudobar */
+                               prevbarae = absx;
+                       }
+                       leftx = absx;
+                       break;
+
+               case S_BAR:
+                       bar_p = mainll_p->u.bar_p;
+                       absx += bar_p->padding;
+
+                       /* apply any timed SSVs */
+                       for (tssv_p = bar_p->timedssv_p; tssv_p != 0;
+                                       tssv_p = tssv_p->next) {
+                               asgnssv(&tssv_p->ssv);
+                       }
+
+                       /*
+                        * If this bar is followed by a clefsig, any clefs in
+                        * it must be printed before this bar.  Note that any
+                        * padding will go before the clef (see above).  But
+                        * the previous measure "ends" after the clefs.
+                        */
+                       for (m2_p = mainll_p; m2_p != 0 &&
+                                       m2_p->str != S_CLEFSIG &&
+                                       m2_p->str != S_CHHEAD;
+                                       m2_p = m2_p->next)
+                               ;
+                       /* if clefsig that belongs to this bar line . . . */
+                       if (m2_p != 0 && m2_p->str == S_CLEFSIG && m2_p->u.
+                                       clefsig_p->clefsize == SMALLSIZE &&
+                                       m2_p->u.clefsig_p->hide == NO) {
+                               clefsig_p = m2_p->u.clefsig_p;
+
+                               /*
+                                * Apply SSVs to get the time & clef changes
+                                * that occur at this bar, if any, since we
+                                * are going to print the new values of them.
+                                * After the width_clefsig, restore the SSVs to
+                                * the proper state at this bar line.
+                                */
+                               for (m2_p = mainll_p; m2_p->str != S_CLEFSIG;
+                                               m2_p = m2_p->next) {
+                                       if (m2_p->str == S_SSV) {
+                                               asgnssv(m2_p->u.ssv_p);
+                                       }
+                               }
+                               wid = width_clefsig(clefsig_p);
+                               setssvstate(mainll_p);
+
+                               /* if wid > effwid, this will overlap the */
+                               /* widest clef by that difference */
+                               clefsig_p->wclefsiga = absx -
+                                               (wid - clefsig_p->effwidth) +
+                                               bardiff(mainll_p, end_p);
+
+                               /* point absx after any clefs in clefsig */
+                               absx += clefsig_p->effwidth -
+                                               (wid - clefsig_p->widestclef);
+                               rightx = clefsig_p->wclefsiga;
+                       } else {        /* no relevant clefsig */
+                               rightx = absx;  /* prev measure "ends" here */
+                       }
+                       bar_p->c[AW] = absx;
+                       absx += width_barline(bar_p);
+                       bar_p->c[AE] = absx;
+                       bar_p->c[AX] = (bar_p->c[AW] + bar_p->c[AE]) / 2.0;
+                       fixfullmeas(firstch_p, (leftx + rightx) / 2.0);
+                       leftx = absx;   /* next measure starts here */
+
+                       /*
+                        * for each staff in the measure just ended, set its AE
+                        * to this bar's AW, and set AX to the midpoint now
+                        * that we know both AW and AE.
+                        */
+                       for (m2_p = mainll_p; m2_p->str != S_CHHEAD;
+                                       m2_p = m2_p->prev) {
+                               if (m2_p->str == S_STAFF) {
+                                       m2_p->u.staff_p->c[AE] = bar_p->c[AW];
+                                       m2_p->u.staff_p->c[AX] =
+                                               (m2_p->u.staff_p->c[AW] +
+                                                m2_p->u.staff_p->c[AE]) / 2.0;
+                               }
+                       }
+
+                       /* remember the AE of this bar */
+                       prevbarae = absx;
+                       break;
+
+               case S_STAFF:
+                       /* as we come to each staff, set AW to prev bar's AE */
+                       mainll_p->u.staff_p->c[AW] = prevbarae;
+                       break;
+
+               case S_CHHEAD:
+                       for (ch_p = mainll_p->u.chhead_p->ch_p; ch_p != 0 &&
+                                    ch_p->width == 0; ch_p = ch_p->ch_p)
+                               setabschord(ch_p, absx);
+                       if ((firstch_p = ch_p) == 0)
+                               break;
+                       absx -= firstch_p->c[RW];
+                       for (ch_p = firstch_p; ch_p != 0; ch_p = ch_p->ch_p) {
+                               setabschord(ch_p, absx);
+                               absx += ch_p->fullwidth;
+                       }
+                       break;
+               }
+       }
+}
+\f
+/*
+ * Name:        setabschord()
+ *
+ * Abstract:    Sets horizontal absolute coordinates for everything in a chord.
+ *
+ * Returns:     void
+ *
+ * Description: This function, given a chord, and its absolute offset, sets
+ *             the horizontal absolute coordinates of everything in it.
+ */
+
+static void
+setabschord(ch_p, nomx)
+
+struct CHORD *ch_p;            /* point at the chord */
+double nomx;                   /* nominal X coord; may shift it right a bit */
+
+{
+       struct GRPSYL *gs_p;    /* point at a group or syllable in chord */
+       struct GRPSYL *g_p;     /* point at a group with notes */
+       float extra;            /* width available beyond what chord needs */
+       int n;                  /* loop counter */
+
+
+       /*
+        * Set the CHORD's horizonal absolute coordinates.  If the chord had
+        * no room to expand (effwidth == fullwidth), there's no question
+        * where its AX has to be.  But otherwise, we want to place it close
+        * to as far left as it can go, but not jammed up against there.
+        */
+       if ((extra = ch_p->fullwidth - effwidth(ch_p)) > 0) {
+               nomx += (extra > 1.20 ? 0.20 : extra / 6);
+       }
+
+       ch_p->c[AX] = nomx;
+       ch_p->c[AW] = nomx + ch_p->c[RW];
+       ch_p->c[AE] = nomx + ch_p->c[RE];
+
+       /*
+        * Loop through all GRPSYLs in this chord, setting absolute horizontal
+        * coordinates.  To avoid the aggravation of dealing with SSVs again,
+        * don't bother checking if the staffs in question are visible, just
+        * do it.  It doesn't hurt anything to increment garbage.
+        */
+       for (gs_p = ch_p->gs_p; gs_p != 0; gs_p = gs_p->gs_p) {
+               /*
+                * For groups, do the group itself and all the notes in it (if
+                * any), and do the same for all preceding grace groups.
+                */
+               if (gs_p->grpsyl == GS_GROUP) {
+                       g_p = gs_p;     /* init to the normal group */
+                       do {
+                               /* do the group itself, based off the chord */
+                               g_p->c[AX] = ch_p->c[AX] + g_p->c[RX];
+                               g_p->c[AW] = ch_p->c[AX] + g_p->c[RW];
+                               g_p->c[AE] = ch_p->c[AX] + g_p->c[RE];
+
+                               /* do each note, based off the group */
+                               for (n = 0; n < g_p->nnotes; n++) {
+                                       g_p->notelist[n].c[AX] = g_p->c[AX] +
+                                                       g_p->notelist[n].c[RX];
+                                       g_p->notelist[n].c[AW] = g_p->c[AX] +
+                                                       g_p->notelist[n].c[RW];
+                                       g_p->notelist[n].c[AE] = g_p->c[AX] +
+                                                       g_p->notelist[n].c[RE];
+                               }
+                               g_p = g_p->prev;
+                       } while (g_p != 0 && g_p->grpvalue == GV_ZERO);
+               } else {
+                       /* this is a syllable; just do the syllable */
+                       gs_p->c[AX] = ch_p->c[AX] + gs_p->c[RX];
+                       gs_p->c[AW] = ch_p->c[AX] + gs_p->c[RW];
+                       gs_p->c[AE] = ch_p->c[AX] + gs_p->c[RE];
+               }
+       }
+}
+\f
+/*
+ * Name:        effwidth()
+ *
+ * Abstract:    Find "effective" width of a chord.
+ *
+ * Returns:     the width
+ *
+ * Description: This function returns the "effective width" of a chord.  This
+ *             is the (minimum) width of its east part, plus the width of the
+ *             west part of the following chord, if there is one.
+ */
+
+static double
+effwidth(ch_p)
+
+struct CHORD *ch_p;            /* point at the chord */
+
+{
+       struct CHORD *next_p;
+
+
+       /* compressible, nonpadded spaces count for nothing */
+       if (ch_p->width == 0)
+               return (0.0);
+
+       /* find the next chord, if any, that is not all compressible, */
+       /*  nonpadded spaces */
+       for (next_p = ch_p->ch_p; next_p != 0; next_p = next_p->ch_p) {
+               if (next_p->width != 0)
+                       break;
+       }
+
+       /*
+        * If it's the last one in the measure, return the east side of the
+        * current chord.  Otherwise, return that plus the west side of the
+        * next nonspace chord.
+        */
+       if (next_p == 0)
+               return (ch_p->c[RE]);
+       else
+               return (ch_p->c[RE] - next_p->c[RW]);
+}
+\f
+/*
+ * Name:        bardiff()
+ *
+ * Abstract:    Find size difference of end of score bar vs. what it will be.
+ *
+ * Returns:     void
+ *
+ * Description: When a REPEATSTART occurs at the end of a score, it gets
+ *             changed to a SINGLEBAR, and a REPEATBOTH becomes a REPEATEND
+ *             (the following pseudobar getting set to REPEATSTART).  Other
+ *             bartypes are left alone.  This function, given the MLL of a bar,
+ *             just returns zero if the bar is not at the end of a score; but
+ *             otherwise it returns the size of that bartype minus the size of
+ *             what it will be replaced by.
+ */
+
+static double
+bardiff(mainll_p, end_p)
+
+struct MAINLL *mainll_p;       /* MLL for the bar line */
+struct MAINLL *end_p;          /* MLL after end of the score */
+
+{
+       struct MAINLL *mll_p;   /* for searching the MLL */
+       struct BAR bar;         /* phony BAR structure */
+       double temp;            /* hold the width of the orginal bar */
+
+
+       /*
+        * Search forward from the bar.  If we hit a CHHEAD before hitting the
+        * end of the score, then this is not the last barline in the score, so
+        * return zero.
+        */
+       for (mll_p = mainll_p; mll_p != end_p; mll_p = mll_p->next) {
+               if (mll_p->str == S_CHHEAD)
+                       return (0.0);
+       }
+
+       /* last bar in the score, so do the arithmetic */
+       switch (mainll_p->u.bar_p->bartype) {
+       case REPEATSTART:
+               bar.bartype = REPEATSTART;
+               temp = width_barline(&bar);
+               bar.bartype = SINGLEBAR;
+               return (temp - width_barline(&bar));
+
+       case REPEATBOTH:
+               bar.bartype = REPEATBOTH;
+               temp = width_barline(&bar);
+               bar.bartype = REPEATEND;
+               return (temp - width_barline(&bar));
+       }
+
+       return (0.0);   /* all other types remain the same; difference = 0 */
+}
+\f
+/*
+ * Name:        fixfullmeas()
+ *
+ * Abstract:    Adjust the AE of full measure symbols (mr, multirest, mrpt).
+ *
+ * Returns:     void
+ *
+ * Description: This function, given the first chord in a measure (the only
+ *             one that can contain a one of these symbols), adjusts the AE
+ *             coord of each GRPSYL in the chords that is one of these.  AW
+ *             stays where it is, near the left bar line, except that for
+ *             multirests it moves it to the right, especially for ones
+ *             that are drawn with rest symbols.  For multirests and
+ *             measure repeats, AX gets moved leftwards a little, to be
+ *             where it would have been for a measure rest, but for measure
+ *             rests, it stays where it is, not far to the right of that.
+ *             For all three things, AE is put near the right bar line, the
+ *             same distance from it that AW is from the left.
+ */
+
+static void
+fixfullmeas(ch_p, x)
+
+struct CHORD *ch_p;            /* point at the chord */
+double x;                      /* absolute X coord of center of measure */
+
+{
+       struct GRPSYL *gs_p;    /* point at a group or syllable in chord */
+
+
+       /* in case we have all spaces */
+       if (ch_p == 0)
+               return;
+
+       debug(32, "fixfullmeas file=%s line=%d x=%f", ch_p->gs_p->inputfile,
+                       ch_p->gs_p->inputlineno, (float)x);
+
+       /* loop through all GRPSYLs, resetting AE/AW for full measure symbols */
+       for (gs_p = ch_p->gs_p; gs_p != 0; gs_p = gs_p->gs_p) {
+               /* skip syllables */
+               if (gs_p->grpsyl != GS_GROUP) {
+                       continue;
+               }
+
+               if (gs_p->is_meas == YES) {
+                       gs_p->c[AE] = x + (x - gs_p->c[AW]);
+               } else if (gs_p->basictime < -1) {
+                       /* multirest; move the left end to the right a little */
+                       set_staffscale(gs_p->staffno);
+                       gs_p->c[AW] += 2.0 * Stepsize;
+                       /*
+                        * For multirests that are drawn with rest symbols,
+                        * the width may need to be reduced.  If half the
+                        * multirest's width exceeds 10 stepsizes, reduce it
+                        * by 0.8 of the excess.
+                        */
+                       if (gs_p->basictime >= -8 && svpath(gs_p->staffno,
+                                               RESTSYMMULT)->restsymmult) {
+                               if (x - gs_p->c[AW] > 10.0 * Stepsize) {
+                                       gs_p->c[AW] += ((x - gs_p->c[AW]) -
+                                                     (10.0 * Stepsize)) * 0.8;
+                               }
+                       }
+                       gs_p->c[AE] = x + (x - gs_p->c[AW]);
+               }
+       }
+
+       /* for multirest/mrpt, put AX where it would have been for a mr */
+       if (ch_p->gs_p->basictime < -1 || is_mrpt(gs_p)) {
+               ch_p->c[AX] = ch_p->c[AW] +
+                               width(FONT_MUSIC, DFLT_SIZE, C_1REST) / 2;
+       }
+}
+\f
+/*
+ * Name:        restore_grpsyl_west()
+ *
+ * Abstract:    Restore all GRPSYLs' west coords when there was a clef there.
+ *
+ * Returns:     void
+ *
+ * Description: In fixclef() in restsyl.c, we altered the west of any GRPSYL
+ *             that was associated with a midmeasure clef.  This was needed so
+ *             that room would be made for the clefs.  Now that the packing
+ *             part of abshorz.c is done, we can restore these coords, for the
+ *             benefit of the print phrase.
+ */
+
+static void
+restore_grpsyl_west()
+
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct GRPSYL *gs_p;            /* point along a GRPSYL list */
+       struct GRPSYL *gs2_p;           /* look for a grace group's main grp */
+       int vidx;                       /* voice index */
+       float size;                     /* to be used for clef */
+       float staffscale;               /* scale for a staff */
+       float clefwid;                  /* width of a clef */
+
+
+       size = 3.0/4.0 * DFLT_SIZE;     /* small size clefs */
+       initstructs();
+
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+               switch (mainll_p->str) {
+               case S_SSV:
+                       /* keep staffscale up to date */
+                       asgnssv(mainll_p->u.ssv_p);
+                       continue;
+               case S_STAFF:
+                       /* break out to handle staff */
+                       break;
+               default:
+                       continue;
+               }
+
+               for (vidx = 0; vidx < MAXVOICES; vidx++) {
+                       for (gs_p = mainll_p->u.staff_p->groups_p[vidx];
+                                       gs_p != 0; gs_p = gs_p->next) {
+                               if (gs_p->clef == NOCLEF) {
+                                       continue; /* no clef, nothing to do */
+                               }
+
+                               staffscale = svpath(gs_p->staffno,
+                                               STAFFSCALE)->staffscale;
+                               clefwid = (clefwidth(gs_p->clef, YES) +
+                                               CLEFPAD) * staffscale;
+                               gs_p->c[RW] += clefwid;
+                               gs_p->c[AW] += clefwid;
+
+                               /*
+                                * If we are a grace group, look ahead to the
+                                * main group and restore it too.
+                                */
+                               if (gs_p->grpvalue == GV_ZERO) {
+                                       for (gs2_p = gs_p; gs2_p->grpvalue ==
+                                       GV_ZERO; gs2_p = gs2_p->next) {
+                                               ;
+                                       }
+                                       gs2_p->c[RW] += clefwid;
+                                       gs2_p->c[AW] += clefwid;
+                               }
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        setipw()
+ *
+ * Abstract:    Set INCHPERWHOLE "coordinate" for all structures having it.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets the special pseudocoord "c[INCHPERWHOLE]"
+ *             for all nongrace GRPSYLs, notes, chords, and BARs.  BARs is
+ *             done right here; for the others, it calls subroutines.
+ */
+
+static void
+setipw()
+
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct MAINLL *m2_p;            /* look forward for bar line */
+       struct GRPSYL *gs_p;            /* point along a GRPSYL list */
+       int timeden;                    /* denominator of a time signature */
+       int v;                          /* index into voices or verses */
+
+
+       debug(16, "setipw");
+       initstructs();                  /* clean out old SSV info */
+
+       /*
+        * Loop through MLL, applying SSVs and processing each visible linked
+        * list of GRPSYLs.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               switch (mainll_p->str) {
+               case S_SSV:
+                       /* this is needed to keep time sig up to date */
+                       asgnssv(mainll_p->u.ssv_p);
+                       break;
+
+               case S_CHHEAD:
+                       /* set the thing for all chords in this measure */
+                       setipwchord(mainll_p);
+                       break;
+
+               case S_STAFF:
+                       /* skip this staff if it's invisible */
+                       if (mainll_p->u.staff_p->visible == NO)
+                               break;
+
+                       /* do all the voices on this staff */
+                       for (v = 0; v < MAXVOICES && (gs_p = mainll_p->u.
+                                       staff_p->groups_p[v]) != 0; v++) {
+                               setipwgrpsyl(mainll_p, gs_p);
+                       }
+
+                       /* do all the verses on this staff */
+                       for (v = 0; v < mainll_p->u.staff_p->nsyllists; v++) {
+                               gs_p = mainll_p->u.staff_p->syls_p[v];
+                               setipwgrpsyl(mainll_p, gs_p);
+                       }
+
+                       break;
+
+               case S_BAR:
+                       /*
+                        * If this is the ending bar line of a score, ignore
+                        * it.  The following measure would refer to its
+                        * preceding CLEFSIG's pseudo bar instead.  So see if
+                        * we hit a FEED while trying to find the next CHHEAD.
+                        * While doing this, keep track of the denominator of
+                        * the time signature, in case it changes at this bar.
+                        */
+                       timeden = Score.timeden;
+                       for (m2_p = mainll_p; m2_p != 0 && m2_p->str != S_FEED
+                                       && m2_p->str != S_CHHEAD;
+                                       m2_p = m2_p->next) {
+                               if (m2_p->str == S_SSV && m2_p->u.ssv_p->used[
+                                               TIME] == YES) {
+                                       timeden = m2_p->u.ssv_p->timeden;
+                               }
+                       }
+                       if (m2_p == 0 || m2_p->str == S_FEED)
+                               break;
+
+                       /*
+                        * This is not the last bar of a score, and m2_p points
+                        * at the CHHEAD of the following measure, with timeden
+                        * being the denominator of the time sig.  The space
+                        * between the bar ("count 0") and the first chord
+                        * ("count 1") must be multiplied by the number of
+                        * counts in a whole note (timeden).
+                        */
+                       mainll_p->u.bar_p->c[INCHPERWHOLE] = timeden *
+                                       (m2_p->u.chhead_p->ch_p->c[AX] -
+                                       mainll_p->u.bar_p->c[AX]);
+                       break;
+
+               case S_CLEFSIG:
+                       /*
+                        * If this clefsig is not at the start of a score,
+                        * ignore it.  If it is, it will contain a pseudo bar
+                        * line, and we need to set that bar's coord just like
+                        * for a normal bar line.
+                        */
+                       if (mainll_p->u.clefsig_p->bar_p == 0)
+                               break;
+
+                       if (mainll_p->next->str != S_CHHEAD)
+                               pfatal("CLEFSIG with pseudo bar not followed by CHHEAD");
+
+                       mainll_p->u.clefsig_p->bar_p->c[INCHPERWHOLE] =
+                               Score.timeden *
+                               (mainll_p->next->u.chhead_p->ch_p->c[AX] -
+                               mainll_p->u.clefsig_p->bar_p->c[AX]);
+                       break;
+               }               
+       }
+}
+\f
+/*
+ * Name:        setipwgrpsyl()
+ *
+ * Abstract:    Set INCHPERWHOLE "coordinate" for the GRPSYLs in one list.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets the special pseudocoord "c[INCHPERWHOLE]"
+ *             for all the nongrace GRPSYLs and notes in one voice or verse
+ *             list hanging off a STAFF.
+ */
+
+static void
+setipwgrpsyl(mainll_p, gs_p)
+
+struct MAINLL *mainll_p;               /* point along main linked list */
+struct GRPSYL *gs_p;                   /* point along this GRPSYL list */
+
+{
+       struct MAINLL *m2_p;            /* look forward for bar line */
+       struct GRPSYL *ngs_p;           /* the next nongrace GRPSYL in list */
+       float inchperwhole;             /* inches per whole note */
+       int n;                          /* loop variable */
+
+
+       debug(32, "setipwgrpsyl file=%s line=%d", gs_p->inputfile,
+                       gs_p->inputlineno);
+       /* get first nongrace GRPSYL */
+       for ( ; gs_p != 0 && gs_p->grpsyl == GS_GROUP &&
+                            gs_p->grpvalue == GV_ZERO; gs_p = gs_p->next)
+               ;
+       if (gs_p == 0)
+               pfatal("nothing but grace notes in measure");
+
+       /*
+        * Loop down the list of GRPSYLs.  gs_p always points the current
+        * (nongrace) GRPSYL, whose inches per whole we want to set.  ngs_p
+        * points at the next nongrace GRPSYL.
+        */
+       for (;;) {
+               /* find next nongrace GRPSYL; break if none */
+               for (ngs_p = gs_p->next;
+                    ngs_p != 0 && ngs_p->grpsyl == GS_GROUP &&
+                                  ngs_p->grpvalue == GV_ZERO;
+                    ngs_p = ngs_p->next)
+                       ;
+               if (ngs_p == 0)
+                       break;
+
+               /*
+                * Distance between them divided by time gives the space a
+                * a whole note theoretically would have been given.
+                */
+               inchperwhole = (ngs_p->c[AX] - gs_p->c[AX]) /
+                               RAT2FLOAT(gs_p->fulltime);
+
+               /* store in GRPSYL & each note (if notes) */
+               gs_p->c[INCHPERWHOLE] = inchperwhole;
+               if (gs_p->grpsyl == GS_GROUP && gs_p->grpcont == GC_NOTES) {
+                       for (n = 0; n < gs_p->nnotes; n++)
+                               gs_p->notelist[n].c[INCHPERWHOLE]
+                                               = inchperwhole;
+               }
+
+               /* point current at next, for next iteration */
+               gs_p = ngs_p;
+       }
+
+       /*
+        * We've hit the end of the measure.  Loop forward through the MLL
+        * until we find the bar line.
+        */
+       for (m2_p = mainll_p;
+            m2_p != 0 && m2_p->str != S_BAR;
+            m2_p = m2_p->next)
+               ;
+       if (m2_p == 0)
+               pfatal("no bar at end of last measure");
+
+       /* this time use bar line as terminating point */
+       inchperwhole = (m2_p->u.bar_p->c[AX] - gs_p->c[AX]) /
+                       RAT2FLOAT(gs_p->fulltime);
+
+       gs_p->c[INCHPERWHOLE] = inchperwhole;
+       if (gs_p->grpsyl == GS_GROUP && gs_p->grpcont == GC_NOTES) {
+               for (n = 0; n < gs_p->nnotes; n++)
+                       gs_p->notelist[n].c[INCHPERWHOLE] = inchperwhole;
+       }
+}
+\f
+/*
+ * Name:        setipwchord()
+ *
+ * Abstract:    Set INCHPERWHOLE "coordinate" for the CHORDs in one list.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets the special pseudocoord "c[INCHPERWHOLE]"
+ *             for all the CHORDs in the list hanging off of one CHHEAD.
+ */
+
+static void
+setipwchord(mainll_p)
+
+struct MAINLL *mainll_p;               /* point at the CHHEAD */
+
+{
+       struct MAINLL *m2_p;            /* look forward for bar line */
+       struct CHORD *ch_p, *nch_p;     /* point at chords */
+
+
+       debug(32, "setipwchord file=%s line=%d", mainll_p->inputfile,
+                               mainll_p->inputlineno);
+       /*
+        * Loop down the list of CHORDs.  ch_p always points the current
+        * CHORD, whose inches per whole we want to set.  nch_p points at
+        * the next CHORD.  When nch_p is 0, ch_p is the last chord, and we
+        * get out of the loop.
+        */
+       for (ch_p = mainll_p->u.chhead_p->ch_p, nch_p = ch_p->ch_p;
+                       nch_p != 0; ch_p = nch_p, nch_p = nch_p->ch_p) {
+               /*
+                * Distance between them divided by time gives the space a
+                * a whole note theoretically would have been given.
+                */
+               ch_p->c[INCHPERWHOLE] = (nch_p->c[AX] - ch_p->c[AX]) /
+                                       RAT2FLOAT(ch_p->duration);
+       }
+
+       /*
+        * We've hit the end of the measure.  Loop forward through the MLL
+        * until we find the bar line.
+        */
+       for (m2_p = mainll_p;
+            m2_p != 0 && m2_p->str != S_BAR;
+            m2_p = m2_p->next)
+               ;
+       if (m2_p == 0)
+               pfatal("no bar at end of last measure");
+
+       /* this time use bar line as terminating point */
+       ch_p->c[INCHPERWHOLE] = (m2_p->u.bar_p->c[AX] - ch_p->c[AX]) /
+                               RAT2FLOAT(ch_p->duration);
+}
+\f
+/*
+ * Name:        fixendings()
+ *
+ * Abstract:    Fix endings at end of score and in pseudobars.
+ *
+ * Returns:     void
+ *
+ * Description: This function finds endings that start at the final bar of a
+ *             score.  It moves them so that they will start at the pseudobar
+ *             at the start of the next score.  Then, wherever an ending is
+ *             continuing through a scorefeed, set the pseudobar's endingloc.
+ */
+
+static void
+fixendings()
+
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct MAINLL *m2_p;            /* look forward for bar line */
+       struct BAR *bar_p;              /* point at preceding bar */
+       char *str_p;                    /* point at an ending string */
+
+       
+       debug(16, "fixendings");
+       /*
+        * Loop through the main linked list, looking for endings that start at
+        * the end of a score, and moving them.  We do it in reverse, to make
+        * it slightly easier to deal with the case of scores that have only
+        * one measure on them.  (Previous endings won't have been moved yet.)
+        */
+       for (mainll_p = Mainlltc_p; mainll_p != 0; mainll_p = mainll_p->prev) {
+               if (mainll_p->str != S_BAR)
+                       continue;
+               if (mainll_p->u.bar_p->endingloc != STARTITEM)
+                       continue;
+
+               /*
+                * We are at a bar where an ending starts.  Find out if this is
+                * at the end of a score, by seeing if we find a FEED before
+                * the next bar.
+                */
+               for (m2_p = mainll_p->next; m2_p != 0 && m2_p->str != S_BAR &&
+                               m2_p->str != S_FEED; m2_p = m2_p->next)
+                       ;
+               if (m2_p == 0)
+                       pfatal("unterminated ending");
+               if (m2_p->str == S_BAR)
+                       continue;
+
+               /*
+                * The ending starts at the last bar of a score.  We need to
+                * know whether a previous ending also ends there, or not.  So
+                * search back to the previous bar.  Since we're doing the main
+                * loop in reverse, we don't have to look at pseudobars, only
+                * real ones.
+                */
+               for (m2_p = mainll_p->prev; m2_p != 0 && m2_p->str != S_BAR;
+                               m2_p = m2_p->prev)
+                       ;
+
+               /*
+                * If the previous bar was the end of an ending or not involved
+                * in one at all, the bar at the end of the score should not be
+                * involved.  Otherwise, there was a preceding ending which
+                * ends here (where the new one starts), so mark that it ends.
+                */
+               if (m2_p == 0 || m2_p->u.bar_p->endingloc == ENDITEM ||
+                                m2_p->u.bar_p->endingloc == NOITEM)
+
+                       mainll_p->u.bar_p->endingloc = NOITEM;
+               else
+                       mainll_p->u.bar_p->endingloc = ENDITEM;
+
+               str_p = mainll_p->u.bar_p->endinglabel;
+               mainll_p->u.bar_p->endinglabel = 0;
+
+               /*
+                * Find the first feed after this bar that is not at the start
+                * of a "block", and mark in the following pseudobar that an
+                * ending starts there.
+                */
+               for (m2_p = mainll_p->next; m2_p != 0 && (m2_p->str != S_FEED ||
+                            m2_p->next != 0 && m2_p->next->str == S_BLOCKHEAD);
+                            m2_p = m2_p->next)
+                       ;
+               if (m2_p == 0) {
+                       pfatal("can't find any music after ending begins");
+               }
+               m2_p->next->u.clefsig_p->bar_p->endingloc = STARTITEM;
+               m2_p->next->u.clefsig_p->bar_p->endinglabel = str_p;
+       }
+
+       /*
+        * Loop again through the main linked list, this time forwards.
+        * Remember each bar as we find one.  Then, adjust the following
+        * pseudobar if need be.
+        */
+       bar_p = 0;              /* no previous bar yet */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+               if (mainll_p->str == S_BAR)
+                       bar_p = mainll_p->u.bar_p;
+               if (mainll_p->str == S_CLEFSIG &&
+                                       mainll_p->u.clefsig_p->bar_p != 0) {
+                       /*
+                        * We're at a pseudobar.  If the preceding bar was
+                        * inside an ending, mark the pseudobar that way too.
+                        * (If this is the first pseudobar, there won't have
+                        * been any preceding bar.)
+                        */
+                       if (bar_p != 0 && bar_p->endingloc == INITEM)
+                               mainll_p->u.clefsig_p->bar_p->endingloc
+                                               = INITEM;
+               }
+       }
+}
+\f
+/*
+ * Name:        fixreh()
+ *
+ * Abstract:    Move rehearsal marks at end of a score to the next score.
+ *
+ * Returns:     void
+ *
+ * Description: This function finds rehearsal marks at the final bar of a
+ *             score.  It moves them so that they will be at the pseudobar
+ *             at the start of the next score.
+ */
+
+static void
+fixreh()
+
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct MAINLL *m2_p;            /* look forward for bar line */
+
+       
+       debug(16, "fixreh");
+       /*
+        * Loop through the main linked list, looking for rehearsal marks at
+        * the end of a score, and moving them.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+               if (mainll_p->str != S_BAR)
+                       continue;
+               if (mainll_p->u.bar_p->reh_type == REH_NONE)
+                       continue;
+
+               /*
+                * We are at a bar with a rehearsal mark.  Find out if this is
+                * at the end of a score, by seeing if we find a FEED before
+                * the next bar.
+                */
+               for (m2_p = mainll_p->next; m2_p != 0 && m2_p->str != S_BAR &&
+                               m2_p->str != S_FEED; m2_p = m2_p->next)
+                       ;
+               if (m2_p == 0)
+                       return; /* nothing more we can do in this case */
+               if (m2_p->str == S_BAR)
+                       continue;
+
+               /*
+                * The ending starts at the last bar of a score.  m2_p is at
+                * the FEED there, but what follows could be either music or a
+                * "block".  If it is a block, we need to keep moving forward
+                * until we find a FEED followed by music.
+                */
+               while (m2_p != 0 && ! IS_CLEFSIG_FEED(m2_p)) {
+                       m2_p = m2_p->next;
+               }
+               if (m2_p == 0) {
+                       return; /* there is no more music, can't move reh */
+               }
+
+               /*
+                * We found the FEED.  Move the rehearsal mark to the pseudo
+                * bar after the FEED.
+                */
+               m2_p->next->u.clefsig_p->bar_p->reh_type =
+                               mainll_p->u.bar_p->reh_type;
+               mainll_p->u.bar_p->reh_type = REH_NONE;
+
+               m2_p->next->u.clefsig_p->bar_p->reh_string =
+                               mainll_p->u.bar_p->reh_string;
+               mainll_p->u.bar_p->reh_string = 0;
+
+               m2_p->next->u.clefsig_p->bar_p->dist =
+                               mainll_p->u.bar_p->dist;
+               mainll_p->u.bar_p->dist = 0;
+
+               m2_p->next->u.clefsig_p->bar_p->dist_usage =
+                               mainll_p->u.bar_p->dist_usage;
+               mainll_p->u.bar_p->dist_usage = SD_NONE;
+       }
+}
+\f
+/*
+ * Name:        clrinhprint()
+ *
+ * Abstract:    Clear the inhibitprint on tablature staffs when appropriate.
+ *
+ * Returns:     void
+ *
+ * Description: This function clears the inhibitprint bit in the first group
+ *             of a tablature staff after a scorefeed.  (Because in that
+ *             situation, the group should be printed regardless of the usual
+ *             conditions that inhibit printing.)  Also, parentheses should be
+ *             put around every note (fret number) in such groups.
+ */
+
+static void
+clrinhprint()
+
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct GRPSYL *gs_p;            /* point at first group */
+       int sawscorefeed;               /* did we just see a scorefeed? */
+       int vidx;                       /* voice index */
+       int n;                          /* loop through the notes */
+
+       
+       debug(16, "clrinhprint");
+       sawscorefeed = YES;             /* "new score" at start of song */
+
+       /*
+        * Loop through main linked list, looking for visible tablature STAFFs,
+        * scorefeeds, and bar lines.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               switch (mainll_p->str) {
+               case S_FEED:
+                       sawscorefeed = YES;     /* just saw a feed */
+                       continue;
+               case S_BAR:
+                       sawscorefeed = NO;      /* next bar, forget the feed */
+                       continue;
+               case S_STAFF:
+                       /*
+                        * If we just saw a scorefeed, and this is a visible
+                        * tablature staff, break to handle it.  Otherwise
+                        * continue to the next loop iteration.
+                        */
+                       if (sawscorefeed == YES &&
+                       mainll_p->u.staff_p->visible == YES &&
+                       is_tab_staff(mainll_p->u.staff_p->staffno))
+                               break;
+                       continue;
+               default:
+                       continue;
+               }
+
+               /* loop through each possible voice on tab staff */
+               for (vidx = 0; vidx < MAXVOICES; vidx++) {
+
+                       /* if voice doesn't exist, break out */
+                       gs_p = mainll_p->u.staff_p->groups_p[vidx];
+                       if (gs_p == 0)
+                               break;
+
+                       /* if not a note group, there's nothing to do */
+                       if (gs_p->grpcont != GC_NOTES)
+                               continue;
+
+                       /*
+                        * If inhibitprint was set, we need to put parens
+                        * around the notes (frets) and clear the bit.
+                        */
+                       if (gs_p->inhibitprint == YES) {
+                               for (n = 0; n < gs_p->nnotes; n++)
+                                       gs_p->notelist[n].FRET_HAS_PAREN = YES;
+                               gs_p->inhibitprint = NO;
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        hidestaffs()
+ *
+ * Abstract:    Make staffs invisible if visible=whereused and they're empty.
+ *
+ * Returns:     void
+ *
+ * Description: If the user set visible=whereused for staffs, up until now we
+ *             have been treating it as visible=y, because the internal field
+ *             visible==YES.  But now that we know where all the scorefeeds
+ *             are, this function looks at hidesilent for the given score, and
+ *             when a staff should be invisible based on that, inserts SSVs
+ *             and sets the visible field in the STAFF structures to make it
+ *             invisible.
+ */
+
+static int
+hidestaffs(mainll_p, ml2_p)
+
+struct MAINLL *mainll_p;       /* point at feed at start of score */
+struct MAINLL *ml2_p;          /* point at last thing on the score */
+
+{
+       struct SSV *ssv_p;      /* a static SSV containing visibility */
+       int s;                  /* staff number */
+       int firstvis;           /* first visible staff in a score */
+       int foundvis;           /* is a staff after first still visible? */
+       int forced_invis;       /* did we force any staffs invisible? */
+       int ressv;              /* must we reapply SSVs from the start? */
+
+
+       debug(16, "hidestaffs");
+
+       /*
+        * Loop through main linked list, applying SSVs and looking for FEEDs.
+        * When a FEED is found, check all the staffs and make the appropriate
+        * ones invisible.
+        */
+       /* find the first (currently) visible staff in this score */
+       firstvis = 0;
+       for (s = 1; s <= Score.staffs; s++) {
+               if (svpath(s, VISIBLE)->visible == YES) {
+                       firstvis = s;
+                       break;
+               }
+       }
+       if (firstvis == 0) {
+               pfatal("no visible staffs in score");
+       }
+
+       /*
+        * Working bottom up, check each currently visible staff to see whether
+        * it should be made invisible.  If so, make it so.  But if nothing
+        * below the first visible staff ends up visible, we leave it alone,
+        * since at least one staff must always be visible.
+        * There are cases when silent() has to apply some SSVs.  In such
+        * cases, it sets ressv=YES.  Sadly, we have to reapply SSVs from the
+        * start in that case.
+        */
+       foundvis = NO;
+       forced_invis = NO;
+       for (s = Score.staffs; s >= firstvis; s--) {
+               if (s == firstvis && foundvis == NO) {
+                       /* only the top visible staff remains visible */
+                       break;
+               }
+               ssv_p = svpath(s, VISIBLE);
+               if (ssv_p->visible == NO) {     /* already invisible */
+                       continue;
+               }
+               if (ssv_p->hidesilent == YES) {
+                       if (silent(mainll_p, ml2_p, s, &ressv) == YES) {
+                               /* silent() forced it invisible */
+                               forced_invis = YES;
+                       } else {
+                               /* silent() left it visible */
+                               foundvis = YES;
+                       }
+                       if (ressv == YES) {
+                               setssvstate(mainll_p);
+                       }
+               } else {        /* hidesilent == NO */
+                       foundvis = YES; /* leave it visible */
+               }
+       }
+
+       return (forced_invis);
+}
+\f
+/*
+ * Name:        silent()
+ *
+ * Abstract:    Make a staff invisible for this score, if appropriate.
+ *
+ * Returns:     YES if we made it invisible, else NO
+ *
+ * Description: This function decides whether the given staff should be made
+ *             invisible on the given score (line).  It should be called only
+ *             when visible==YES and hidesilent==YES.  If it should be made
+ *             invisible, it does that by inserting new "input" SSVs into the
+ *             MLL before and after that line, and setting the visible field
+ *             in the staffs to NO.  There are cases where this function calls
+ *             asgnssv(); in those cases it sets *ressv_p to YES, otherwise NO.
+ */
+
+static int
+silent(feedmll_p, ml2_p, s, ressv_p)
+
+struct MAINLL *feedmll_p;      /* point along main linked list */
+struct MAINLL *ml2_p;          /* point at MLL item at end of this score */
+int s;                         /* staff number */
+int *ressv_p;                  /* must the caller reapply SSVs? */
+
+{
+       struct MAINLL *mll_p;   /* point along MLL */
+       struct MAINLL *lastbar_p; /* last bar line in score */
+       struct MAINLL *ins_p;   /* point at MLL after which a new SSV goes */
+       struct MAINLL *new_p;   /* point at MLL struct for a new SSV */
+       struct SSV *ssv_p;      /* an SSV */
+       struct STAFF *staff_p;  /* point at a STAFF */
+       struct STAFF *pstaff_p; /* point at the previous STAFF */
+       struct GRPSYL *gs_p;    /* point at a group or syllable */
+       struct STUFF *stuff_p;  /* point along a STUFF list */
+       int vidx;               /* voice or verse index */
+
+
+       *ressv_p = NO;          /* no SSVs have been applied yet */
+
+       /* find the last bar line in this score; it's where we should stop */
+       lastbar_p = 0;
+       for (mll_p = feedmll_p->next; mll_p != ml2_p && mll_p->str != S_FEED;
+                               mll_p = mll_p->next) {
+               if (mll_p->str == S_BAR) {
+                       lastbar_p = mll_p;
+               }
+       }
+       /* if none, there is no music here */
+       if (lastbar_p == 0) {
+               return (NO);    /* nothing to hide */
+       }
+
+       /*
+        * Loop through this score, checking SSVs and looking in the STAFFs for
+        * this staff number, looking for reasons we must keep the staff
+        * visible.
+        */
+       for (mll_p = feedmll_p; mll_p != lastbar_p; mll_p = mll_p->next) {
+               switch (mll_p->str) {
+               case S_SSV:
+                       /*
+                        * To minimize the chances that we will apply an SSV
+                        * and thus have to initstructs() and reapply from the
+                        * beginning, apply only if it is relevent to what we
+                        * are doing.
+                        */
+                       ssv_p = mll_p->u.ssv_p;
+                       if (ssv_p->context != C_SCORE && ssv_p->staffno != s) {
+                               /* this SSV is irrelevant to our staff */
+                               continue;
+                       }
+                       if (ssv_p->used[VISIBLE] != NO) {
+                               /*
+                                * This SSV could affect our staff's visibility.
+                                * Apply it, and remember that we've now messed
+                                * with the fixed SSVs, and so we'll have to
+                                * reapply from the start.
+                                */
+                               asgnssv(ssv_p);
+                               *ressv_p = YES;
+                       }
+                       /*
+                        * This staff started this score with visible==YES and
+                        * hidesilent==YES.  We know we are not going to see an
+                        * SSV that causes our staff to go invisible, since
+                        * that would have forced a scorefeed.  But we could
+                        * see one that causes our hidesilent value to be NO,
+                        * and in that case we can immediately return NO, since
+                        * it must remain visible.
+                        */
+                       if (svpath(s, VISIBLE)->hidesilent == NO) {
+                               return (NO);
+                       }
+                       continue;
+
+               case S_STAFF:
+                       staff_p = mll_p->u.staff_p;
+                       if (staff_p->staffno != s) {
+                               continue;       /* some other staff, ignore */
+                       }
+                       break;          /* break out to handle our staff */
+
+               default:
+                       continue;
+               }
+
+               /* decide whether this staff can be made invisible */
+
+               /*
+                * Look at each group in each possible voice.  If any contain
+                * notes, our staff must remain visible.
+                */
+               for (vidx = 0; vidx < MAXVOICES; vidx++) {
+                       for (gs_p = staff_p->groups_p[vidx]; gs_p != 0;
+                                       gs_p = gs_p->next) {
+                               if (gs_p->grpcont == GC_NOTES) {
+                                       return (NO);
+                               }
+                       }
+               }
+
+               /* if there are any syllables, our staff must remain visible */
+               if (staff_p->nsyllists != 0) {
+                       return (NO);
+               }
+
+               /* if there is any stuff, our staff must remain visible */
+               if (staff_p->stuff_p != 0) {
+                       return (NO);
+               }
+
+               /*
+                * If the previous MLL structure is a staff, it could have
+                * lyrics or "stuff" between it and our staff.  If this
+                * previous staff is already invisible, ignore it since these
+                * things would be invisible.  But the previous staff is
+                * visible, check for any of them being "between", in which
+                * case our staff must remain visible.
+                */
+               if (mll_p->prev->str == S_STAFF) {
+                       pstaff_p = mll_p->prev->u.staff_p;
+                       if (pstaff_p->visible == YES) {
+                               for (vidx = 0; vidx < pstaff_p->nsyllists;
+                                                       vidx++) {
+                                       if (pstaff_p->sylplace[vidx] ==
+                                                               PL_BETWEEN) {
+                                               return (NO);
+                                       }
+                               }
+                               for (stuff_p = pstaff_p->stuff_p; stuff_p != 0;
+                                               stuff_p = stuff_p->next) {
+                                       if (stuff_p->place == PL_BETWEEN) {
+                                               return (NO);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /*
+        * At this point we've looked through everything and found that there
+        * is no need to keep this staff visible.  So we are going to force it
+        * invisible.  If a staff's SSV says visible==NO but it has voice(s)
+        * with visible==YES, it ends up being visible anyhow.  So in addition
+        * to forcing the staff to visible=NO, we will unset all its voices'
+        * visibility.  Rather than checking how many voices there are, it's
+        * easiest just to force all possible ones invisible.
+        */
+
+       /*
+        * Set ins_p to the SSV after which the new ones should be put.  There
+        * may be a CLEFSIG before the FEED; if so, they should be put before
+        * there, otherwise just before the FEED.  This is to maintain the
+        * correct ordering of structures; see comment at the end of structs.h.
+        * If the FEED is at the start, ins_p will be 0.
+        */
+       ins_p = feedmll_p->prev;
+       if (ins_p != 0 && ins_p->str == S_CLEFSIG) {
+               ins_p = ins_p->prev;
+       }
+
+       /* force staff's visible to NO */
+       new_p = newMAINLLstruct(S_SSV, -1);
+       ssv_p = new_p->u.ssv_p;
+       ssv_p->context = C_STAFF;
+       ssv_p->staffno = s;
+       ssv_p->used[VISIBLE] = YES;
+       ssv_p->visible = NO;
+       insertMAINLL(new_p, ins_p);
+
+       /* force voices' visible to unset */
+       for (vidx = 0; vidx < MAXVOICES; vidx++) {
+               new_p = newMAINLLstruct(S_SSV, -1);
+               ssv_p = new_p->u.ssv_p;
+               ssv_p->context = C_VOICE;
+               ssv_p->staffno = s;
+               ssv_p->voiceno = vidx + 1;
+               ssv_p->used[VISIBLE] = UNSET;
+               insertMAINLL(new_p, ins_p);
+       }
+
+       /* do not let any SSVs on this line alter this staff's visibility */
+       for (mll_p = feedmll_p; mll_p != lastbar_p; mll_p = mll_p->next) {
+               if (mll_p->str != S_SSV) {
+                       continue;
+               }
+               ssv_p = mll_p->u.ssv_p;
+               /*
+                * Since we know we are overriding the score, we don't care if
+                * the score is changing.  Just force all staff and voice SSVs
+                * for this staff to not be setting VISIBLE.
+                */
+               if (ssv_p->context != C_SCORE && ssv_p->staffno == s) {
+                       ssv_p->used[VISIBLE] = NO;
+               }
+       }
+
+       /* the SSVs to be put at the end go after the last bar line */
+       ins_p = lastbar_p;
+
+       /*
+        * Insert "input" SSVs that will cause the staff's fixed SSV and its
+        * voices' fixed SSVs to be restored to how they would have been if we
+        * hadn't changed anything.  That is the state they are in right now.
+        */
+       new_p = newMAINLLstruct(S_SSV, -1);
+       ssv_p = new_p->u.ssv_p;
+       ssv_p->context = C_STAFF;
+       ssv_p->staffno = s;
+       if (Staff[s-1].used[VISIBLE] == YES) {
+               ssv_p->used[VISIBLE] = YES;
+               ssv_p->visible    = Staff[s-1].visible;
+               ssv_p->hidesilent = Staff[s-1].hidesilent;
+       } else {
+               ssv_p->used[VISIBLE] = UNSET;
+       }
+       insertMAINLL(new_p, ins_p);
+
+       for (vidx = 0; vidx < MAXVOICES; vidx++) {
+               new_p = newMAINLLstruct(S_SSV, -1);
+               ssv_p = new_p->u.ssv_p;
+               ssv_p->context = C_VOICE;
+               ssv_p->staffno = s;
+               ssv_p->voiceno = vidx + 1;
+               if (Voice[s-1][vidx].used[VISIBLE] == YES) {
+                       ssv_p->used[VISIBLE] = YES;
+                       ssv_p->visible    = Voice[s-1][vidx].visible;
+                       ssv_p->hidesilent = Voice[s-1][vidx].hidesilent;
+               } else {
+                       ssv_p->used[VISIBLE] = UNSET;
+               }
+               insertMAINLL(new_p, ins_p);
+       }
+
+       /* set visible to NO in every staff of this number on this line */
+       for (mll_p = feedmll_p; mll_p != lastbar_p; mll_p = mll_p->next) {
+               if (mll_p->str == S_STAFF) {
+                       staff_p = mll_p->u.staff_p;
+                       if (staff_p->staffno == s) {
+                               staff_p->visible = NO;
+                       }
+               }
+       }
+
+       return (YES);
+}
+\f
+/*
+ * Name:        getmultinum()
+ *
+ * Abstract:    Find number of measures in the next staff's multirest.
+ *
+ * Returns:     The number, or 0 if next staff is not a multirest.
+ *
+ * Description: This function is given an MLL struct, and if it's not a STAFF,
+ *             searches forward to the next STAFF.  It returns as stated above.
+ */
+
+static int
+getmultinum(mll_p)
+
+struct MAINLL *mll_p;          /* point along MLL, starts at the CLEFSIG */
+
+{
+       int basictime;  /* of the first group in the first following staff */
+
+
+       /* find the first staff after this clefsig */
+       for ( ; mll_p != 0 && mll_p->str != S_STAFF; mll_p = mll_p->next) {
+               ;
+       }
+
+       /* if no staff, there is no multirest */
+       if (mll_p == 0) {
+               return (0);
+       }
+
+       basictime = mll_p->u.staff_p->groups_p[0]->basictime;
+       return (basictime < -1 ? -basictime : 0);
+}
diff --git a/mup/mup/absvert.c b/mup/mup/absvert.c
new file mode 100644 (file)
index 0000000..b07a2b3
--- /dev/null
@@ -0,0 +1,3422 @@
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ * 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ * Name:       absvert.c
+ *
+ * Description:        This file contains functions for setting all absolute
+ *             vertical coordinates.
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+/*
+ * Define the maximum number of scores that could ever fit on a page, when all
+ * staffs and scores are packed as tightly as possible.  The 8 * STEPSIZE is
+ * the height of the five lines of a staff, and the other factor in the
+ * denominator is the minimum distance between staffs or scores, whichever is
+ * smaller.  If a staff has less than 5 lines, it is still given as much space
+ * as a 5 line staff, so that's why we can use 8 * STEPSIZE here as the
+ * smallest possible staff size.
+ */
+#define MAXSCORES      ( (int)(PGHEIGHT /                              \
+       (MINSTFSCALE * STEPSIZE * (8 + MIN(MINMINSTSEP, MINMINSCSEP)))) + 1 )
+
+#define        FUDGE   0.001   /* fudge factor for round off error */
+
+/* determine what clef, if any, will be printed on a staff */
+#define CLEF2PRINT(staffno)    \
+       (svpath(staffno, STAFFLINES)->printclef == SS_NORMAL ?  \
+                       svpath(staffno, CLEF)->clef : NOCLEF)
+
+/* define amount of horz and vert padding between at-end grids */
+#define HPADGRID       (2.0 * STEPSIZE)
+#define VPADGRID       (2.0 * STEPSIZE)
+
+/* maximum length of a chord name that we care about for sorting purposes */
+#define MAXCHNAME      (100)
+
+static void relscore P((struct MAINLL *mllfeed_p));
+static void relstaff P((struct MAINLL *feed_p, int s1, int s2, double botoff,
+               double betweendist));
+static void posscores P((void));
+static void abspage P((struct MAINLL *page_p, float cursep[], float maxsep[],
+               float curpad[], float maxpad[], int totscores,
+               double remheight, double y_start));
+static void absstaff P((struct FEED *feed_p, struct STAFF *staff_p));
+static double grids_atend P((double vertavail, int firstpage,
+               struct FEED *mfeed_p, struct FEED *gfeed_p));
+static int compgrids P((const void *g1_p_p, const void *g2_p_p));
+static void proc_css P((void));
+static void one_css P((struct STAFF *ts_p, struct STAFF *os_p,
+               struct GRPSYL *tg_p, RATIONAL time));
+static void horzavoid P((void));
+static void avoidone P((struct MAINLL *mainll_p, struct GRPSYL *cssg_p,
+               RATIONAL time));
+static void set_csb_stems P((void));
+static void onecsb P((struct GRPSYL *gs1_p, struct GRPSYL *gs2_p));
+static int calcline P((struct GRPSYL *start1_p, struct GRPSYL *end1_p,
+               struct GRPSYL *start2_p, struct GRPSYL *end2_p,
+               struct GRPSYL *first_p, struct GRPSYL *last_p,
+               int topdir, int botdir,
+               float *b0_p, float *b1_p));
+static void samedir P((struct GRPSYL *first_p, struct GRPSYL *last_p,
+               struct GRPSYL *start1_p, struct GRPSYL *start2_p,
+               struct GRPSYL *end1_p, float *b0_p, float *b1_p,
+               double deflen, int one_end_forced, int slope_forced,
+               double forced_slope));
+static void oppodir P((struct GRPSYL *first_p, struct GRPSYL *last_p,
+               struct GRPSYL *start1_p, struct GRPSYL *start2_p,
+               float *b0_p, float *b1_p, double deflen, int one_end_forced,
+               int slope_forced, double forced_slope));
+static struct GRPSYL *nextcsb P((struct GRPSYL *gs_p));
+static struct GRPSYL *nxtbmnote P((struct GRPSYL *gs_p, struct GRPSYL *first_p,
+               struct GRPSYL *endnext_p));
+\f
+/*
+ * Name:        absvert()
+ *
+ * Abstract:    Set all absolute vertical coordinates.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets all absolute vertical coordinates.  First it
+ *             calls relscore() for each score, to position the staffs in that
+ *             score relative to the score.  Then it calls posscores() to
+ *             decide how many scores to put on each page, and set all the
+ *             absolute coordinates.  Finally it completes the work for
+ *             cross staff stemming (CSS) and cross staff beaming (CSB).
+ */
+
+void
+absvert()
+
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+
+
+       debug(16, "absvert");
+       /*
+        * Find each section of the main linked list, delimited by FEEDs.  For
+        * each such section, call relscore() to fix the score internally
+        * (relative to itself, all staffs and between stuff).  Keep SSVs
+        * up to date so that we always know what the user requested
+        * separations are.
+        */
+       initstructs();                  /* clean out old SSV info */
+
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+               switch (mainll_p->str) {
+               case S_SSV:
+                       asgnssv(mainll_p->u.ssv_p);
+                       break;
+
+               case S_FEED:
+                       relscore(mainll_p);
+                       break;
+               }
+       }
+
+       /*
+        * Position the scores on the pages, setting all absolute vertical
+        * coordinates.
+        */
+       posscores();
+
+       /*
+        * Process groups that have cross staff stemming, if there were any.
+        */
+       if (CSSused == YES) {
+               proc_css();
+       }
+
+       /*
+        * Set stem lengths for groups involved in cross staff beaming, if
+        * there were any.
+        */
+       if (CSBused == YES) {
+               set_csb_stems();
+       }
+}
+\f
+/*
+ * Name:        relscore()
+ *
+ * Abstract:    Set certain relative coords to be relative to score.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through the part of the main linked list
+ *             for this score.  It adjusts the relative vertical coords of
+ *             STAFFs, and also of GRPSYLs (syllables) and STUFFs of the
+ *             things that are "between" staffs.  In the end, the STAFFs will
+ *             be relative to the score (FEED), and the between things will
+ *             be relative to the staff above them.  Yes, I suppose this
+ *             belongs in relvert.c, but relvert.c has enough work to do.
+ */
+
+static void
+relscore(mllfeed_p)
+
+struct MAINLL *mllfeed_p;      /* FEED at start of this score */
+
+{
+       struct MAINLL *mainll_p;/* point along main linked list */
+       struct STAFF *cstaff_p; /* point at current staff */
+       struct STAFF *pstaff_p; /* point at previous staff */
+       struct FEED *feed_p;    /* point at FEED structure itself */
+       float cstaffoffset;     /* current staff offset from score */
+       float staffdist;        /* dist between prev & cur staff inner lines*/
+       float halfnonbetween;   /* (staffdist - heightbetween) / 2 */
+       float betweendist;      /* from prev staff center line to base line */
+       float prevhalf;         /* half the height of previous staff */
+       float curhalf;          /* half the height of current staff */
+       float limit;            /* smallest dist allowed between inner lines */
+       float needed;           /* dist between inner lines to avoid collis */
+       int prevclef;           /* clef on the previous staff */
+       float prevscale;        /* staffscale of the previous staff */
+       float spad;             /* staffpad (inches) below previous staff */
+       float clefroom;         /* room for clefs and/or measure numbers */
+       static int first = YES; /* is this the first score in the song? */
+
+
+       debug(32, "relscore file=%s line=%d", mllfeed_p->inputfile,
+                       mllfeed_p->inputlineno);
+       feed_p = mllfeed_p->u.feed_p;
+
+       /*
+        * If this score is actually a block, all we have to do is set the
+        * relative vertical coords of the FEED.  We set RY to be the center.
+        */
+       if (mllfeed_p->next != 0 && mllfeed_p->next->str == S_BLOCKHEAD) {
+               feed_p->c[RN] = mllfeed_p->next->u.blockhead_p->height / 2.0;
+               feed_p->c[RY] = 0;              /* RY is always 0 */
+               feed_p->c[RS] = -feed_p->c[RN];
+               feed_p->lastdist = 0.0;
+               return;
+       }
+
+       /*
+        * Find the first STAFF in this score (will be in first measure).
+        */
+       for (mainll_p = mllfeed_p->next; mainll_p != 0 &&
+                       mainll_p->str != S_FEED && mainll_p->str != S_STAFF;
+                       mainll_p = mainll_p->next)
+               ;
+       if (mainll_p == 0 || mainll_p->str != S_STAFF)
+               return; /* ignore items when there's a feed at end of song */
+
+       /* init variables for main loop */
+       cstaffoffset = 0;               /* top staff Y == score Y */
+       pstaff_p = 0;                   /* there is no previous staff */
+       prevclef = NOCLEF;
+       prevscale = 1.0;
+       spad = 0.0;             /* keep lint happy; will be set before used */
+
+       /*
+        * Loop through all STAFF structures in the first measure of this
+        * score.  Skip invisible ones.  cstaff_p always points at the staff
+        * we are working on, and pstaff_p always points to the previous
+        * visible staff (so is 0 while we are working on the first visible
+        * staff of the score).  For each visible staff except the first, we
+        * figure out how far down it should be from the one above it, and
+        * set its relative vertical coords relative to the score.  Also, we
+        * figure out where to put the things that are "between" this staff
+        * and the one above, and set them relative to the above staff.
+        */
+       for ( ; mainll_p->str == S_STAFF; mainll_p = mainll_p->next) {
+
+               cstaff_p = mainll_p->u.staff_p;
+
+               /*
+                * If this staff is invisible, ignore it completely.
+                */
+               if (cstaff_p->visible == NO)
+                       continue;
+
+               /*
+                * If it's the first visible staff, there are no coords to set,
+                * since its offset is 0 and the "between" objects below it
+                * will be handled by the next loop.  Also set first and last
+                * visible staff numbers in the FEED in this loop, and the
+                * relative vertical coords of the score.
+                */
+               if (pstaff_p == 0) {
+                       /* set first visible staff number */
+                       feed_p->firstvis = cstaff_p->staffno;
+
+                       /* feed's RN is same as first visible staff's RN */
+                       feed_p->c[RN] = cstaff_p->c[RN];
+                       feed_p->c[RY] = 0;              /* RY is always 0 */
+
+                       /* these next 3 will be changed later if more staffs */
+                       feed_p->c[RS] = cstaff_p->c[RS];
+                       feed_p->lastvis = cstaff_p->staffno;
+                       feed_p->lastdist = cstaff_p->c[RY] - cstaff_p->c[RS] -
+                               staffvertspace(cstaff_p->staffno) / 2.0;
+
+                       pstaff_p = cstaff_p;    /* previous visible staff */
+                       prevclef = CLEF2PRINT(pstaff_p->staffno);
+                       prevscale = svpath(pstaff_p->staffno, STAFFSCALE)->
+                                       staffscale;
+                       spad = svpath(pstaff_p->staffno, STAFFPAD)->staffpad
+                               * STEPSIZE * prevscale;
+                       continue;               /* no coords to set */
+               }
+
+               /* set half the height of the previous and current staffs */
+               prevhalf = staffvertspace(pstaff_p->staffno) / 2.0;
+               curhalf = staffvertspace(cstaff_p->staffno) / 2.0;
+
+               /*
+                * The space needed between the bottom line of the previous
+                * staff and the top line of the current staff to avoid
+                * collisions is how far up from the current staff things
+                * stick, plus how far down from the previous staff things
+                * stick, plus the height of anything "between" the two.
+                * To this we add spad for extra padding (overlap if negative).
+                */
+               needed = (cstaff_p->c[RN] - curhalf) +
+                        ((pstaff_p->c[RY] - pstaff_p->c[RS]) - prevhalf) +
+                        pstaff_p->heightbetween + spad;
+               /*
+                * Set the distance between those two lines to be what the
+                * user requested, or what was calculated above as "needed",
+                * whichever is greater.  Set halfnonbetween to be half of
+                * this result, minus half the height of the "between" items.
+                */
+               /* never closer than this */
+               limit = svpath(pstaff_p->staffno,MINSTSEP)->minstsep * STEPSIZE;
+               clefroom = clefspace(prevclef, prevscale,
+                       CLEF2PRINT(cstaff_p->staffno),
+                       svpath(cstaff_p->staffno, STAFFSCALE)->staffscale,
+                       Score.measnum == YES && has_ending(cstaff_p->staffno)
+                       && first == NO);
+               limit = MAX(limit, clefroom);
+
+               staffdist = MAX(limit, needed); /* between prev & current */
+
+               /*
+                * Find half the room between the inner staff lines that is not
+                * going to be used by the "between" items.  But pretend that
+                * the "between" items are bigger by "spad" than they really
+                * are, so that half of staffpad will go on each side of them.
+                */
+               halfnonbetween = (staffdist - (pstaff_p->heightbetween + spad))
+                               / 2.0;
+
+               /* set cstaffoffset for relative to score */
+               cstaffoffset -= (prevhalf + staffdist + curhalf);
+
+               /*
+                * The "between" items are currently placed relative to a base
+                * line that they were piled onto.  We would like to center
+                * them between the staffs, but if one staff sticks out more
+                * than the other, it may not be possible.  Center as close as
+                * possible.  betweendist is how far the base line is from the
+                * center line of the previous staff.
+                */
+               if ((pstaff_p->c[RY] - pstaff_p->c[RS]) - prevhalf >
+                                       halfnonbetween) {
+                       /*
+                        * The top staff sticks down far enough that we have
+                        * to put the "between" items below center.  Jam them
+                        * against the top staff.
+                        */
+                       betweendist = (pstaff_p->c[RY] - pstaff_p->c[RS]) +
+                                               pstaff_p->heightbetween + spad;
+               } else if (cstaff_p->c[RN] - curhalf > halfnonbetween) {
+                       /*
+                        * The bottom staff sticks up far enough that we have
+                        * to put the "between" items above center.  Jam them
+                        * against the bottom staff.
+                        */
+                       betweendist = (prevhalf + staffdist + curhalf) -
+                                               cstaff_p->c[RN];
+               } else {
+                       /*
+                        * There is room to center the between items.
+                        */
+                       betweendist = prevhalf + staffdist - halfnonbetween;
+               }
+
+               /* change baseline of padding to actual baseline */
+               betweendist -= spad / 2.0;
+
+               /*
+                * For all STAFF structures of these staff numbers in this
+                * score, change relative coords as described below.
+                */
+               relstaff(mllfeed_p, pstaff_p->staffno, cstaff_p->staffno,
+                               cstaffoffset, betweendist);
+
+               /* last loop iteration leaves right value in these variables */
+               feed_p->lastvis = cstaff_p->staffno;
+               feed_p->c[RS] = cstaff_p->c[RS];
+               feed_p->lastdist = cstaff_p->c[RY] - cstaff_p->c[RS] - curhalf;
+
+               pstaff_p = cstaff_p;
+               prevclef = CLEF2PRINT(pstaff_p->staffno);
+               prevscale = svpath(pstaff_p->staffno, STAFFSCALE)->staffscale;
+               spad = svpath(pstaff_p->staffno, STAFFPAD)->staffpad
+                               * STEPSIZE * prevscale;
+       }
+
+       first = NO;     /* next score will not be the first */
+}
+\f
+/*
+ * Name:        relstaff()
+ *
+ * Abstract:    Set certain relative coords to be relative to score.
+ *
+ * Returns:     void
+ *
+ * Description:        This function is given two staff structures for consecutive
+ *             visible staffs.  For all STAFF structures of these staff
+ *             numbers in this score, set the bottom staff's coords relative
+ *             to the score, and set the "between" items' coords (for what's
+ *             between top and bottom staff) relative to the top staff.
+ */
+
+static void
+relstaff(feed_p, s1, s2, botoff, betweendist)
+
+struct MAINLL *feed_p;         /* pointer to FEED for this score */
+int s1;                                /* number of top staff */
+int s2;                                /* number of bottom staff */
+double botoff;                 /* center line of bottom, relative to score */
+double betweendist;            /* center line of top to base line of between*/
+
+{
+       struct MAINLL *mainll_p;/* point along main linked list */
+       struct STAFF *staff_p;  /* pointer to a staff */
+       struct GRPSYL *syl_p;   /* pointer to a syllable */
+       struct STUFF *stuff_p;  /* pointer to stuff to draw */
+       int n;                  /* loop variable */
+
+
+       debug(32, "relstaff file=%s line=%d s1=%d s2=%d botoff=%f betweendist=%f",
+                       feed_p->inputfile, feed_p->inputlineno, s1, s2,
+                       (float)botoff, (float)betweendist);
+       /*
+        * Loop through the section of the main linked list for this score,
+        * looking for every STAFF for one of the two given staffs.
+        */
+       for (mainll_p = feed_p->next; mainll_p != 0 && mainll_p->str != S_FEED;
+                               mainll_p = mainll_p->next) {
+
+               if (mainll_p->str == S_STAFF &&
+                               mainll_p->u.staff_p->staffno == s1) {
+
+                       staff_p = mainll_p->u.staff_p;
+
+                       /*
+                        * Subtract betweendist from all relative coords of
+                        * "between" items hanging off this staff, to make them
+                        * relative to this staff instead of the base line.
+                        */
+                       for (n = 0; n < staff_p->nsyllists; n++) {
+                               if (staff_p->sylplace[n] == PL_BETWEEN) {
+                                       for (syl_p = staff_p->syls_p[n];
+                                                       syl_p != 0;
+                                                       syl_p = syl_p->next) {
+                                               syl_p->c[RN] -= betweendist;
+                                               syl_p->c[RY] -= betweendist;
+                                               syl_p->c[RS] -= betweendist;
+                                       }
+                               }
+                       }
+                       for (stuff_p = staff_p->stuff_p; stuff_p != 0;
+                                       stuff_p = stuff_p->next) {
+                               if (stuff_p->place == PL_BETWEEN) {
+                                       stuff_p->c[RN] -= betweendist;
+                                       stuff_p->c[RY] -= betweendist;
+                                       stuff_p->c[RS] -= betweendist;
+                               }
+                       }
+               }
+
+               if (mainll_p->str == S_STAFF &&
+                               mainll_p->u.staff_p->staffno == s2) {
+
+                       staff_p = mainll_p->u.staff_p;
+
+                       /*
+                        * Make this staff relative to the score instead of
+                        * relative to its own center line.
+                        */
+                       staff_p->c[RN] += botoff;
+                       staff_p->c[RY] = botoff;
+                       staff_p->c[RS] += botoff;
+               }
+       }
+}
+\f
+/*
+ * Name:        posscores()
+ *
+ * Abstract:    Place which scores on which pages, and set all vertical coords.
+ *
+ * Returns:     void
+ *
+ * Description: This function decides how many scores are going to fit on each
+ *             page, based on how big they are and how much minimum space the
+ *             user wants put between them.  It calls abspage() for each page
+ *             to do final positioning and coordinate setting.
+ */
+
+static void
+posscores()
+
+{
+       struct MAINLL *mainll_p;/* point along main LL */
+       struct TIMEDSSV *tssv_p;/* point along timed SSV lists */
+       struct MAINLL *page_p;  /* point at first FEED of a page */
+       struct MAINLL *ppage_p; /* point at first FEED of previous page */
+       struct MAINLL *gridpage_p; /* point at FEED for grids-at-end */
+       struct MAINLL *origpage_p; /* remember original page_p */
+       struct FEED *cfeed_p;   /* point at current scorefeed */
+       struct FEED *pfeed_p;   /* point at previous scorefeed */
+       float availheight;      /* available height on page (middle window) */
+       float remheight;        /* remaining height on page */
+       float y_start;          /* where y begins (at top of _win) */
+       float limit;            /* smallest distance allowed between scores */
+       int prevclef;           /* clef on last visible staff of prev score */
+       float clefroom;         /* room for clefs and/or measure numbers */
+       float excess;           /* extra room needed for top score */
+       float abovetopline;     /* dist from top line of score to top of score*/
+       float ink;              /* distance ink extends between inner lines */
+       float padding;          /* space between farthest extents */
+       float scoreheight;      /* height of current score */
+       float topheight, botheight;     /* height of a "top" or "bot" block */
+       int aftertitle;         /* is this the page after a title page? */
+       int firstpage;          /* are we working on the first page? */
+       int totscores;          /* number of scores on a page */
+
+       /* the following are all in inches, unlike scorepad/scoresep parms */
+       float curminpad;        /* current minscpad */
+       float curmaxpad;        /* current maxscpad */
+       float *curpad;          /* malloc: pad above each score */
+       float *maxpad;          /* malloc: maxscpad above each score */
+       float curminsep;        /* current minscsep */
+       float curmaxsep;        /* current maxscsep */
+       float *cursep;          /* malloc: sep above each score */
+       float *maxsep;          /* malloc: maxscsep above each score */
+
+       int is_block;           /* is there a block after this FEED? */
+       struct BLOCKHEAD *rememtop2_p, *remembot2_p; /* remember most current*/
+       struct BLOCKHEAD *head_p;       /* point at Header or Header2 */
+       struct BLOCKHEAD *foot_p;       /* point at Footer or Footer2 */
+
+
+       debug(16, "posscores");
+       /*
+        * In each of these arrays, array[idx] refers to distance below score
+        * number idx on a page, numbering the scores from 1 to N.  For sep, 
+        * only indices 1 through N-1 are used.  For pad, indices 0 through N
+        * are used, where 0 means above the first score and N below the last.
+        * The "sep" arrays are for distances between the outermost staff lines
+        * of neighboring scores.  The "pad" arrays are for distances between
+        * the outermost thing sticking out of those scores.  The "above"
+        * arrays are for distance currently allocated.  The "max" arrays are
+        * for the max limits we impose (when we can).
+        */
+       MALLOCA(float, cursep, MAXSCORES);
+       MALLOCA(float, curpad, MAXSCORES + 1);
+       MALLOCA(float, maxsep, MAXSCORES);
+       MALLOCA(float, maxpad, MAXSCORES + 1);
+
+       initstructs();          /* init SSVs */
+
+       /* the following need to be initialized for the coming loop */
+       curminsep = Score.minscsep * STEPSIZE;
+       curminpad = Score.minscpad * STEPSIZE;
+       curmaxsep = Score.maxscsep * STEPSIZE;
+       curmaxpad = Score.maxscpad * STEPSIZE;
+       pfeed_p = 0;
+       firstpage = YES;
+       mainll_p = Mainllhc_p;
+       rememtop2_p = remembot2_p = 0;
+
+       /* the following don't really need to be initialized; we're doing it */
+       /* just to prevent useless 'used before set' warnings */
+       page_p = 0;
+       ppage_p = 0;
+       remheight = 0;
+       y_start = 0;
+       totscores = 0;
+       prevclef = NOCLEF;
+       botheight = 0.0;
+       foot_p = 0;
+
+       /*
+        * Loop through the main linked list, looking at each feed.  Assuming
+        * the scores are packed as tightly as allowed, see how many will fit
+        * on each page.  Whenever a page fills up, call abspage() to
+        * distribute the extra white space as well as possible and set all
+        * the absolute vertical coords for that page.  At the end, call it
+        * again for the last page.
+        */
+       while (mainll_p != 0) {
+               switch (mainll_p->str) {
+               case S_FEED:
+                       break;  /* go handle this score */
+               case S_SSV:
+                       /* apply, and reset vars in case some changed */
+                       asgnssv(mainll_p->u.ssv_p);
+                       curminsep = Score.minscsep * STEPSIZE;
+                       curmaxsep = Score.maxscsep * STEPSIZE;
+                       curminpad = Score.minscpad * STEPSIZE;
+                       curmaxpad = Score.maxscpad * STEPSIZE;
+                       mainll_p = mainll_p->next;
+                       continue;
+               case S_BAR:
+                       /* apply timed SSVs; they won't affect the above
+                        * variables, but they could affect clef, which we
+                        * will need later */
+                       for (tssv_p = mainll_p->u.bar_p->timedssv_p;
+                                       tssv_p != 0; tssv_p = tssv_p->next) {
+                               asgnssv(&tssv_p->ssv);
+                       }
+                       mainll_p = mainll_p->next;
+                       continue;
+               default:
+                       mainll_p = mainll_p->next;
+                       continue;
+               }
+
+               /* if there is nothing after this FEED, break out */
+               if (mainll_p->next == 0) {
+                       break;
+               }
+
+               cfeed_p = mainll_p->u.feed_p;   /* set convenient pointer */
+
+               /*
+                * If firstpage is set, normally there would be no pagefeed,
+                * because the first FEED on that page is marked as a pagefeed
+                * only if the user requested it.  If they did, that means
+                * there was a title page with no music on it.  We need to
+                * remember this fact, so that we know to use header2/footer2
+                * instead of header/footer.  Only the title page would use
+                * header/footer.
+                */
+               aftertitle = firstpage == YES && cfeed_p->pagefeed == YES;
+
+               /* see if there is a block after this feed */
+               is_block = mainll_p->next != 0 &&
+                               mainll_p->next->str == S_BLOCKHEAD;
+
+               scoreheight = cfeed_p->c[RN] - cfeed_p->c[RS];
+
+               if (pfeed_p == 0) {
+                       /*
+                        * We are at the top of a page.  Point at the header
+                        * and footer that apply.  Note that if the header or
+                        * footer is unused, its height will be 0.
+                        */
+                       if (firstpage == YES && aftertitle == NO) {
+                               head_p = &Header;
+                               foot_p = &Footer;
+                       } else {
+                               head_p = &Header2;
+                               foot_p = &Footer2;
+                       }
+
+                       /* if not the first page, set pagefeed */
+                       if (firstpage == NO) {
+                               cfeed_p->pagefeed = YES;
+                       }
+
+                       /* remember most recent settings of top2 and bot2 */
+                       if (cfeed_p->top2_p != 0) {
+                               rememtop2_p = cfeed_p->top2_p;
+                       }
+                       if (cfeed_p->bot2_p != 0) {
+                               remembot2_p = cfeed_p->bot2_p;
+                       }
+
+                       /*
+                        * Decide what is to be printed at the top and
+                        * bottom (inside the header(2)/footer(2) if any).
+                        * On the first page and at every pagefeed where top_p
+                        * is set, that is to be used, so leave it alone.
+                        * Otherwise use the most recent top2_p setting, so
+                        * save the value into top_p.  Later in this function,
+                        * and also in the print phase, top_p is used, not
+                        * top2_p, with exception of grids-at-end pages.
+                        */
+                       if (firstpage == NO && cfeed_p->top_p == 0) {
+                               cfeed_p->top_p = rememtop2_p;
+                       }
+                       /* analogous for bottom */
+                       if (firstpage == NO && cfeed_p->bot_p == 0) {
+                               cfeed_p->bot_p = remembot2_p;
+                       }
+
+                       /* set height of "top" & "bot" if they exist, else 0 */
+                       topheight = cfeed_p->top_p != 0 ?
+                                       cfeed_p->top_p->height : 0.0;
+                       botheight = cfeed_p->bot_p != 0 ?
+                                       cfeed_p->bot_p->height : 0.0;
+
+                       /*
+                        * Remove these items' size from the space available
+                        * for music, and set music's starting point.
+                        */
+                       availheight = PGHEIGHT - EFF_TOPMARGIN - EFF_BOTMARGIN
+                               - head_p->height - foot_p->height
+                               - topheight - botheight;
+
+                       y_start = PGHEIGHT - EFF_TOPMARGIN
+                               - head_p->height - topheight;
+
+                       /*
+                        * If a header or top exists on this page, we need to
+                        * have pad below it.  Since we're initially packing as
+                        * tightly as possible, assume the minimum.  Reduce the
+                        * available room by that amount.  Analogous for
+                        * footer/bottom.
+                        */
+                       if (head_p->height + topheight > 0.0) {
+                               availheight -= curminpad;
+                       }
+                       if (foot_p->height + botheight > 0.0) {
+                               availheight -= curminpad;
+                       }
+
+                       /* increase score's RN and scoreheight if need be */
+                       if (is_block) {
+                               /*
+                                * Blocks have no clef or measure number, but
+                                * clefspace() still will return a little
+                                * something for padding, so add that in.
+                                */
+                               excess = clefspace(NOCLEF, 1.0, NOCLEF, 1.0,NO);
+                               cfeed_p->c[RN] += excess;
+                               scoreheight += excess;
+                       } else {
+                               /*
+                                * If clef (and measure number if that is to be
+                                * printed) stick up higher than anything else,
+                                * adjust the size of the score to allow for it.
+                                */
+                               clefroom = clefspace(NOCLEF, 1.0,
+                                       CLEF2PRINT(cfeed_p->firstvis), 1.0,
+                                       Score.measnum == YES &&firstpage == NO);
+                               abovetopline = cfeed_p->c[RN] -
+                                       staffvertspace(cfeed_p->firstvis) / 2.0;
+                               excess = clefroom - abovetopline;
+                               if (excess > 0.0) {
+                                       cfeed_p->c[RN] += excess;
+                                       scoreheight += excess;
+                               }
+                       }
+
+                       if (scoreheight > availheight) {
+                               if (Score.units == INCHES) {
+                                       ufatal("score is too high (%.2f inches) to fit on one page (limit %.2f)",
+                                       scoreheight * Score.scale_factor,
+                                       availheight * Score.scale_factor);
+                               } else {
+                                       ufatal("score is too high (%.2f cm) to fit on one page (limit %.2f)",
+                                       scoreheight * Score.scale_factor *
+                                       CMPERINCH, availheight *
+                                       Score.scale_factor * CMPERINCH);
+                               }
+                       }
+
+                       /*
+                        * Set pad above the top score.  If there is a header
+                        * or top, use the values from scorepad.  If not, force
+                        * both to 0, so that none will be allowed.
+                        */
+                       if (head_p->height + topheight > 0.0) {
+                               curpad[0] = curminpad;
+                               maxpad[0] = curmaxpad;
+                       } else {
+                               curpad[0] = 0.0;
+                               maxpad[0] = 0.0;
+                       }
+
+                       remheight = availheight - scoreheight;
+                       totscores = 1;
+                       pfeed_p = cfeed_p;
+                       ppage_p = page_p;
+                       page_p = mainll_p;
+                       mainll_p = mainll_p->next;
+                       firstpage = NO;
+                       if (is_block)
+                               prevclef = NOCLEF;
+                       else
+                               prevclef = CLEF2PRINT(pfeed_p->lastvis);
+
+               } else {
+
+                       /*
+                        * This will be the second or later score on this page,
+                        * if it fits, and the user did not request a manual
+                        * pagefeed.  Figure out what the minimum padding can
+                        * be between this score and the previous.  "ink" is
+                        * the distance things on the bottom visible staff of
+                        * the previous score extend from its bottom line down,
+                        * plus the distance things on the top visible staff of
+                        * the current score extend from its top line up.
+                        * curminpad is the minimum white space the user wants
+                        * to allow between scores.
+                        */
+                       if (is_block) {
+                               ink = pfeed_p->lastdist;
+                               clefroom = clefspace(prevclef, 1.0, NOCLEF,
+                                       1.0, NO);
+                       } else {
+                               ink = pfeed_p->lastdist + (cfeed_p->c[RN] -
+                                       staffvertspace(cfeed_p->firstvis)/2.0);
+                               clefroom = clefspace(prevclef, 1.0,
+                                       CLEF2PRINT(cfeed_p->firstvis), 1.0,
+                                       Score.measnum);
+                       }
+                       limit = MAX(curminsep, clefroom);
+                       if (ink < limit - curminpad) {
+                               padding = limit - ink;
+                       } else {
+                               padding = curminpad;
+                       }
+
+                       if (padding + scoreheight <= remheight &&
+                                               cfeed_p->pagefeed == NO) {
+                               /* this score fits on this page */
+                               remheight -= padding + scoreheight;
+                               cursep[totscores] = ink + padding;
+                               maxsep[totscores] = curmaxsep;
+                               curpad[totscores] = padding;
+                               maxpad[totscores] = curmaxpad;
+                               totscores++;
+                               pfeed_p = cfeed_p;
+                               mainll_p = mainll_p->next;
+                               if (is_block)
+                                       prevclef = NOCLEF;
+                               else
+                                       prevclef = CLEF2PRINT(pfeed_p->lastvis);
+                       } else {
+                               /* the score does not fit */
+                               /*
+                                * Set pad below the bottom score.  If there is
+                                * a footer or bottom, use the values from
+                                * scorepad.  If not, force both to 0, so that
+                                * none will be allowed.
+                                */
+                               if (foot_p->height + botheight > 0.0) {
+                                       curpad[totscores] = curminpad;
+                                       maxpad[totscores] = curmaxpad;
+                               } else {
+                                       curpad[totscores] = 0.0;
+                                       maxpad[totscores] = 0.0;
+                               }
+
+                               abspage(page_p, cursep, maxsep, curpad,
+                                               maxpad, totscores,
+                                               remheight, y_start);
+                               pfeed_p = 0;
+                       }
+               }
+       }
+
+       /* in case it changes, remember the original page_p */
+       origpage_p = page_p;
+
+       /* find out what is after the last FEED */
+       if (page_p->next != 0 && (page_p->next->str == S_CLEFSIG ||
+                                 page_p->next->str == S_BLOCKHEAD)) {
+               /*
+                * The last top-of-page feed has music/block(s) after it.  Let
+                * page_p continue to point at it, and for now let gridpage_p
+                * be null.
+                */
+               gridpage_p = 0;
+       } else {
+               /*
+                * The last top-of-page feed is after all music/blocks.  Point
+                * page_p at the previous one, and use this one for gridpage_p.
+                */
+               gridpage_p = page_p;
+               page_p = ppage_p;
+       }
+
+       /*
+        * Before distributing the scores on the last page, if there are chord
+        * grids to be printed at the end, find whether they fit on this page
+        * (their height doesn't exceed remheight minus white).  If so, the
+        * subroutine places them at the bottom and returns their height.  If
+        * they don't fit, it returns zero and puts them on a separate page.
+        */
+       if (Atend_info.grids_used > 0) {
+               float gridheight;
+
+               /*
+                * In case grids need to go on later page(s), we need to make
+                * sure there is a FEED at the end of the MLL.  Its top_p and
+                * bot_p will be used on the first grid page, and top2_p and
+                * bot2_p will be used on later pages.
+                */
+               if (gridpage_p == 0) {
+                       /* find last thing in MLL that's not LINE/CURVE/PRHEAD*/
+                       for (mainll_p = Mainlltc_p;
+                                       mainll_p->str == S_LINE ||
+                                       mainll_p->str == S_CURVE ||
+                                       mainll_p->str == S_PRHEAD;
+                                       mainll_p = mainll_p->prev)
+                               ;
+                       if (mainll_p->str == S_FEED) {
+                               /* FEED, so reuse for gridpage FEED */
+                               /* (it wasn't a top-of-page FEED before) */
+                               gridpage_p = mainll_p;
+                       } else {
+                               /* alloc new FEED to be used for grid pages */
+                               gridpage_p = newMAINLLstruct(S_FEED, -1);
+                               insertMAINLL(gridpage_p, Mainlltc_p);
+                       }
+
+                       /*
+                        * Both the first and later grid pages should use what
+                        * is currently remembered for top2 and bot2.
+                        */
+                       gridpage_p->u.feed_p->top_p =
+                               gridpage_p->u.feed_p->top2_p = rememtop2_p;
+                       gridpage_p->u.feed_p->bot_p =
+                               gridpage_p->u.feed_p->bot2_p = remembot2_p;
+               } else {
+                       /* set pointers that are not already set */
+                       if (gridpage_p->u.feed_p->top2_p == 0) {
+                               gridpage_p->u.feed_p->top2_p = rememtop2_p;
+                       }
+                       if (gridpage_p->u.feed_p->top_p == 0) {
+                               gridpage_p->u.feed_p->top_p =
+                                               gridpage_p->u.feed_p->top2_p;
+                       }
+                       if (gridpage_p->u.feed_p->bot2_p == 0) {
+                               gridpage_p->u.feed_p->bot2_p = remembot2_p;
+                       }
+                       if (gridpage_p->u.feed_p->bot_p == 0) {
+                               gridpage_p->u.feed_p->bot_p =
+                                               gridpage_p->u.feed_p->bot2_p;
+                       }
+               }
+
+               /*
+                * (remheight - curminpad) is how much space is available on the
+                * last page for grids.   firstpage is needed to know whether
+                * to use Header or Header2 (etc.) in calculations.   The next
+                * two parms are needed for finding the correct top and bottom
+                * sizes for the last music page, and any grid-only pages.
+                */
+               gridheight = grids_atend(remheight - curminpad, firstpage,
+                       page_p->u.feed_p, gridpage_p->u.feed_p);
+
+               if (gridheight > 0.0) {
+                       /* reduce remaining height by grids and curminpad */
+                       remheight -= gridheight + curminpad;
+               }
+       }
+
+       /*
+        * Set pad below the bottom score.  If there is a footer
+        * or bottom, use the values from scorepad.  If not, force
+        * both to 0, so that none will be allowed.
+        */
+       if (foot_p->height + botheight > 0.0) {
+               curpad[totscores] = curminpad;
+               maxpad[totscores] = curmaxpad;
+       } else {
+               curpad[totscores] = 0.0;
+               maxpad[totscores] = 0.0;
+       }
+
+       abspage(origpage_p, cursep, maxsep, curpad, maxpad, totscores,
+                       remheight, y_start);
+
+       FREE(cursep);
+       FREE(maxsep);
+       FREE(curpad);
+       FREE(maxpad);
+}
+\f
+/*
+ * Name:        abspage()
+ *
+ * Abstract:    Set all absolute vertical coordinates on a page.
+ *
+ * Returns:     void
+ *
+ * Description: This function positions the scores on this page as well as
+ *             possible, and then sets all the absolute vertical coordinates
+ *             for the scores and everything in them.
+ */
+
+static void
+abspage(page_p, cursep, maxsep, curpad, maxpad, totscores, remheight,
+               y_start)
+
+struct MAINLL *page_p; /* point at first FEED for this page */
+float cursep[];                /* this score's top line to above score's bottom line */
+float maxsep[];                /* the max we'd like to expand cursep to */
+float curpad[];                /* white pad between this score and above score */
+float maxpad[];                /* the max we'd like to expand curpad to */
+int totscores;         /* number of scores on this page */
+double remheight;      /* extra vertical space available, to be distributed */
+double y_start;                /* Y coord of top of first score (before padding) */
+
+{
+       struct MAINLL *mainll_p;/* point along main LL */
+       struct FEED *feed_p;    /* point at a score feed on this page */
+       struct CHORD *ch_p;     /* point at a chord on this page */
+       struct STAFF *staff_p;  /* point at a staff on this page */
+       float min;              /* smallest number in curpad or cursep */
+       float min2;             /* second smallest number in curpad or sep */
+       float share;            /* space to add to the min numbers each loop */
+       int mins;               /* how many numbers are tied for min */
+       int n;                  /* loop variable */
+       int *is_min;            /* pointer to array malloc'ed below */
+       int *hit_max;           /* pointer to array malloc'ed below */
+       int allmax;             /* have all scores used the max sep allowed? */
+
+
+       debug(32,"abspage file=%s line=%d totscores=%d remheight=%f y_start=%f",
+                       page_p->inputfile, page_p->inputlineno, totscores,
+                       (float)remheight, (float)y_start);
+       /*
+        * Array to hold which of the distances in curpad or cursep are
+        * minimal.
+        */
+       MALLOCA(int, is_min, MAXSCORES + 1);
+       /*
+        * Malloc an array to hold YES or NO as to whether this score's
+        * curpad or cursep has reached the maximum allowed.
+        */
+       MALLOCA(int, hit_max, MAXSCORES + 1);
+
+       /*
+        * The current values in curpad[] and cursep[] are for the case of
+        * the scores being packed as tightly as the stuff sticking out of them
+        * and the user's specification of minscpad and minscsep allow.
+        * maxpad[] and maxsep[] have the values of maxscpad and maxscsep
+        * above each.  Now we need to spread the score out, distributing
+        * remheight appropriately.
+        */
+       /*
+        * First, "smooth out" curpad[], so that the numbers in it will be as
+        * equal as possible, subject to maxpad[], but ignoring maxsep[].
+        */
+       while (remheight > FUDGE) {
+               /*
+                * For each score, remember in hit_max whether its curpad
+                * meets or exceeds the max pad allowed.  The fudge factor is
+                * so we'll pretend we made it, even if there is roundoff
+                * error.  If all scores' curpads have reached that, we're
+                * done, so break out.
+                */
+               allmax = YES;
+               for (n = 0; n <= totscores; n++) {
+                       if (curpad[n] >= maxpad[n] - FUDGE) {
+                               hit_max[n] = YES;
+                       } else {
+                               hit_max[n] = NO;
+                               allmax = NO;
+                       }
+               }
+               if (allmax == YES) {
+                       break;
+               }
+
+               /*
+                * Find the smallest curpad among scores that haven't hit
+                * their max.
+                */
+               min = 1000;
+               for (n = 0; n <= totscores; n++) {
+                       if (hit_max[n] == NO && curpad[n] < min)
+                               min = curpad[n];
+               }
+
+               mins = 0;       /* number of curpads tied for min */
+               min2 = 1000;    /* second smallest curpad value */
+
+               /*
+                * In this loop, mark which of the curpads are tied for the
+                * "min" value, and count how many are tied (mins).  Also, find
+                * the second smallest value (min2).  All this is done only for
+                * scores that haven't hit their max.
+                */
+               for (n = 0; n <= totscores; n++) {
+                       if (hit_max[n] == NO) {
+                               if (curpad[n] == min) {
+                                       is_min[n] = YES;
+                                       mins++;
+                               } else {
+                                       is_min[n] = NO;
+                                       if (curpad[n] < min2) {
+                                               min2 = curpad[n];
+                                       }
+                               }
+                       }
+               }
+
+               /*
+                * Don't let min2 exceed the maxpad of any eligible score.
+                * That way, when we spread the scores out to min2, we won't be
+                * spreading any of them beyond where they are allowed to go.
+                * In the next loop, ones that have reached their limit will
+                * get hit_max[] == YES, while other scores can continue to be
+                * spread more.
+                */
+               for (n = 0; n <= totscores; n++) {
+                       if (hit_max[n] == NO && min2 > maxpad[n]) {
+                               min2 = maxpad[n];
+                       }
+               }
+
+               /*
+                * We're going to add to all those minimum curpads, either
+                * using up all of remheight, or bringing them up equal to
+                * min2, whichever is lower.  We add the same amount to the
+                * curseps, since they change by the same amount as we move
+                * a score.
+                */
+               share = remheight / mins;
+               if (share > min2 - min) {
+                       share = min2 - min;
+               }
+               for (n = 0; n <= totscores; n++) {
+                       if (hit_max[n] == NO && is_min[n] == YES) {
+                               curpad[n] += share;
+                               cursep[n] += share;
+                       }
+               }
+
+               /* decrement remheight by the amount we just used */
+               remheight -= mins * share;
+       }
+
+       /*
+        * "Smooth out" cursep[], so that the numbers in it will be as
+        * equal as possible, subject to maxsep[], but ignoring maxpad[].
+        * If there is only one score, the first "for" loop won't execute, and
+        * we'll break out.
+        */
+       while (remheight > FUDGE) {
+               /*
+                * For each score, remember in hit_max whether its cursep
+                * meets or exceeds the max sep allowed.  The fudge factor is
+                * so we'll pretend we made it, even if there is roundoff
+                * error.  If all scores' curseps have reached that, we're
+                * done, so break out.
+                */
+               allmax = YES;
+               for (n = 1; n < totscores; n++) {
+                       if (cursep[n] >= maxsep[n] - FUDGE) {
+                               hit_max[n] = YES;
+                       } else {
+                               hit_max[n] = NO;
+                               allmax = NO;
+                       }
+               }
+               if (allmax == YES) {
+                       break;
+               }
+
+               /*
+                * Find the smallest cursep among scores that haven't hit
+                * their max.
+                */
+               min = 1000;
+               for (n = 1; n < totscores; n++) {
+                       if (hit_max[n] == NO && cursep[n] < min)
+                               min = cursep[n];
+               }
+
+               mins = 0;       /* number of curseps tied for min */
+               min2 = 1000;    /* second smallest cursep value */
+
+               /*
+                * In this loop, mark which of the curseps are tied for the
+                * "min" value, and count how many are tied (mins).  Also, find
+                * the second smallest value (min2).  All this is done only for
+                * scores that haven't hit their max.
+                */
+               for (n = 1; n < totscores; n++) {
+                       if (hit_max[n] == NO) {
+                               if (cursep[n] == min) {
+                                       is_min[n] = YES;
+                                       mins++;
+                               } else {
+                                       is_min[n] = NO;
+                                       if (cursep[n] < min2) {
+                                               min2 = cursep[n];
+                                       }
+                               }
+                       }
+               }
+
+               /*
+                * Don't let min2 exceed the maxsep of any eligible score.
+                * That way, when we spread the scores out to min2, we won't be
+                * spreading any of them beyond where they are allowed to go.
+                * In the next loop, ones that have reached their limit will
+                * get hit_max[] == YES, while other scores can continue to be
+                * spread more.
+                */
+               for (n = 1; n < totscores; n++) {
+                       if (hit_max[n] == NO && min2 > maxsep[n]) {
+                               min2 = maxsep[n];
+                       }
+               }
+
+               /*
+                * We're going to add to all those minimum curseps, either
+                * using up all of remheight, or bringing them up equal to
+                * min2, whichever is lower.
+                */
+               share = remheight / mins;
+               if (share > min2 - min) {
+                       share = min2 - min;
+               }
+               for (n = 1; n < totscores; n++) {
+                       if (hit_max[n] == NO && is_min[n] == YES) {
+                               cursep[n] += share;
+                       }
+               }
+
+               /* decrement remheight by the amount we just used */
+               remheight -= mins * share;
+       }
+
+       /* move to top of first score */
+       y_start -= curpad[0];
+
+       feed_p = 0;     /* flag that we haven't seen the first FEED yet */
+
+       /*
+        * Loop through the main linked list for this page, setting all
+        * absolute vertical coordinates.
+        */
+       for (mainll_p = page_p, n = 0; mainll_p != 0 && ! (n == totscores &&
+                       mainll_p->str == S_FEED); mainll_p = mainll_p->next) {
+
+               switch (mainll_p->str) {
+               case S_SSV:
+                       /* by end of page, SSVs will be up to date for there */
+                       asgnssv(mainll_p->u.ssv_p);
+                       break;
+
+               case S_FEED:
+                       /*
+                        * If this is the first FEED on the page, and what
+                        * follows is music (not a block), move to the top line
+                        * of the first score.
+                        */
+                       if (feed_p == 0 && IS_CLEFSIG_FEED(mainll_p)) {
+                               y_start = y_start - page_p->u.feed_p->c[RN] +
+                                staffvertspace(page_p->u.feed_p->firstvis)/2.0;
+                       }
+
+                       /*
+                        * Set the score's absolute coordinates.  The feed_p
+                        * pointer will be used by other cases in later loops.
+                        */
+                       feed_p = mainll_p->u.feed_p;
+
+                       /* if next is 0, this is a trailing feed, and it */
+                       /*  really has no meaningful coords */
+                       if (mainll_p->next == 0)
+                               continue;
+
+                       if (mainll_p->next->str == S_BLOCKHEAD) {
+                               /* move from top of block to middle of block */
+                               y_start -= feed_p->c[RN];
+                       } else {
+                               /* move from top line of score to middle of
+                                * first staff */
+                               y_start -= staffvertspace(feed_p->firstvis)/2.0;
+                       }
+
+                       feed_p->c[AN] = y_start + feed_p->c[RN];
+                       feed_p->c[AY] = y_start;
+                       feed_p->c[AS] = y_start + feed_p->c[RS];
+
+                       /* unless last score, set up y_start for next one */
+                       if (n < totscores - 1) {
+                               /* top line of next score */
+                               y_start = y_start + feed_p->c[RS] +
+                                       feed_p->lastdist - cursep[n + 1];
+                       }
+
+                       n++;
+                       break;
+
+               case S_CHHEAD:
+                       /*
+                        * Set each chord's absolute coordinates the same as
+                        * the feed.  These are pretty arbitrary, since they
+                        * are using only for drawing boxes with the MUP_BB
+                        * environment variable.
+                        */
+                       for (ch_p = mainll_p->u.chhead_p->ch_p; ch_p != 0;
+                                       ch_p = ch_p->ch_p) {
+                               ch_p->c[AN] = feed_p->c[AN];
+                               ch_p->c[AY] = feed_p->c[AY];
+                               ch_p->c[AS] = feed_p->c[AS];
+                       }
+                       break;
+
+               case S_BAR:
+                       /*
+                        * Set absolute N, Y, and S for the bar line.  Y can be
+                        * copied from the score's Y; they are both the center
+                        * line of the top visible staff.  But the score's N
+                        * S can stick out, based on the groups present,
+                        * whereas the bar line's N is the top line of the top
+                        * staff, and its S is the bottom line of the bottom
+                        * staff.
+                        */
+                       mainll_p->u.bar_p->c[AN] = feed_p->c[AY] +
+                               halfstaffhi(feed_p->firstvis);
+                       mainll_p->u.bar_p->c[AY] = feed_p->c[AY];
+                       mainll_p->u.bar_p->c[AS] = feed_p->c[AS] +
+                                       feed_p->lastdist;
+                       break;
+
+               case S_CLEFSIG:
+                       /*
+                        * If the clefsig doesn't contain a pseudo bar, just
+                        * break.  But otherwise, set this bar's coords just
+                        * like a normal bar.
+                        */
+                       if (mainll_p->u.clefsig_p->bar_p == 0)
+                               break;
+                       mainll_p->u.clefsig_p->bar_p->c[AN] = feed_p->c[AY] +
+                               halfstaffhi(feed_p->firstvis);
+                       mainll_p->u.clefsig_p->bar_p->c[AY] = feed_p->c[AY];
+                       mainll_p->u.clefsig_p->bar_p->c[AS] = feed_p->c[AS] +
+                               feed_p->lastdist - halfstaffhi(feed_p->lastvis);
+                       break;
+
+               case S_STAFF:
+                       /* if visible, set all abs vertical coords on staff */
+                       staff_p = mainll_p->u.staff_p;
+                       if (staff_p->visible == YES)
+                               absstaff(feed_p, staff_p);
+                       break;
+               }
+
+       }
+
+       FREE(is_min);
+       FREE(hit_max);
+}
+\f
+/*
+ * Name:        absstaff()
+ *
+ * Abstract:    Set all absolute vertical coordinates for a STAFF structure.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets all the absolute vertical coords for a
+ *             STAFF structure; those of the staff itself, and those of
+ *             everything hanging off it.
+ */
+
+static void
+absstaff(feed_p, staff_p)
+
+struct FEED *feed_p;           /* FEED for the score we're on */
+struct STAFF *staff_p;         /* the staff to be set */
+
+{
+       struct GRPSYL *gs_p;    /* point at a group of syllable */
+       struct STUFF *stuff_p;  /* point at a STUFF structure */
+       struct CRVLIST *pp_p;   /* point at a coord for phrase point */
+       int v;                  /* index to voices or verses */
+       int n;                  /* loop variable */
+
+
+       debug(32, "absstaff file=%s line=%d", staff_p->groups_p[0]->inputfile,
+                       staff_p->groups_p[0]->inputlineno);
+       /* set the staff's own coords */
+       staff_p->c[AN] = feed_p->c[AY] + staff_p->c[RN];
+       staff_p->c[AY] = feed_p->c[AY] + staff_p->c[RY];
+       staff_p->c[AS] = feed_p->c[AY] + staff_p->c[RS];
+
+       /* do the voice(s) */
+       for (v = 0; v < MAXVOICES; v++) {
+               for (gs_p = staff_p->groups_p[v]; gs_p != 0; gs_p = gs_p->next){
+                       gs_p->c[AY] = staff_p->c[AY] + gs_p->c[RY];
+                       gs_p->c[AN] = staff_p->c[AY] + gs_p->c[RN];
+                       gs_p->c[AS] = staff_p->c[AY] + gs_p->c[RS];
+
+                       /* if it's a group with notes, do the notes too */
+                       if (gs_p->grpcont == GC_NOTES) {
+                               for (n = 0; n < gs_p->nnotes; n++) {
+                                       gs_p->notelist[n].c[AY] = staff_p->c[AY]
+                                               + gs_p->notelist[n].c[RY];
+                                       gs_p->notelist[n].c[AN] = staff_p->c[AY]
+                                               + gs_p->notelist[n].c[RN];
+                                       gs_p->notelist[n].c[AS] = staff_p->c[AY]
+                                               + gs_p->notelist[n].c[RS];
+                               }
+                       }
+               }
+       }
+
+       /* do the verse(s) */
+       for (v = 0; v < staff_p->nsyllists; v++) {
+               for (gs_p = staff_p->syls_p[v]; gs_p != 0; gs_p = gs_p->next){
+                       gs_p->c[AY] = staff_p->c[AY] + gs_p->c[RY];
+                       gs_p->c[AN] = staff_p->c[AY] + gs_p->c[RN];
+                       gs_p->c[AS] = staff_p->c[AY] + gs_p->c[RS];
+               }
+       }
+
+       /* do the stuff */
+       for (stuff_p = staff_p->stuff_p; stuff_p != 0; stuff_p = stuff_p->next){
+               stuff_p->c[AY] = staff_p->c[AY] + stuff_p->c[RY];
+               stuff_p->c[AN] = staff_p->c[AY] + stuff_p->c[RN];
+               stuff_p->c[AS] = staff_p->c[AY] + stuff_p->c[RS];
+
+               /* if it's a phrase/tie/slur, do the phrase points too */
+               if (stuff_p->stuff_type == ST_PHRASE ||
+                   stuff_p->stuff_type == ST_TIESLUR ||
+                   stuff_p->stuff_type == ST_TABSLUR ||
+                   stuff_p->stuff_type == ST_BEND) {
+                       for (pp_p = stuff_p->crvlist_p; pp_p != 0;
+                                               pp_p = pp_p->next)
+                               pp_p->y += staff_p->c[AY];
+               }
+       }
+}
+\f
+/*
+ * Name:        grids_atend()
+ *
+ * Abstract:    Determine placement of chord grids to be printed at the end.
+ *
+ * Returns:     height of all the grids printed on this page
+ *
+ * Description: This function determines the placement of chord grids that are
+ *             to be printed at the end of the song, and sets up the data in
+ *             Atend_info accordingly.
+ */
+
+static double
+grids_atend(vertavail, firstpage, mfeed_p, gfeed_p)
+
+double vertavail;      /* space available for grids and spreading out scores*/
+int firstpage;         /* is this first page (there's only 1 page of music)?*/
+struct FEED *mfeed_p;  /* FEED at start of last music page */
+struct FEED *gfeed_p;  /* FEED applying to grid-only pages (may be same) */
+
+{
+       struct GRID *grid_p;            /* point at a grid */
+       int ngrids;                     /* no. of grids used */
+       float north, south, east, west; /* coords for one grid */
+       float farnorth, farsouth, fareast, farwest; /* farthest for any grid */
+       float hstrwid;                  /* half the width of chord string */
+       float havail;                   /* horizonal space available */
+       int inrow;                      /* no. of grids in one row */
+       int nrows;                      /* no. of rows of grids */
+       float totalheight;              /* of all the rows */
+       float white;                    /* scorepad in inches */
+       float upheight;                 /* height of header + top */
+       float downheight;               /* height of bottom + footer */
+
+
+       debug(32, "grids_atend vertavail=%f", (float)vertavail);
+
+       /* malloc array of pointers to the grids that were used */
+       MALLOCA(struct GRID *, Atend_info.grid_p, Atend_info.grids_used);
+
+       /*
+        * Set pointers to the grids that were used.  While doing this, find
+        * the farthest extent of any grid, for each of the 4 directions.  The
+        * size of the chord string must also be considered in this.
+        */
+       ngrids = 0;
+       farnorth = farsouth = fareast = farwest = 0.0;
+       for (grid_p = 0; (grid_p = nextgrid(grid_p)) != 0;  ) {
+               if (grid_p->used == NO)
+                       continue;
+               Atend_info.grid_p[ngrids++] = grid_p;
+               gridsize(grid_p, -1, &north, &south, &east, &west);
+               north += strheight(grid_p->name);
+               hstrwid = strwidth(grid_p->name) / 2.0;
+               if (north > farnorth)
+                       farnorth = north;
+               if (south < farsouth)
+                       farsouth = south;
+               if (hstrwid > east)
+                       east = hstrwid;
+               if (east > fareast)
+                       fareast = east;
+               if (-hstrwid < west)
+                       west = -hstrwid;
+               if (west < farwest)
+                       farwest = west;
+       }
+
+       /* sort the pointers by grid name */
+       qsort((char *)Atend_info.grid_p, ngrids, sizeof (struct GRID *),
+                       compgrids);
+
+       /* horizontal available width to use */
+       havail = PGWIDTH - eff_leftmargin((struct MAINLL *)0)
+                        - eff_rightmargin((struct MAINLL *)0);
+
+       /*
+        * Find max we could put in one row, allowing padding.  Note that we do
+        * not try to optimize the packing at all:  the biggest grid coord in
+        * any direction is what we use.  The "padding" to the right of the
+        * rightmost grid is not needed, so let it hang into the margin.
+        */
+       inrow = (havail + HPADGRID) / (fareast - farwest + HPADGRID);
+       if (inrow == 0) {
+               ufatal("chord grid is too wide to fit on a page");
+       }
+
+       /* this determines how many rows there will be; it will not change */
+       nrows = (ngrids + inrow - 1) / inrow;
+
+       /*
+        * It could be that the last row would be far from full.  So attempt to
+        * spread the grids more equally between rows.
+        */
+       while (nrows > 1 && inrow > 1) {
+               inrow--;                /* try one less grid per row */
+               if ((ngrids + inrow - 1) / inrow > nrows) {
+                       /* whoops, no. of rows increased, so undo last decr. */
+                       inrow++;
+                       break;
+               }
+       }
+
+       Atend_info.grids_per_row = inrow;
+
+       /* spread them out appropriately */
+       Atend_info.horz_sep = havail / (nrows == 1 ? ngrids : inrow);
+
+       /*
+        * Normally, the first grid's X is as far from the left margin as the
+        * last (on that line) grid's X is from the right margin.  But if any
+        * grids have "N fr", fareast may be bigger than -farwest.  So move
+        * everything to the left by half the difference.
+        */
+       Atend_info.firstgrid_x = eff_leftmargin((struct MAINLL *)0) +
+                       Atend_info.horz_sep / 2.0 - (fareast + farwest) / 2.0;
+
+       /*
+        * Base the vertical separation on the maximum case plus padding.  Of
+        * course, no padding is needed below the bottom row, so subtract it.
+        */
+       Atend_info.vert_sep = farnorth - farsouth + VPADGRID;
+       totalheight = nrows * Atend_info.vert_sep - VPADGRID;
+
+       white = Score.minscpad * STEPSIZE;
+
+       if (totalheight <= vertavail && gfeed_p->pagefeed == NO) {
+               /*
+                * It fits on the last page of music.  Set the absolute coord
+                * so that it rests above the footer and/or bottom block (if
+                * any) and bottom margin.
+                */
+               Atend_info.firstgrid_y = EFF_BOTMARGIN + totalheight - farnorth;
+
+               downheight = (firstpage == YES ? &Footer : &Footer2)->height +
+                       (mfeed_p->bot_p != 0 ? mfeed_p->bot_p->height : 0.0);
+               if (downheight > 0) {
+                       Atend_info.firstgrid_y += downheight + white;
+               }
+
+               Atend_info.rows_per_page = nrows;
+
+               return (totalheight);
+       }
+
+       /*
+        * All grids must go on later page(s).  Find how much height must be
+        * reserved for header/top and bottom/footer on those pages.  Since
+        * this cannot be the first page, we always use Header2 and Footer2.
+        */
+       upheight = Header2.height +
+                       (gfeed_p->top_p != 0 ? gfeed_p->top_p->height : 0.0);
+       downheight = Footer2.height +
+                       (gfeed_p->bot_p != 0 ? gfeed_p->bot_p->height : 0.0);
+
+       /* make the grid page FEED a pagefeed, in case it isn't already */
+       gfeed_p->pagefeed = YES;
+
+       /*
+        * It will have to go on other page(s).  Set the absolute coord to put
+        * it at the top.
+        */
+       Atend_info.separate_page = YES;
+       Atend_info.firstgrid_y = PGHEIGHT - EFF_TOPMARGIN -
+                       upheight - farnorth;
+       if (upheight > 0) {
+               Atend_info.firstgrid_y -= white;
+       }
+
+       /* reset vertavail to the amount of space on a whole page */
+       vertavail = PGHEIGHT - EFF_TOPMARGIN - EFF_BOTMARGIN;
+       if (upheight > 0)
+               vertavail -= upheight + white;
+       if (downheight > 0)
+               vertavail -= downheight + white;
+
+       /* find number of rows per page; must be at least 1 */
+       Atend_info.rows_per_page = (vertavail + VPADGRID) / Atend_info.vert_sep;
+       if (Atend_info.rows_per_page == 0)
+               ufatal("chords grids are too high to fit on a page");
+
+       /*
+        * If there is at least 1 full page, spread the rows out evenly.  The
+        * same spacing will be used on later pages, even though the last page
+        * may not be full.  That's okay.
+        */
+       if (nrows >= Atend_info.rows_per_page) {
+               Atend_info.vert_sep = (vertavail + VPADGRID) /
+                               Atend_info.rows_per_page;
+       }
+
+       return (0.0);   /* nothing goes on the last page of music */
+}
+\f
+/*
+ * Name:        compgrids()
+ *
+ * Abstract:    Compare grid names; used by qsort.
+ *
+ * Returns:     negative or positive
+ *
+ * Description: This function returns its result based on whether the grid
+ *             pointed to by g1_p should precede or follow g2_p.  It uses
+ *             their names in alphabetical order, basically, but it also
+ *             understands accidentals.  They will never be equal because the
+ *             grids are all unique.
+ */
+
+static int
+compgrids(g1_p_p, g2_p_p)
+
+#ifdef __STDC__
+const void *g1_p_p;    /* the two grid pointers to compare */
+const void *g2_p_p;
+#else
+char *g1_p_p;          /* the two grid pointers to compare */
+char *g2_p_p;
+#endif
+
+{
+       char *name[2];          /* pointers into first and second names */
+       char *asc_ptr;          /* point at the first name in ASCII */
+       char chbuff[MAXCHNAME]; /* hold the ASCII name of the first chord */
+       int accnum[2];          /* accidental number, -2 to 2  (&& to x) */
+       int ridx[2];            /* index to rest of string */
+       int k;                  /* loop variable */
+
+
+       /*
+        * Translate the chords names to the way the user entered them (as
+        * closely as possible).  Since ascii_str() overwrites the same static
+        * area each time, we have to copy the first name to our own buffer.
+        * Rather than wasting time using malloc(), just put it in a fixed
+        * buffer.  If someone has an absurd name longer than MAXCHNAME, just
+        * cut it off.
+        */
+       asc_ptr = ascii_str((*(struct GRID **)g1_p_p)->name, YES, NO, TM_CHORD);
+       if ((int)strlen(asc_ptr) < MAXCHNAME) {
+               (void)strcpy(chbuff, asc_ptr);
+       } else {
+               (void)strncpy(chbuff, asc_ptr, MAXCHNAME - 1);
+               chbuff[MAXCHNAME - 1] = '\0';
+       }
+       name[0] = chbuff;
+       name[1] = ascii_str((*(struct GRID **)g2_p_p)->name, YES, NO, TM_CHORD);
+
+       /*
+        * If chord letters differ, return based on that.  For bizarre cases
+        * like letters not A through G, or null string, que sera sera.
+        */
+       if (name[0][0] != name[1][0])
+               return (name[0][0] - name[1][0]);
+
+       /*
+        * The first chars (presumably chord letters) were the same.  They
+        * can't be \0 because then the whole strings would be equal (null
+        * string) but we know chord names are unique.  For each name, set a
+        * number for its accidental, and index to what follows, if anything.
+        */
+       for (k = 0; k < 2; k++) {
+               switch (name[k][1]) {
+               case '&':
+                       if (name[k][2] == '&') {
+                               accnum[k] = -2; /* double flat */
+                               ridx[k] = 3;
+                       } else {
+                               accnum[k] = -1; /* flat */
+                               ridx[k] = 2;
+                       }
+                       break;
+               case '#':
+                       accnum[k] = 1;          /* sharp */
+                       ridx[k] = 2;
+                       break;
+               case 'x':
+                       accnum[k] = 2;          /* double sharp */
+                       ridx[k] = 2;
+                       break;
+               default:
+                       accnum[k] = 0;          /* no acc is like a natural */
+                       ridx[k] = 1;
+                       break;
+               }
+       }
+
+       /* if accidentals differ, that rules */
+       if (accnum[0] != accnum[1])
+               return (accnum[0] - accnum[1]);
+
+       /* else the rest of it decides */
+       return (strcmp(&name[0][ridx[0]], &name[1][ridx[1]]));
+}
+\f
+/*
+ * Name:        proc_css()
+ *
+ * Abstract:    Process groups involved with cross staff stemming.
+ *
+ * Returns:     void
+ *
+ * Description: This function does all the remaining work necessary for groups
+ *             involved in cross staff stemming.
+ */
+
+static void
+proc_css()
+
+{
+       struct MAINLL *mainll_p;        /* point along main LL */
+       struct MAINLL *prevvis_p;       /* previous visible staff */
+       struct MAINLL *nextvis_p;       /* next visible staff */
+       struct TIMEDSSV *tssv_p;        /* point along a timed SSV list */
+       struct STAFF *thisstaff_p;      /* point at a staff */
+       struct GRPSYL *thisg_p;         /* point at a group */
+       struct STUFF *stuff_p;          /* point at a stuff structure */
+       struct CRVLIST *pp_p;           /* point at a coord for phrase point */
+       RATIONAL vtime;                 /* start time of groups */
+       int vidx;                       /* voice index */
+
+
+       debug(16, "proc_css");
+       initstructs();                  /* clean out old SSV info */
+
+       /*
+        * Loop through the whole MLL, looking for visible staffs, and keeping
+        * SSVs up to date (including midmeasure SSVs, since CSS notes are
+        * affected by clef changes).
+        */
+       prevvis_p = 0;
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               switch (mainll_p->str) {
+               case S_STAFF:
+                       thisstaff_p = mainll_p->u.staff_p;
+                       /* if staff is invisible, skip it */
+                       if (thisstaff_p->visible == NO) {
+                               continue;
+                       }
+                       break;          /* go handle this visible staff */
+               case S_SSV:
+                       /* assign normal SSV */
+                       asgnssv(mainll_p->u.ssv_p);
+                       continue;
+               case S_BAR:
+                       /* assign preceding measure's timed SSVs */
+                       for (tssv_p = mainll_p->u.bar_p->timedssv_p;
+                                       tssv_p != 0;
+                                       tssv_p = tssv_p->next) {
+                               asgnssv(&tssv_p->ssv);
+                       }
+                       /* FALL THROUGH */
+               default:
+                       /* set prev to null in preparation for next measure */
+                       prevvis_p = 0;
+                       continue;
+               }
+
+               /* look for next visible staff, skipping invisible */
+               for (nextvis_p = mainll_p->next; nextvis_p != 0 &&
+                               nextvis_p->str == S_STAFF &&
+                               nextvis_p->u.staff_p->visible == NO;
+                               nextvis_p = nextvis_p->next) {
+                       ;
+               }
+               /* if no more visible staffs in score, set next to null */
+               if (nextvis_p != 0 && nextvis_p->str != S_STAFF) {
+                       nextvis_p = 0;
+               }
+
+               /*
+                * thisstaff_p is a visible staff, and prevvis_p and nextvis_p
+                * are the MLL structs for the previous and next visible staffs,
+                * if they exist.  Loop through the voices on the this staff.
+                */
+               for (vidx = 0; vidx < MAXVOICES; vidx++) {
+                       /*
+                        * Loop through the groups of this voice, keeping track
+                        * of the elapsed time, looking for groups that have
+                        * CSS, and calling one_css() for them.
+                        */
+                       vtime = Zero;
+                       for (thisg_p = thisstaff_p->groups_p[vidx]; thisg_p !=0;
+                                       vtime = radd(vtime, thisg_p->fulltime),
+                                       thisg_p = thisg_p->next) {
+
+                               switch (thisg_p->stemto) {
+                               case CS_SAME:
+                                       continue;
+                               case CS_ABOVE:
+                                       if (prevvis_p == 0) {
+                                               l_ufatal(mainll_p->inputfile,
+                                               mainll_p->inputlineno,
+                                               "cannot cross staff stem 'with above' from top visible staff");
+                                       }
+                                       one_css(thisstaff_p,
+                                               prevvis_p->u.staff_p,
+                                               thisg_p, vtime);
+                                       break;
+                               case CS_BELOW:
+                                       if (nextvis_p == 0) {
+                                               l_ufatal(mainll_p->inputfile,
+                                               mainll_p->inputlineno,
+                                               "cannot cross staff stem 'with below' from bottom visible staff");
+                                       }
+                                       one_css(thisstaff_p,
+                                               nextvis_p->u.staff_p,
+                                               thisg_p, vtime);
+                                       break;
+                               }
+                       }
+               }
+
+               prevvis_p = mainll_p;
+       }
+
+       /*
+        * Now we have to call beamstem() again, to do the work that it
+        * couldn't do before on groups affected by CSS.
+        */
+       CSSpass = YES;
+       beamstem();
+
+       /*
+        * Do "horizontal avoidance": moving CSS groups sideways if necessary
+        * because they would collide with groups on the other staff.
+        */
+       horzavoid();
+
+       /*
+        * Back in relvert.c, we skipped placing tie/slur/bend/phrases whose
+        * endpoint groups were affected by CSS.  Now that we know where the
+        * final group boundaries are, we set up the coords for these items.
+        * tieslur_points and phrase_points destroy groups' AN and AS, and
+        * depends on them starting out as zero.  So zero them now and restore
+        * them later.  Because these items can cross bar lines, we need
+        * to zap all of these coords in this first loop, and have a separate
+        * loop to do the main work (and restore the groups' coords).
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+               if (mainll_p->str != S_STAFF) {
+                       continue;
+               }
+               thisstaff_p = mainll_p->u.staff_p;
+
+               for (vidx = 0; vidx < MAXVOICES; vidx++) {
+                       for (thisg_p = thisstaff_p->groups_p[vidx];
+                                       thisg_p != 0; thisg_p = thisg_p->next) {
+                               thisg_p->c[AN] = 0.0;
+                               thisg_p->c[AS] = 0.0;
+                       }
+               }
+       }
+
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+               if (mainll_p->str != S_STAFF) {
+                       continue;
+               }
+               thisstaff_p = mainll_p->u.staff_p;
+
+               /*
+                * Find and handle every tie/slur/bend/phrase starting in this
+                * staff.
+                */
+               for (stuff_p = thisstaff_p->stuff_p;
+                               stuff_p != 0; stuff_p = stuff_p->next) {
+                       switch (stuff_p->stuff_type) {
+                       case ST_PHRASE:
+                               if (css_affects_phrase(stuff_p,
+                                                       mainll_p) == YES) {
+                                       phrase_points(mainll_p, stuff_p);
+
+                                       stuff_p->c[AY] = thisstaff_p->c[AY]
+                                                      + stuff_p->c[RY];
+                                       stuff_p->c[AN] = thisstaff_p->c[AY]
+                                                      + stuff_p->c[RN];
+                                       stuff_p->c[AS] = thisstaff_p->c[AY]
+                                                      + stuff_p->c[RS];
+
+                                       /* do the phrase points too */
+                                       for (pp_p = stuff_p->crvlist_p;
+                                            pp_p != 0; pp_p = pp_p->next) {
+
+                                               pp_p->y += thisstaff_p->c[AY];
+                                       }
+                               }
+                               break;
+                       case ST_TIESLUR:
+                       case ST_BEND:
+                               if (css_affects_tieslurbend(stuff_p,
+                                                       mainll_p) == YES) {
+                                       if (stuff_p->stuff_type == ST_TIESLUR) {
+                                               tieslur_points(mainll_p, stuff_p);
+                                       } else {
+                                               bend_points(mainll_p, stuff_p);
+                                       }
+
+                                       stuff_p->c[AY] = thisstaff_p->c[AY]
+                                                      + stuff_p->c[RY];
+                                       stuff_p->c[AN] = thisstaff_p->c[AY]
+                                                      + stuff_p->c[RN];
+                                       stuff_p->c[AS] = thisstaff_p->c[AY]
+                                                      + stuff_p->c[RS];
+
+                                       /* do the tie/slur/bend points too */
+                                       for (pp_p = stuff_p->crvlist_p;
+                                            pp_p != 0; pp_p = pp_p->next) {
+
+                                               pp_p->y += thisstaff_p->c[AY];
+                                       }
+                               }
+                               break;
+                       }
+               }
+
+               /*
+                * phrase_points destroys groups' AN and AS.  And some code in
+                * the second pass of beamstem.c doesn't set the absolute
+                * coords of groups.  So go through now and set the absolute
+                * coords of all groups.
+                */
+               for (vidx = 0; vidx < MAXVOICES; vidx++) {
+                       for (thisg_p = thisstaff_p->groups_p[vidx];
+                                       thisg_p != 0; thisg_p = thisg_p->next) {
+                               thisg_p->c[AN] = thisstaff_p->c[AY]
+                                               + thisg_p->c[RN];
+                               thisg_p->c[AY] = thisstaff_p->c[AY]
+                                               + thisg_p->c[RY];
+                               thisg_p->c[AS] = thisstaff_p->c[AY]
+                                               + thisg_p->c[RS];
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        one_css()
+ *
+ * Abstract:    Process one group involved with cross staff stemming.
+ *
+ * Returns:     void
+ *
+ * Description: This function processes one CSS group.  It moves the CSS notes
+ *             in the group to fall into the correct place on the other staff.
+ *             When necessary, it also adjusts the group boundary.
+ */
+
+static void
+one_css(ts_p, os_p, tg_p, time)
+
+struct STAFF *ts_p;            /* This Staff, the normal one for the grpsyl */
+struct STAFF *os_p;            /* Other Staff that the grpsyl has notes on */
+struct GRPSYL *tg_p;           /* This Grpsyl */
+RATIONAL time;                 /* time offset of this grpsyl */
+
+{
+       struct GRPSYL *og_p;    /* Other Grpsyl (some grpsyl on other staff) */
+       int foundclef;          /* found a clef change on other staff? */
+       RATIONAL cleftime;      /* time at which the last clef change happens*/
+       RATIONAL tt;            /* temporary time variable */
+       float offset;           /* distance from old note position to new */
+       int upfromc4;           /* steps up from middle C */
+       int clef;               /* clef in force on other staff */
+       int vidx;               /* voice index */
+       int n;                  /* loop variable */
+
+
+       /*
+        * Set globals like Staffscale according our staff.  The parse phase
+        * ensures that the two staffs have the same staffscale.
+        */
+       set_staffscale(ts_p->staffno);
+
+       /*
+        * We need to find out what clef is in force on the other staff.  We
+        * start with the current value; but it may change midmeasure.  We
+        * can't just use the timed SSVs, because there are weird cases
+        * where the clef got put farther to the right (because the clef was
+        * changed before rests or spaces).  So we have to search all the
+        * voices for clefs.  We look for the rightmost clef that does not
+        * exceed the given time value.
+        */
+       /* find clef in force on other staff at start of this measure */
+       clef = svpath(os_p->staffno, CLEF)->clef;
+       foundclef = NO;
+       cleftime = Zero;
+       for (vidx = 0; vidx < MAXVOICES; vidx++) {
+               tt = Zero;
+               for (og_p = os_p->groups_p[vidx]; og_p != 0 && LE(tt, time);
+                               og_p = og_p->next) {
+                       /* if group has a clef, and either it's the first group
+                        * found to have one or it's later than the latest such
+                        * group found so far . . . */
+                       if (og_p->clef != NOCLEF &&
+                                       (foundclef == NO || GT(tt, cleftime))) {
+                               foundclef = YES;
+                               clef = og_p->clef;      /* remember this clef*/
+                               cleftime = tt;          /* and when it was */
+                       }
+                       tt = radd(tt, og_p->fulltime);
+               }
+       }
+
+       /*
+        * Everything that has to move will move by the same offset.  Calculate
+        * it, using the first CSS note.  First find its stepsup on the new
+        * staff, like setnotes.c does for the normal staff.  Subtract new
+        * minus old vertical positions.
+        */
+       n = FCNI(tg_p);
+       upfromc4 = (tg_p->notelist[n].octave - 4) * 7 +
+               Letshift[ tg_p->notelist[n].letter - 'a' ];
+       tg_p->notelist[n].stepsup = upfromc4 + clef - ALTO;
+       offset = (os_p->c[AY] + tg_p->notelist[n].stepsup * Stepsize) -
+               tg_p->notelist[n].c[AY];
+
+       /* move all the CSS notes and their dots */
+       for ( ; n <= LCNI(tg_p); n++) {
+               upfromc4 = (tg_p->notelist[n].octave - 4) * 7 +
+                       Letshift[ tg_p->notelist[n].letter - 'a' ];
+               tg_p->notelist[n].stepsup = upfromc4 + clef - ALTO;
+               tg_p->notelist[n].c[RN] += offset;
+               tg_p->notelist[n].c[RY] += offset;
+               tg_p->notelist[n].c[RS] += offset;
+               tg_p->notelist[n].c[AN] += offset;
+               tg_p->notelist[n].c[AY] += offset;
+               tg_p->notelist[n].c[AS] += offset;
+               if (tg_p->dots > 0) {
+                       tg_p->notelist[n].ydotr += offset;
+               }
+       }
+
+       /*
+        * If the CSS note(s) were not on the stemside, stemlen and group
+        * boundaries were set already in beamstem.c, but we need to fix them
+        * here to account for moving the CSS notes.
+        */
+       if (STEMSIDE_CSS(tg_p) == NO) {
+               if (tg_p->stemlen != 0.0) {
+                       tg_p->stemlen += fabs(offset);
+               }
+               if (tg_p->stemdir == UP) {
+                       tg_p->c[RS] = tg_p->notelist[tg_p->nnotes - 1].c[RS]
+                                       - Stdpad;
+                       tg_p->c[AS] = tg_p->notelist[tg_p->nnotes - 1].c[AS]
+                                       - Stdpad;
+               } else {
+                       tg_p->c[RN] = tg_p->notelist[0].c[RN] + Stdpad;
+                       tg_p->c[AN] = tg_p->notelist[0].c[AN] + Stdpad;
+               }
+       }
+}
+\f
+/*
+ * Name:        horzavoid()
+ *
+ * Abstract:    Move CSS groups horizontally to avoid collisions on other staff.
+ *
+ * Returns:     void
+ *
+ * Description: This function goes through the MLL, and for each CSS group,
+ *             calls a function to do horizontal avoidance.
+ */
+
+static void
+horzavoid()
+
+{
+       struct MAINLL *mainll_p;        /* point along main LL */
+       struct GRPSYL *gs_p;            /* point at a group */
+       int vidx;                       /* voice index */
+       RATIONAL time;                  /* start time of a group */
+
+
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+               if (mainll_p->str != S_STAFF) {
+                       continue;
+               }
+
+               for (vidx = 0; vidx < MAXVOICES; vidx++) {
+                       time = Zero;
+                       for (gs_p = mainll_p->u.staff_p->groups_p[vidx];
+                                       gs_p != 0; gs_p = gs_p->next) {
+                               if (gs_p->stemto != CS_SAME) {
+                                       avoidone(mainll_p, gs_p, time);
+                               }
+                               time = radd(time, gs_p->fulltime);
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        avoidone()
+ *
+ * Abstract:    Move CSS group horizontally to avoid collisions on other staff.
+ *
+ * Returns:     void
+ *
+ * Description: This function finds whether the given group collides with any
+ *             groups on the other staff.  If so, it moves that group, along
+ *             with all other groups on its staff and their preceding grace
+ *             groups, to the right enough so that the group no longer
+ *             collides.  But it won't move it so far that it would collide
+ *             with a later group on its own staff.
+ */
+
+static void
+avoidone(mainll_p, cssg_p, time)
+
+struct MAINLL *mainll_p;       /* the MLL for our group's staff */
+struct GRPSYL *cssg_p;         /* the CSS group we are working on */
+RATIONAL time;                 /* time offset of this group */
+
+{
+       struct MAINLL *mll_p;   /* point along main LL */
+       int otherstaffno;       /* staff where the CSS notes are */
+       struct GRPSYL *gs_p;    /* point along grpsyl lists */
+       struct GRPSYL *gs2_p;   /* another pointer along grpsyl lists */
+       struct CHORD *ch_p;     /* point at chord we're in */
+       float movedist;         /* distance to move groups */
+       float otherhorz;        /* east boundary of groups on other staff */
+       float slope;            /* slope of a beam */
+       float deltax;           /* change in X coord of stem tip */
+       int gotone;             /* flag variable */
+       int n;                  /* loop variable */
+
+
+       /* never move the group if the user is forcing it with "ho" */
+       if (cssg_p->ho_usage != HO_NONE) {
+               return;
+       }
+
+       /*
+        * Find the other staff's number.
+        */
+       if (cssg_p->stemto == CS_ABOVE) {
+               for (mll_p = mainll_p->prev; mll_p != 0 && mll_p->str == S_STAFF
+               && mll_p->u.staff_p->visible == NO; mll_p = mll_p->prev) {
+                       ;
+               }
+       } else {
+               for (mll_p = mainll_p->next; mll_p != 0 && mll_p->str == S_STAFF
+               && mll_p->u.staff_p->visible == NO; mll_p = mll_p->next) {
+                       ;
+               }
+       }
+       if (mll_p == 0 || mll_p->str != S_STAFF) {
+               pfatal("missing staff in avoidone");
+       }
+       otherstaffno = mll_p->u.staff_p->staffno;
+
+       /*
+        * Find what groups, if any, the other staff has at this time value.
+        * First we find the GPRSYL at which the search begins.
+        */
+       if (cssg_p->stemto == CS_ABOVE) {
+               /*
+                * We will start the search at this first grpsyl in the chord.
+                */
+               ch_p = gs2ch(mainll_p, cssg_p);
+               gs_p = ch_p->gs_p;
+       } else {
+               /*
+                * We will start the search at our group, or if it is grace,
+                * the main group that follows.
+                */
+               for (gs_p = cssg_p; gs_p->grpvalue == GV_ZERO;
+                               gs_p = gs_p->next) {
+                       ;
+               }
+               ch_p = 0;       /* remember we don't know the chord */
+       }
+
+       /* find the first GRPSYL, if any, on the other staff at this time */
+       for ( ; gs_p != 0 && gs_p->staffno < otherstaffno; gs_p = gs_p->gs_p) {
+               ;
+       }
+
+       /* if no groups on the other staff, there is no need to move anything */
+       if (gs_p == 0 || gs_p->grpsyl == GS_SYLLABLE ||
+                       gs_p->staffno > otherstaffno) {
+               return;
+       }
+
+       /*
+        * Find the easternmost extent of any group on the other staff that
+        * extends far enough vertically to run into our group.  We don't care
+        * about grace groups, because they are on the west side, and we are
+        * going to move our group to the east side.
+        */
+       gotone = NO;
+       otherhorz = 0.0;        /* avoid "used before set" warning */
+       for ( ; gs_p != 0 && gs_p->grpsyl == GS_GROUP &&
+                       gs_p->staffno == otherstaffno; gs_p = gs_p->gs_p) {
+               /* spaces never interfere; mr and mrpt rarely do, and their
+                * coords make them seem really wide, so ignore them too */
+               if (gs_p->grpcont == GC_SPACE || gs_p->is_meas == YES) {
+                       continue;
+               }
+               if (cssg_p->stemto == CS_ABOVE && cssg_p->c[AN] <= gs_p->c[AS]){
+                       continue;
+               }
+               if (cssg_p->stemto == CS_BELOW && cssg_p->c[AS] >= gs_p->c[AN]){
+                       continue;
+               }
+               if (gotone == NO || gs_p->c[AE] > otherhorz) {
+                       otherhorz = gs_p->c[AE];
+                       gotone = YES;
+               }
+       }
+
+       /*
+        * If our group doesn't reach the other staff's groups vertically,
+        * there is no need to move anything.
+        */
+       if (gotone == NO) {
+               return;
+       }
+
+       /*
+        * Find how far we'd need to move our group to the right to be beyond
+        * any of the other staff's groups.  If somehow that is not positive,
+        * there is no need to move.
+        */
+       movedist = otherhorz - cssg_p->c[AW];
+       if (movedist <= 0.0) {
+               return;
+       }
+
+       /* find the first nongrace group at this time on our staff */
+       if (cssg_p->vno == 1) {
+               for (gs_p = cssg_p; gs_p->grpvalue == GV_ZERO;
+                               gs_p = gs_p->next) {
+                       ;
+               }
+       } else {
+               if (ch_p == 0) {
+                       ch_p = gs2ch(mainll_p, cssg_p);
+               }
+               /* find the first GRPSYL, if any, on our staff at this time */
+               for (gs_p = ch_p->gs_p; gs_p != 0 && gs_p->staffno <
+                               cssg_p->staffno; gs_p = gs_p->gs_p) {
+                       ;
+               }
+       }
+
+       /*
+        * For each group on this staff in this chord, and for all their
+        * preceding grace groups, move them to the east.  Adjust stem lengths
+        * of beamed groups.
+        */
+       for ( ; gs_p != 0 && gs_p->grpsyl == GS_GROUP &&
+                       gs_p->staffno == cssg_p->staffno; gs_p = gs_p->gs_p) {
+
+               /* never move the group if the user is forcing it with "ho" */
+               if (gs_p->ho_usage != HO_NONE) {
+                       continue;
+               }
+
+               /*
+                * If the group is beamed and the beam is not horizontal, the
+                * stem length needs to be changed so it will meet the beam.
+                */
+               if (gs_p->beamloc != NOITEM && gs_p->grpcont == GC_NOTES) {
+                       /*
+                        * Find a neighboring group in the beamed set so we can
+                        * find the beam's slope.  The prev group is already
+                        * corrected; our group and the next group haven't been
+                        * moved yet; so the stems of all 3 are currently
+                        * touching the beam and are valid for finding slope.
+                        */
+                       if (gs_p->beamloc == STARTITEM) {
+                               gs2_p = nextsimilar(gs_p);
+                       } else {
+                               gs2_p = prevsimilar(gs_p);
+                       }
+                       slope = (find_y_stem(gs2_p) - find_y_stem(gs_p)) /
+                               (find_x_stem(gs2_p) - find_x_stem(gs_p));
+
+                       deltax = slope * movedist;
+
+                       if (gs_p->stemdir == UP) {
+                               gs_p->stemlen += deltax;
+                               gs_p->c[RN] += deltax;
+                               gs_p->c[AN] += deltax;
+                       } else {
+                               gs_p->stemlen -= deltax;
+                               gs_p->c[RS] += deltax;
+                               gs_p->c[AS] += deltax;
+                       }
+               }
+
+               /*
+                * Always do our group (a nongrace group), then loop
+                * additionally for all preceding graces.
+                */
+               gs2_p = gs_p;
+               do {
+                       gs2_p->c[AW] += movedist;
+                       gs2_p->c[AX] += movedist;
+                       gs2_p->c[AE] += movedist;
+
+                       /* if it's a group with notes, do the notes too */
+                       if (gs2_p->grpcont == GC_NOTES) {
+                               for (n = 0; n < gs2_p->nnotes; n++) {
+                                       gs2_p->notelist[n].c[AW] += movedist;
+                                       gs2_p->notelist[n].c[AX] += movedist;
+                                       gs2_p->notelist[n].c[AE] += movedist;
+                               }
+                       }
+
+                       gs2_p = gs2_p->prev;
+               } while (gs2_p != 0 && gs2_p->grpvalue == GV_ZERO);
+       }
+}
+\f
+/*
+ * Name:        set_csb_stems()
+ *
+ * Abstract:    Set stem lengths for groups involved in cross staff beaming.
+ *
+ * Returns:     void
+ *
+ * Description: This function searches the MLL for cross staff beaming places.
+ *             For each one, it calls onecsb() to set the stem lengths.
+ */
+
+static void
+set_csb_stems()
+
+{
+       struct MAINLL *mainll_p;        /* point along main LL */
+       struct MAINLL *mll_p;           /* point along main LL again */
+       struct STAFF *staff1_p, *staff2_p; /* point at top and bottom staffs */
+       struct GRPSYL *gs1_p, *gs2_p;   /* point at top and bottom groups */
+       int v, bv;                      /* loop thru voices, top and bottom */
+       RATIONAL vtime1, vtime2;        /* start time of groups */
+
+
+       debug(16, "set_csb_stems");
+       initstructs();                  /* clean out old SSV info */
+
+       /*
+        * Loop through the whole MLL, looking for visible staffs that are
+        * not the last visible staff in their score.  Then find cross staff
+        * beamings and call a function to set stem lengths.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+               /* apply SSVs to keep staffscale up to date */
+               if (mainll_p->str == S_SSV) {
+                       asgnssv(mainll_p->u.ssv_p);
+                       continue;
+               }
+
+               if (mainll_p->str != S_STAFF)
+                       continue;
+
+               /* if staff is invisible, skip it */
+               staff1_p = mainll_p->u.staff_p;
+               if (staff1_p->visible == NO)
+                       continue;
+
+               /* look for next visible staff, skipping invisible */
+               for (mll_p = mainll_p->next; mll_p != 0 && mll_p->str ==
+                               S_STAFF && mll_p->u.staff_p->visible == NO;
+                               mll_p = mll_p->next)
+                       ;
+               /* if no more visible staffs in score, skip */
+               if (mll_p == 0 || mll_p->str != S_STAFF)
+                       continue;
+
+               staff2_p = mll_p->u.staff_p;
+
+               /*
+                * staff1_p and staff2_p are two neighboring visible staffs
+                * (possibly with invisible ones in between).  Loop through the
+                * voices on the top staff.  For ones that don't exist, their
+                * pointers will be 0 and the inside loop will do nothing.
+                */
+               for (v = 0; v < MAXVOICES; v++) {
+                       /*
+                        * Loop through the groups of this voice, keeping track
+                        * of the elapsed time, looking for the first group of
+                        * each CSB set that is joined with the staff below.
+                        * It could be any of the voices on the staff below.
+                        * The parser deals with any checks concerning voices
+                        * being in the way of each other.
+                        */
+                       vtime1 = Zero;
+                       for (gs1_p = staff1_p->groups_p[v]; gs1_p != 0;
+                                       vtime1 = radd(vtime1, gs1_p->fulltime),
+                                       gs1_p = gs1_p->next) {
+
+                               if (gs1_p->beamto != CS_BELOW ||
+                                   gs1_p->beamloc != STARTITEM)
+                                       continue;
+
+                               for (bv = 0; bv < MAXVOICES; bv++) {
+                                       vtime2 = Zero;
+                                       for (gs2_p = staff2_p->groups_p[bv];
+                                                       gs2_p != 0 &&
+                                                       (LT(vtime2, vtime1) ||
+                                                       gs2_p->grpvalue ==
+                                                               GV_ZERO);
+                                                       gs2_p = gs2_p->next) {
+                                               vtime2 = radd(vtime2,
+                                                       gs2_p->fulltime);
+                                       }
+                                       if (gs2_p != 0 && EQ(vtime2, vtime1) &&
+                                           gs2_p->beamto == CS_ABOVE &&
+                                           gs2_p->beamloc == STARTITEM) {
+
+                                               onecsb(gs1_p, gs2_p);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        onecsb()
+ *
+ * Abstract:    Set stem lengths for one instance of cross staff beaming.
+ *
+ * Returns:     void
+ *
+ * Description: This function finds the stem directions on the two staffs of
+ *             a CSB and the first and last groups of it that are note groups.
+ *             If the user didn't specify the stem lengths for those outer
+ *             groups (which determines the equation of the beams), it calls a
+ *             function to decide what the equation should be; otherwise it
+ *             finds the equation in-line.  Then it sets all the groups' stem
+ *             lengths.
+ */
+
+/*
+ * Given the STARTITEM group of a CSB (whether notes or space), return the
+ * first CSB group that is notes.  Embedded grace groups are not part of CSB.
+ */
+#define FIRSTCSB(gs_p) (gs_p->grpcont == GC_NOTES ? gs_p : nextcsb(gs_p))
+
+static void
+onecsb(start1_p, start2_p)
+
+struct GRPSYL *start1_p;       /* first GRPSYL on top staff */
+struct GRPSYL *start2_p;       /* first GRPSYL on bottom staff */
+
+{
+       struct GRPSYL *gs_p;    /* point at a group */
+       int topdir, botdir;     /* stem directions of the two lists */
+       struct GRPSYL *end1_p, *end2_p; /* ending group in each list */
+       struct GRPSYL *first_p, *last_p;/* first and last note groups in CSB */
+       float firstx, lastx;    /* x coords of end of stems */
+       float firsty, lasty;    /* y coords of stems */
+       float b0, b1;           /* y intercept and slope of the beam */
+       float stemshift;        /* x distance of stem from center of note */
+       float x;                /* x coord of a stem */
+       float outstem;  /* the part of the stemlen outside notes of group */
+       float hi;               /* height of a "with" list item */
+       int n;                  /* loop variable */
+
+
+       /*
+        * Set globals like Staffscale for use by the rest of the file.  The
+        * parse phase ensures that the two staffs have the same staffscale.
+        */
+       set_staffscale(start1_p->staffno);
+
+       topdir = botdir = UP;   /* prevent useless 'used before set' warnings */
+
+       /*
+        * Find stemdir of the top groups.  (They will be consistent; that was
+        * enforced in dobunch().)  Set end1_p to the last group.
+        */
+       for (gs_p = FIRSTCSB(start1_p); gs_p != 0; gs_p = nextcsb(gs_p)) {
+               if (gs_p->grpcont == GC_NOTES)
+                       topdir = gs_p->stemdir;
+       }
+       for (end1_p = start1_p; end1_p != 0 && end1_p->beamloc != ENDITEM;
+                       end1_p = nextnongrace(end1_p))
+               ;
+       if (end1_p == 0)
+               pfatal("no ENDITEM in beamed set (onecsb[1])");
+
+       /* do the same for the bottom groups */
+       for (gs_p = FIRSTCSB(start2_p); gs_p != 0; gs_p = nextcsb(gs_p)) {
+               if (gs_p->grpcont == GC_NOTES)
+                       botdir = gs_p->stemdir;
+       }
+       for (end2_p = start2_p; end2_p != 0 && end2_p->beamloc != ENDITEM;
+                       end2_p = nextnongrace(end2_p))
+               ;
+       if (end2_p == 0)
+               pfatal("no ENDITEM in beamed set (onecsb[2])");
+
+       if (topdir == UP && botdir == DOWN) {
+               l_ufatal(start2_p->inputfile, start2_p->inputlineno,
+               "when beaming across staffs, cannot have stems up on top staff and down on bottom");
+       }
+
+       /*
+        * Set first_p and last_p to the first and last note groups, whichever
+        * staff(s) they are on.
+        */
+       first_p = start1_p->grpcont == GC_NOTES ? start1_p : start2_p;
+       last_p = end1_p->grpcont == GC_NOTES ? end1_p : end2_p;
+
+       /*
+        * Find half the width of a note head; the stems will need to be
+        * shifted by that amount from the center of the notes so that they
+        * will meet the edge of the notes properly.
+        */
+       stemshift = getstemshift(first_p);
+
+
+       /*
+        * The user must either specify a stem length for both first and last
+        * groups, or neither.  (The parse phase enforces that.)  If neither,
+        * call a function to determine a line for a beam.  It sets b0 and b1
+        * for that line.
+        */
+       if (IS_STEMLEN_UNKNOWN(first_p->stemlen) ||
+           IS_STEMLEN_UNKNOWN(last_p->stemlen)) {
+               /*
+                * User did not provide both outer stem lengths.  Find the best
+                * line.  But if the stemlen parm was zero, we get back "NO",
+                * and we set all stems to zero.
+                */
+               if (calcline(start1_p, end1_p, start2_p, end2_p, first_p,
+                               last_p, topdir, botdir, &b0, &b1) == NO) {
+                       for (gs_p = first_p; gs_p != end1_p->next;
+                            gs_p = nxtbmnote(gs_p, start1_p, end1_p->next)) {
+                               gs_p->stemlen = 0.0;
+                       }
+                       return;
+               }
+       } else {
+               /*
+                * User provided outer stem lengths.  If they are zero, force
+                * all groups to zero and get out.  There will be no stems and
+                * no beams.
+                */
+               if (first_p->stemlen == 0.0 && last_p->stemlen == 0.0) {
+                       for (gs_p = first_p; gs_p != end1_p->next;
+                            gs_p = nxtbmnote(gs_p, start1_p, end1_p->next)) {
+                               gs_p->stemlen = 0.0;
+                       }
+                       return;
+               }
+
+               /*
+                * User provided outer stem lengths; calculate b0 and b1.
+                * First get Y coords of endpoints of first and last stems.
+                */
+               first_p->stemlen *= Staffscale;
+               last_p->stemlen *= Staffscale;
+               firsty = first_p->stemdir == UP ?
+                       first_p->notelist[0].c[AY] + first_p->stemlen :
+                       first_p->notelist[ first_p->nnotes - 1 ].c[AY]
+                               - first_p->stemlen;
+               lasty = last_p->stemdir == UP ?
+                       last_p->notelist[0].c[AY] + last_p->stemlen :
+                       last_p->notelist[ last_p->nnotes - 1 ].c[AY]
+                               - last_p->stemlen;
+               /*
+                * If first and last are opposite, adjust the right end of
+                * the line.
+                */
+               if (first_p->stemdir != last_p->stemdir)
+                       lasty += end_bm_offset(start1_p, last_p, 8);
+
+               /* get X coords; calculate b0 and b1 */
+               firstx = first_p->c[AX] + stemshift *
+                               (first_p->stemdir == DOWN ? -1 : 1);
+               lastx = last_p->c[AX] + stemshift *
+                               (last_p->stemdir == DOWN ? -1 : 1);
+               b1 = (lasty - firsty) / (lastx - firstx); /* slope */
+               b0 = firsty - b1 * firstx;                /* y intercept */
+       }
+
+
+       /*
+        * At this point we know the equation for the beams.  Figure out and
+        * set the correct stem lengths for all of these beamed groups.
+        */
+       if (topdir == botdir) {         /* all stems have the same direction */
+               if (first_p->stemdir == DOWN)
+                       stemshift = -stemshift;
+
+               /* loop through the top staff's groups */
+               for (gs_p = FIRSTCSB(start1_p); gs_p != 0; gs_p=nextcsb(gs_p)){
+                       x = gs_p->c[AX] + stemshift;
+
+                       /* first set stemlen to beam's Y coord minus note's */
+                       gs_p->stemlen = (b0 + b1 * x) - BNOTE(gs_p).c[AY];
+
+                       /* if stems are down, reverse it */
+                       if (gs_p->stemdir == DOWN)
+                               gs_p->stemlen = -(gs_p->stemlen);
+
+                       finalstemadjust(gs_p);
+               }
+               /* loop through the bottom staff's groups */
+               for (gs_p = FIRSTCSB(start2_p); gs_p != 0; gs_p=nextcsb(gs_p)){
+                       x = gs_p->c[AX] + stemshift;
+
+                       /* first set stemlen to beam's Y coord minus note's */
+                       gs_p->stemlen = (b0 + b1 * x) - BNOTE(gs_p).c[AY];
+
+                       /* if stems are down, reverse it */
+                       if (gs_p->stemdir == DOWN)
+                               gs_p->stemlen = -(gs_p->stemlen);
+
+                       /* if negative (note on wrong side of beam), error */
+                       if (gs_p->stemlen < 0) {
+                               l_ufatal(gs_p->inputfile, gs_p->inputlineno,
+                                       "stem length was forced negative");
+                       }
+
+                       finalstemadjust(gs_p);
+               }
+       } else {        /* topdir != botdir; some stems have different dir */
+
+               struct GRPSYL *prev_p;          /* previous CSB group */
+               struct GRPSYL *firstsub_p;      /* first group of a subbeam */
+               struct GRPSYL *lastsub_p;       /* last group of a subbeam */
+               struct GRPSYL *sub_p;           /* a group in a subbeam */
+               int minbeams;                   /* no. of beams all share */
+               int beams;                      /* no. of beams of a group */
+               int slowbasic;                  /* slowest basictime in CSB */
+               int fastbasic;                  /* fastest basictime in CSB */
+               int basic;                      /* a basictime value */
+               float bhigh;                    /* height of beams */
+               float extra;            /* amount to lengthen all stems by */
+
+
+               /*
+                * Find the minimum number of beams of the groups in the CSB
+                * set.  That will be the number of beams that they all share.
+                */
+               minbeams = 999;         /* way more than there could ever be */
+               for (gs_p = first_p; gs_p != end1_p->next;
+                               gs_p = nxtbmnote(gs_p, start1_p, end1_p->next)){
+                       beams = drmo(gs_p->basictime) - 2;
+                       if (beams < minbeams)
+                               minbeams = beams;
+               }
+
+               /*
+                * Find height of all the beams: the distance between the
+                * centers of the outer beams.  This should agree with 
+                * the numbers in prntdata.c.
+                */
+               bhigh = (minbeams - 1) * Staffscale *
+                       (first_p->grpsize == GS_NORMAL ? FLAGSEP : 4.0 * POINT);
+
+               /*
+                * Change the y intercept such that the first stem is lengthened
+                * by half of this height.  The line is at the outer beam, from
+                * the perspective of the first group.
+                */
+               b0 += first_p->stemdir == UP ? bhigh / 2.0 : -bhigh / 2.0;
+
+               /*
+                * First set stem lengths to reach the line of the main beam.
+                * At this point, we don't yet include the distance between the
+                * notes of multinote groups.  While we're at it, find the
+                * slowest basictime of any group in the CSB set.
+                * Also find the fastest basictime.
+                */
+               slowbasic = 1024;       /* faster than any could be */
+               fastbasic = 8;          /* slowest that any could be */
+               /* loop through the top staff's groups: all stems down */
+               for (gs_p = FIRSTCSB(start1_p); gs_p != 0; gs_p=nextcsb(gs_p)){
+                       x = gs_p->c[AX] - stemshift;
+
+                       /* first set stemlen to note's Y coord minus beam's */
+                       gs_p->stemlen = gs_p->notelist[ gs_p->nnotes - 1 ].
+                                       c[AY] - (b0 + b1 * x);
+
+                       slowbasic = MIN(slowbasic, gs_p->basictime);
+                       fastbasic = MAX(fastbasic, gs_p->basictime);
+               }
+               /* loop through the bottom staff's groups; all stems up */
+               for (gs_p = FIRSTCSB(start2_p); gs_p != 0; gs_p=nextcsb(gs_p)){
+                       x = gs_p->c[AX] + stemshift;
+
+                       /* first set stemlen to beam's Y coord minus note's */
+                       gs_p->stemlen = (b0 + b1 * x) - gs_p->notelist[0].c[AY];
+
+                       slowbasic = MIN(slowbasic, gs_p->basictime);
+                       fastbasic = MAX(fastbasic, gs_p->basictime);
+               }
+
+               /*
+                * Find the minimum number of beams (based on the slowest
+                * basictime) and subtract 1 to find the number of additional
+                * beams that all groups share beyond the first beam.  Multiply
+                * by the distance the centers of neighboring beams.
+                */
+               extra = ((drmo(slowbasic) - 2) - 1) * Staffscale *
+                       (first_p->grpsize == GS_NORMAL ? FLAGSEP : 4.0 * POINT);
+
+               /*
+                * For each group with stemdir opposite to that of the first
+                * group, lengthen its stemlen by that amount.
+                */
+               for (gs_p = first_p; gs_p != end1_p->next; gs_p =
+                               nxtbmnote(gs_p, start1_p, end1_p->next)) {
+
+                       if (gs_p->stemdir != first_p->stemdir)
+                               gs_p->stemlen += extra;
+               }
+
+               /*
+                * Loop for each basictime being used that is shorter than the
+                * longest one; that is, for each level of subbeam that is
+                * needed anywhere.
+                */
+               for (basic = slowbasic * 2; basic <= fastbasic; basic *= 2) {
+
+                       /* loop through all note groups in the CSB */
+                       for (prev_p = 0, gs_p = first_p;
+                            gs_p != end1_p->next;
+                            prev_p = gs_p, gs_p = nxtbmnote(gs_p, start1_p,
+                                       end1_p->next)) {
+                               /*
+                                * If this group has at least as fast a basic-
+                                * time as the one we're now dealing with, and
+                                * the previous group doesn't (or there is no
+                                * previous group), a new subbeam must begin
+                                * here (or it could be just a partial beam).
+                                * If not, "continue" here.
+                                */
+                               if (gs_p->basictime < basic || (gs_p != first_p
+                                               && prev_p->basictime >= basic)){
+                                       continue;
+                               }
+
+                               /* point at the start of this subbeam */
+                               firstsub_p = gs_p;
+
+                               /*
+                                * Set lastsub_p to right end of the subbeam,
+                                * the group right before the basictime becomes
+                                * slower than the level we are dealing with.
+                                */
+                               for (lastsub_p = sub_p = firstsub_p; sub_p !=
+                                    end1_p->next; sub_p = nxtbmnote(sub_p,
+                                    start1_p, end1_p->next)) {
+
+                                       if (sub_p == 0 ||
+                                           sub_p->basictime < basic) {
+                                               break;
+                                       }
+                                       lastsub_p = sub_p;
+                               }
+
+                               /*
+                                * Loop through subbeam, lengthening the stems
+                                * of all the note groups whose stem direction
+                                * is opposite to the first group's.  Lengthen
+                                * them enough for one more beam.
+                                */
+                               for (sub_p = firstsub_p; sub_p != end1_p->next;
+                                    sub_p = nxtbmnote(sub_p, start1_p,
+                                    end1_p->next)) {
+
+                                       if (sub_p->stemdir != firstsub_p->
+                                                       stemdir) {
+                                               sub_p->stemlen +=
+                                               (sub_p->grpsize == GS_NORMAL ?
+                                               FLAGSEP : 4.0 * POINT) *
+                                               Staffscale;
+                                       }
+
+                                       if (sub_p == lastsub_p) {
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+               /* adjust all stems in the CSB */
+               for (gs_p = first_p;
+                    gs_p != end1_p->next;
+                    gs_p = nxtbmnote(gs_p, start1_p, end1_p->next)) {
+
+                       /* if negative (note on wrong side of beam), error */
+                       if (gs_p->stemlen < 0) {
+                               l_ufatal(gs_p->inputfile, gs_p->inputlineno,
+                                       "stem length was forced negative");
+                       }
+
+                       /* add distance between outer notes of group */
+                       gs_p->stemlen += (gs_p->notelist[0].stepsup -
+                       gs_p->notelist[ gs_p->nnotes - 1 ].stepsup) * Stepsize;
+               }
+
+       }
+
+       /*
+        * In beamstem.c, setgroupvert() expanded the north and south
+        * boundaries of groups to allow for stems (except for CSB groups) and
+        * "with" items (except for CSB where normwith was NO).  The exceptions
+        * were because in those cases we needed to know the stem lengths and
+        * we didn't yet.  Well, now we know.  So do the job here.
+        *
+        * The extension for the stem is the length of the exterior part of it
+        * minus half the size of the stem side note (about a STEPSIZE), since
+        * the note itself is already included in the group boundary.  Each
+        * "with" item is allowed enough space for its height, or MINWITHHEIGHT,
+        * whichever is greater.  In the print phase, items of height less than
+        * MINWITHHEIGHT will be placed so as to avoid staff lines as much as
+        * possible.
+        */
+       for (gs_p = first_p; gs_p != end1_p->next; gs_p = nxtbmnote(gs_p,
+                       start1_p, end1_p->next)) {
+               outstem = gs_p->stemlen
+                       - (gs_p->notelist[0].c[RY]
+                       - gs_p->notelist[ gs_p->nnotes - 1 ].c[RY]);
+               if (gs_p->stemdir == UP)
+                       gs_p->c[AN] += outstem - Stepsize;
+               else
+                       gs_p->c[AS] -= outstem - Stepsize;
+
+               if (gs_p->normwith == NO) {
+                       for (n = 0; n < gs_p->nwith; n++) {
+                               hi = strheight(gs_p->withlist[n]);
+                               hi = MAX(hi, Staffscale * MINWITHHEIGHT);
+                               if (gs_p->stemdir == UP)
+                                       gs_p->c[AN] += hi;
+                               else
+                                       gs_p->c[AS] -= hi;
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        calcline()
+ *
+ * Abstract:    Calculate the equation of the line for the beams of a CSB set.
+ *
+ * Returns:     YES if an equation was calculated, NO if there are no stems.
+ *
+ * Description: This function uses linear regression to figure out where the
+ *             best place to put the beam is, for a CSB set.  Then, based on
+ *             whether the stems on the two staffs have the same direction, it
+ *             calls the appropriate function to adjust the results of the
+ *             linear regression as needed.
+ */
+
+static int
+calcline(start1_p, end1_p, start2_p, end2_p, first_p, last_p, topdir, botdir,
+               b0_p, b1_p)
+
+struct GRPSYL *start1_p;       /* first group in first voice */
+struct GRPSYL *start2_p;       /* first group in second voice */
+struct GRPSYL *end1_p;         /* last group in first voice */
+struct GRPSYL *end2_p;         /* last group in second voice */
+struct GRPSYL *first_p;                /* first note group in either voice */
+struct GRPSYL *last_p;         /* last note group in either voice */
+int topdir, botdir;            /* stem directions of top and bottom voices */
+float *b0_p, *b1_p;            /* y intercept and slope to return */
+
+{
+       float defstemsteps;     /* default stem length */
+       int one_end_forced;     /* is stem len forced on one end only? */
+       int slope_forced;       /* is the slope of the beam forced? */
+       float forced_slope;     /* slope that the user forced */
+       struct GRPSYL *gs_p;    /* loop through the groups in the beamed set */
+       float sx, sy;           /* sum of x and y coords of notes */
+       float xbar, ybar;       /* average x and y coords of notes */
+       float top, bottom;      /* numerator & denominator for finding b1 */
+       float temp;             /* scratch variable */
+       float b0, b1;           /* y intercept and slope */
+       float deflen;           /* default len of a stem, based on basictime */
+       int num;                /* number of notes */
+
+
+       if (fabs(first_p->beamslope - NOBEAMANGLE) < 0.001) {
+               slope_forced = NO;
+               forced_slope = 0.0;     /* not used, keep lint happy */
+       } else {
+               slope_forced = YES;
+               forced_slope = tan(first_p->beamslope * PI / 180.0);
+       }
+       one_end_forced = IS_STEMLEN_KNOWN(first_p->stemlen) !=
+                        IS_STEMLEN_KNOWN(last_p->stemlen);
+
+       /*
+        * Find how long we'd like stems to be, ignoring for the moment groups
+        * that need to be longer due to multiple beams.
+        */
+       /* average default stems lengths of the two voices */
+       defstemsteps = (vvpath(start1_p->staffno, start1_p->vno, STEMLEN)->
+                       stemlen + 
+                       vvpath(start2_p->staffno, start2_p->vno, STEMLEN)->
+                       stemlen) / 2.0;
+       /* if this is zero, both stemlens must be zero, so no stems */
+       if (defstemsteps == 0.0 && ! slope_forced && ( ! one_end_forced ||
+                       first_p->stemlen == 0.0 || last_p->stemlen == 0.0)) {
+               return (NO);
+       }
+       if (allsmall(start1_p, end1_p) == NO ||
+                               allsmall(start2_p, end2_p) == NO) {
+               /* at least one group has a normal size note */
+               deflen = defstemsteps * Stepsize;
+       } else {
+               /* all groups have all small notes */
+               deflen = defstemsteps * SM_STEMFACTOR * Stepsize;
+       }
+
+       /*
+        * Use linear regression to find the best-fit line through where the
+        * ends of the stems would be if they were the standard length.  In
+        * setbeam() where a similar thing was done for non-CSB beams, we used
+        * the centers of the notes, which was okay because at this point in
+        * the game we're really just interested in finding the slope.  But
+        * in CSB, sometimes the stems of the two staffs go in opposite
+        * directions, so we really need to consider the ends of the stems.
+        *
+        * In this function, we will always be concerned with the X coord of
+        * the group as a whole (disregarding any notes that are on the "wrong"
+        * side of the stem) but the Y coord of the note of the group that's
+        * nearest to the beam (thus the BNOTE macro).
+        *
+        * First get sum of x and y coords, to find averages.
+        */
+       sx = sy = 0;
+       num = 0;
+       for (gs_p = FIRSTCSB(start1_p); gs_p != 0; gs_p = nextcsb(gs_p)) {
+               sx += gs_p->c[AX];
+               sy += BNOTE(gs_p).c[AY] + (topdir == UP ? deflen : -deflen);
+               num++;                  /* count number of notes */
+       }
+       for (gs_p = FIRSTCSB(start2_p); gs_p != 0; gs_p = nextcsb(gs_p)) {
+               sx += gs_p->c[AX];
+               sy += BNOTE(gs_p).c[AY] + (botdir == UP ? deflen : -deflen);
+               num++;                  /* count number of notes */
+       }
+
+       xbar = sx / num;
+       ybar = sy / num;
+
+       /* accumulate numerator & denominator of regression formula for b1 */
+       top = bottom = 0;
+       for (gs_p = FIRSTCSB(start1_p); gs_p != 0; gs_p = nextcsb(gs_p)) {
+               temp = gs_p->c[AX] - xbar;
+               top += temp * (BNOTE(gs_p).c[AY] +
+                               (topdir == UP ? deflen : -deflen) - ybar);
+               bottom += temp * temp;
+       }
+       for (gs_p = FIRSTCSB(start2_p); gs_p != 0; gs_p = nextcsb(gs_p)) {
+               temp = gs_p->c[AX] - xbar;
+               top += temp * (BNOTE(gs_p).c[AY] +
+                               (botdir == UP ? deflen : -deflen) - ybar);
+               bottom += temp * temp;
+       }
+
+       b1 = top / bottom;              /* slope */
+       b0 = ybar - b1 * xbar;          /* y intercept */
+
+       /* equation of regression line:  y = b0 + b1 * x   */
+
+       if (topdir == botdir) {
+               samedir(first_p, last_p, start1_p, start2_p, end1_p, &b0, &b1,
+                               deflen, one_end_forced, slope_forced,
+                               forced_slope);
+       } else {
+               oppodir(first_p, last_p, start1_p, start2_p, &b0, &b1, deflen,
+                               one_end_forced, slope_forced, forced_slope);
+       }
+
+       /* return the calculated slope and intercept */
+       *b0_p = b0;
+       *b1_p = b1;
+
+       return (YES);
+}
+\f
+/*
+ * Name:        samedir()
+ *
+ * Abstract:    Adjust b0 and b1 when stems are all the same direction.
+ *
+ * Returns:     void
+ *
+ * Description: This function is used in the case that the stems on the two
+ *             staffs of the CSB have the same direction.  It is given the
+ *             y intercept and slope of the beam as calculated by linear
+ *             regression.  It adjusts these values if need be.  The algorithm
+ *             is similar to the one in setbeam() in beamstem.c.  But here we
+ *             have to deal with two linked lists of groups, and we don't have
+ *             to deal with grace notes or alternations.
+ */
+
+static void
+samedir(first_p, last_p, start1_p, start2_p, end1_p, b0_p, b1_p, deflen,
+               one_end_forced, slope_forced, forced_slope)
+
+struct GRPSYL *first_p, *last_p;       /* first and last note groups in CSB */
+struct GRPSYL *start1_p, *start2_p;    /* first groups of 1st & 2nd voices */
+struct GRPSYL *end1_p;         /* last group of 1st voice */
+float *b0_p, *b1_p;            /* y intercept and slope */
+double deflen;                 /* default len of a stem, based on group size*/
+int one_end_forced;            /* is stem len forced on one end only? */
+int slope_forced;              /* is the slope of the beam forced? */
+double forced_slope;           /* slope that the user forced */
+
+{
+       struct GRPSYL *gs_p;    /* loop through the groups in the beamed set */
+       float firstx, lastx;    /* x coord of first & last note (end of stem)*/
+       float firsty, lasty;    /* y coord of first & last note (end of stem)*/
+       float maxb0, minb0;     /* max and min y intercepts */
+       float stemshift;        /* x distance of stem from center of note */
+       float b0, b1;           /* working copy of y intercept and slope */
+       float temp;             /* temp variable */
+       float shortdist;        /* amount of stem shortening allowed (inches)*/
+       int bf;                 /* number of beams/flags */
+       int shortest;           /* basictime of shortest note in group */
+
+
+       /* set working copies from the original values */
+       b0 = *b0_p;
+       b1 = *b1_p;
+
+       /*
+        * Find half the width of a note head; the stems will need to be
+        * shifted by that amount from the center of the notes so that they
+        * will meet the edge of the notes properly.  If the stems are up,
+        * they will be on the right side of (normal) notes, else left.  Set
+        * the X positions for the first and last stems.
+        */
+       stemshift = getstemshift(first_p);
+       if (first_p->stemdir == DOWN)
+               stemshift = -stemshift;
+       firstx = first_p->c[AX] + stemshift;    /* first group's stem */
+       lastx = last_p->c[AX] + stemshift;      /* last group's stem */
+
+       /*
+        * The original line derived by linear regression must be adjusted in
+        * certain ways.  First, override it if the user wants that; otherwise
+        * adjust according to the beamslope parameter.
+        */
+       if (slope_forced) {
+               b1 = forced_slope;
+       } else {
+               b1 = adjslope(start1_p, b1, NO);
+       }
+
+       /*
+        * Calculate a new y intercept (b0).  First pass parallel lines
+        * through each note, and record the maximum and minimum y intercepts
+        * that result.
+        */
+       b0 = BNOTE(first_p).c[AY] - b1 * first_p->c[AX];
+       maxb0 = minb0 = b0;             /* init to value for first note */
+       /* look at rest of them on each of the two staffs */
+       for (gs_p = FIRSTCSB(start1_p); gs_p != 0; gs_p = nextcsb(gs_p)) {
+               b0 = BNOTE(gs_p).c[AY] - b1 * gs_p->c[AX];
+               if (b0 > maxb0)
+                       maxb0 = b0;
+               else if (b0 < minb0)
+                       minb0 = b0;
+       }
+       for (gs_p = FIRSTCSB(start2_p); gs_p != 0; gs_p = nextcsb(gs_p)) {
+               b0 = BNOTE(gs_p).c[AY] - b1 * gs_p->c[AX];
+               if (b0 > maxb0)
+                       maxb0 = b0;
+               else if (b0 < minb0)
+                       minb0 = b0;
+       }
+
+       /*
+        * Find the basictime of the shortest note in the CSB set, considering
+        * also any slashes on it.  Then update the default stem length based
+        * on that.
+        */
+       shortest = 0;
+       for (gs_p = first_p; gs_p != end1_p->next; gs_p = nxtbmnote(gs_p,
+                       start1_p, end1_p->next)) {
+               bf = drmo(gs_p->basictime) - 2; /* no. of beams/flags */
+               bf += abs(gs_p->slash_alt);     /* slashes */
+               /*
+                * In certain cases where there are accidentals, we need to
+                * artificially increase bf to keep the beams from overlapping
+                * with the accidental.
+                */
+               if (gs_p != first_p && gs_p->stemdir == UP &&
+                               gs_p->notelist[0].accidental != '\0' &&
+                               gs_p->notelist[0].accidental != 'x' &&
+                               b1 > 0 && bf > 1) {
+                       bf += 3.5 * b1 * (STEPSIZE / FLAGSEP) * ((bf > 1) +
+                                       (gs_p->notelist[0].accidental == 'B'));
+               }
+               if (bf > shortest)
+                       shortest = bf;
+       }
+
+       if (shortest > 2) {
+               /* don't use "==" due to floating point roundoff error */
+               if (deflen > 6 * Stepsize) {
+                       /* at least one group has a normal size note */
+                       deflen += (shortest - 2) * Flagsep;
+               } else {
+                       /* all groups have all small notes */
+                       deflen += (shortest - 2) * 4.0 * POINT * Staffscale;
+               }
+       }
+
+       /*
+        * The outer edge of the beam should be deflen steps away from the
+        * average position of the notes, as defined by the linear regression
+        * line.  But don't allow any note to be closer than a certain number
+        * of steps less than that, the number as given by the stemshorten parm.
+        * We use the average of the two stemshorten values for the two voices.
+        */
+       shortdist = (vvpath(start1_p->staffno, start1_p->vno, STEMSHORTEN)
+                       ->stemshorten +
+                    vvpath(start2_p->staffno, start2_p->vno, STEMSHORTEN)
+                       ->stemshorten) / 2.0 * Stepsize;
+       if (first_p->stemdir == UP) {
+               if (maxb0 - minb0 > shortdist)
+                       b0 = maxb0 + deflen - shortdist;
+               else
+                       b0 += deflen;
+       } else { /* DOWN */
+               if (maxb0 - minb0 > shortdist)
+                       b0 = minb0 - deflen + shortdist;
+               else
+                       b0 -= deflen;
+       }
+
+       firsty = b0 + b1 * firstx;      /* y coord near left end of beam */
+       lasty = b0 + b1 * lastx;        /* y coord near right end of beam */
+
+       /*
+        * At this point, like setbeam(), we could force the stems of notes
+        * that are pointing to the center of their staffs to reach that center
+        * line.  But it's questionable whether that should be done in cross
+        * staff beaming situations.  We choose not to.
+        */
+
+       /*
+        * If y at the ends of the beam differs by less than a step (allowing a
+        * fudge factor for roundoff error), force the beam horizontal by
+        * setting one end farther away from the notes.  But don't do it if the
+        * user is forcing a particular slope.
+        */
+       if ( ! slope_forced && fabs(firsty - lasty) < Stepsize - 0.001) {
+               if (first_p->stemdir == UP) {
+                       if (firsty > lasty) {
+                               lasty = firsty;
+                       } else {
+                               firsty = lasty;
+                       }
+               } else {        /* DOWN */
+                       if (firsty < lasty) {
+                               lasty = firsty;
+                       } else {
+                               firsty = lasty;
+                       }
+               }
+       }
+
+       /* recalculate slope and y intercept from (possibly) new endpoints */
+       b1 = (lasty - firsty) / (lastx - firstx);       /* slope */
+       b0 = firsty - b1 * firstx;                      /* y intercept */
+
+       /*
+        * At this point, like setbeam(), we could do the equivalent of
+        * embedgrace() and avoidothervoice().  But those functions themselves
+        * wouldn't work here as they are, and/or we don't have the necessary
+        * info handy for calling them.  These problems are fairly rare, on top
+        * of cross staff beaming already being fairly rare.  If something
+        * collides, the user can always manually set the stem lengths.
+        */
+
+       /*
+        * If one end's stem len was forced but not the other, now is the time
+        * to apply that forcing.  So in effect, we have taken the beam as
+        * determined by the normal algorithm and now we change the vertical
+        * coord of this end.  If the slope was also forced, move the other
+        * end by the same amount so that the slope won't change.
+        */
+       if (one_end_forced) {
+               if (IS_STEMLEN_KNOWN(first_p->stemlen)) {
+                       first_p->stemlen *= Staffscale;
+                       temp = firsty;
+                       firsty = BNOTE(first_p).c[AY] + first_p->stemlen *
+                                       (first_p->stemdir == UP ? 1.0 : -1.0);
+                       if (slope_forced) {
+                               lasty += firsty - temp;
+                       }
+               } else {
+                       last_p->stemlen *= Staffscale;
+                       temp = lasty;
+                       lasty = BNOTE(last_p).c[AY] + last_p->stemlen *
+                                       (last_p->stemdir == UP ? 1.0 : -1.0);
+                       if (slope_forced) {
+                               firsty += lasty - temp;
+                       }
+               }
+
+               /* recalculate */
+               b1 = (lasty - firsty) / (lastx - firstx); /* slope */
+               b0 = firsty - b1 * firstx;              /* y intercept */
+       }
+
+       /* send back the newly calculated values */
+       *b0_p = b0;
+       *b1_p = b1;
+}
+\f
+/*
+ * Name:        oppodir()
+ *
+ * Abstract:    Adjust b0 and b1 when stems are in opposite directions.
+ *
+ * Returns:     void
+ *
+ * Description: This function is used in the case that the stems on the two
+ *             staffs of the CSB all have opposite directions.  It is given
+ *             the y intercept and slope of the beam as calculated by linear
+ *             regression.  It adjusts these values if need be.
+ */
+
+static void
+oppodir(first_p, last_p, start1_p, start2_p, b0_p, b1_p, deflen,
+               one_end_forced, slope_forced, forced_slope)
+
+struct GRPSYL *first_p, *last_p;       /* first and last note groups in CSB */
+struct GRPSYL *start1_p, *start2_p;    /* first groups of 1st & 2nd voices */
+float *b0_p, *b1_p;            /* y intercept and slope */
+double deflen;                 /* default len of a stem, based on group size*/
+int one_end_forced;            /* is stem len forced on one end only? */
+int slope_forced;              /* is the slope of the beam forced? */
+double forced_slope;           /* slope that the user forced */
+
+{
+       struct GRPSYL *gs_p;    /* loop through the groups in the beamed set */
+       float firstx, lastx;    /* x coord of first & last note (end of stem)*/
+       float firsty, lasty;    /* y coord of first & last note (end of stem)*/
+       float maxb0, minb0;     /* max and min y intercepts */
+       float stemshift;        /* x distance of stem from center of note */
+       float b0, b1;           /* working copy of y intercept and slope */
+       float temp;             /* temp variable */
+
+
+       /* set working copies from the original values */
+       b0 = *b0_p;
+       b1 = *b1_p;
+
+       /*
+        * Find half the width of a note head; the stems will need to be
+        * shifted by that amount from the center of the notes so that they
+        * will meet the edge of the notes properly.  If the stems are up,
+        * they will be on the right side of (normal) notes, else left.  Set
+        * the X positions for the first and last stems.
+        */
+       stemshift = getstemshift(first_p);
+       if (first_p->stemdir == DOWN)
+               stemshift = -stemshift;
+       firstx = first_p->c[AX] + stemshift;    /* first group's stem */
+       lastx = last_p->c[AX] + stemshift;      /* last group's stem */
+
+       /*
+        * The original line derived by linear regression must be adjusted in
+        * certain ways.  First, override it if the user wants that; otherwise
+        * adjust according to the beamslope parameter.
+        */
+       if (slope_forced) {
+               b1 = forced_slope;
+       } else {
+               b1 = adjslope(start1_p, b1, YES);
+       }
+
+       /*
+        * Calculate a new y intercept (b0).  First pass parallel lines
+        * through each note, and record the minimum y intercept for the top
+        * staff and the maximum for the bottom staff that result.
+        */
+       minb0 = 1000.0;         /* init way positive */
+       /* look at rest of them on each of the two staffs */
+       for (gs_p = FIRSTCSB(start1_p); gs_p != 0; gs_p = nextcsb(gs_p)) {
+               b0 = BNOTE(gs_p).c[AY] - b1 * gs_p->c[AX];
+               if (b0 < minb0)
+                       minb0 = b0;
+       }
+       maxb0 = -1000.0;        /* init way negative */
+       for (gs_p = FIRSTCSB(start2_p); gs_p != 0; gs_p = nextcsb(gs_p)) {
+               b0 = BNOTE(gs_p).c[AY] - b1 * gs_p->c[AX];
+               if (b0 > maxb0)
+                       maxb0 = b0;
+       }
+
+       /*
+        * Make the y intercept be the average of these.  That means the top
+        * staff's shortest stem will be equal in length to the bottom staff's.
+        */
+       b0 = (maxb0 + minb0) / 2.0;
+
+       firsty = b0 + b1 * firstx;      /* y coord near left end of beam */
+       lasty = b0 + b1 * lastx;        /* y coord near right end of beam */
+
+       /*
+        * If y at the ends of the beam differs by less than a step (allowing a
+        * fudge factor for roundoff error), force the beam horizontal,
+        * averaging the two values.
+        */
+       if ( ! slope_forced && fabs(firsty - lasty) < Stepsize - 0.001) {
+               lasty = (firsty + lasty) / 2.;
+               firsty = lasty;
+       }
+
+       /* recalculate slope and y intercept from (possibly) new endpoints */
+       b1 = (lasty - firsty) / (lastx - firstx);       /* slope */
+       b0 = firsty - b1 * firstx;                      /* y intercept */
+
+       /*
+        * If one end's stem len was forced but not the other, now is the time
+        * to apply that forcing.  So in effect, we have taken the beam as
+        * determined by the normal algorithm and now we change the vertical
+        * coord of this end.  If the slope was also forced, move the other
+        * end by the same amount so that the slope won't change.
+        */
+       if (one_end_forced) {
+               if (IS_STEMLEN_KNOWN(first_p->stemlen)) {
+                       first_p->stemlen *= Staffscale;
+                       temp = firsty;
+                       firsty = BNOTE(first_p).c[AY] + first_p->stemlen *
+                                       (first_p->stemdir == UP ? 1.0 : -1.0);
+                       if (slope_forced) {
+                               lasty += firsty - temp;
+                       }
+               } else {
+                       last_p->stemlen *= Staffscale;
+                       temp = lasty;
+                       lasty = BNOTE(last_p).c[AY] + last_p->stemlen *
+                                       (last_p->stemdir == UP ? 1.0 : -1.0);
+                       if (slope_forced) {
+                               firsty += lasty - temp;
+                       }
+               }
+
+               /* recalculate */
+               b1 = (lasty - firsty) / (lastx - firstx); /* slope */
+               b0 = firsty - b1 * firstx;              /* y intercept */
+       }
+
+       /* send back the newly calculated values */
+       *b0_p = b0;
+       *b1_p = b1;
+}
+\f
+/*
+ * Name:        nextcsb()
+ *
+ * Abstract:    Find the next note group on this staff in this CSB.
+ *
+ * Returns:     pointer to next note group in CSB on this staff, 0 if none
+ *
+ * Description: This function looks for the next group on this staff that is
+ *             still in this CSB set (therefore nongrace), and contains notes
+ *             (not a space).
+ */
+
+static struct GRPSYL *
+nextcsb(gs_p)
+
+struct GRPSYL *gs_p;           /* current group, must be in a CSB */
+
+{
+       /* if we are already at the last group in the set, no next group */
+       if (gs_p->beamloc == ENDITEM)
+               return (0);
+
+       /* loop forward, considering only nongrace groups */
+       for (gs_p = nextnongrace(gs_p); gs_p != 0; gs_p = nextnongrace(gs_p)) {
+               /* if we find a note group, return it */
+               if (gs_p->grpcont == GC_NOTES)
+                       return (gs_p);
+               /* must be a space (rests not allowed); if enditem, give up */
+               if (gs_p->beamloc == ENDITEM)
+                       return (0);
+       }
+
+       return (0);     /* hit the end of the measure (shouldn't happen) */
+}
+\f
+/*
+ * Name:        nxtbmnote()
+ *
+ * Abstract:    Find the next note group in this CSB (this staff or the other).
+ *
+ * Returns:     pointer to next note group in CSB, endnext_p if none
+ *
+ * Description: This function looks for the next group that is still in this
+ *             CSB set (therefore nongrace), and contains notes (not a space
+ *             or a rest), whichever staff it may be on.
+ */
+
+static struct GRPSYL *
+nxtbmnote(gs_p, first_p, endnext_p)
+
+struct GRPSYL *gs_p;           /* current group, must be in a CSB */
+struct GRPSYL *first_p;                /* first group in top staff of the CSB */
+struct GRPSYL *endnext_p;      /* what to return if we hit the end */
+
+{
+       /*
+        * Keep finding the next nonspace group, until we hit the end or we
+        * find one that is not a rest.
+        */
+       do {
+               gs_p = nxtbmgrp(gs_p, first_p, endnext_p);
+       } while (gs_p != endnext_p && gs_p->grpcont != GC_NOTES);
+       return (gs_p);
+}
diff --git a/mup/mup/assign.c b/mup/mup/assign.c
new file mode 100644 (file)
index 0000000..9c938dd
--- /dev/null
@@ -0,0 +1,2181 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* Assign values to internal variables in an SSV struct. The functions in
+ * this file are called from the parse phase. */
+
+
+#include <string.h>
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+/* there are several cases where we ultimately want arrays, but don't
+ * know in advance how many elements will be in the array. This could be
+ * done by building a linked list first, then malloc-ing the right size and
+ * copying everything. However, what we'll do is allocate CHUNK elements
+ * to start, and realloc if necessary. When we're done, we realloc down
+ * to the actual size */
+#define CHUNK  (8)
+
+/* minimum allowable height or width of page (in inches)
+ * after subtracting off the margins */
+#define MIN_USABLE_SPACE       0.5
+
+
+/* Macros to adjust numbers between inches to centimeters . */
+
+/* Given a number in inches, use that number if in inches mode.
+ * If in centimeter mode, then use the equivalent distance in centimeters,
+ * rounded to the nearest quarter of a centimeter. */
+#define ADJUST4UNITS(n)  (Score.units == INCHES ? n : NEARESTQUARTER(n * CMPERINCH))
+
+/* Given an input number, leave as is if in inches mode. If in centimeter
+ * mode, treat the number as being in centimeters, and convert to the inch
+ * equivalent distance. */
+#define ADJUST2INCHES(n)  { if (Score.units == CM) n /= CMPERINCH; }
+
+static struct STAFFSET *Curr_staffset_p;/* staffset currently
+                                        * being filled in */
+static int Ss_count;                   /* num of elements in Curr_staffset_p
+                                        * currently actually being used */
+static int Ss_length;                  /* num of elements allocated
+                                        * to Curr_staffset_p */
+
+static struct TOP_BOT *Curr_barstlist_p;/* bar style list being filled in */
+static int Barst_count;                        /* number of elements in
+                                        * Curr_barstlist_p that are currently
+                                        * filled in with valid values */
+static int Barst_length;               /* number of elements allocated to
+                                        * Curr_barstlist_p */
+
+struct BEAMLIST {
+       RATIONAL *list_p;               /* beam list being filled in */
+       int count;                      /* elements filled in list_p */
+       int length;                     /* elements allocated to list_p */
+};
+/* These store info from the beamstyle parameter. */
+static struct BEAMLIST Curr_beamstyle;
+static struct BEAMLIST Curr_subbeamstyle;
+static int Subbeam_index;              /* Index into Curr_subbeamstyle where
+                                        * the most recent '(' was, or -1 if
+                                        * no pending unmatched parenthesis. */
+static char *parmformat = "%s parameter";      /* for error messages */
+
+/* functions to do all the various checks. They check the context,
+ * range, power_of2, etc, and
+ * mark the variable as used if everything passes the checks. The first
+ * is for int variables (actually short) in SSV, the second for floats */
+static int do_assign P((int var, int value, int min, int max,
+               int cont, int empty_value, char *name,
+               struct MAINLL *mainll_item_p, short *ptr2dest));
+
+static int do_fassign P((int var, double value, double min,
+               double max, int cont, char *name, struct MAINLL *mainll_item_p,
+               float *ptr2dest));
+static void chg_too_late P((char *var_name));
+
+/* comparison functions to be passed to qsort */
+static int comp_staffset P((const void *item1_p,
+               const void *item2_p));
+static int comp_barst P((const void *item1_p, const void *item2_p));
+static int is_tablature_staff P((struct SSV *ssv_p));
+static void init_beamlist P((struct BEAMLIST *beamlist_p));
+static void add2outerbeam P((RATIONAL value));
+\f
+
+/* assign a value to an SSV variable having a domain of short,
+ * after doing any appropriate checks */
+
+void
+assign_int(var, value, mainll_item_p)
+
+int var;                       /* SSV index of which variable to set */
+int value;                     /* what to set it to */
+struct MAINLL *mainll_item_p;  /* where to store SSV info in main list */
+
+{
+       /* all of these things except font can only go
+        * into score/staff sorts of things,
+        * not head/foot. If we are in a head/foot, the MAINLL will be null */
+       if (Context == C_MUSIC || Context == C_GRIDS || Context == C_HEADSHAPES
+                               || (mainll_item_p == 0 && var != SIZE)) {
+               yyerror("trying to set parameter value in wrong context");
+               return;
+       }
+
+
+       if (mainll_item_p != (struct MAINLL *) 0) {
+               debug(4, "assign_int file=%s line=%d var=%d t value=%d",
+                       mainll_item_p->inputfile, mainll_item_p->inputlineno, var, value);
+       }
+
+       /* handle each variable appropriately */
+       switch (var) {
+
+       case SIZE:
+               Curr_size = value;
+               if ( Context & C_BLOCKHEAD ) {
+                       (void) rangecheck(value, MINSIZE, MAXSIZE, "size");
+
+                       /* special case -- size can be set in block,
+                        * and there we don't put in SSV struct,
+                        * just save its value in Curr_size */
+                       return;
+               }
+               else {
+                       (void) do_assign(var, value, MINSIZE, MAXSIZE,
+                               C_SCORE | C_STAFF, NO, "size",
+                               mainll_item_p, &(mainll_item_p->u.ssv_p->size));
+                       /* set in Score, in case we get an "all" */
+                       if (Context == C_SCORE) {
+                               Score.size = (short) value;
+                       }
+               }
+               break;
+
+       case LYRICSSIZE:
+               if (do_assign(var, value, MINSIZE, MAXSIZE, C_SCORE | C_STAFF,
+                               NO, "lyricssize", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->lyricssize) )
+                               == YES) {
+                       /* save values for any lyrics that come later */
+                       if (Context == C_SCORE) {
+                               /* set in case we get some "all" lyrics */
+                               Score.lyricssize = (short) value;
+                       }
+                       setlyrsize(mainll_item_p->u.ssv_p->staffno, value);
+               }
+               break;
+
+       case MEASNUMSIZE:
+               (void) do_assign(var, value, MINSIZE, MAXSIZE, C_SCORE,
+                               NO, "measnumsize", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->measnumsize) );
+               break;
+
+       case SYLPOSITION:
+               (void) do_assign(var, value, MINSYLPOSITION, MAXSYLPOSITION,
+                               C_SCORE | C_STAFF,
+                               NO, "sylposition", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->sylposition) );
+               break;
+
+       case DEFOCT:
+               (void) do_assign(var, value, MINOCTAVE, MAXOCTAVE,
+                               C_SSV, NO, "defoct", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->defoct) );
+               if (Context != C_SCORE &&
+                               is_tab_staff(mainll_item_p->u.ssv_p->staffno)
+                               == YES) {
+                       yyerror("defoct not allowed on tablature staff");
+               }
+               else {
+                       asgnssv(mainll_item_p->u.ssv_p);
+               }
+               break;
+
+       case NUMSTAFF:
+               if (do_assign(var, value, MINSTAFFS, MAXSTAFFS, C_SCORE, NO,
+                                       "staffs", mainll_item_p,
+                                       &(mainll_item_p->u.ssv_p->staffs) )
+                                       == YES) {
+
+                       /* can only change number of staffs if not in the
+                        * middle of doing music data. We exclaimed about
+                        * the user error in end_prev_context(), so if this
+                        * occurs, we just skip over the code in the "if"
+                        */
+                       if (List_of_staffs_p == (struct MAINLL *) 0) {
+                               /* NUMSTAFFS is a special case,
+                                * in that several other
+                                * items have to do error checking
+                                * based on the number of staffs specified,
+                                * so we have to set it immediately rather than
+                                * waiting for the whole SSV struct
+                                * to be built. */
+                               Score.staffs = (short) value;
+
+                               /* if the number of scores changes,
+                                * there can't be any
+                                * pending "til" clauses on STUFF */
+                               chk4dangling_til_clauses(
+                                               "change in number of staffs");
+
+                               /* any pedal information is no long valid */
+                               reset_ped_state();
+                       }
+               }
+               break;
+
+       case VISIBLE:
+               /* actually yacc already guarantees will be in range */
+               (void) do_assign(var, value, 0, 1, C_SCORE|C_STAFF|C_VOICE, NO,
+                               "visible", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->visible) );
+               break;
+
+       case MEASNUM:
+               /* actually yacc already guarantees will be in range */
+               (void) do_assign(var, value, 0, 1, C_SCORE, NO,
+                               "measnum", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->measnum) );
+               break;
+
+       case CANCELKEY:
+               /* actually yacc already guarantees will be in range */
+               (void) do_assign(var, value, 0, 1, C_SCORE | C_STAFF, NO,
+                               "cancelkey", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->cancelkey) );
+               break;
+
+       case MINSTSEP:
+               (void) do_assign(var, value, MINMINSTSEP, MAXSEPVAL,
+                               C_SCORE | C_STAFF, NO, "staffsep", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->minstsep) );
+               break;
+
+       case MINSCSEP:
+               (void) do_assign(var, value, MINMINSCSEP, MAXSEPVAL,
+                               C_SCORE, NO, "min scoresep", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->minscsep) );
+               break;
+
+       case MAXSCSEP:
+               (void) do_assign(var, value, MINMAXSCSEP, MAXSEPVAL,
+                               C_SCORE, NO, "max scoresep", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->maxscsep) );
+               break;
+
+       case CHORDDIST:
+               (void) do_assign(var, value, MINCHORDDIST, MAXCHORDDIST,
+                               C_SCORE | C_STAFF, NO, "chorddist",
+                               mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->chorddist) );
+               break;
+
+       case DIST:
+               (void) do_assign(var, value, MINDIST, MAXDIST,
+                               C_SCORE | C_STAFF, NO, "dist", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->dist) );
+               break;
+
+       case DYNDIST:
+               (void) do_assign(var, value, MINDYNDIST, MAXDYNDIST,
+                               C_SCORE | C_STAFF, NO, "dyndist",
+                               mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->dyndist) );
+               break;
+
+       case STAFFPAD:
+               (void) do_assign(var,value, MINSTPAD, MAXSTPAD,
+                               C_SCORE | C_STAFF, NO,
+                               "staffpad", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->staffpad) );
+               break;
+
+       case MINSCPAD:
+               (void) do_assign(var, value, MINMINSCPAD, MAXPADVAL,
+                               C_SCORE, NO, "min scorepad", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->minscpad) );
+               break;
+
+       case MAXSCPAD:
+               (void) do_assign(var, value, MINMAXSCPAD, MAXPADVAL,
+                               C_SCORE, NO, "max scorepad", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->maxscpad) );
+               break;
+
+       case DIVISION:
+               chg_too_late("division");
+               (void) do_assign(var, value, MINDIVISION, MAXDIVISION,
+                               C_SCORE, NO, "division", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->division) );
+               /* division values that aren't divisible by 2 and 3 are
+                * unlikely to be right and are likely to lead to rational
+                * overflow in MIDI code, so give warning */
+               if ((value % 6) != 0) {
+                       l_warning(Curr_filename, yylineno,
+                                               "dubious division value");
+               }
+
+               break;
+
+       case RELEASE:
+               (void) do_assign(var, value, MINRELEASE, MAXRELEASE,
+                               C_SCORE | C_STAFF | C_VOICE, NO,
+                               "release", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->release) );
+               break;
+
+       case PANELSPERPAGE:
+               chg_too_late("panelsperpage");
+               (void) do_assign(var, value, MINPANELSPERPAGE, MAXPANELSPERPAGE,
+                               C_SCORE, NO,
+                               "panelsperpage", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->panelsperpage) );
+               break;
+
+       case RESTCOMBINE:
+               (void) do_assign(var, value,
+                               MINRESTCOMBINE, MAXRESTCOMBINE,
+                               C_SCORE, NORESTCOMBINE,
+                               "restcombine", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->restcombine) );
+               break;
+
+       case FIRSTPAGE:
+               chg_too_late("firstpage");
+               (void) do_assign(var, value, MINFIRSTPAGE, MAXFIRSTPAGE,
+                               C_SCORE, NO,
+                               "firstpage", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->firstpage) );
+               break;
+
+       case GRIDFRET:
+               (void) do_assign(var, value, MINGRIDFRET, MAXGRIDFRET,
+                               C_SCORE | C_STAFF, NOGRIDFRET,
+                               "gridfret", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->gridfret) );
+               break;
+
+       case GRIDSWHEREUSED:
+               (void) do_assign(var, value, 0, 1,
+                               C_SCORE | C_STAFF, NO,
+                               "gridswhereused", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->gridswhereused) );
+               break;
+
+       case GRIDSATEND:
+               (void) do_assign(var, value, 0, 1, C_SCORE, NO,
+                               "gridsatend", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->gridsatend) );
+               break;
+
+       case TABWHITEBOX:
+               /* actually yacc already guarantees will be in range */
+               (void) do_assign(var, value, 0, 1,
+                               C_SCORE | C_STAFF | C_VOICE, NO,
+                               "tabwhitebox", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->tabwhitebox) );
+               break;
+
+       case ONTHELINE:
+               /* This only makes sense on 1-line staffs, but we decided
+                * it is best to silently accept it elsewhere. For example,
+                * you might want to set it in score context to apply to all
+                * the 1-line staffs there are. */
+               (void) do_assign(var, value, 0, 1,
+                               C_SCORE | C_STAFF | C_VOICE, NO,
+                               "ontheline", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->ontheline) );
+               break;
+
+       case WARN:
+               (void) do_assign(var, value, 0, 1,
+                               C_SCORE, NO, "warn", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->warn) );
+               break;
+
+       case NUMBERMRPT:
+               (void) do_assign(var, value, 0, 1,
+                               C_SCORE | C_STAFF, NO, "numbermrpt", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->numbermrpt) );
+               break;
+
+       case PRINTMULTNUM:
+               (void) do_assign(var, value, 0, 1,
+                               C_SCORE | C_STAFF, NO, "printmultnum", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->printmultnum) );
+               break;
+
+       case RESTSYMMULT:
+               (void) do_assign(var, value, 0, 1,
+                               C_SCORE | C_STAFF, NO, "restsymmult", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->restsymmult) );
+               break;
+
+       default:
+               pfatal("bad parameter name\n");
+               break;
+       }
+}
+\f
+
+/* do all the error checks for an int variable. If it passes all checks,
+ * set the used flag to YES and return YES. If something fails, return NO. */
+/* Checks are: must be within range, must be in valid context, the MAINLL
+ * struct passed must be non-NULL, and if the pow2 flag is YES, the value
+ * must be a power of two. Also give warning if field already used.  Getting
+ * a null pointer is not fatal--it can happen if user tried to do something
+ * in the wrong context. */
+
+static int
+do_assign(var, value, min, max, cont, empty_value, name, mainll_item_p, ptr2dest)
+
+int var;                       /* which variable to set */
+int value;                     /* what to set it to */
+int min;                       /* minimum valid value */
+int max;                       /* maximum valid value */
+int cont;                      /* valid context(s)  (bitmap) */
+int empty_value;               /* if NO, value must be strictly within the
+                                * given min/max. If != NO, it is an extra
+                                * value, outside the min/max range, that
+                                * is legal, and indicates
+                                * user set the value to empty */
+char *name;                    /* of internal variable, for error messages */
+struct MAINLL *mainll_item_p;  /* which structure to set it in */
+short *ptr2dest;               /* the address of the variable to be set */
+
+{
+       char fullname[50];      /* name + " parameter" */
+       if (mainll_item_p == (struct MAINLL *) 0) {
+               l_yyerror(Curr_filename, yylineno, "wrong context for setting %s",
+                               name);
+               return(NO);
+       }
+       (void) sprintf(fullname, parmformat, name);
+       if (contextcheck(cont, fullname) == NO) {
+               return(NO);
+       }
+
+       /* exclaim if already set in this SSV */
+       used_check(mainll_item_p, var, name);
+
+       /* do the checks */
+       if (empty_value != NO && erangecheck(value, min, max, empty_value, name) == NO) {
+               return(NO);
+       }
+       else if (empty_value == NO && rangecheck(value, min, max, name) == NO) {
+               return(NO);
+       }
+       /* passed all the checks-- assign and mark it as used */
+       mainll_item_p->u.ssv_p->used[var] = YES;
+       *ptr2dest = (short) value;
+       return(YES);
+}
+\f
+
+/* do assignment of float type SSV variables */
+
+void
+assign_float(var, value, mainll_item_p)
+
+int var;                       /* which variable to set */
+double value;                  /* what to set it to */
+struct MAINLL *mainll_item_p;  /* where to store info */
+
+{
+
+       /* all of these things can only go into score/staff sorts of things,
+        * not head/foot. If we are in a head/foot, the MAINLL will be null */
+       if (mainll_item_p == 0 || Context == C_MUSIC) {
+               yyerror("trying to set parameter value in wrong context");
+               return;
+       }
+
+       debug(4, "assign_float file=%s line=%d var=%d  value=%f",
+               mainll_item_p->inputfile, mainll_item_p->inputlineno, var, value);
+
+       /* some changes are only allowed before music data is entered */
+       if (Got_some_data == YES) {
+               switch (var) {
+               case TOPMARGIN:
+               case BOTMARGIN:
+               case LEFTMARGIN:
+               case RIGHTMARGIN:
+                       chg_too_late( "margin");
+                       break;
+               case SCALE_FACTOR:
+                       chg_too_late( "scale");
+                       break;
+               case PAGEHEIGHT:
+               case PAGEWIDTH:
+                       chg_too_late( "page size");
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       /* if pagesize minus the margins get too small (or even worse,
+        * negative), we better complain */
+       switch (var) {
+       case TOPMARGIN:
+       case BOTMARGIN:
+       case LEFTMARGIN:
+       case RIGHTMARGIN:
+       case PAGEHEIGHT:
+       case PAGEWIDTH:
+               chkmargin(Score.topmargin, Score.botmargin, Score.leftmargin,
+                                       Score.rightmargin);
+               break;
+       default:
+               break;
+       }
+
+       switch (var) {
+
+       case TOPMARGIN:
+               if (do_fassign(var, (double) value,
+                               (double) ADJUST4UNITS(MINVMARGIN),
+                               (double) ADJUST4UNITS(Score.pageheight - MIN_USABLE_SPACE),
+                               C_SCORE, "topmargin", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->topmargin) )
+                               == YES) {
+                       ADJUST2INCHES(mainll_item_p->u.ssv_p->topmargin)
+
+                       /* put in score so we can check for margins exceeding paper size */
+                       Score.topmargin = mainll_item_p->u.ssv_p->topmargin;
+               }
+               break;
+
+       case BOTMARGIN:
+               if (do_fassign(var, (double) value,
+                               (double) ADJUST4UNITS(MINVMARGIN),
+                               (double) ADJUST4UNITS(Score.pageheight - MIN_USABLE_SPACE),
+                               C_SCORE, "bottommargin", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->botmargin) )
+                               == YES) {
+                       ADJUST2INCHES(mainll_item_p->u.ssv_p->botmargin)
+                       Score.botmargin = mainll_item_p->u.ssv_p->botmargin;
+               }
+               break;
+
+       case LEFTMARGIN:
+               if (do_fassign(var, (double) value,
+                               (double) ADJUST4UNITS(MINHMARGIN),
+                               (double) ADJUST4UNITS(Score.pagewidth - MIN_USABLE_SPACE),
+                               C_SCORE, "leftmargin", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->leftmargin) )
+                               == YES) {
+                       ADJUST2INCHES(mainll_item_p->u.ssv_p->leftmargin)
+                       Score.leftmargin = mainll_item_p->u.ssv_p->leftmargin;
+               }
+               break;
+
+       case RIGHTMARGIN:
+               if (do_fassign(var, (double) value,
+                               (double) ADJUST4UNITS(MINHMARGIN),
+                               (double) ADJUST4UNITS(Score.pagewidth - MIN_USABLE_SPACE),
+                               C_SCORE, "rightmargin", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->rightmargin) )
+                               == YES) {
+                       ADJUST2INCHES(mainll_item_p->u.ssv_p->rightmargin)
+                       Score.rightmargin = mainll_item_p->u.ssv_p->rightmargin;
+               }
+               break;
+
+       case PACKFACT:
+               (void) do_fassign(var, (double) value,
+                               (double) MINPACKFACT, (double) MAXPACKFACT,
+                               C_SCORE, "packfact", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->packfact) );
+               break;
+
+       case PACKEXP:
+               (void) do_fassign(var, (double) value,
+                               (double) MINPACKEXP, (double) MAXPACKEXP,
+                               C_SCORE, "packexp", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->packexp) );
+               break;
+
+       case SCALE_FACTOR:
+               (void) do_fassign(var, (double) value,
+                               (double) MINSCALE, (double) MAXSCALE,
+                               C_SCORE, "scale factor", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->scale_factor) );
+               break;
+
+       case STAFFSCALE:
+               (void) do_fassign(var, (double) value,
+                               (double) MINSTFSCALE, (double) MAXSTFSCALE,
+                               C_SCORE | C_STAFF, "staffscale", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->staffscale) );
+               break;
+
+       case GRIDSCALE:
+               (void) do_fassign(var, (double) value,
+                               (double) MINGRIDSCALE, (double) MAXGRIDSCALE,
+                               C_SCORE | C_STAFF, "gridscale", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->gridscale) );
+               break;
+
+       case PAGEHEIGHT:
+               if (do_fassign(var, (double) value,
+                               (double) ADJUST4UNITS(MINPAGEHEIGHT),
+                               (double) ADJUST4UNITS(MAXPAGEHEIGHT),
+                               C_SCORE, "pageheight", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->pageheight) )
+                               == YES) {
+                       ADJUST2INCHES(mainll_item_p->u.ssv_p->pageheight)
+                       Score.pageheight = mainll_item_p->u.ssv_p->pageheight;
+               }
+               break;
+
+       case PAGEWIDTH:
+               if (do_fassign(var, (double) value,
+                               (double) ADJUST4UNITS(MINPAGEWIDTH),
+                               (double) ADJUST4UNITS(MAXPAGEWIDTH),
+                               C_SCORE, "pagewidth", mainll_item_p,
+                               &(mainll_item_p->u.ssv_p->pagewidth) )
+                               == YES) {
+                       ADJUST2INCHES(mainll_item_p->u.ssv_p->pagewidth)
+                       Score.pagewidth = mainll_item_p->u.ssv_p->pagewidth;
+               }
+               break;
+
+       case LYRICSALIGN:
+               (void) do_fassign(var, (double) value,
+                       (double) MINLYRICSALIGN,
+                       (double) MAXLYRICSALIGN,
+                       C_SCORE | C_STAFF, "lyricsalign", mainll_item_p,
+                       &(mainll_item_p->u.ssv_p->lyricsalign) );
+               break;
+
+       case PAD:
+               (void) do_fassign(var, (double) value,
+                       (double) MINPAD,
+                       (double) MAXPAD,
+                       C_SCORE | C_STAFF | C_VOICE, "pad", mainll_item_p,
+                       &(mainll_item_p->u.ssv_p->pad) );
+               /* What the user calls zero means notes can
+                * just touch, but internally we want zero to mean the
+                * default of 1 point of padding, so adjust. */
+               mainll_item_p->u.ssv_p->pad -= POINT;
+               break;
+
+       case STEMLEN:
+               (void) do_fassign(var, (double) value,
+                       (double) MINSTEMLEN,
+                       (double) MAXSTEMLEN,
+                       C_SSV, "stemlen", mainll_item_p,
+                       &(mainll_item_p->u.ssv_p->stemlen) );
+               break;
+
+
+       case STEMSHORTEN:
+               (void) do_fassign(var, (double) value,
+                       (double) MINSTEMSHORTEN,
+                       (double) MAXSTEMSHORTEN,
+                       C_SSV, "stemshorten", mainll_item_p,
+                       &(mainll_item_p->u.ssv_p->stemshorten) );
+               break;
+
+       default:
+               pfatal("invalid float parameter");
+               break;
+       }
+}
+
+\f
+
+/* Handle parameters that have two float numbers as their value */
+
+void
+assign_2floats(var, value1, value2, mainll_item_p)
+
+int var;                       /* which variable to set */
+double value1, value2;         /* which values to set */
+struct MAINLL *mainll_item_p;  /* where to store info */
+
+{
+       switch (var) {
+
+       case BEAMSLOPE:
+               /* First float value is the factor */
+               if (do_fassign(var, (double) value1,
+                       (double) MINBEAMFACT,
+                       (double) MAXBEAMFACT,
+                       C_SCORE | C_STAFF | C_VOICE, "beamslope factor",
+                       mainll_item_p,
+                       &(mainll_item_p->u.ssv_p->beamfact) ) == YES) {
+
+                       /* Fool do_fassign into thinking we haven't set the used
+                        * flag yet. This is a little kludgy... */
+                       mainll_item_p->u.ssv_p->used[var] = NO;
+
+                       /* Second value is the max angle in degrees */
+                       (void) do_fassign(var, value2,
+                                       (double) MINBEAMMAX,
+                                       (double) MAXBEAMMAX,
+                                       C_SCORE | C_STAFF | C_VOICE,
+                                       "beamslope maximum slope angle",
+                                       mainll_item_p,
+                                       &(mainll_item_p->u.ssv_p->beammax) );
+               }
+               break;
+
+       default:
+               pfatal("bad var value for assign_2floats %d", var);
+               /*NOTREACHED*/
+               break;
+       }
+}
+\f
+
+/* If user tries to change something that can only be changed before music
+ * data is entered, but music has been entered, print error message. */
+
+static void
+chg_too_late(var_name)
+
+char *var_name;
+
+{
+       if (Got_some_data == YES) {
+               l_yyerror(Curr_filename, yylineno,
+                       "Can't change %s after music or block data has been entered",
+                       var_name);
+       }
+}
+\f
+
+/* Do error checks for a float variable. If it passes all checks,
+ * set the used flag to YES and return YES.
+ * If something fails check, return NO.
+ * Checks are: value within range, valid context, and MAINLL struct pointer
+ * passed non-NULL.
+ * Also give warning if field already used.
+ */
+
+static int
+do_fassign(var, value, min, max, cont, name, mainll_item_p, ptr2dest)
+
+int var;                       /* which variable to set */
+double value;                  /* what to set it to */
+double min;                    /* minimum valid value */
+double max;                    /* maximum valid value */
+int cont;                      /* valid context(s) (bitmap) */
+char *name;                    /* for error messages */
+struct MAINLL *mainll_item_p;  /* which structure to set it in */
+float *ptr2dest;               /* pointer to the float variable
+                                * to be assigned */
+
+{
+       char fullname[50];      /* name + " parameter" */
+
+       if (mainll_item_p == (struct MAINLL *) 0) {
+               l_yyerror(Curr_filename, yylineno, "wrong context for setting %s",                              name);
+               return(NO);
+       }
+       (void) sprintf(fullname, parmformat, name);
+       if ( contextcheck(cont, fullname) == NO) {
+               return(NO);
+       }
+
+       /* exclaim if already set in this SSV */
+       used_check(mainll_item_p, var, name);
+
+       /* do checks */
+       if (frangecheck(value, min, max, name) == NO) {
+               return(NO);
+       }
+       else {
+               /* passed all the checks-- assign and mark it as used */
+               mainll_item_p->u.ssv_p->used[var] = YES;
+               *ptr2dest = value;
+               return(YES);
+       }
+}
+\f
+
+/* assign value to vscheme variable */
+
+void
+assign_vscheme(numvoices, vtype, mainll_item_p)
+
+int numvoices;                 /* 1, 2, or 3 */
+int vtype;                     /* V_1, V_2FREESTEM, or V_2OPSTEM. For 3 voice
+                                * case, this is still one of the V_2* values,
+                                * and in that case it specifies whether
+                                * the stems are free or opposing,
+                                * with the numvoices indicating the 3 */
+struct MAINLL *mainll_item_p;  /* where to assign it */
+
+{
+       /* check for proper context */
+       if (contextcheck(C_SCORE | C_STAFF, "vscheme parameter") == NO) {
+               return;
+       }
+
+       /* exclaim if already set in this SSV */
+       used_check(mainll_item_p, VSCHEME, "vscheme");
+
+       if (rangecheck(numvoices, MINVOICES, MAXVOICES, "vscheme value") == NO) {
+               return;
+       }
+
+       /* check for valid combination */
+       if ( (numvoices == 1) && (vtype != V_1) ) {
+               yyerror("can't have 'o' or 'f' qualifier when vscheme=1");
+               return;
+       }
+
+       if ( (numvoices == 2 || numvoices == 3) && (vtype == V_1) ) {
+               yyerror("'o' or 'f' qualifier required when vscheme=2 or vscheme=3");
+               return;
+       }
+
+       /* The 3 voice things are really just the 2 voice ones, but a third
+        * voice is allowed. They get passed in as V_2*, so fix that */
+       if (numvoices == 3) {
+               if (vtype == V_2FREESTEM) {
+                       vtype = V_3FREESTEM;
+               }
+               else if (vtype == V_2OPSTEM) {
+                       vtype = V_3OPSTEM;
+               }
+       }
+
+       /* set variable to requested value */
+       mainll_item_p->u.ssv_p->vscheme = (short) vtype;
+       mainll_item_p->u.ssv_p->used[VSCHEME] = YES;
+
+       asgnssv(mainll_item_p->u.ssv_p);
+}
+\f
+
+/* assign value to voicecombine parameter */
+
+void
+assign_vcombine(qualifier, mainll_p)
+
+int qualifier;
+struct MAINLL * mainll_p;
+
+{
+       short listed[MAXVOICES + 1];    /* If user mentioned the voice */
+       struct RANGELIST * curr_p;      /* walk through list of voices */
+       int v;                          /* voice */
+       int offset;                     /* index into vcombine array */
+
+
+       if (contextcheck(C_SCORE | C_STAFF, "voicecombine parameter") == NO) {
+               return;
+       }
+       used_check(mainll_p, VCOMBINE, "voicecombine");
+
+       /* Clear list of voices mentioned by user,
+        * and initialize list of voices to combine to none. */
+       for (v = 1; v <= MAXVOICES; v++) {
+               listed[v] = NO;
+               mainll_p->u.ssv_p->vcombine[v-1] = 0;
+       }
+
+       /* We start filling in at beginning of vcombine array */
+       offset = 0;
+
+       /* Add the specified voices in input order to SSV vcombine array */
+       for (curr_p = Vnorange_p; curr_p != 0; curr_p = curr_p->next) {
+               /* add voices into voice combine list after error checks */
+               for (v = curr_p->begin; v <= curr_p->end; v++) {
+                       if (listed[v] == YES) {
+                               l_yyerror(Curr_filename, yylineno,
+                                       "voice %d specified more than once", v);
+                       }
+                       if (offset >= MAXVOICES) {
+                               /* The only way this can happen is if user
+                                * specified at least one voice more than once,
+                                * and we would have already reported that
+                                * above, so no need to print another error.
+                                * But we must not attempt to write beyond
+                                * end of vcombine array, so jump out of loop.
+                                */
+                               break;
+                       }
+                       mainll_p->u.ssv_p->vcombine[offset++] = v;
+                       listed[v] = YES;
+               }
+       }
+
+       free_vnorange();
+       mainll_p->u.ssv_p->vcombinequal = (short) qualifier;
+       mainll_p->u.ssv_p->used[VCOMBINE] = YES;
+       /* Since voicecombine is relatively rare, we set a flag if it is
+        * ever used. If flag is not set, all the voicecombine placement
+        * code can be skipped entirely. If turning off or only a
+        * single voice is specified, that doesn't really count as being used.
+        */
+       if (offset > 1) {
+               Vcombused = YES;
+       }
+}
+\f
+
+/* assign key signature */
+
+void
+assign_key(num, acc, is_minor, mainll_item_p)
+
+int num;                       /* number of sharps or flats */
+int acc;                       /* # or & for sharp or flat */
+int is_minor;                  /* YES or NO */
+struct MAINLL *mainll_item_p;  /* where to assign */
+
+{
+       if (contextcheck( C_SCORE | C_STAFF, "key parameter") == NO) {
+               return;
+       }
+
+       /* exclaim if already set in this SSV */
+       used_check(mainll_item_p, SHARPS, "key");
+
+       /* error check. Must be no more than 7 flats or sharps, and can only
+        * be set in score or staff contexts */
+       if (rangecheck(num, 0, MAXSHARPS,
+                       "number of flats or sharps in key signature") == NO) {
+               return;
+       }
+
+       /* looks okay, so make assignment */
+       /* NOTE: num of flats == negative number of sharps */
+       mainll_item_p->u.ssv_p->sharps = num * (acc == '#' ? 1 : -1);
+       mainll_item_p->u.ssv_p->used[SHARPS] = YES;
+       mainll_item_p->u.ssv_p->is_minor = (short) is_minor;
+
+       asgnssv(mainll_item_p->u.ssv_p);
+}
+\f
+
+/* Assign a string to an SSV variable. It just assigns the pointer for labels,
+ * so temporary strings should be copied before being passed.
+ * For NOTEHEADS, it parses the string and saves the numeric internal numbers.
+ */
+
+void
+assign_string(var, string, mainll_item_p)
+
+int var;                       /* LABEL, LABEL2, or NOTEHEADS */
+char *string;                  /* the string to assign */
+struct MAINLL *mainll_item_p;  /* where to assign it */
+
+{
+       int n;                  /* note shape index */
+       char namebuff[100];     /* For note shape names. Builtin names are
+                                * fairly short, but user could define longer
+                                * ones. We figure 100 should be plenty,
+                                * and ufatal if they try to go longer. */
+       int nameleng;           /* strlen of a name shape name */
+       int context;            /* which context to check */
+       char *error_msg;        /* what to print in error message */
+
+       if (var == NOTEHEADS) {
+               context = C_SSV;
+               error_msg = "noteheads parameter";
+       }
+       else {
+               context = C_SCORE | C_STAFF;
+               error_msg = (var == LABEL ? "label parameter"
+                                       : "label2 parameter");
+       }
+
+       if (contextcheck(context, error_msg) == YES) {
+
+               /* get string into proper internal format */
+               (void) fix_string(string, string[0], string[1],
+                                       Curr_filename, yylineno);
+
+               switch (var) {
+
+               case LABEL:
+                       used_check(mainll_item_p, var, "label");
+                       mainll_item_p->u.ssv_p->label = string;
+                       break;
+
+               case LABEL2:
+                       used_check(mainll_item_p, var, "label2");
+                       mainll_item_p->u.ssv_p->label2 = string;
+                       break;
+
+               case NOTEHEADS:
+                       if (is_tab_staff(mainll_item_p->u.ssv_p->staffno) == YES
+                                       && strcmp(string+2, "allx") != 0
+                                       && strcmp(string+2, "norm") != 0) {
+                               warning("noteheads parameter ignored on tablature staffs (unless allx or norm)");
+                       }
+
+                       /* skip past font/size */
+                       string += 2;
+                       /* split into tokens */
+                       for (n = 0; n < 7; n++) {
+                               /* skip past white space */
+                               while ( isspace(*string) ) {
+                                       string++;
+                               }
+
+                               if ( *string == '\0') {
+                                       break;
+                               }
+
+                               nameleng = strcspn(string, " \t\r\n");
+                               if (nameleng > sizeof(namebuff) - 1) {
+                                       ufatal("note head name too long");
+                               }
+                               strncpy(namebuff, string, nameleng);
+                               namebuff[nameleng] = '\0';
+                               if ((mainll_item_p->u.ssv_p->noteheads[n] =
+                                                       get_shape_num(namebuff))
+                                                       == HS_UNKNOWN) {
+                                       l_yyerror(Curr_filename, yylineno,
+                                               "'%s' is not a valid headshape name",
+                                               namebuff);
+                               }
+                               string += nameleng;
+                       }
+                       if (n == 1) {
+                               /* copy same shape for all 7 */
+                               for (  ; n < 7; n++) {
+                                       mainll_item_p->u.ssv_p->noteheads[n] =
+                                       mainll_item_p->u.ssv_p->noteheads[0];
+                               }
+                       }
+
+                       /* Skip past trailing white space, and make sure we got
+                        * right number of tokens. */
+                       while ( isspace(*string) ) {
+                               string++;
+                       }
+                       if (n != 7 || *string != '\0') {
+                               yyerror("wrong number of notehead names: expecting either 1 or 7");
+                       }
+                       break;
+               default:
+                       pfatal("invalid string variable type");
+                       /*NOTREACHED*/
+                       break;
+               }
+
+               mainll_item_p->u.ssv_p->used[var] = YES;
+       }
+}
+\f
+
+/* make a copy of a string and return pointer to it,
+ * or return NULL if string was NULL. The incoming string is a regular C-style
+ * string. The returned string is 2 bytes longer, with the font in the first
+ * byte, size in the second byte, and the copy of the original string in the
+ * remainder. */
+
+char *
+copy_string(string, font, size)
+
+char *string;          /* make a copy of this string */
+int font;              /* use this font */
+int size;              /* use this point size */
+
+{
+       char *copy;     /* pointer to new copy of string */
+
+
+       if (string == (char *) 0) {
+               return (string);
+       }
+
+       /* need 2 extra bytes at beginning for font and size,
+        * and 1 at end for '\0' */
+       MALLOCA(char, copy, strlen(string) + 3);
+
+       /* fill in font and size in first 2 bytes */
+       *copy = (char) font;
+       *(copy + 1) = (char) size;
+
+       /* copy the string and return pointer to copy */
+       (void) strcpy(copy + 2, string);
+       return(copy);
+}
+\f
+
+/* Assign time signature in SSV.
+ * Derives the effective numerator/denominator and the RATIONAL time value
+ * from the timerep, and fills them in the SSV. If there are alternating
+ * time signatures, that will be for the first of them, and a pointer
+ * to the remaining signature(s) will be returned via next_alternation_p.
+ * If there are additive time signatures, the effective num/den will
+ * be based on the largest denominator.
+ */
+
+void
+assign_timesig(mainll_item_p, visibility, next_alternation_p)
+
+struct MAINLL *mainll_item_p;   /* SSV to assign time signature in */
+int visibility;                        /* YES, NO, or EACHMEAS */
+char **next_alternation_p;     /* If this time signature includes alternating
+                                * time signatures, as in  3/4  4/4,
+                                * this will be filled in with a pointer to
+                                * where the next alternate time signature
+                                * begins in the timerep. If there are no
+                                * alternating time signatures, it will be
+                                * filled by a null pointer. */
+
+{
+       struct SSV *ssv_p;              /* mainll_item_p->u.ssv_p */
+       RATIONAL curr_value;            /* There may be compound time
+                                        * signatures, and each of those
+                                        * may have multiple numerator
+                                        * components, so this is used for
+                                        * getting value of one fraction */
+       int biggest_denominator;        /* for calculating effective
+                                        * numerator and denominator */
+       char *t;                        /* to walk through timerep */
+
+
+       if (contextcheck(C_SCORE, "time parameter") == NO) {
+               return;
+       }
+
+       /* exclaim if already set in this SSV */
+       used_check(mainll_item_p, TIME, "time signature");
+
+       ssv_p = mainll_item_p->u.ssv_p;
+
+       ssv_p->timevis = visibility;
+
+       curr_value = Zero;
+       ssv_p->time = Zero;
+       biggest_denominator = 0;
+       *next_alternation_p = 0;
+
+       for (t = ssv_p->timerep; *t != TSR_END; t++) {
+               if (*t == TSR_CUT) {
+                       curr_value.n = 2;
+                       curr_value.d = 2;
+               }
+               else if (*t == TSR_COMMON) {
+                       curr_value.n = 4;
+                       curr_value.d = 4;
+               }
+               else if (*t == TSR_SLASH) {
+                       curr_value.d = *++t;
+               }
+               else if (*t == TSR_ALTERNATING) {
+                       *next_alternation_p = ++t;
+                       break;
+               }
+               else if (*t == TSR_ADD) {
+                       continue;
+               }
+               else {
+                       curr_value.n += *t;
+                       continue;
+               }
+               biggest_denominator = MAX(biggest_denominator, curr_value.d);
+               rred(&curr_value);
+               ssv_p->time = radd(ssv_p->time, curr_value);
+               curr_value = Zero;
+       }
+
+       /* If there were mixed denominators, use the biggest for the
+        * purpose of effective numerator and denominator */
+       if (biggest_denominator > ssv_p->time.d) {
+               ssv_p->timenum = ssv_p->time.n * (biggest_denominator / ssv_p->time.d);
+       }
+       else {
+               ssv_p->timenum = ssv_p->time.n;
+       }
+       ssv_p->timeden = biggest_denominator;
+
+       /* mark time as used */
+       mainll_item_p->u.ssv_p->used[TIME] = YES;
+
+       /* We have to set this for real immediately, since beamstyle and
+        * other things may need to have it set */
+       asgnssv(mainll_item_p->u.ssv_p);
+
+       if (mainll_item_p->u.ssv_p->used[BEAMSTLIST] == YES) {
+               l_warning(Curr_filename, yylineno,
+                               "changing time signature clears beamstyle");
+               /* have to actually clear it here, because otherwise it
+                * would still get assigned in ssv.c because beamstyle is
+                * done after the code for time signature */
+               mainll_item_p->u.ssv_p->used[BEAMSTLIST] = NO;
+               mainll_item_p->u.ssv_p->nbeam = 0;
+               if (mainll_item_p->u.ssv_p->beamstlist != (RATIONAL *) 0) {
+                       FREE(mainll_item_p->u.ssv_p->beamstlist);
+               }
+       }
+}
+\f
+
+/* assign a font variable (FONT, LYRICSFONT, FONTFAMILY, LYRICSFAMILY) */
+
+void
+set_font(var, value, mainll_item_p)
+
+int var;                       /* which variable to set */
+int value;                     /* which font to set it too */
+struct MAINLL *mainll_item_p;  /* where to assign it in main list */
+
+{
+       char *varname;  /* name of variable, for error messages */
+       char fullname[50];      /* varname + " parameter" */
+
+
+       /* determine the name of the variable, for error messages */
+       switch(var) {
+       case FONT:
+               varname = "font";
+               break;
+       case LYRICSFONT:
+               varname = "lyricsfont";
+               break;
+       case MEASNUMFONT:
+               varname = "measnumfont";
+               break;
+       case FONTFAMILY:
+               varname = "fontfamily";
+               break;
+       case LYRICSFAMILY:
+               varname = "lyricsfontfamily";
+               break;
+       case MEASNUMFAMILY:
+               varname = "measnumfontfamily";
+               break;
+       default:
+               pfatal("bad font variable");
+               /*NOTREACHED*/
+               return;
+       }
+       (void) sprintf(fullname, parmformat, varname);
+
+       /* if being called from SSV, exclaim if already set */
+       if ((Context & C_SSV) != 0) {
+               used_check(mainll_item_p, var, varname);
+       }
+
+       switch (var) {
+
+       case FONT:
+               Curr_font = value;
+
+               if (Context & C_BLOCKHEAD) {
+                       /* Special case. In block, we just
+                        * keep track of the current font */
+                       return;
+               }
+               else if (contextcheck(C_SCORE | C_STAFF, fullname) == YES) {
+                       mainll_item_p->u.ssv_p->font = (short) value;
+               }
+               else {
+                       return;
+               }
+
+               break;
+
+       case FONTFAMILY:
+               Curr_family = value;
+
+               if (Context & C_BLOCKHEAD) {
+                       /* Special case. In block, we just
+                        * keep track of the current font */
+                       return;
+               }
+               else if (contextcheck(C_SCORE | C_STAFF, fullname) == YES) {
+                       mainll_item_p->u.ssv_p->fontfamily = (short) value;
+               }
+               else {
+                       return;
+               }
+
+               break;
+
+       case LYRICSFONT:
+               if (contextcheck(C_SCORE | C_STAFF, fullname) == YES) {
+                       mainll_item_p->u.ssv_p->lyricsfont = (short) value;
+
+                       /* assign immediately in case there is a following
+                        * font family change that needs to read it */
+                       mainll_item_p->u.ssv_p->used[var] = YES;
+                       asgnssv(mainll_item_p->u.ssv_p);
+                       setlyrfont(mainll_item_p->u.ssv_p->staffno, value);
+                       return;
+               }
+               else {
+                       return;
+               }
+
+               /*NOTREACHED*/
+               break;
+
+       case LYRICSFAMILY:
+               if (contextcheck(C_SCORE | C_STAFF, fullname) == YES) {
+                       mainll_item_p->u.ssv_p->lyricsfamily = (short) value;
+                       /* assign immediately, so we can reset all
+                        * lyrics info for this staff */
+                       mainll_item_p->u.ssv_p->used[var] = YES;
+                       asgnssv(mainll_item_p->u.ssv_p);
+
+                       setlyrfont(mainll_item_p->u.ssv_p->staffno,
+                               svpath(mainll_item_p->u.ssv_p->staffno,
+                               LYRICSFONT)->lyricsfont);
+                       return;
+               }
+               else {
+                       return;
+               }
+
+               /*NOTREACHED*/
+               break;
+
+       case MEASNUMFONT:
+               if (contextcheck(C_SCORE, fullname) == YES) {
+                       mainll_item_p->u.ssv_p->measnumfont = (short) value;
+               }
+               else {
+                       return;
+               }
+               break;
+
+       case MEASNUMFAMILY:
+               if (contextcheck(C_SCORE, fullname) == YES) {
+                       mainll_item_p->u.ssv_p->measnumfamily = (short) value;
+               }
+               else {
+                       return;
+               }
+               break;
+
+       default:
+               pfatal("unknown font variable");
+               break;
+       }
+
+       mainll_item_p->u.ssv_p->used[var] = YES;
+}
+\f
+
+/* set number of stafflines and whether or not to print clef. Number of
+ * lines must be 1 or 5, unless it's a tablature staff,
+ * in which case it can be anything from MINTABLINES to MAXTABLINES.
+ * In any case, it must be set before any music data. */
+
+void
+asgn_stafflines(numlines, printclef, mainll_item_p)
+
+int numlines;  /* 1 or 5 for normal, or MINTABLINES to MAXTABLINES for tablature */
+int printclef; /* SS_* */
+struct MAINLL *mainll_item_p;  /* where to set value */
+
+{
+       int is_tab;     /* YES if is tablature staff */
+       int staff_index;
+
+       
+       if (mainll_item_p == (struct MAINLL *) 0) {
+               /* must be in here due to some user syntax error */
+               return;
+       }
+
+       is_tab = is_tablature_staff(mainll_item_p->u.ssv_p);
+       if (is_tab == YES) {
+               if (contextcheck(C_STAFF, "stafflines=tab") == NO) {
+                       return;
+               }
+       }
+       else {
+               if (contextcheck(C_SCORE | C_STAFF, "stafflines parameter") == NO) {
+                       return;
+               }
+       }
+
+       /* exclaim if already set in this SSV */
+       used_check(mainll_item_p, STAFFLINES, "stafflines");
+
+       if (is_tab == YES) {
+               /* is a tablature staff */
+               (void) rangecheck(numlines, MINTABLINES, MAXTABLINES,
+                                       "number of tab strings specified");
+       }
+       else {
+               /* not a tablature staff */
+               if (numlines != 5 && numlines != 1) {
+                       yyerror("stafflines must be 1 or 5");
+               }
+       }
+
+
+       mainll_item_p->u.ssv_p->stafflines = (short) numlines;
+
+       /* single line never has clef except the drum clef,
+        * so if user didn't explictly set 'n' we do it for them */
+       if (numlines == 1 && printclef == SS_NORMAL) {
+               printclef = NO;
+       }
+       mainll_item_p->u.ssv_p->printclef = (short) printclef;
+       mainll_item_p->u.ssv_p->used[STAFFLINES] = YES;
+
+       /* index into Staff array is staffno - 1 */
+       staff_index = mainll_item_p->u.ssv_p->staffno - 1;
+
+       /* need to do extra consistency check for tablature staffs */
+       if (is_tab == YES) {
+               
+               if (staff_index == 0) {
+                       yyerror("staff 1 can't be a tablature staff");
+               }
+               else {
+                       if (is_tablature_staff( &(Staff[staff_index - 1]) ) == YES
+                               || (staff_index < MAXSTAFFS - 1 &&
+                               is_tablature_staff( &(Staff[staff_index + 1]) )
+                               == YES) ) {
+                           yyerror("can't have two consecutive tablature staffs");
+                       }
+                       if (svpath(mainll_item_p->u.ssv_p->staffno - 1,
+                                       STAFFLINES)->stafflines != 5) {
+                               yyerror("staff before a tablature staff must be a 5-line staff");
+                       }
+               }
+       }
+       else {
+               /* if trying to establish a non-5-line non-tablature staff,
+                * and it's not the bottom staff, and the staff below is a
+                * tablature staff, that's a no-no */
+               if (numlines != 5 && staff_index < MAXSTAFFS - 1 &&
+                               is_tablature_staff( &(Staff[staff_index + 1]) )
+                               == YES) {
+                       yyerror("staff before a tablature staff must be a 5-line staff");
+               } 
+       }
+
+       /* assign, so we can do error checking on tablature staffs
+        * for future SSVs that we process */
+       asgnssv(mainll_item_p->u.ssv_p);
+}
+\f
+
+/* When the input contains a rangelist, we need to allocate some space for
+ * the information. Allocate an array of length CHUNK. Set the Ss_count to start
+ * filling in element 0, and mark the Ss_length as CHUNK. As we add elements,
+ * Ss_count will be incremented, and the array size enlarged if it overflows.
+ */
+
+void
+new_staffset()
+
+{
+       CALLOC(STAFFSET, Curr_staffset_p, CHUNK);
+
+       Ss_count = 0;
+       Ss_length = CHUNK;
+}
+\f
+
+/* add information about one staffset, at the current offset in the list,
+ * re-allocating additional space if necessary */
+
+void
+add_staffset(start, end, label1, label2)
+
+int start, end;                /* of the range */
+char *label1, *label2; /* malloc-ed copies of labels for the range, or NULL */
+
+{
+       /* Murphey's Law insurance */
+       if (Curr_staffset_p == (struct STAFFSET *) 0) {
+               pfatal("NULL staffset");
+       }
+
+       /* swap if backwards */
+       if ( start > end) {
+               int tmp;
+
+               tmp = start;
+               start = end;
+               end = tmp;
+       }
+
+       /* if we guessed too small, need to make a bigger array */
+       if (Ss_count >= Ss_length) {
+               Ss_length += CHUNK;
+               REALLOC(STAFFSET, Curr_staffset_p, Ss_length);
+       }
+
+       /* fill in values */
+       Curr_staffset_p[Ss_count].topstaff = (short) start;
+       Curr_staffset_p[Ss_count].botstaff = (short) end;
+       if (label1 != (char *) 0) {
+               (void) fix_string(label1, label1[0], label1[1],
+                                       Curr_filename, yylineno);
+       }
+       Curr_staffset_p[Ss_count].label = label1;
+       if (label2 != (char *) 0) {
+               (void) fix_string(label2, label2[0], label2[1],
+                                       Curr_filename, yylineno);
+       }
+       Curr_staffset_p[Ss_count].label2 = label2;
+
+       /* one more item in list */
+       Ss_count++;
+}
+\f
+
+/* When we have collected an entire list of ranges, assign the
+ * list to the appropriate place in the SSV struct.
+ * (Using "set" instead of "assign" for function name because some
+ * people's compilers are too stupid to tell the difference in names
+ * after 8 characters, which would clash with another function name) */
+
+void
+set_staffset(var, mainll_item_p)
+
+int var;                       /* which rangelist to set */
+struct MAINLL *mainll_item_p;  /* which struct to assign it in */
+
+{
+       register int i;         /* index through ranges */
+       short okay = NO;        /* if passed all overlap checks */
+
+
+       /* can only do this in score context */
+       if (contextcheck(C_SCORE, "list of staff ranges") == NO) {
+               return;
+       }
+
+       /* first we need to make sure no ranges are out of range */
+       /* go through the list of ranges */
+       for (i = 0; i < Ss_count; i++) {
+
+               /* range check. Make sure it is within number of staffs that
+                * user specified. Since when we assign the user-specified
+                * number, we make sure that is within MAXSTAFFS, it will
+                * be within the absolute maximum as well.
+                */
+               if (rangecheck(Curr_staffset_p[i].botstaff, 1, Score.staffs,
+                                       "brace/bracket staff number") == NO) {
+                       return;
+               }
+       }
+       
+       /* if explicitly empty, can free space */
+       if (Ss_count == 0) {
+               FREE(Curr_staffset_p);
+       }
+       else {
+               /* we probably have too much space allocated, shed the rest */
+               REALLOC(STAFFSET, Curr_staffset_p, Ss_count);
+
+               /* sort lowest to highest */
+               qsort( (char *) Curr_staffset_p, (unsigned int) Ss_count,
+                                       sizeof(struct STAFFSET), comp_staffset);
+       }
+
+       if (mainll_item_p == (struct MAINLL *) 0) {
+               pfatal("NULL SSV for staffset");
+       }
+
+       /* now assign to appropriate variable */
+       switch (var) {
+
+       case BRACELIST:
+               mainll_item_p->u.ssv_p->bracelist = (Ss_count == 0 ?
+                               (struct STAFFSET *) 0 : Curr_staffset_p);
+               mainll_item_p->u.ssv_p->nbrace = (short) Ss_count;
+               okay = brac_check(Curr_staffset_p, Ss_count,
+                                       Score.bracklist, Score.nbrack);
+               used_check(mainll_item_p, var, "brace");
+               break;
+
+       case BRACKLIST:
+               mainll_item_p->u.ssv_p->bracklist = (Ss_count == 0 ?
+                               (struct STAFFSET *) 0 : Curr_staffset_p);
+               mainll_item_p->u.ssv_p->nbrack = (short) Ss_count;
+               okay = brac_check(Score.bracelist, Score.nbrace,
+                                       Curr_staffset_p, Ss_count);
+               used_check(mainll_item_p, var, "bracket");
+               break;
+
+       default:
+               pfatal("unknown staffset type");
+               break;
+       }
+
+       if (okay == YES) {
+               mainll_item_p->u.ssv_p->used[var] = YES;
+
+               /* assign now, so we can check for overlap */
+               asgnssv(mainll_item_p->u.ssv_p);
+       }
+
+       /* the list has been attached to its permanent place, so
+        * reset the temporary pointer to an empty list */
+       Curr_staffset_p = (struct STAFFSET *) 0;
+       Ss_count = 0;
+}
+\f
+
+/* compare 2 STAFFSETs for sorting using qsort */
+
+static int
+comp_staffset(item1_p, item2_p)
+
+#ifdef __STDC__
+const void *item1_p;   /* the two items to compare */
+const void *item2_p;
+#else
+char *item1_p; /* the two items to compare */
+char *item2_p;
+#endif
+
+{
+       int top1, top2;
+       int bot1, bot2;
+
+       top1 = ((struct STAFFSET *)item1_p)->topstaff;
+       top2 = ((struct STAFFSET *)item2_p)->topstaff;
+       bot1 = ((struct STAFFSET *)item1_p)->botstaff;
+       bot2 = ((struct STAFFSET *)item2_p)->botstaff;
+
+       if (top1 < top2) {
+               return(-1);
+       }
+
+       else if (top1 > top2) {
+               return(1);
+       }
+
+       else if (bot1 < bot2) {
+               return(-1);
+       }
+
+       else if (bot1 > bot2) {
+               return(1);
+       }
+
+       else {
+               return(0);
+       }
+}
+\f
+
+/* allocate an array of TOP_BOT structs for building up a list of bar style
+ * information (which staffs to bar together) */
+
+void
+new_barstlist()
+
+{
+       CALLOC(TOP_BOT, Curr_barstlist_p, CHUNK);
+
+       /* initialize used and allocated lengths */
+       Barst_count = 0;
+       Barst_length = CHUNK;
+}
+\f
+
+/* add a pair of staff numbers to bar style list */
+
+void
+add_barst(start, end)
+
+int start;     /* first staff to bar together */
+int end;       /* last staff to bar together */
+
+{
+       if (Curr_barstlist_p == (struct TOP_BOT *) 0) {
+               pfatal("NULL barstlist");
+       }
+
+       /* swap if backwards */
+       if ( start > end) {
+               int tmp;
+
+               tmp = start;
+               start = end;
+               end = tmp;
+       }
+
+       /* if we guessed too small, make a bigger array */
+       if (Barst_count >= Barst_length) {
+
+               Barst_length += CHUNK;
+
+               REALLOC(TOP_BOT, Curr_barstlist_p, Barst_length);
+       }
+
+       Curr_barstlist_p[Barst_count].top = (short) start;
+       Curr_barstlist_p[Barst_count].bottom = (short) end;
+
+       /* one more item on list */
+       Barst_count++;
+}
+\f
+
+/* When we have collected an entire list of ranges, assign the
+ * list to the appropriate place in the SSV struct */
+
+void
+set_barstlist(mainll_item_p)
+
+struct MAINLL *mainll_item_p;  /* which struct to assign it in */
+
+{
+       register int i, s;              /* index for ranges and staffs */
+       short mentioned[MAXSTAFFS + 1]; /* mark whether each staff occurs in
+                                        * this list somewhere. Element 0 is
+                                        * unused */
+
+
+       if (contextcheck(C_SCORE, "barstyle parameter") == NO) {
+               return;
+       }
+
+       /* exclaim if alrady set in this SSV */
+       used_check(mainll_item_p, BARSTLIST, "barstyle");
+
+       /* first we need to make sure no ranges overlap or are out of range */
+
+       /* initialize that we haven't seen anything yet */
+       for (s = 1; s < MAXSTAFFS + 1; s++) {
+               mentioned[s] = NO;
+       }
+
+       /* go through the list of ranges */
+       for (i = 0; i < Barst_count; i++) {
+
+               /* range check. */
+               if (rangecheck(Curr_barstlist_p[i].bottom, 1, Score.staffs,
+                               "barstyle staff number") == NO) {
+                       continue;
+               }
+               
+               /* fill in each in the range as having been mentioned.
+                * If already mentioned, we have a problem */
+               for (s = Curr_barstlist_p[i].top;
+                                       s <= Curr_barstlist_p[i].bottom; s++) {
+
+                       if (mentioned[s] == YES) {
+                               yyerror("overlapping range in bar list");
+                       }
+
+                       else {
+                               mentioned[s] = YES;
+                       }
+               }
+       }
+       
+       /* if explicitly empty, free space */
+       if (Barst_count == 0) {
+               FREE(Curr_barstlist_p);
+       }
+
+       else {
+               /* we probably have too much space allocated, shed the rest */
+               REALLOC(TOP_BOT, Curr_barstlist_p, Barst_count);
+
+               /* sort lowest to highest */
+               qsort ( (char *) Curr_barstlist_p, (unsigned int) Barst_count,
+                       sizeof(struct TOP_BOT), comp_barst);
+       }
+
+       if (mainll_item_p == (struct MAINLL *) 0) {
+               pfatal("NULL SSV for barstlist");
+       }
+
+       /* fill in data */
+       mainll_item_p->u.ssv_p->nbarst = (short) Barst_count;
+       if (Barst_count > 0) {
+               mainll_item_p->u.ssv_p->barstlist = Curr_barstlist_p;
+       }
+
+       mainll_item_p->u.ssv_p->used[BARSTLIST] = YES;
+
+       /* now that list has been assigned to its proper place,
+        * re-initialize pointer to null to prepare for another list */
+       Curr_barstlist_p = (struct TOP_BOT *) 0;
+       Barst_count = 0;
+}
+\f
+
+/* compare 2 barslist items for sorting using qsort */
+
+static int
+comp_barst(item1_p, item2_p)
+
+#ifdef __STDC__
+const void *item1_p;   /* the two items to compare */
+const void *item2_p;
+#else
+char *item1_p; /* the two items to compare */
+char *item2_p;
+#endif
+
+{
+       if ( ((struct TOP_BOT *)item1_p)->top
+                               < ((struct TOP_BOT *)item2_p)->top) {
+               return(-1);
+       }
+
+       else if ( ((struct TOP_BOT *)item1_p)->top
+                               > ((struct TOP_BOT *)item2_p)->top) {
+               return(1);
+       }
+
+       else {
+               /* actually this should never occur */
+               return(0);
+       }
+}
+\f
+
+/* Initialize and allocate space for beamstyle information */
+
+void
+new_beamlist()
+
+{
+       init_beamlist(&Curr_beamstyle);
+       init_beamlist(&Curr_subbeamstyle);
+       Subbeam_index = -1;
+}
+
+
+/* Initalize a BEAMLIST struct.
+ * Allocate CHUNK entries, and mark that 0 of them are currently used.
+ */
+
+static void
+init_beamlist(beamlist_p)
+
+struct BEAMLIST *beamlist_p;
+
+{
+       MALLOCA(RATIONAL, beamlist_p->list_p, CHUNK);
+       beamlist_p->count = 0;
+       beamlist_p->length = CHUNK;
+}
+\f
+
+/* This function is called at the parenthesis to begin a sub-beam grouping.
+ * It saves the current index into the subbeam list. At the ending parenthesis,
+ * we add up add the subbeam list time values since that saved index.
+ */
+
+void
+begin_subbeam()
+
+{
+       if (Subbeam_index >= 0) {
+               yyerror("Nested sub-beam groups not allowed");
+               return;
+       }
+       Subbeam_index = Curr_subbeamstyle.count;
+}
+
+void
+end_subbeam()
+{
+       RATIONAL tot_time;
+
+       /* Do error checks */
+       if (Subbeam_index < 0) {
+               yyerror("Missing '(' for sub-beam grouping");
+               return;
+       }
+       if (Subbeam_index >= Curr_subbeamstyle.count - 1) {
+               warning("sub-beam grouping needs at least two values");
+       }
+
+       /* Count up all the time values of subbeams that make up the
+        * single outer beam. */
+       for (tot_time = Zero; Subbeam_index < Curr_subbeamstyle.count;
+                                               Subbeam_index++) {
+               tot_time = radd(tot_time, Curr_subbeamstyle.list_p[Subbeam_index]);
+       }
+       add2outerbeam(tot_time);
+       Subbeam_index = -1;
+}
+\f
+
+/* Add an entry to the current beam list */
+
+void
+add_beamlist(value)
+
+RATIONAL value;                /* what to add to beam list */
+
+{
+       /* If we guessed too small, make a bigger array */
+       if (Curr_subbeamstyle.count >= Curr_subbeamstyle.length) {
+               Curr_subbeamstyle.length += CHUNK;
+               REALLOCA(RATIONAL, Curr_subbeamstyle.list_p, Curr_subbeamstyle.length);
+       }
+
+       Curr_subbeamstyle.list_p[Curr_subbeamstyle.count] = value;
+       (Curr_subbeamstyle.count)++;
+
+       /* If not in a subbeam grouping, goes into Curr_beamstyle too */
+       if (Subbeam_index < 0) {
+               add2outerbeam(value);
+       }
+}
+\f
+
+/* Add entry to time values for the outermost beam. In the case of subbeaming,
+ * the value will be the sum of the subbeams values; otherwise it will be
+ * the same as that in the subbeam list.
+ */
+
+static void
+add2outerbeam(value)
+
+RATIONAL value;
+
+{
+       /* If we guessed too small, make a bigger array */
+       if (Curr_beamstyle.count >= Curr_beamstyle.length) {
+               Curr_beamstyle.length += CHUNK;
+               REALLOCA(RATIONAL, Curr_beamstyle.list_p, Curr_beamstyle.length);
+       }
+       Curr_beamstyle.list_p[Curr_beamstyle.count] = value;
+       (Curr_beamstyle.count)++;
+}
+\f
+
+/* Assign current beam list to SSV structure in main list */
+
+void
+set_beamlist(mainll_item_p)
+
+struct MAINLL *mainll_item_p;          /* where to attach list */
+
+{
+       if (contextcheck(C_SSV, "beamstyle parameter") == NO) {
+               return;
+       }
+
+       /* exclaim if already set in this SSV */
+       used_check(mainll_item_p, BEAMSTLIST, "beamstyle");
+
+       /* Shed any extra allocated space */
+       if (Curr_beamstyle.count == 0) {
+               FREE(Curr_beamstyle.list_p);
+               Curr_beamstyle.list_p = 0;
+       }
+       else if (Curr_beamstyle.count < Curr_beamstyle.length) {
+               REALLOCA(RATIONAL, Curr_beamstyle.list_p, Curr_beamstyle.count);
+       }
+       if (Curr_subbeamstyle.count == 0) {
+               FREE(Curr_subbeamstyle.list_p);
+               Curr_subbeamstyle.list_p = 0;
+       }
+       else if (Curr_subbeamstyle.count < Curr_subbeamstyle.length) {
+               REALLOCA(RATIONAL, Curr_subbeamstyle.list_p, Curr_subbeamstyle.count);
+       }
+
+       if (mainll_item_p == (struct MAINLL *) 0) {
+               pfatal("NULL SSV for beamlist");
+       }
+
+       if (Context != C_SCORE && is_tab_staff(mainll_item_p->u.ssv_p->staffno)
+                                       == YES) {
+               yyerror("beamstyle not allowed on tablature staff");
+               return;
+       }
+
+       /* attach to the SSV struct and mark as used */
+       mainll_item_p->u.ssv_p->beamstlist = Curr_beamstyle.list_p;
+       mainll_item_p->u.ssv_p->subbeamstlist = Curr_subbeamstyle.list_p;
+       mainll_item_p->u.ssv_p->nbeam = (short) Curr_beamstyle.count;
+       mainll_item_p->u.ssv_p->nsubbeam = (short) Curr_subbeamstyle.count;
+       mainll_item_p->u.ssv_p->used[BEAMSTLIST] = YES;
+
+       if (Curr_beamstyle.count > 0) {
+               /* make sure time adds up to exactly a measure */
+               RATIONAL tot_time;      /* sum of times in beamstyle list */
+               register int n;
+
+               tot_time = Zero;
+
+               for (n = 0; n < Curr_beamstyle.count; n++) {
+                       tot_time = radd(tot_time, Curr_beamstyle.list_p[n]);
+               }
+
+               if (NE(tot_time, Score.time)) {
+                       yyerror("beam list does not add up to a measure");
+               }
+       }
+
+       /* Mark temporary lists as invalid */
+       Curr_beamstyle.list_p = 0;
+       Curr_subbeamstyle.list_p = 0;
+
+       asgnssv(mainll_item_p->u.ssv_p);
+}
+\f
+
+void
+assign_unit(unittype, mainll_p)
+
+int unittype;
+struct MAINLL *mainll_p;
+
+{
+       if (contextcheck(C_SCORE, "units parameter") == NO) {
+               return;
+       }
+
+       mainll_p->u.ssv_p->units = unittype;
+       Score.units = unittype;
+}
+\f
+
+/* return YES if given SSV refers to a tablature staff, NO if not.
+ * This function is different than the is_tab_staff() function in that
+ * this takes an ssv_p and thus can be used on a user's SSV, whereas
+ * is_tab_staff takes a staff number and only works on the SSVs in
+ * the Staff array. */
+
+static int
+is_tablature_staff(ssv_p)
+
+struct SSV *ssv_p;
+
+{
+       return (ssv_p->strinfo != (struct STRINGINFO *) 0 ? YES : NO);
+}
+\f
+
+/* add information about a string for a tablature staff. This gets put
+ * in a malloc-ed strinfo array off the ssv_p struct */
+
+void
+add_tab_string_info(letter, accidental, nticks, octave, ssv_p)
+
+int letter;            /* pitch letter 'a' to 'g' */
+int accidental;                /* #, &, or \0, others are blocked by parser */
+int nticks;            /* how many tick marks, to distinguish multiple
+                        * strings with the same pitch/accidental */
+int octave;            /* for MIDI and translating to tabnote staff */
+struct SSV *ssv_p;     /* add the info to this struct */
+
+{
+       int index;      /* which strinfo array element we are filling in */
+       int i;
+
+
+       /* increment number of stafflines. This gets done for real later
+        * by asgn_stafflines(), but we do it here to keep track of how
+        * many structs we have malloc-ed from previous calls to this function
+        * for previous strings */
+       (ssv_p->stafflines)++;
+
+       /* first get space. If first one to add, malloc, otherwise realloc */
+       if (ssv_p->stafflines == 1) {
+               MALLOC(STRINGINFO, ssv_p->strinfo, ssv_p->stafflines);
+       }
+       else {
+               REALLOC(STRINGINFO, ssv_p->strinfo, ssv_p->stafflines);
+       }
+
+       /* get the index of the new element we are adding */
+       index = ssv_p->stafflines - 1;
+
+       /* fill in the data */
+       ssv_p->strinfo[index].letter = (char) letter;
+       ssv_p->strinfo[index].accidental = (char) accidental;
+       ssv_p->strinfo[index].nticks = (short) nticks;
+       ssv_p->strinfo[index].octave
+               = (short) (octave == USE_DFLT_OCTAVE ? TABDEFOCT : octave);
+
+       /* check for duplicate strings */
+       for (i = 0; i < index; i++) {
+               if (ssv_p->strinfo[i].letter == letter
+                               && ssv_p->strinfo[i].accidental == accidental
+                               && ssv_p->strinfo[i].nticks == nticks) {
+                       l_yyerror(Curr_filename, yylineno,
+                               "duplicate %c%c%sstring, use ' marks to distinguish",
+                               letter, accidental ? accidental : ' ',
+                               accidental ? " " : "");
+               }
+       }
+}
+\f
+
+/* Save user-specified measure number in given bar struct,
+ * after verifying it is valid (that is it > 0).
+ */
+
+void
+set_mnum(bar_p, mnum)
+
+struct BAR *bar_p;
+int mnum;
+
+{
+       char *old_reh_string;
+       char num_string[8];
+
+       if (mnum < 1) {
+               l_yyerror(Curr_filename, yylineno, "mnum must be > 0");
+       }
+       else if (bar_p->mnum != 0) {
+               l_yyerror(Curr_filename, yylineno,
+                       "mnum cannot be specified more than once per bar");
+       }
+       else {
+               Meas_num = bar_p->mnum = mnum;
+               /* If user had already specified " reh mnum" on this bar,
+                * we would already have made a reh_string for it, so we
+                * have to undo that. It would be nicer to delay the call
+                * to set_reh_string till after we've set mnum, but by then
+                * we would have lost the information we needed unless we
+                * added a bunch more code, so even though this approach
+                * isn't ideal, it's easiest. This shouldn't happen very
+                * often anyway. */
+               if ( (bar_p->reh_type == REH_MNUM) &&
+                                       (bar_p->reh_string != (char *) 0) ) {
+                       old_reh_string = bar_p->reh_string;
+                       (void) sprintf(num_string, "%d", mnum);
+                       bar_p->reh_string = copy_string(num_string,
+                                       (int) old_reh_string[0],
+                                       (int) old_reh_string[1]);
+                       FREE(old_reh_string);
+               }
+       }
+}
+\f
+
+/* Give error if margin is too wide, If any is negative, use from Score */
+
+void
+chkmargin(topmargin, botmargin, leftmargin, rightmargin)
+
+double topmargin;
+double botmargin;
+double leftmargin;
+double rightmargin;
+
+{
+       if (topmargin < 0.0) {
+               topmargin = Score.topmargin;
+       }
+       if (botmargin < 0.0) {
+               botmargin = Score.botmargin;
+       }
+       if (leftmargin < 0.0) {
+               leftmargin = Score.leftmargin;
+       }
+       if (rightmargin < 0.0) {
+               rightmargin = Score.rightmargin;
+       }
+       if (((Score.pageheight - topmargin - botmargin) < MIN_USABLE_SPACE)
+                       || ((Score.pagewidth - leftmargin - rightmargin)
+                       < MIN_USABLE_SPACE)) {
+               yyerror("page size minus margins is too small");
+       }
+}
+\f
+
+/* function to let other files get to the ADJUST2INCHES macro */
+
+double
+adjust2inches(value)
+
+double value;
+
+{
+       ADJUST2INCHES(value);
+       return(value);
+}
diff --git a/mup/mup/beaming.c b/mup/mup/beaming.c
new file mode 100644 (file)
index 0000000..482fb94
--- /dev/null
@@ -0,0 +1,1082 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions called at parse time to deal with beaming. */
+
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+static void subbeam P((struct SSV *ssv_p, RATIONAL outer_time, int obi,
+       struct GRPSYL *begin_gs_p, struct GRPSYL *end_gs_p));
+static struct GRPSYL *verify_crossbeam P((struct GRPSYL *gs_p,
+       struct GRPSYL *other_gs_p, RATIONAL start_time, RATIONAL *end_time_p,
+       int staffno, int size));
+static void
+slopelencheck P((struct GRPSYL *first_p, struct GRPSYL *last_p, char *bmtype));
+
+
+/* this function will get called whenever a group is not the start or end
+ * of a custom beam group. This will fill in the beamloc based on past
+ * history. If we were most recently in a custom beam group, we still are.
+ * If we weren't before, we aren't now either. The non-custom beaming
+ * gets done later after we have collected a whole bar in do_beaming()
+ * which is called via do_bar(). */
+
+void
+setbeamloc(curr_grp_p, last_grp_p)
+
+struct GRPSYL *curr_grp_p;     /* the group we're working on */
+struct GRPSYL *last_grp_p;     /* the last group we did */
+
+{
+       if (curr_grp_p->grpvalue == GV_ZERO) {
+               /* grace notes don't get handled here */
+               curr_grp_p->beamloc = NOITEM;
+               return;
+       }
+
+       /* if the previous group is a grace group, that doesn't count. Back
+        * up in the list to the first non-grace or beginning of list */
+       for (  ; last_grp_p != (struct GRPSYL *) 0
+                                       && last_grp_p->grpvalue == GV_ZERO;
+                                       last_grp_p = last_grp_p->prev) {
+               ;
+       }
+
+       if (last_grp_p != (struct GRPSYL *) 0) {
+
+               switch (last_grp_p->beamloc) {
+
+               case STARTITEM:
+               case INITEM:
+                       curr_grp_p->beamto = last_grp_p->beamto;
+                       /* Make sure notes are 8th or shorter. Spaces (which
+                        * are allowed in cross-staff beams) can be longer. */
+                       if (curr_grp_p->basictime < 8) {
+                               /* At this point, spaces are still
+                                * pseudo-pitches, so have to figure out
+                                * if this group is really notes */
+                               int letter;     /* pitch */
+                               int n;          /* index through notelist */
+                               for (n = 0; n < curr_grp_p->nnotes; n++) {
+                                       letter = curr_grp_p->notelist[n].letter;
+                                       if ((letter >= 'a' && letter <= 'g') ||
+                                                       letter == PP_NO_PITCH) {
+                                               yyerror("beamed notes must be 8th or shorter");
+                                               break;
+                                       }
+                               }
+                       }
+
+                       /* if previous began beaming, we must be inside now */
+                       /* if in beam before, we still are */
+                       curr_grp_p->beamloc = INITEM;
+                       break;
+
+               case ENDITEM:
+               case NOITEM:
+               default:
+                       /* if previous was ending beaming, or
+                        * we weren't inside a beam, must be no beam now */
+                       curr_grp_p->beamloc = NOITEM;
+                       break;
+               }
+       }
+       else {
+               /* nothing specified before, so no beam */
+               curr_grp_p->beamloc = NOITEM;
+       }
+}
+\f
+
+/* take a quick jaunt through a GRPSYL list, seeing if custom
+ * beaming was already done. If so, return YES, otherwise NO.
+ * If there are any non-grace groups with beaming info, there must
+ * have been custom beaming. Also, verify that user didn't attempt to
+ * custom beam a mixture of normal and cue size notes,
+ * or try to put illegal rests or spaces inside a beam.
+ * Spaces are only allowed in cross-staff beams, unless user explicitly
+ * says to beam across spaces. Rests are also only allowed in beams if
+ * the user explicitly states they should be. Rests and spaces cannot be on
+ * the ends, and must be eighth note or shorter.
+ * We allow beaming together chords that are stemmed to another staff
+ * only if all such instances are to the same staff--not some to staff above
+ * and others to staff below--because beaming involving 3 staffs at once is
+ * just too hard to deal with.
+ * Also check that any esbm has at least 2 notes before and after it.
+ */
+
+int
+has_cust_beaming(grpsyl_p)
+
+struct GRPSYL *grpsyl_p;       /* list of GRPSYLs to check */
+
+{
+       int has = NO;
+       int size = GS_NORMAL;
+       int numnotes = 0;       /* how many notes groups, for esbm check */
+       short stemto = CS_SAME; /* to check for mixed CS_ABOVE/CS_BELOW */
+       struct GRPSYL *start_p = 0;     /* first beamed group */
+
+       for (   ; grpsyl_p != (struct GRPSYL *) NULL;
+                               grpsyl_p = grpsyl_p->next) {
+
+               if ((grpsyl_p->grpvalue != GV_ZERO)
+                               && (grpsyl_p->beamloc != NOITEM)) {
+                       /* have non-grace with beam info set */
+                       has = YES;
+
+                       /* check for size or cross-staff stem mixtures */
+                       if (grpsyl_p->beamloc == STARTITEM) {
+                               size = grpsyl_p->grpsize;
+                               numnotes = 0;
+                               stemto = CS_SAME;
+                       }
+                       /* check for size mixture. But only do non-cross-staff
+                        * beams here, because it's a lot easier to do the
+                        * cross-staff beam check in chk_crossbeams() */
+                       else if (grpsyl_p->grpsize != size
+                                       && grpsyl_p->beamto == CS_SAME) {
+                               l_yyerror(grpsyl_p->inputfile,
+                                       grpsyl_p->inputlineno,
+                                       "can't beam normal and cue notes together");
+                       }
+
+                       if (grpsyl_p->grpcont != GC_NOTES) {
+                               if (grpsyl_p->grpcont == GC_REST) {
+                                       if (grpsyl_p->basictime < 8) {
+                                               l_yyerror(grpsyl_p->inputfile,
+                                                       grpsyl_p->inputlineno,
+                                                       "rests inside a beam must be less than quarter note duration");
+                                       }
+                                       if (grpsyl_p->beamloc != INITEM) {
+                                               l_yyerror(grpsyl_p->inputfile,
+                                                       grpsyl_p->inputlineno,
+                                                       "beam cannot %s with a rest",
+                                               grpsyl_p->beamloc == STARTITEM ?
+                                               "begin" : "end");
+                                       }
+                               }
+                               else if (grpsyl_p->beamto == CS_SAME) {
+                                       if (grpsyl_p->beamloc != INITEM) {
+                                               l_yyerror(grpsyl_p->inputfile,
+                                               grpsyl_p->inputlineno,
+                                               "beam cannot begin or end with a space");
+                                       }
+                                       if (grpsyl_p->basictime < 8) {
+                                               l_yyerror(grpsyl_p->inputfile,
+                                               grpsyl_p->inputlineno,
+                                               "spaces inside a beam must be less than quarter note duration");
+                                       }
+                               }
+                       }
+                       else if (grpsyl_p->grpvalue != GV_ZERO) {
+                               numnotes++;
+                       }
+
+                       if (grpsyl_p->stemto != CS_SAME) {
+                               if (stemto != CS_SAME && grpsyl_p->stemto
+                                                               != stemto) {
+                                       l_yyerror(grpsyl_p->inputfile,
+                                       grpsyl_p->inputlineno,
+                                       "beam cannot include chords with stems to both above and below staffs");
+                               }
+                               stemto = grpsyl_p->stemto;
+                       }
+
+                       if (grpsyl_p->beamloc == INITEM &&
+                                       IS_STEMLEN_KNOWN(grpsyl_p->stemlen)) {
+                               l_yyerror(grpsyl_p->inputfile,
+                                       grpsyl_p->inputlineno,
+                                       "stem len specification not allowed inside a beam");
+                       }
+       
+                       if (grpsyl_p->beamloc == STARTITEM) {
+                               start_p = grpsyl_p;
+                       }
+                       else if (grpsyl_p->beamloc == ENDITEM) {
+                               if (start_p != 0) {
+                                       slopelencheck(start_p, grpsyl_p, "beam");
+                                       start_p = 0;
+                               }
+                       }
+
+                       if (grpsyl_p->breakbeam == YES
+                                       && grpsyl_p->beamto == CS_SAME) {
+                               if (numnotes < 2) {
+                                       l_warning(grpsyl_p->inputfile,
+                                               grpsyl_p->inputlineno,
+                                               "esbm must be preceeded by at least 2 beamed notes");
+                                       grpsyl_p->breakbeam = NO;
+                               }
+                               else {
+                                       struct GRPSYL *g_p;
+
+                                       /* Check that there are
+                                        * at least 2 following beamed notes */
+                                       numnotes = 0;
+                                       for (g_p = grpsyl_p->next; g_p != 0;
+                                                       g_p = g_p->next) {
+                                               if (g_p->grpcont == GC_NOTES &&
+                                                   g_p->grpvalue != GV_ZERO) {
+                                                       numnotes++;
+                                               }
+                                               if (g_p->breakbeam == YES) {
+                                                       break;
+                                               }
+                                               if (g_p->beamloc == ENDITEM) {
+                                                       break;
+                                               }
+                                       }
+                                       if (numnotes < 2) {
+                                               l_warning(grpsyl_p->inputfile,
+                                                       grpsyl_p->inputlineno,
+                                                       "esbm must be followed by at least 2 beamed notes");
+                                               grpsyl_p->breakbeam = NO;
+                                       }
+                                       else if (grpsyl_p->grpcont != GC_NOTES) {
+                                               /* User really should have put
+                                                * the esbm on the preceeding
+                                                * NOTES group. We'll be nice
+                                                * and move it for them.
+                                                */
+                                               grpsyl_p->breakbeam = NO;
+                                               for (g_p = grpsyl_p->prev;
+                                                               g_p->grpcont != GC_NOTES;
+                                                               g_p = g_p->prev) {
+                                                       ;
+                                               }
+                                               g_p->breakbeam = YES;
+                                       }
+                               }
+                               numnotes = 0;
+                       }
+               }
+       }
+
+       return(has);
+}
+\f
+
+/* beam notes together according to user-specified default beaming style */
+
+void
+do_beaming(gs_p, grpsize, staffno, vno)
+
+struct GRPSYL *gs_p;           /* list of GRPSYLs to do beaming on */
+int grpsize;                   /* GS_NORMAL or GS_SMALL
+                                * (grace are handled separately) */
+int staffno;
+int vno;                       /* voice number */
+
+{
+       struct SSV *ssv_beaminfo_p;     /* ssv having relevent beam info */
+       register int n;                 /* index into beamstyle list */
+       RATIONAL styletime;             /* accumulated time to beam together */
+       RATIONAL tot_time;              /* cumulative grpsyl time */
+       struct GRPSYL *first_p;         /* first in beam group */
+       struct GRPSYL *last_p;          /* last in beam group */
+       int stop;                       /* YES if need to stop beaming */
+       int beamrests;                  /* if to include rests inside beams */
+       int beamspaces;                 /* if to include spaces inside beams */
+       short stemto = CS_SAME;         /* check for mixed CS_ABOVE/CS_BELOW */
+       short restart = NO;             /* YES if could start another beam
+                                        * with current group, even though
+                                        * it can go with previous */
+
+
+
+       debug(4, "do_beaming file=%s line=%d grpsize=%d staff=%d voice=%d",
+               gs_p->inputfile, gs_p->inputlineno, grpsize, staffno, vno);
+
+       /* if no default beaming scheme for this voice, then nothing to do--
+        * any custom beaming would have already been done */
+       ssv_beaminfo_p = vvpath(staffno, vno, BEAMSTLIST);
+       if (ssv_beaminfo_p->nbeam == 0) {
+               return;
+       }
+
+       /* ok. We may need to do some beaming. Go through the beamstlist and
+        * see if there are any groups to beam together */
+
+       /* initialize */
+       /* point to first non-grace group */
+       for (  ; gs_p != (struct GRPSYL *) 0 && gs_p->grpcont == GC_NOTES
+                       && gs_p->grpvalue == GV_ZERO; gs_p = gs_p->next) {
+               ;
+       }
+
+       /* if no groups, nothing to do */
+       if (gs_p == (struct GRPSYL *) 0) {
+               return;
+       }
+
+       beamrests = vvpath(staffno, vno, BEAMSTLIST)->beamrests;
+       beamspaces = vvpath(staffno, vno, BEAMSTLIST)->beamspaces;
+       styletime = tot_time = Zero;
+       for (n = 0; n < ssv_beaminfo_p->nbeam; n++) {
+               styletime = radd(styletime, ssv_beaminfo_p->beamstlist[n]);
+
+               if (GE(tot_time, styletime)) {
+                       /* we're already past this beamstyle segment */
+                       continue;
+               }
+
+               for (first_p = last_p = 0, stop = NO;
+                               LT(tot_time, styletime); gs_p = gs_p->next) {
+
+                       if (gs_p == 0) {
+                               /* Must be too few groups in measure.
+                                * This error will already have been
+                                * reported elsewhere.
+                                */
+                               return;
+                       }
+
+                       /* ignore grace */
+                       while (gs_p->grpvalue == GV_ZERO) {
+                               gs_p = gs_p->next;
+                               if (gs_p == 0) {
+                                       /* Must have tried to end a measure
+                                        * with grace. Already reported. */
+                                       return;
+                               }
+                       }
+
+                       tot_time = radd(tot_time, gs_p->fulltime);
+                       if (GE(tot_time, styletime)) {
+                               /* This group puts us at or past
+                                * the current beamstyle segment */
+                               stop = YES;
+                       }
+
+                       /* only 8th and shorter get beamed */
+                       if (gs_p->basictime < 8 || (gs_p->grpcont == GC_SPACE &&
+                                               beamspaces == NO) ) {
+                               stop = YES;
+                       }
+                       else if (gs_p->grpcont == GC_REST && beamrests == NO) {
+                               stop = YES;
+                       }
+                       else if (gs_p->grpsize != grpsize) {
+                               /*  Wrong size to beam on this call */
+                               stop = YES;
+                       }
+                       else if (gs_p->stemto != CS_SAME && stemto != CS_SAME
+                                       && gs_p->stemto != stemto) {
+                               /* We don't allow beaming across three staffs,
+                                * so have to stop current beam, but could
+                                * possibly beam this group with following
+                                * groups, as long as they don't have a
+                                * conflicting stemto */
+                               stop = YES;
+                               restart = YES;
+                       }
+                       else if (gs_p->grpcont == GC_NOTES && 
+                                               LE(tot_time, styletime)) {
+                               /* found something beam-able */
+                               if (first_p == 0) {
+                                       first_p = gs_p;
+                               }
+                               last_p = gs_p;
+                       }
+                       if (gs_p->stemto != CS_SAME) {
+                               stemto = gs_p->stemto;
+                       }
+
+                       if (stop == YES) {
+                               if (first_p != 0 && last_p != 0
+                                                       && first_p != last_p) {
+                                       /* Disallow illegal combinations of
+                                        * slope and stem length */
+                                       slopelencheck(first_p, last_p, "beam");
+
+                                       /* If there are subbeam groupings,
+                                        * do those. */
+                                       subbeam(ssv_beaminfo_p,
+                                               rsub(styletime, ssv_beaminfo_p->beamstlist[n]),
+                                               n, first_p, last_p);
+
+                                       /* mark beginning of beam group */
+                                       first_p->beamloc = STARTITEM;
+
+                                       /* mark all intermediate groups,
+                                        * skipping grace */
+                                       for (first_p = first_p->next;
+                                                       first_p != last_p;
+                                                       first_p = first_p->next) {
+
+                                               if (first_p->grpvalue
+                                                               == GV_ZERO) {
+                                                       continue;
+                                               }
+
+                                               first_p->beamloc = INITEM;
+
+                                               if (IS_STEMLEN_KNOWN(first_p->stemlen)) {
+                                                       l_yyerror(first_p->inputfile, first_p->inputlineno,
+                                                           "stem len specification not allowed inside a beam");
+                                               }
+                                       }
+
+                                       /* mark the end of the beam group */
+                                       last_p->beamloc = ENDITEM;
+                               }
+
+                               /* Re-init for any more bunches to beam */
+                               first_p = last_p = 0;
+                               stop = NO;
+                               stemto = CS_SAME;
+                               if (restart == YES) {
+                                       if (gs_p->grpcont == GC_NOTES) {
+                                               first_p = gs_p;
+                                       }
+                                       restart = NO;
+                               }
+                       }
+               }
+       }
+}
+\f
+
+/* Once a STARTITEM and ENDITEM groups of the regular beamstyle
+ * have been identified, go through them to see if there should
+ * be subgroups. If so, mark breakbeam = YES on the last group of
+ * each subgroup.
+ */
+
+static void
+subbeam(ssv_p, outer_time, obi, begin_gs_p, end_gs_p)
+
+struct SSV *ssv_p;     /* to get beamstlist and subbeamstlist */
+RATIONAL outer_time;   /* Time in measure when outer beam begins */
+int obi;               /* outer beam index, subscript into ssv_p->beamstlist */
+struct GRPSYL *begin_gs_p;
+struct GRPSYL *end_gs_p;
+
+{
+       int sbi;        /* sub beam index, subscript of ssv_p->subbeamstlist */
+       RATIONAL subgroup_time; /* duration of items in subbeamstlist */
+       RATIONAL tot_time;      /* sum of note groups in subbeaming */
+       struct GRPSYL *gs_p;    /* walk through groups */
+       struct GRPSYL *last_notegroup_p;/* Most recent GC_NOTES GRPSYL */
+
+
+       /* Check if more than one beam subgroup
+        * makes up the outer beam grouping. */
+       if (ssv_p->nbeam == ssv_p->nsubbeam) {
+               /* There are no sub-beam groupings anywhere in the measure */
+               return;
+       }
+
+       /* Find the subbeamlist entry that matches with the outer beam entry */
+       subgroup_time = Zero;
+       for (sbi = 0; LT(subgroup_time, outer_time); sbi++) {
+               subgroup_time = radd(subgroup_time, ssv_p->subbeamstlist[sbi]);
+       }
+
+       if ( EQ(ssv_p->beamstlist[obi], ssv_p->subbeamstlist[sbi]) ) {
+               /* Outer and subbeam have the same time duration,
+                * so there aren't any subgroups in this outer beam grouping. */
+               return;
+       }
+
+       /* There are subgroups inside the outer beam grouping,
+        * so we may need to set one or more breakbeams. */
+       subgroup_time = ssv_p->subbeamstlist[sbi];
+
+       /* If beam starts later than the outer beamstyle item begins,
+        * (e.g., if there was a rest at the beginning of the beam time),
+        * we have to count that time as already taken up from the subbeam.
+        */
+       for (tot_time = Zero, gs_p = begin_gs_p->prev; gs_p != 0;
+                                                       gs_p = gs_p->prev) {
+               tot_time = radd(tot_time, gs_p->fulltime);
+       }
+       tot_time = rsub(tot_time, outer_time);
+       last_notegroup_p = 0;
+       for (gs_p = begin_gs_p; gs_p != end_gs_p; gs_p = gs_p->next) {
+
+               /* Grace notes are irrelevant */
+               if (gs_p->grpvalue == GV_ZERO) {
+                       continue;
+               }
+
+               /* Remember where last note group is, in case we
+                * need to set breakbeam on it. */
+               if (gs_p->grpcont == GC_NOTES) {
+                       last_notegroup_p = gs_p;
+               }
+
+               /* Add up group time values until the total equals
+                * or exceeds that of the subgroup. */
+               tot_time = radd(tot_time, gs_p->fulltime);
+               if (LT(tot_time, subgroup_time)) {
+                       /* not far enough yet */
+                       continue;
+               }
+       
+               /* If the value exceeds, there is a note spanning the
+                * subgroup boundary, so just ignore the subgrouping. */
+               if (GT(tot_time, subgroup_time)) {
+                       tot_time = rsub(tot_time, subgroup_time);
+                       subgroup_time = ssv_p->subbeamstlist[++sbi];
+                       if (gs_p->grpcont != GC_NOTES) {
+                               last_notegroup_p = 0;
+                       }
+               }
+
+               else {
+                       /* A group ends right at the subbeam boundary. 
+                        * Set breakbeam on last group, if there was one. 
+                        */
+                       if (last_notegroup_p != 0) {
+                               last_notegroup_p->breakbeam = YES;
+                       }
+
+                       /* The current subbeam is finished.
+                        * Move on to the next subbeam, if there is one. */
+                       if (++sbi < ssv_p->nsubbeam) {
+                               subgroup_time = ssv_p->subbeamstlist[sbi];
+                               /* Since we know the subbeam we just
+                                * finished ended exactly
+                                * at the subbeam boundary,
+                                * we set to time taken up so far
+                                * by the new subbeam to zero. 
+                                */
+                               tot_time = Zero;
+                               last_notegroup_p = 0;
+                       }
+               }
+       }
+}
+\f
+
+/* alt groups must always have beamloc set, so fix them */
+
+void
+set_alt_beams(gs_p)
+
+struct GRPSYL *gs_p;   /* a measure's worth of GRPSYLs for a voice */
+
+{
+       struct GRPSYL *other_gs_p;      /* group on other end of alt pair */
+
+
+       debug(4, "set_alt_beams file=%s line=%d",
+                       gs_p->inputfile, gs_p->inputlineno);
+
+       /* walk through the list, fixing any alt groups */
+       for (   ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+
+               /* check if is an alt pair */
+               if (gs_p->slash_alt < 0) {
+
+                       if (gs_p->next == (struct GRPSYL *) 0) {
+                               /* no second group in alt, will be flagged
+                                * elsewhere */
+                               continue;
+                       }
+
+                       /* set the pair as a beam group */
+                       gs_p->beamloc = STARTITEM;
+                       gs_p->next->beamloc = ENDITEM;
+
+                       slopelencheck(gs_p, gs_p->next, "alt");
+
+                       /* middle phase wants to have both notes in an alt group
+                        * have their alt field set, so do that */
+                       gs_p->next->slash_alt = gs_p->slash_alt;
+
+                       /* adjust preceeding and following groups if necessary.
+                        * If was already in a beam group, split off the other
+                        * parts into their own groups or put flags on the
+                        * extras if they are down to one group */
+
+                       /* find previous normal group if any and adjust */
+                       for (other_gs_p = gs_p->prev;
+                                       other_gs_p != (struct GRPSYL *) 0;
+                                       other_gs_p = other_gs_p->prev) {
+
+                               if (other_gs_p->grpvalue != GV_ZERO) {
+                                       if (other_gs_p->grpcont == GC_REST) {
+                                               other_gs_p->beamloc = NOITEM;
+                                       }
+                                       else {
+                                               break;
+                                       }
+                               }
+                       }
+
+                       if (other_gs_p != (struct GRPSYL *) 0) {
+
+                               switch (other_gs_p->beamloc) {
+
+                               case INITEM:
+                                       other_gs_p->beamloc = ENDITEM;
+                                       break;
+
+                               case STARTITEM:
+                                       other_gs_p->beamloc = NOITEM;
+                                       break;
+
+                               default:
+                                       break;
+                               }
+                       }
+                                       
+                       /* now do the same for the following group */
+                       for (other_gs_p = gs_p->next->next;
+                                       other_gs_p != (struct GRPSYL *) 0;
+                                       other_gs_p = other_gs_p->next) {
+
+                               if (other_gs_p->grpvalue != GV_ZERO) {
+                                       if (other_gs_p->grpcont == GC_REST) {
+                                               other_gs_p->beamloc = NOITEM;
+                                       }
+                                       else {
+                                               break;
+                                       }
+                               }
+                       }
+
+                       if (other_gs_p != (struct GRPSYL *) 0) {
+
+                               switch (other_gs_p->beamloc) {
+
+                               case INITEM:
+                                       other_gs_p->beamloc = STARTITEM;
+                                       break;
+
+                               case ENDITEM:
+                                       other_gs_p->beamloc = NOITEM;
+                                       break;
+
+                               default:
+                                       break;
+                               }
+                       }
+
+                       /* skip over the second in the pair */
+                       gs_p = gs_p->next;
+               }
+       }
+}
+\f
+
+/* Given a list of GRPSYLs on a visible voice
+ * having "bm with staff below" do all the error checking.
+ * This list of groups has to be for the bottom visible voice
+ * for the duration of the beam.
+ * There has to be a set of groups on the top non-space visible
+ * voice of the first visible staff below,
+ * which starts a "bm with staff above" at exactly
+ * the same time value. The ebm values also have to match. At every
+ * point inside the beam, one voice must have notes and the other voice
+ * must have spaces.
+ *
+ * Have to be careful in this function,
+ * because the gs_p->staffno and gs_p->vno may not be filled in yet,
+ * so have to use the staffno from the STAFF struct, and get vno from the
+ * first gs_p, which the caller is supposed to have filled in correctly.
+ *
+ * Returns the staff number of the staff containing the matching
+ * "bm with staff above" or -1 if no such staff was found.
+ */
+
+int
+chk_crossbeam(gs_p, mll_p)
+
+struct GRPSYL *gs_p;   /* first group in above voice of cross staff beam */
+struct MAINLL *mll_p;  /* gs_p hangs off of here */
+
+{
+       struct GRPSYL *g_p;             /* for walking through group list */
+       struct GRPSYL *other_p;         /* group on other staff */
+       struct MAINLL *assoc_mll_p;     /* other staff hangs off of here */
+       struct GRPSYL *assoc_grps_p;    /* the measure-worth of groups in
+                                        * the voice being beamed to */
+       RATIONAL start_time, end_time;  /* of the above voice */
+       RATIONAL other_start, other_end;/* time of groups on below staff */
+       int user_specified_stem_len;    /* YES or NO */
+       int size = GS_NORMAL;
+       int assoc_vno;                  /* voice number on below staff */
+       struct STAFF *staff_p;
+       int staffno;
+       int vno;
+
+
+       /* only the first gs_p is guaranteed to have the right vno at this
+        * point, so save that. */
+       vno = gs_p->vno;
+       staff_p = mll_p->u.staff_p;
+       staffno = staff_p->staffno;
+
+       /* find where in the measure the beam begins, by adding up the
+        * time values of all the groups prior to the first beamed group */
+       for (start_time = Zero, g_p = gs_p->prev; g_p != (struct GRPSYL *) 0;
+                                       g_p = g_p->prev) {
+               start_time = radd(start_time, g_p->fulltime);
+       }
+
+       /* find how long the beam lasts. Also see if there are any small
+        * groups */
+       for (end_time = start_time, g_p = gs_p; g_p != (struct GRPSYL *) 0;
+                                       g_p = g_p->next) {
+               /* accumulate the time */
+               end_time = radd(end_time, g_p->fulltime);
+
+               /* check for small groups */
+               if (g_p->grpcont == GC_NOTES && g_p->grpsize == GS_SMALL
+                                               && g_p->grpvalue != GV_ZERO) {
+                       size= GS_SMALL;
+               }
+
+               /* end of the beam? */
+               if (g_p->beamloc == ENDITEM && g_p->grpvalue != GV_ZERO) {
+                       break;
+               }
+       }
+       if (g_p == (struct GRPSYL *) 0) {
+               /* maybe this should be silent, since another error message
+                * should already be printed, but this will point out that
+                * the problem was on a cross-staff beam */
+               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                                       "can't find end of cross-staff beam");
+               return(-1);
+       }
+
+       /* Make sure this is the bottom voice of the above staff.
+        * If it's voice 2 (subscript 1) then it is for sure.
+        * Otherwise, have to make sure the second and third voices, if any,
+        * have all spaces for the duration of the cross-staff beam */
+       if (vno != 1) {
+               /* If voice 2 is visible and not all spaces,
+                * or if we are working on voice 1 while voice 3 is
+                * visible and not all space, there is a problem. */
+               if (vvpath(staffno, 2, VISIBLE)->visible == YES &&
+                               hasspace(staff_p->groups_p[1], start_time,
+                               end_time) == NO || (vno == 0 &&
+                               vvpath(staffno, 3, VISIBLE)->visible == YES &&
+                               hasspace(mll_p->u.staff_p->groups_p[2],
+                               start_time, end_time) == NO)) {
+                       l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                               "cross-staff beam must be from bottom voice of staff %d",
+                               mll_p->u.staff_p->staffno);
+                       return(-1);
+               }
+       }
+
+       /* Find the associated voice, and the associated bm group
+        * in that voice. First find the next visible staff */
+       for (assoc_mll_p = mll_p->next;   ; assoc_mll_p = assoc_mll_p->next) {
+               if (assoc_mll_p == (struct MAINLL *) 0 ||
+                                               assoc_mll_p->str != S_STAFF) {
+                       l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                                       "no visible staff below to beam with");
+                       return(-1);
+               }
+
+               if (svpath(assoc_mll_p->u.staff_p->staffno, VISIBLE)->visible
+                                                       == YES) {
+                       /* found the right staff */
+                       break;
+               }
+       }
+
+       /* Associated voice is probably voice 1 of the below staff.
+        * But there is a slight possibility it is voice 2, or even voice 3.
+        * Skip over voices that are all spaces for the duration of the beam.
+        * Since voice 3 is the "middle" voice, we check 1, then 3, then 2.
+        */
+       if (vvpath(staffno, 1, VISIBLE)->visible == YES &&
+                       hasspace(assoc_mll_p->u.staff_p->groups_p[0],
+                       start_time, end_time) == NO) {
+               assoc_grps_p = assoc_mll_p->u.staff_p->groups_p[0];
+               assoc_vno = 0;
+       }
+       else if (vvpath(staffno, 3, VISIBLE)->visible == YES &&
+                       hasspace(assoc_mll_p->u.staff_p->groups_p[2],
+                       start_time, end_time) == NO) {
+               assoc_grps_p = assoc_mll_p->u.staff_p->groups_p[2];
+               assoc_vno = 2;
+       }
+       else if (vvpath(staffno, 2, VISIBLE)->visible == YES &&
+                       hasspace(assoc_mll_p->u.staff_p->groups_p[1],
+                       start_time, end_time) == NO) {
+               assoc_grps_p = assoc_mll_p->u.staff_p->groups_p[1];
+               assoc_vno = 1;
+       }
+       else {
+               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                               "cross-staff beam has no notes on staff %d",
+                               assoc_mll_p->u.staff_p->staffno);
+               return(-1);
+       }
+
+       /* Tab staffs can't be involved in cross-staff beaming */
+       if (is_tab_staff(mll_p->u.staff_p->staffno) ||
+                       is_tab_staff(assoc_mll_p->u.staff_p->staffno)) {
+               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                               "cross-staff beaming not allowed on tab staff");
+               return(-1);
+       }
+
+       /* We don't allow the different staffs to have different staffscale
+        * values: it doesn't really make much sense to allow it, and avoids
+        * all the issues like how wide to make the beams.
+        */
+       if (svpath(mll_p->u.staff_p->staffno, STAFFSCALE)->staffscale !=
+                       svpath(assoc_mll_p->u.staff_p->staffno,
+                       STAFFSCALE)->staffscale) {
+               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                       "staffs involved with cross-staff beams must have identical staffscale values");
+               /* We did find which to associate with, even though
+                * its staffscale was wrong. */
+               return(assoc_mll_p->u.staff_p->staffno);
+       }
+
+       /* find the group that ought to be the "bm with staff above" group, by
+        * going that far time-wise into the measure on the associated voice */
+       for (other_start = Zero, other_p = assoc_grps_p;
+                               other_p != (struct GRPSYL *) 0;
+                               other_p = other_p->next) {
+
+               if (GT(other_start, start_time)) {
+                       /* too far. pretend to be at end of list so we
+                        * and fall out of loop to print the error message
+                        * for this case */
+                       other_p = (struct GRPSYL *) 0;
+                       break;
+               }
+
+               if (EQ(other_start, start_time)) {
+                       /* found it! */
+                       break;
+               }
+
+               if (other_p->grpvalue == GV_ZERO) {
+                       continue;
+               }
+
+               /* have to keep going. Keep track of how far we are in time */
+               other_start = radd(other_start, other_p->fulltime);
+       }
+
+       /* skip past any grace groups */
+       while (other_p != 0 && other_p->grpvalue == GV_ZERO) {
+               other_p = other_p->next;
+       }
+
+       /* If we didn't find a voice below, or that voice's group
+        * isn't the start of a beam with above, there is a problem.
+        * In the second case, maybe user really meant to beam with some
+        * lower voice, but that would collide, which we don't allow.
+        */
+       if (other_p == (struct GRPSYL *) 0 || other_p->beamloc != STARTITEM
+                                       || other_p->beamto != CS_ABOVE) {
+               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                       "'bm with staff below' has no matching 'bm with staff above' (may be missing, invisible, or on wrong voice)");
+               return(assoc_mll_p->u.staff_p->staffno);
+       }
+
+       /* check if user specified a stem length on the first group */
+       if (IS_STEMLEN_KNOWN(gs_p->stemlen)
+                               || IS_STEMLEN_KNOWN(other_p->stemlen)) {
+               user_specified_stem_len = YES;
+       }
+       else {
+               user_specified_stem_len = NO;
+       }
+
+       /* go through the two voices. For each note group, verify that
+        * the other voice has space during that time period. Do the "other"
+        * staff first, because in a previous version of this function it
+        * had to be done in that order to avoid possible null pointer
+        * dereference. Now things have changed, so that doesn't matter
+        * any more, but I don't want to change the order, to make sure I
+        * don't break something.
+        */
+       other_p = verify_crossbeam(other_p,
+                       mll_p->u.staff_p->groups_p[vno], start_time,
+                       &other_end, assoc_mll_p->u.staff_p->staffno, size);
+       gs_p = verify_crossbeam(gs_p, assoc_grps_p, start_time, &end_time,
+                       mll_p->u.staff_p->staffno, size);
+
+       /* we should be pointing to the ebm group for each staff,
+        * unless of course, something went wrong, like user didn't
+        * specify an ebm */
+       if (gs_p == (struct GRPSYL *) 0 || other_p == (struct GRPSYL *) 0) {
+               /* maybe this should be silent, since another error message
+                * should already be printed, but this will point out that
+                * the problem was on a cross-staff beam */
+               l_yyerror(assoc_grps_p->inputfile, assoc_grps_p->inputlineno,
+                       "failed to find ebm for cross-staff beam");
+               return(assoc_mll_p->u.staff_p->staffno);
+       }
+
+       if (NE(end_time, other_end)) {
+               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                       "ebm not at same time in measure for both voices of cross-staff beam");
+       }
+
+       /* Disallow illegal combinations of slope and stem length */
+       slopelencheck(gs_p, other_p, "beam");
+
+       return(assoc_mll_p->u.staff_p->staffno);
+}
+\f
+
+/* Given the first group of a cross-staff beam, and the beginning of the
+ * list of GRPSYLs in the associated voice (the voice beamed to), and the
+ * time into the measure where the beam starts, check each group. Verify
+ * that each GC_NOTES group has GC_SPACE in the other voice and vice-versa.
+ * Also check that all note groups are the same size, and mark the spaces
+ * as the correct size so that everything in the beam has the same size.
+ * Return a pointer to the last group in the beam (null if something goes
+ * wrong). Also, return the time into the measure of the end of the beam,
+ * via the end_time_p pointer.
+ */
+
+static struct GRPSYL *
+verify_crossbeam(gs_p, other_gs_p, start_time, end_time_p, staffno, size)
+
+struct GRPSYL *gs_p;   /* first group in list to be checked */
+struct GRPSYL *other_gs_p; /* the groups_p of the associated voice */
+RATIONAL start_time;   /* when the beam begins */
+RATIONAL *end_time_p;  /* time through end of beam will be returned here */
+int staffno;
+int size;              /* GS_NORMAL or GS_SMALL */
+
+{
+       RATIONAL end_time;
+       int has_at_least_1_note_group = NO;
+
+
+       /* go through each group in the beam */
+       for (  ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+
+               /* skip over any grace groups */
+               if (gs_p->grpvalue == GV_ZERO) {
+                       continue;
+               }
+
+               /* find the end time of the group, for passing to hasspace() */
+               end_time = radd(start_time, gs_p->fulltime);
+
+               /* if notes, other voice must have space */
+               if (gs_p->grpcont == GC_NOTES) {
+                       if (hasspace(other_gs_p, start_time, end_time) == NO) {
+                               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                                       "cross-staff beam must always have notes in one voice and space in the other voice");
+                               return (struct GRPSYL *) 0;
+                       }
+                       has_at_least_1_note_group = YES;
+                       if (gs_p->grpsize != size) {
+                               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                               "can't mix normal and cue size chords in cross-staff beam");
+                       }
+               }
+
+               /* conversely, if space, other voice must not have space */
+               else if (gs_p->grpcont == GC_SPACE) {
+                       struct GRPSYL *g_p;
+                       RATIONAL t;
+                       int oldcont = GC_SPACE;
+
+                       /* This is somewhat like hasspace() except that checks
+                        * that the entire duration is space. Here we need
+                        * to check if there is space at least somewhere during
+                        * the time period. If so, user error.
+                        */
+                       for (g_p = other_gs_p, t = Zero; LT(t, start_time);
+                                                       g_p = g_p->next) {
+                               if (g_p->grpvalue == GV_ZERO) {
+                                       continue;
+                               }
+                               t = radd(t, g_p->fulltime);
+                               oldcont = g_p->grpcont;
+                       }
+                       if (GT(t, start_time) && oldcont == GC_SPACE) {
+                               /* group spilling into this time is space */
+                               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                                       "cross-staff beam must always have notes in one voice and space in the other voice");
+                               return (struct GRPSYL *) 0;
+                       }
+                       for (   ; g_p != 0 && LT(t, end_time); g_p = g_p->next) {
+                               if (g_p->grpvalue == GV_ZERO) {
+                                       continue;
+                               }
+                               if (g_p->grpcont == GC_SPACE) {
+                                       l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                                               "cross-staff beam must always have notes in one voice and space in the other voice");
+                                       return (struct GRPSYL *) 0;
+                               }
+                               t = radd(t, g_p->fulltime);
+                       }
+
+                       /* mark size of spaces. Normally space can't be cue                              * size, but in this case, it makes it easier for later
+                        * code (in print phrase at least) if everything in the
+                        * beam--even spaces--is marked as cue size */
+                       gs_p->grpsize = size;
+               }
+
+               /* esbm is not currently allowed on cross-staff beams.
+                * It would much more complicated than normal beams,
+                * because the "primary" beam might perhaps best be the top,
+                * the bottom, or the middle, depending on where the notes are.
+                * Placement and print phase would have to know about that,
+                * so that stems could be adjusted properly,
+                * and beams drawn in the right places.
+                */
+               if (gs_p->breakbeam == YES) {
+                       l_warning(gs_p->inputfile, gs_p->inputlineno,
+                                       "esbm is not supported on cross-staff beams; being ignored");
+                       gs_p->breakbeam = NO;
+               }
+
+               /* see if we reached the end of the beam */
+               if (gs_p->beamloc == ENDITEM) {
+                       *end_time_p = end_time;
+                       if (has_at_least_1_note_group == NO) {
+                               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                                       "cross-staff beam has no notes on staff %d",
+                                       staffno);
+                       }
+
+                       return(gs_p);
+               }
+
+               /* arrange for next time through the loop, by moving the
+                * start_time to the next group */
+               start_time = end_time;
+       }
+
+       /* failed to find an ebm */
+       return (struct GRPSYL *) 0;
+}
+\f
+
+/* User is not allowed to specify length on both ends of a beam along with
+ * a slope, because they could becontradictory. */
+
+static void
+slopelencheck(first_p, last_p, bmtype)
+
+struct GRPSYL *first_p;                /* first beamed group */
+struct GRPSYL *last_p;         /* last beamed group */
+char *bmtype;                  /* "beam" or "alt" */
+
+{
+       if (IS_STEMLEN_KNOWN(first_p->stemlen) == YES &&
+                       IS_STEMLEN_KNOWN(last_p->stemlen) == YES &&
+                       fabs(first_p->beamslope - NOBEAMANGLE) > 0.001) {
+               l_yyerror(last_p->inputfile, last_p->inputlineno,
+                       "can't specify both end stem lengths and slope for %s",
+                       bmtype);
+       }
+}
diff --git a/mup/mup/beamstem.c b/mup/mup/beamstem.c
new file mode 100644 (file)
index 0000000..6ff26fc
--- /dev/null
@@ -0,0 +1,2645 @@
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ * Name:       beamstem.c
+ *
+ * Description:        This file contains functions for setting lengths of note
+ *             stems, which also involves beaming considerations.
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+/*
+ * Several functions need to know the value of the "stemlen" parameter, so
+ * instead of them all calling vvpath, define a holding place here.
+ */
+static float Defstemsteps;
+
+static void proclist P((struct MAINLL *mainll_p, int vno));
+static void proctablist P((struct MAINLL *mainll_p, int vno));
+static int stemforced P((struct GRPSYL *gs_p, struct GRPSYL *ogs_p));
+static void setbeam P((struct GRPSYL *start_p, struct GRPSYL *end_p,
+               struct GRPSYL *ogs_p)); 
+static void restore_ry P((struct GRPSYL *start_p, struct GRPSYL *end_p));
+static double embedgrace P((struct GRPSYL *start_p, double b1, double b0));
+static double embedclef P((struct GRPSYL *start_p, double b1, double b0));
+static double beamoff P((struct GRPSYL *gs_p, int side, double boundary,
+               struct GRPSYL *start_p));
+static void embedrest P((struct GRPSYL *start_p, struct GRPSYL *last_p,
+               double b1, double b0));
+static double avoidothervoice P((struct GRPSYL *start_p, struct GRPSYL *last_p,
+               double b1, double b0, struct GRPSYL *ogs_p));
+static void setgroupvert P((int, struct GRPSYL *, struct GRPSYL *));
+static void settuplet P((struct GRPSYL *start_p, struct STAFF *staff_p));
+static void expgroup P((struct GRPSYL *gs_p, struct GRPSYL *ogs_p));
+static void applywith P((struct GRPSYL *gs_p, int side));
+\f
+/*
+ * Name:        beamstem()
+ *
+ * Abstract:    Set stem lengths for all notes that have stems or slash/alt.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through the main linked list.  For each
+ *             linked list of groups on each visible staff, it calls proclist
+ *             to set stem lengths.
+ */
+
+void
+beamstem()
+
+{
+       register struct MAINLL *mainll_p; /* point along main linked list */
+       int n;                          /* loop variable */
+
+
+       debug(16, "beamstem CSSpass=%d", CSSpass);
+       initstructs();                  /* clean out old SSV info */
+
+       /*
+        * Loop once for each item in the main linked list.  Apply any SSVs
+        * that are found.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+               if (mainll_p->str == S_SSV) {
+
+                       asgnssv(mainll_p->u.ssv_p);
+
+               } else if (mainll_p->str == S_STAFF &&
+                               mainll_p->u.staff_p->visible == YES &&
+                               ! is_mrpt(mainll_p->u.staff_p->groups_p[0])) {
+                       /*
+                        * For this visible staff, call a subroutine to process
+                        * each list of groups on it.
+                        */
+                       for (n = 0; n < MAXVOICES; n++) {
+                               if (mainll_p->u.staff_p->groups_p[n] != 0) {
+                                       /* set global default stem steps */
+                                       Defstemsteps = vvpath(mainll_p->
+                                               u.staff_p->staffno,
+                                               n + 1, STEMLEN)->stemlen;
+                                       if (is_tab_staff(mainll_p->u.staff_p->
+                                                       staffno)) {
+                                               proctablist(mainll_p, n);
+                                       } else {
+                                               proclist(mainll_p, n);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        proclist()
+ *
+ * Abstract:    Process linked list of groups.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through the linked list of groups for one
+ *             voice for one measure, first handling the grace groups, then
+ *             doing a second loop for the nongrace groups.  For each non-
+ *             beamed note that needs it, it sets the stem length.  For each
+ *             beamed group, it calls setbeam to figure out the equation
+ *             of the beam, and set the stem lengths accordingly.  It also
+ *             sets the relative vertical coords of the groups.  These coords
+ *             then get altered to include "with" lists and tuplet marks.
+ */
+
+static void
+proclist(mainll_p, vno)
+
+struct MAINLL *mainll_p;       /* MLL struct for staff we're dealing with */
+int vno;                       /* voice we're to deal with, 0 to MAXVOICES-1 */
+
+{
+       struct GRPSYL *gs_p;    /* point to first group in a linked list */
+       struct GRPSYL *ogs_p;   /* point to first group in other linked list */
+       struct STAFF *staff_p;  /* point to the staff it's connected to */
+       struct GRPSYL *savegs_p;/* save incoming gs_p */
+       struct GRPSYL *beamst_p;/* point at first group of a beamed set */
+       float notedist;         /* distance between outer notes of a group */
+       float defsteps;         /* additional default steps long to make stem*/
+       int bf;                 /* number of beams/flags */
+
+
+       debug(32, "proclist file=%s line=%d vno=%d", mainll_p->inputfile,
+                       mainll_p->inputlineno, vno);
+       /*
+        * Set pointers to 1st group in our list and in the "other" list, as
+        * appropriate.  Voices 1 and 2 (vno=0,1) refer to each other as the
+        * "other" voice.  (If there is only one voice, ogs_p is set to voice 2
+        * (vno=1) which is a null pointer.)  Voice 3 (vno=2) always ignores
+        * the other voices, so for it, ogs_p is a null pointer.
+        */
+       gs_p = mainll_p->u.staff_p->groups_p[ vno ];
+       ogs_p = vno == 2 ? (struct GRPSYL *)0 :
+                       mainll_p->u.staff_p->groups_p[ ! vno ];
+
+       staff_p = mainll_p->u.staff_p;  /* also point at staff */
+
+       /* set globals like Staffscale for use by the rest of the file */
+       set_staffscale(staff_p->staffno);
+
+       beamst_p = 0;   /* prevent useless 'used before set' warnings */
+
+       /*
+        * Loop through every group, skipping rests, spaces, and nongrace
+        * groups, setting the stem length of grace groups.
+        */
+       for (savegs_p = gs_p; gs_p != 0; gs_p = gs_p->next) {
+               if (gs_p->grpcont != GC_NOTES)
+                       continue;
+               if (gs_p->grpvalue == GV_NORMAL)
+                       continue;
+
+               /*
+                * If we are at the start of a beamed set of groups, remember
+                * this place.  Then, when we find the end of the set, call
+                * setbeam to figure out the equation of the beam and set the
+                * stem lengths.
+                */
+               if (gs_p->beamloc != NOITEM) {
+                       if (gs_p->beamloc == STARTITEM)
+                               beamst_p = gs_p;
+                       if (gs_p->beamloc == ENDITEM)
+                               setbeam(beamst_p, nextsimilar(gs_p), ogs_p);
+
+                       continue;
+               }
+
+               /* if we get here, this group is not in a beamed set */
+
+               /* if not affected by CSS, do on normal pass, and only then */
+               /* if affected by CSS, do on CSS pass, and only then */
+               if (css_affects_stemtip(gs_p) != CSSpass) {
+                       continue;
+               }
+
+               /*
+                * If the user specified a nonzero stem length, that's only the
+                * part of it that's not between the notes.  So add the distance
+                * between the outer notes of the group.  However, if they
+                * specified 0, they should get no stem.
+                */
+               if (IS_STEMLEN_KNOWN(gs_p->stemlen)) {
+                       if (gs_p->stemlen != 0.0) {
+                               gs_p->stemlen *= Staffscale;
+                               notedist = gs_p->notelist[0].c[RY] - gs_p->
+                                       notelist[ gs_p->nnotes - 1 ].c[RY];
+                               gs_p->stemlen += notedist;
+                       }
+                       continue;
+               }
+
+               /*
+                * Grace quarter notes default to just a note head and no stem.
+                * So set their stem length to 0.
+                */
+               if (gs_p->basictime == 4) {
+                       gs_p->stemlen = 0;
+                       continue;
+               }
+
+               /*
+                * If stemlen parm is zero, force length to zero.  This will
+                * look bad for non-quarter notes, but that's what they
+                * asked for.
+                */
+               if (Defstemsteps == 0.0) {
+                       gs_p->stemlen = 0.0;
+                       continue;
+               }
+
+               /*
+                * Set the stems to the requested length, plus the distance
+                * between the highest and lowest note of the group, except
+                * longer for notes with more than 2 flags or beams.  Unlike
+                * nongrace groups, stems need not reach the center line of
+                * the staff.
+                */
+               /* find distance between outer notes of the group */
+               notedist = gs_p->notelist[0].c[RY] -
+                       gs_p->notelist[ gs_p->nnotes - 1 ].c[RY];
+
+               /* set len to default length + distance between outer notes */
+               gs_p->stemlen = (Defstemsteps * SM_STEMFACTOR) * Stepsize +
+                               notedist;
+
+               bf = drmo(gs_p->basictime) - 2; /* no. of beams/flags */
+               if (bf > 2)
+                       gs_p->stemlen += (bf - 2) * Smflagsep;
+       }
+
+       /*
+        * Loop through every grace group, skipping rests and spaces,
+        * setting the relative vertical coordinates.
+        */
+       setgroupvert(GV_ZERO, savegs_p, ogs_p);
+
+       /*
+        * Loop through every group, skipping rests, spaces and grace groups,
+        * setting the stem length of all nongrace groups.
+        *
+        * WARNING:  The code in this loop is similar to stemroom() in
+        * setgrps.c.  If you change one, you probably will need to change
+        * the other.
+        */
+       for (gs_p = savegs_p; gs_p != 0; gs_p = gs_p->next) {
+               if (gs_p->grpcont != GC_NOTES)
+                       continue;
+               if (gs_p->grpvalue == GV_ZERO)
+                       continue;
+               /*
+                * If this is cross staff beaming, don't do anything now.  We
+                * can't do anything until the absolute vertical coords are set
+                * in absvert.c.
+                */
+               if (gs_p->beamto != CS_SAME) {
+                       continue;
+               }
+
+               /*
+                * If we are at the start of a beamed set of groups, remember
+                * this place.  Then, when we find the end of the set, call
+                * setbeam to figure out the equation of the beam and set the
+                * stem lengths.
+                */
+               if (gs_p->beamloc != NOITEM) {
+                       if (gs_p->beamloc == STARTITEM)
+                               beamst_p = gs_p;
+                       if (gs_p->beamloc == ENDITEM)
+                               setbeam(beamst_p, nextsimilar(gs_p), ogs_p);
+                       continue;
+               }
+
+               /* if we get here, this group is not in a beamed set */
+
+               /* if not affected by CSS, do on normal pass, and only then */
+               /* if affected by CSS, do on CSS pass, and only then */
+               if (css_affects_stemtip(gs_p) != CSSpass) {
+                       continue;
+               }
+
+               /*
+                * Only half notes and shorter have stems, but whole and double
+                * whole notes still need to have a pseudo stem length set if
+                * alternation beams are to be drawn between two neighboring
+                * groups, or the group has slashes.
+                */
+               if (gs_p->basictime <= 1 && gs_p->slash_alt == 0)
+                       continue;       /* no stem and no pseudo stem */
+
+               /*
+                * If the user specified a nonzero stem length, that's only the
+                * part of it that's not between the notes.  So add the distance
+                * between the outer notes of the group.  But if they specified
+                * 0, leave it as 0.
+                */
+               if (IS_STEMLEN_KNOWN(gs_p->stemlen)) {
+                       if (gs_p->stemlen == 0.0)
+                               continue;
+
+                       gs_p->stemlen *= Staffscale;
+                       notedist = gs_p->notelist[0].c[RY] -
+                               gs_p->notelist[ gs_p->nnotes - 1 ].c[RY];
+                       gs_p->stemlen += notedist;
+                       continue;
+               }
+
+               /* if stemlen parm is zero, force length to zero */
+               if (Defstemsteps == 0.0) {
+                       gs_p->stemlen = 0.0;
+                       continue;
+               }
+
+               /* 
+                * Set the stems initially to one octave long (or 5 stepsizes
+                * for cue notes), plus the distance between the highest and
+                * lowest note of the group, except longer for notes with more
+                * than 2 flags or beams.  In any case, for normal sized notes,
+                * real stems must reach the center line of the staff in most
+                * cases.
+                */
+               /* find distance between outer notes of the group */
+               notedist = gs_p->notelist[0].c[RY] -
+                       gs_p->notelist[ gs_p->nnotes - 1 ].c[RY];
+               /* set len to default length + distance between outer notes */
+               defsteps = Defstemsteps *
+                       (allsmall(gs_p, gs_p) == YES ? SM_STEMFACTOR : 1.0);
+               gs_p->stemlen = defsteps * Stepsize + notedist;
+
+               /* add more, if needed, for flags/beams/slashes/alternations */
+               if (gs_p->basictime >= 8)
+                       bf = drmo(gs_p->basictime) - 2; /* no. of beams/flags*/
+               else
+                       bf = 0;                 /* none on quarter or longer */
+               bf += abs(gs_p->slash_alt);     /* slashes or alternations */
+               if (gs_p->slash_alt > 0 && gs_p->basictime >= 16)
+                       bf++;   /* slashes need an extra one if 16, 32, ... */
+               if (bf > 2)
+                       gs_p->stemlen += (bf - 2) * Flagsep;
+
+               /*
+                * If the note may have flag(s), stem up, and has dot(s), we
+                * must prevent the flag(s) from hitting the dot(s), by
+                * lengthening the stem.
+                */
+               if (gs_p->basictime >= 8 && gs_p->stemdir == UP &&
+                               gs_p->dots != 0) {
+                       if (gs_p->notelist[0].stepsup % 2 == 0) {
+                               /* note is on a line */
+                               if (gs_p->basictime == 8)
+                                       gs_p->stemlen += Stepsize;
+                               else
+                                       gs_p->stemlen += 2 * Stepsize;
+                       } else {
+                               /* note is on a space */
+                               if (gs_p->basictime > 8)
+                                       gs_p->stemlen += Stepsize;
+                       }
+               }
+
+               /*
+                * Real (printed) stems must reach the center line for normal
+                * groups, though they need not for cue groups or voice 3 or
+                * when the stem direction has been forced the "wrong way" or
+                * when all the notes are on another staff.
+                */
+               if (gs_p->basictime >= 2 && gs_p->grpsize == GS_NORMAL &&
+                               vno != 2 && stemforced(gs_p, ogs_p) == NO &&
+                               NNN(gs_p) > 0) {
+
+                       if (gs_p->stemdir == UP && gs_p->notelist[ gs_p->nnotes
+                                       - 1 ].c[RY] < -(gs_p->stemlen)) {
+                               gs_p->stemlen = -gs_p->notelist[ gs_p->nnotes-1
+                                               ].c[RY];
+                       }
+
+                       if (gs_p->stemdir == DOWN && gs_p->notelist[ 0 ].c[RY]
+                                               > gs_p->stemlen) {
+                               gs_p->stemlen = gs_p->notelist[ 0 ].c[RY];
+                       }
+               }
+       }
+
+       /*
+        * Loop through every nongrace group, skipping rests and spaces,
+        * setting the relative vertical coordinates.
+        */
+       setgroupvert(GV_NORMAL, savegs_p, ogs_p);
+
+       /*
+        * Loop through every group, looking for tuplets.  When encountering
+        * the first item in a tuplet, call a subroutine to figure out where
+        * the bracket should go, and based on that alter the RN or RS of
+        * the groups in the tuplet.  However, if this is a tuplet whose
+        * number and bracket are not to be printed, don't call the subrountine.
+        * Also, it should not be done when there is cross staff beaming.  Mup
+        * does not automatically print tuplet numbers or brackets in CSB sets.
+        */
+       for (gs_p = savegs_p; gs_p != 0; gs_p = gs_p->next) {
+               if ((gs_p->tuploc == STARTITEM || gs_p->tuploc == LONEITEM) &&
+                   gs_p->beamto == CS_SAME && gs_p->printtup != PT_NEITHER)
+                       settuplet(gs_p, staff_p);
+       }
+}
+\f
+/*
+ * Name:        proctablist()
+ *
+ * Abstract:    Process linked list of groups on a tablature staff.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through the linked list of groups for one
+ *             measure of a tablature staff.  It sets the relative vertical
+ *             coords of the groups.  These coords then get altered to include
+ *             "with" lists and tuplet marks.
+ */
+
+static void
+proctablist(mainll_p, vno)
+
+struct MAINLL *mainll_p;       /* MLL struct for staff we're dealing with */
+int vno;                       /* voice we're to deal with, 0 to MAXVOICES-1 */
+
+{
+       struct GRPSYL *gs_p;    /* point to first group in a linked list */
+       struct GRPSYL *ogs_p;   /* point to first group in other linked list */
+       int stepdiff;           /* steps between highest & lowest of a group */
+       int defsteps;           /* additional default steps long to make stem*/
+       int bf;                 /* number of beams/flags (really slashes) */
+
+
+       debug(32, "proctablist file=%s line=%d", mainll_p->inputfile,
+                       mainll_p->inputlineno);
+       /* no such thing as cross staff stemming for tab */
+       if (CSSpass == YES) {
+               return;
+       }
+
+       /*
+        * Set pointers to 1st group in our list and in the "other" list, as
+        * appropriate.  Voices 1 and 2 (vno=0,1) refer to each other as the
+        * "other" voice.  (If there is only one voice, ogs_p is set to voice 2
+        * (vno=1) which is a null pointer.)  Voice 3 (vno=2) always ignores
+        * the other voices, so for it, ogs_p is a null pointer.
+        */
+       gs_p = mainll_p->u.staff_p->groups_p[ vno ];
+       ogs_p = vno == 2 ? (struct GRPSYL *)0 :
+                       mainll_p->u.staff_p->groups_p[ ! vno ];
+
+       /*
+        * Loop through every group, setting some group vertical coordinates.
+        */
+       for ( ; gs_p != 0; gs_p = gs_p->next) {
+               /*
+                * Just as for nontablature groups, RY is always 0, the center
+                * of the staff, even if it falls outside the group's
+                * rectangle.  RN and RS were set in locllnotes() and
+                * intertab() in setnotes.c. 
+                */
+               gs_p->c[RY] = 0;
+
+               /*
+                * Slashes and "with" lists are allowed only if there are
+                * frets, so if there aren't any frets, skip the rest.
+                */
+               if (gs_p->grpcont != GC_NOTES || gs_p->nnotes == 0)
+                       continue;
+
+               /*
+                * No tab groups have stems, but we still need to set a pseudo
+                * stem length if the group has slashes and otherwise 0.
+                */
+               if (gs_p->slash_alt == 0) {
+                       gs_p->stemlen = 0;      /* no slashes */
+               } else {
+                       /* find distance between outer frets of the group */
+                       stepdiff = gs_p->notelist[0].stepsup -
+                               gs_p->notelist[ gs_p->nnotes - 1 ].stepsup;
+
+                       /* default length + distance between outer notes */
+                       defsteps = Defstemsteps * (allsmall(gs_p, gs_p) == YES
+                                       ? SM_STEMFACTOR : 1.0);
+                       gs_p->stemlen = stepdiff * Stepsize * TABRATIO +
+                                       defsteps * Stepsize;
+
+                       bf = abs(gs_p->slash_alt);      /* slashes */
+                       if (gs_p->basictime >= 16)
+                               bf++;   /* slashes need extra 1 if 16, 32, ...*/
+                       if (bf > 2)
+                               gs_p->stemlen += (bf - 2) * Flagsep;
+
+                       if (gs_p->stemdir == UP) {
+                               gs_p->c[RN] = gs_p->notelist[gs_p->nnotes - 1]
+                                               .c[RN] + gs_p->stemlen;
+                       } else {
+                               gs_p->c[RS] = gs_p->notelist[0]
+                                               .c[RY] - gs_p->stemlen;
+                       }
+               }
+
+               /* decrease RS based on "with" lists */
+               expgroup(gs_p, ogs_p);
+       }
+}
+\f
+/*
+ * Name:        stemforced()
+ *
+ * Abstract:    Did the user force stem(s) to go the wrong way?
+ *
+ * Returns:     YES    at least one group was forced
+ *             NO      no groups were forced
+ *
+ * Description: This function figures out whether the user forced *gs_p's stem
+ *             to go DOWN for voice 1 or UP for voice 2 when the vscheme and
+ *             the other voice would normally prevent it; or if *gs_p is at
+ *             the start of a beamed set, it checks this for all groups in
+ *             the set.
+ */
+
+static int
+stemforced(gs_p, ogs_p)
+
+struct GRPSYL *gs_p;           /* the group we are asking about */
+struct GRPSYL *ogs_p;          /* first group in other voice's linked list */
+
+{
+       RATIONAL starttime;     /* of the group in question */
+       RATIONAL endtime;       /* of the group in question */
+       struct GRPSYL *gs2_p;   /* loop through groups */
+
+
+       /* voice 3 never cares, so is never considered to be forced */
+       if (gs_p->vno == 3) {
+               return (NO);
+       }
+
+       /* grace cannot be forced */
+       if (gs_p->grpvalue == GV_ZERO) {
+               return (NO);
+       }
+
+       switch (svpath(gs_p->staffno, VSCHEME)->vscheme) {
+       case V_1:
+               return (NO);    /* no forcing is needed in this vscheme */
+       case V_2OPSTEM:
+       case V_3OPSTEM:
+               /*
+                * If and only if a stem is backwards, we are forced.  Note
+                * that even for the beamed case, we only have to check one
+                * group, since all stems in the set go the same direction.
+                */
+               if (gs_p->vno == 1 && gs_p->stemdir == DOWN ||
+                   gs_p->vno == 2 && gs_p->stemdir == UP) {
+                       return (YES);
+               }
+               return (NO);
+       }
+
+       /*
+        * We are in one of the freestem vschemes.
+        */
+
+       /* if the other voice doesn't exist, we know we were not forced */
+       if (ogs_p == 0) {
+               return (NO);    /* other voice does not exist */
+       }
+
+       /* if all stems are normal, we are not forced (only need to check 1) */
+       if (gs_p->vno == 1 && gs_p->stemdir == UP ||
+           gs_p->vno == 2 && gs_p->stemdir == DOWN) {
+               return (NO);
+       }
+
+       /* check if the other voice is all spaces during this time */
+
+       /* find start time of *gs_p by summing all previous groups */
+       starttime = Zero;
+       for (gs2_p = gs_p->prev; gs2_p != 0; gs2_p = gs2_p->prev) {
+               starttime = radd(starttime, gs2_p->fulltime);
+       }
+
+       /* find end time of *gs_p (or the whole beamed set) */
+       endtime = starttime;
+       for (gs2_p = gs_p; gs2_p != 0; gs2_p = gs2_p->next) {
+               endtime = radd(endtime, gs2_p->fulltime);
+               if (gs2_p->beamloc == NOITEM || gs2_p->beamloc == ENDITEM &&
+                                               gs_p->grpvalue != GV_ZERO) {
+                       break;
+               }
+       }
+
+       if (hasspace(ogs_p, starttime, endtime) == YES) {
+               return (NO);    /* all spaces, forcing was not needed */
+       } else {
+               return (YES);   /* notes/rests, we were forced */
+       }
+}
+\f
+/*
+ * Name:        setbeam()
+ *
+ * Abstract:    Set stem lengths for a beamed set of groups.
+ *
+ * Returns:     void
+ *
+ * Description: This function uses linear regression to figure out where the
+ *             best place to put the beam is, for a beamed set of groups, or
+ *             two groups that are alted together.  (Although there are
+ *             special cases where the beam needs to be forced horizontal
+ *             instead of using linear regression.)  But if the user specified
+ *             the stem lengths of the first and last group, it just goes with
+ *             that, instead of using linear regression.  It then sets the
+ *             stem lengths for all the groups in the set.
+ *
+ *             Groups involved in cross staff beaming should never call here.
+ *             That work must be done later in absvert.c.
+ */
+
+static void
+setbeam(start_p, end_p, ogs_p)
+
+struct GRPSYL *start_p;                /* first in beamed set */
+struct GRPSYL *end_p;          /* after last in beamed set */
+struct GRPSYL *ogs_p;          /* first group in other voice's GRPSYL list */
+
+{
+       struct GRPSYL *gs_p;    /* loop through the groups in the beamed set */
+       struct GRPSYL *last_p;  /* point at last valid group before end_p */
+       float sx, sy;           /* sum of x and y coords of notes */
+       float xbar, ybar;       /* average x and y coords of notes */
+       float top, bottom;      /* numerator & denominator for finding b1 */
+       float temp;             /* scratch variable */
+       float startx, endx;     /* x coord of first and last note */
+       float starty, endy;     /* y coord of first and last note */
+       float b0, b1;           /* y intercept and slope */
+       float maxb0, minb0;     /* max and min y intercepts */
+       float stemshift;        /* x distance of stem from center of note */
+       float deflen;           /* default len of a stem, based on basictime */
+       float shortdist;        /* amount of stem shortening allowed (inches)*/
+       float x;                /* x coord of a stem */
+       int css_affects_beam;   /* does CSS affect the position of the beam? */
+       int all_notes_other_staff; /* all notes in all groups on other staff */
+       int one_end_forced;     /* is stem len forced on one end only? */
+       int slope_forced;       /* is the slope of the beam forced? */
+       float forced_slope;     /* slope that the user forced */
+       int bf;                 /* number of beams/flags */
+       int shortest;           /* basictime of shortest note in group */
+       int num;                /* number of notes */
+       short *steps;           /* stepsup of beamside notes */
+       int patlen;             /* length of a pattern of notes */
+       int match;              /* does the pattern match? */
+       int k;                  /* loop variable */
+       int n;                  /* loop variable */
+
+
+       /*
+        * Find whether CSS affects the position of the beam, and whether all
+        * groups have all their notes on the other staff.  css_affects_stemtip
+        * asks (for this beamed case) whether any group's other-staff notes
+        * are stemside; that is, whether the stem points to the other staff,
+        * because then obviously the coord of the stem tip depends on where
+        * those notes are.  If all of this group's notes are on the other
+        * staff, you might expect that we would have to regard the stem tip as
+        * affected even if the stem is towards the normal staff.  But we
+        * prefer to pretend they aren't, so that we can handle more beamed
+        * sets on the first pass.  We fake out those groups (see the comment a
+        * little later).  And yet, if all the groups are this way, we do
+        * regard the beam as affected, because then we aren't going to enforce
+        * the rule about stems reaching the middle staff line.
+        */
+       /* first set normal (non-CSS) values */
+       css_affects_beam = NO;
+       all_notes_other_staff = NO;
+       if (CSSused == YES) {   /* don't waste time looking if CSS not used */
+               all_notes_other_staff = YES;
+               css_affects_beam = css_affects_stemtip(start_p);
+               for (gs_p = start_p; gs_p != end_p; gs_p = nextsimilar(gs_p)) {
+                       if (NNN(gs_p) != 0) {
+                               all_notes_other_staff = NO;
+                       }
+               }
+               if (all_notes_other_staff == YES) {
+                       css_affects_beam = YES;
+               }
+       }
+
+       /*
+        * If the beam is not affected by CSS, handle this beamed set on the
+        * first pass only.  If it is affected, handle it on the second
+        * pass only.
+        */
+       if (css_affects_beam != CSSpass) {
+               return;
+       }
+
+       /*
+        * If the beam is "not affected by CSS", there could still be groups
+        * where all the notes are CSS.  We fake them out here, setting the
+        * BNOTE's RY an octave from the center line.  We need some plausible
+        * value there for finding the beam position.  AY hasn't been used yet,
+        * so use it as a holding area.  We need to restore RY before returning
+        * from this function.
+        */
+       if (CSSused == YES && CSSpass == NO) {
+               for (gs_p = start_p; gs_p != end_p; gs_p = nextsimilar(gs_p)) {
+                       if (NNN(gs_p) == 0) {
+                               BNOTE(gs_p).c[AY] = BNOTE(gs_p).c[RY];
+                               BNOTE(gs_p).c[RY] = 7 * Stepsize *
+                                       ((gs_p->stemdir == UP) ? -1.0 : 1.0);
+                       }
+               }
+       }
+
+       last_p = 0;     /* prevent useless 'used before set' warnings */
+
+       /* find the last valid group */
+       for (gs_p = start_p; gs_p != end_p; gs_p = nextsimilar(gs_p)) {
+               last_p = gs_p;
+       }
+
+       /*
+        * If the user specified the stem length on one end (first or last) but
+        * not the other, remember that fact.  In that case we will execute the
+        * normal (both ends unforced) algorithm, but then at the last minute
+        * force the end that was given.
+        */
+       one_end_forced = IS_STEMLEN_KNOWN(start_p->stemlen) !=
+                        IS_STEMLEN_KNOWN(last_p->stemlen);
+
+       /*
+        * If the user specified the stem length for the first and last groups,
+        * simply use these values to define where the beam is, and set all the
+        * stem lengths.
+        */
+       if (IS_STEMLEN_KNOWN(start_p->stemlen) &&
+           IS_STEMLEN_KNOWN(last_p->stemlen)) {
+
+               /*
+                * If the first and last groups had stemlen set to zero, force
+                * all groups to have stemlen zero, and return.  No beam will
+                * be drawn.
+                */
+               if (start_p->stemlen == 0.0 && last_p->stemlen == 0.0) {
+                       for (gs_p = start_p; gs_p != end_p;
+                                       gs_p = nextsimilar(gs_p)) {
+                               gs_p->stemlen = 0.0;
+                       }
+                       restore_ry(start_p, end_p);
+                       return;
+               }
+
+               /* they weren't both zero, so continue on finding the beam */
+               start_p->stemlen *= Staffscale;
+               stemshift = getstemshift(start_p);
+               if (start_p->stemdir == DOWN)
+                       stemshift = -stemshift;
+               last_p->stemlen *= Staffscale;
+
+               /* find coords of the ends of the stems on the outer groups */
+               startx = start_p->c[AX] + stemshift;
+               endx = last_p->c[AX] + stemshift;
+               starty = BNOTE(start_p).c[RY] + start_p->stemlen *
+                               (start_p->stemdir == UP ? 1.0 : -1.0);
+               endy = BNOTE(last_p).c[RY] + last_p->stemlen *
+                               (last_p->stemdir == UP ? 1.0 : -1.0);
+
+               /* find slope and y intercept of line through those points */
+               b1 = (starty - endy) / (startx - endx);
+               b0 = starty - b1 * startx;
+
+               /* loop through all groups, setting stem length */
+               for (gs_p = start_p; gs_p != end_p; gs_p = nextsimilar(gs_p)) {
+                       x = gs_p->c[AX] + stemshift;    /* X coord of stem */
+
+                       /* first set stemlen to beam's Y coord minus note's */
+                       gs_p->stemlen = (b0 + b1 * x) - BNOTE(gs_p).c[RY];
+
+                       /* if stems are down, reverse it */
+                       if (gs_p->stemdir == DOWN)
+                               gs_p->stemlen = -(gs_p->stemlen);
+
+                       finalstemadjust(gs_p);
+               }
+
+               /* set relative vertical coords of any embedded rests */
+               embedrest(start_p, last_p, b1, b0);
+
+               restore_ry(start_p, end_p);
+               return;
+       }
+
+       /*
+        * If the user forced the beam's angle to some value, find what that is
+        * in terms of slope.  Later we will force this value to be used.  The
+        * 0.001 is to allow for floating point roundoff error.
+        */
+       if (fabs(start_p->beamslope - NOBEAMANGLE) < 0.001) {
+               slope_forced = NO;
+               forced_slope = 0.0;     /* not used, keep lint happy */
+       } else {
+               slope_forced = YES;
+               forced_slope = tan(start_p->beamslope * PI / 180.0);
+       }
+
+       /*
+        * When both end groups have stemlen zero, we set all groups' stemlens
+        * to zero, and no beam will be drawn.  Above we handled the case
+        * where the user forced both ends to zero.  Here we handle the case
+        * where the ends are defaulting to zero, or one end is defaulting to
+        * zero and the user forced the other one.  But don't do this if the
+        * slope is forced.
+        */
+       if (Defstemsteps == 0.0 && ! slope_forced && ( ! one_end_forced ||
+                       start_p->stemlen == 0.0 || last_p->stemlen == 0.0)) {
+               for (gs_p = start_p; gs_p != end_p; gs_p = nextsimilar(gs_p)) {
+                       gs_p->stemlen = 0.0;
+               }
+               restore_ry(start_p, end_p);
+               return;
+       }
+
+       /*
+        * Use linear regression to find the best-fit line through the centers
+        * of the notes.  In this function, we will always be concerned with
+        * the X coord of the group as a whole (disregarding any notes that are
+        * on the "wrong" side of the stem) but the Y coord of the note of the
+        * group that's nearest to the beam (thus the BNOTE macro).  The X
+        * coords used are absolute, but the Y coords are relative to the
+        * center line of the staff, since we don't know the absolute Y coords
+        * yet, and it wouldn't affect the result anyway.
+        *
+        * First get sum of x and y coords, to find averages.
+        */
+       sx = sy = 0;
+       num = 0;
+       for (gs_p = start_p; gs_p != end_p; gs_p = nextsimilar(gs_p)) {
+               sx += gs_p->c[AX];
+               sy += BNOTE(gs_p).c[RY];
+               num++;                  /* count number of notes */
+       }
+
+       xbar = sx / num;
+       ybar = sy / num;
+
+       /* accumulate numerator & denominator of regression formula for b1 */
+       top = bottom = 0;
+       for (gs_p = start_p; gs_p != end_p; gs_p = nextsimilar(gs_p)) {
+               temp = gs_p->c[AX] - xbar;
+               top += temp * (BNOTE(gs_p).c[RY] - ybar);
+               bottom += temp * temp;
+       }
+
+       b1 = top / bottom;              /* slope */
+       /*
+        * We could also figure:
+        *      b0 = ybar - b1 * xbar;          y intercept
+        * to get the equation of the regression line:  y = b0 + b1 * x
+        * but we're going to change b0 later anyway.  Now, there are certain
+        * cases where we want to override the slope determined by regression,
+        * so revise b1 if that is the case.
+        */
+
+       /* if first and last notes are equal, force horizontal */
+       if (BNOTE(start_p).stepsup == BNOTE(last_p).stepsup)
+               b1 = 0.0;
+
+       /* check for more reasons to force the beam horizontal */
+       if (b1 != 0.0 && num >= 3) {
+               /* get an array of each group's beamside note's stepsup */
+               MALLOCA(short, steps, num);
+               for (n = 0, gs_p = start_p; n < num;
+                               n++, gs_p = nextsimilar(gs_p)) {
+                       steps[n] = BNOTE(gs_p).stepsup;
+               }
+
+               /*
+                * Check for a repeating pattern of notes.  Try every possible
+                * pattern length <= half as long as set.  If found, force the
+                * beam horizontal.
+                */
+               for (patlen = num / 2; patlen >= 2; patlen--) {
+                       /* must be an integer number of pattern repetitions */
+                       if (num % patlen != 0) {
+                               continue;       /* groups were left over */
+                       }
+                       /* see if initial pattern repeats perfectly */
+                       match = YES;
+                       for (n = 0; n < patlen && match == YES; n++) {
+                               for (k = n + patlen; k < num; k += patlen) {
+                                       if (steps[k] != steps[n]) {
+                                               match = NO;
+                                               break;
+                                       }
+                               }
+                       }
+                       /* if all repeats matched, force horizontal & break */
+                       if (match == YES) {
+                               b1 = 0.0;
+                               break;
+                       }
+               }
+
+               /*
+                * If still not horizontal, check for the case where all the
+                * beamside notes are the same except for just the first, or
+                * just the last, being different and in the direction
+                * opposite the stemdir.  If so, force horizontal.
+                */
+               if (b1 != 0.0) {
+                       /* make sure all the inner groups are the same */
+                       match = YES;
+                       for (n = 2; n < num - 1; n++) {
+                               if (steps[n] != steps[1]) {
+                                       match = NO;
+                                       break;
+                               }
+                       }
+                       /* if inner groups same, check the other conditions */
+                       if (match == YES) {
+                               if (start_p->stemdir == DOWN) {
+                                       if ((steps[0] > steps[1] &&
+                                           steps[num-1] == steps[1]) ||
+                                           (steps[0] == steps[1] &&
+                                           steps[num-1] > steps[1])) {
+                                               b1 = 0.0;
+                                       }
+                               } else {        /* UP */
+                                       if ((steps[0] < steps[1] &&
+                                           steps[num-1] == steps[1]) ||
+                                           (steps[0] == steps[1] &&
+                                           steps[num-1] < steps[1])) {
+                                               b1 = 0.0;
+                                       }
+                               }
+                       }
+               }
+               FREE(steps);
+       }
+
+       /*
+        * Find half the width of a note head; the stems will need to be
+        * shifted by that amount from the center of the notes so that they
+        * will meet the edge of the notes properly.  If the stems are up,
+        * they will be on the right side of (normal) notes, else left.  Set
+        * the X positions for the first and last stems.  (If these are alted
+        * groups, the noteheadchar may not be 4; but this is close enough.)
+        */
+       stemshift = getstemshift(start_p);
+       if (start_p->stemdir == DOWN)
+               stemshift = -stemshift;
+       startx = start_p->c[AX] + stemshift;    /* first group's stem */
+       endx = last_p->c[AX] + stemshift;       /* last group's stem */
+
+       /*
+        * The original slope derived by linear regression must be adjusted in
+        * certain ways.  First, override it if the user wants that; otherwise
+        * adjust according to the beamslope parameter.
+        */
+       if (slope_forced) {
+               b1 = forced_slope;
+       } else {
+               b1 = adjslope(start_p, b1, NO);
+       }
+
+       /*
+        * Calculate a new y intercept (b0).  First pass parallel lines
+        * through each note, and record the maximum and minimum y intercepts
+        * that result.
+        */
+       b0 = BNOTE(start_p).c[RY] - b1 * start_p->c[AX];
+       maxb0 = minb0 = b0;             /* init to value for first note */
+       /* look at rest of them */
+       for (gs_p = nextsimilar(start_p); gs_p != end_p;
+                       gs_p = nextsimilar(gs_p)) {
+               b0 = BNOTE(gs_p).c[RY] - b1 * gs_p->c[AX];
+               if (b0 > maxb0)
+                       maxb0 = b0;
+               else if (b0 < minb0)
+                       minb0 = b0;
+       }
+
+       /*
+        * Find the basictime of the shortest note in the group, considering
+        * also any slashes or alternations on it.  (Except that slash has a
+        * different meaning on grace groups, and doesn't affect their stem
+        * length.)  Then set the default stem length based on that.
+        */
+       shortest = 0;
+       for (gs_p = start_p; gs_p != end_p; gs_p = nextsimilar(gs_p)) {
+               if (gs_p->basictime >= 8)
+                       bf = drmo(gs_p->basictime) - 2; /* no. of beams/flags*/
+               else
+                       bf = 0;                 /* none on quarter or longer */
+               if (gs_p->grpvalue == GV_NORMAL)
+                       bf += abs(gs_p->slash_alt);/* slashes or alternations */
+               /*
+                * In certain cases where there are accidentals, we need to
+                * artificially increase bf to keep the beams from overlapping
+                * with the accidental.
+                */
+               if (gs_p != start_p && gs_p->stemdir == UP &&
+                               gs_p->notelist[0].accidental != '\0' &&
+                               gs_p->notelist[0].accidental != 'x' &&
+                               b1 > 0 && bf > 1) {
+                       bf += 3.5 * b1 * (Stepsize / Flagsep) * ((bf > 1) +
+                                       (gs_p->notelist[0].accidental == 'B'));
+               }
+               if (bf > shortest)
+                       shortest = bf;
+       }
+       if (allsmall(start_p, last_p) == NO) {
+               /* at least one group has a normal size note */
+               deflen = Defstemsteps * Stepsize;
+               if (shortest > 2)
+                       deflen += (shortest - 2) * Flagsep;
+       } else {
+               /* all groups have all small notes */
+               deflen = Defstemsteps * SM_STEMFACTOR * Stepsize;
+               if (shortest > 2)
+                       deflen += (shortest - 2) * 4.0 * POINT * Staffscale;
+       }
+
+       /*
+        * The outer edge of the beam should be deflen steps away from the
+        * average position of the notes, as defined by the linear regression
+        * line.  But don't allow any note to be closer than a certain number
+        * of steps less than that, the number as given by the stemshorten parm.
+        */
+       shortdist = vvpath(start_p->staffno, start_p->vno, STEMSHORTEN)
+                       ->stemshorten * Stepsize;
+       if (start_p->stemdir == UP) {
+               if (maxb0 - minb0 > shortdist)
+                       b0 = maxb0 + deflen - shortdist;
+               else
+                       b0 += deflen;
+       } else { /* DOWN */
+               if (maxb0 - minb0 > shortdist)
+                       b0 = minb0 - deflen + shortdist;
+               else
+                       b0 -= deflen;
+       }
+
+       /*
+        * Another adjustment may be needed so that all stems will reach the
+        * center line of the staff.  (Not to be done for small groups, or when
+        * all notes in all groups are on the other staff [CSS], or when
+        * some stemdirs have been forced wrong way despite the other voice, or
+        * we have alternations and no normal beams, or for voice 3.)
+        */
+       starty = b0 + b1 * startx;      /* y coord near left end of beam */
+       endy = b0 + b1 * endx;          /* y coord near right end of beam */
+       if (start_p->basictime >= 2 && start_p->grpsize == GS_NORMAL &&
+                       stemforced(start_p, ogs_p) == NO &&
+                       start_p->vno != 3 && all_notes_other_staff == NO) {
+               if (slope_forced) {
+                       /* move both ends the same amount to preserve slope */
+                       if (start_p->stemdir == UP) {
+                               if (starty < 0) {
+                                       endy -= starty;
+                                       starty = 0;
+                               }
+                               if (endy < 0) {
+                                       starty -= endy;
+                                       endy = 0;
+                               }
+                       } else { /* DOWN */
+                               if (starty > 0) {
+                                       endy -= starty;
+                                       starty = 0;
+                               }
+                               if (endy > 0) {
+                                       starty -= endy;
+                                       endy = 0;
+                               }
+                       }
+               } else {
+                       /* move just the end(s) that need to be moved */
+                       if (start_p->stemdir == UP) {
+                               if (starty < 0)
+                                       starty = 0;
+                               if (endy < 0)
+                                       endy = 0;
+                       } else { /* DOWN */
+                               if (starty > 0)
+                                       starty = 0;
+                               if (endy > 0)
+                                       endy = 0;
+                       }
+               }
+       }
+
+       /*
+        * If the first and last groups's stems now end at the center line, and
+        * the beam slope used to be nonzero, force one end to be a step beyond
+        * the center line, so that the beam will still have some slope to it.
+        * But don't do this if the user is forcing the beam's slope.
+        */
+       if ( ! slope_forced && fabs(starty) < Stdpad &&
+                               fabs(endy) < Stdpad && b1 != 0.0) {
+               if (start_p->stemdir == UP) {
+                       if (b1 > 0.0) {
+                               endy = Stepsize;
+                       } else if (b1 < 0.0) {
+                               starty = Stepsize;
+                       }
+               } else {        /* DOWN */
+                       if (b1 > 0.0) {
+                               starty = -Stepsize;
+                       } else if (b1 < 0.0) {
+                               endy = -Stepsize;
+                       }
+               }
+       }
+
+       /*
+        * If y at the ends of the beam differs by less than a step (allowing a
+        * fudge factor for roundoff error), force the beam horizontal by
+        * setting one end farther away from the notes.  But don't do it if the
+        * user is forcing a particular slope.
+        */
+       if ( ! slope_forced && fabs(starty - endy) < Stepsize - 0.001) {
+               if (start_p->stemdir == UP) {
+                       if (starty > endy) {
+                               endy = starty;
+                       } else {
+                               starty = endy;
+                       }
+               } else {        /* DOWN */
+                       if (starty < endy) {
+                               endy = starty;
+                       } else {
+                               starty = endy;
+                       }
+               }
+       }
+
+       /* recalculate slope and y intercept from (possibly) new endpoints */
+       b1 = (endy - starty) / (endx - startx);         /* slope */
+       b0 = starty - b1 * startx;                      /* y intercept */
+       temp = b0;                      /* remember this value for later */
+
+       /* do some additional work for nongrace groups */
+       if (start_p->grpvalue == GV_NORMAL) {
+               /*
+                * If this is not an alted pair, there may be embedded grace
+                * notes, and we may need to lengthen our stems to avoid them.
+                */
+               if (start_p->slash_alt >= 0)
+                       b0 = embedgrace(start_p, b1, b0);
+
+               /* may need to lengthen stems to avoid embedded clefs */
+               b0 = embedclef(start_p, b1, b0);
+
+               /* set relative vertical coords of any embedded rests */
+               embedrest(start_p, last_p, b1, b0);
+
+               /*
+                * If there is another voice, we might need to lengthen our
+                * stems so their notes won't run into our beam.  If we had
+                * embedded rests, they would also be moved.
+                */
+               b0 = avoidothervoice(start_p, last_p, b1, b0, ogs_p);
+
+               /* update these by the amount the y intercept changed */
+               starty += temp - b0;
+               endy += temp - b0;
+       }
+
+       restore_ry(start_p, end_p);
+
+       /*
+        * If one end's stem len was forced but not the other, now is the time
+        * to apply that forcing.  So in effect, we have taken the beam as
+        * determined by the normal algorithm and now we change the vertical
+        * coord of this end.  If the slope was also forced, move the other
+        * end by the same amount so that the slope won't change.
+        */
+       if (one_end_forced) {
+               if (IS_STEMLEN_KNOWN(start_p->stemlen)) {
+                       start_p->stemlen *= Staffscale;
+                       temp = starty;
+                       starty = BNOTE(start_p).c[RY] + start_p->stemlen *
+                                       (start_p->stemdir == UP ? 1.0 : -1.0);
+                       if (slope_forced) {
+                               endy += starty - temp;
+                       }
+               } else {
+                       last_p->stemlen *= Staffscale;
+                       temp = endy;
+                       endy = BNOTE(last_p).c[RY] + last_p->stemlen *
+                                       (last_p->stemdir == UP ? 1.0 : -1.0);
+                       if (slope_forced) {
+                               starty += endy - temp;
+                       }
+               }
+
+               /* recalculate */
+               b1 = (endy - starty) / (endx - startx); /* slope */
+               b0 = starty - b1 * startx;              /* y intercept */
+
+               /*
+                * Re-do embedded rests now that things have moved.  As for the
+                * other adjustments above, we can't re-do them because they
+                * may force stem lengths to change.  If things collide, too
+                * bad, the user forced the one stem length.  It might be
+                * possible to avoid the collision by moving the other end,
+                * but likely not, and it's too late now anyhow.
+                */
+               embedrest(start_p, last_p, b1, b0);
+       }
+
+       /*
+        * At this point we know where to put the main beam (the one needed for
+        * eighth notes).  Figure out and set the correct stem lengths for all
+        * of these beamed groups.
+        */
+       for (gs_p = start_p; gs_p != end_p; gs_p = nextsimilar(gs_p)) {
+               x = gs_p->c[AX] + stemshift;    /* X coord of stem */
+
+               /* first set stemlen to beam's Y coord minus note's */
+               gs_p->stemlen = (b0 + b1 * x) - BNOTE(gs_p).c[RY];
+
+               /* if stems down, reverse stemlen, should make it positive */
+               if (gs_p->stemdir == DOWN) {
+                       gs_p->stemlen = -(gs_p->stemlen);
+               }
+               /* but if negative length, error */
+               if (gs_p->stemlen < 0) {
+                       l_ufatal(gs_p->inputfile, gs_p->inputlineno,
+                                       "stem length was forced negative");
+               }
+
+               finalstemadjust(gs_p);
+       }
+}
+\f
+/*
+ * Name:        restore_ry()
+ *
+ * Abstract:    Restore RY coordinates if need be.
+ *
+ * Returns:     void
+ *
+ * Description: This function undoes what the code near the start of setbeam()
+ *             did.  But it doesn't have to set AY back, because it is garbage
+ *             and will be overwritten later anyway.
+ */
+
+static void
+restore_ry(start_p, end_p)
+
+struct GRPSYL *start_p;                /* first in beamed set */
+struct GRPSYL *end_p;          /* after last in beamed set */
+
+{
+       struct GRPSYL *gs_p;    /* loop through the groups in the beamed set */
+
+
+       if (CSSused == YES && CSSpass == NO) {
+               for (gs_p = start_p; gs_p != end_p; gs_p = nextsimilar(gs_p)) {
+                       if (NNN(gs_p) == 0) {
+                               BNOTE(gs_p).c[RY] = BNOTE(gs_p).c[AY];
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        embedgrace()
+ *
+ * Abstract:    Change the Y intercept if necessary for embedded grace groups.
+ *
+ * Returns:     new y intercept value (may be no change)
+ *
+ * Description: When grace groups are embedded inside a set of nongrace groups,
+ *             the beam(s) for the nongrace may have to be put farther away
+ *             from their note heads, so that these beams won't collide with
+ *             the grace groups.  This function returns the new Y intercept
+ *             for the equation of the nongraces' main beam, which accom-
+ *             plishes this.  When there aren't any embedded grace groups,
+ *             or they are in certain positions, this Y intercept will be the
+ *             same as the old Y intercept.
+ */
+
+static double
+embedgrace(start_p, b1, b0)
+
+struct GRPSYL *start_p;        /* first group in nongrace beamed set */
+double b1;             /* slope */
+double b0;             /* y intercept */
+
+{
+       struct GRPSYL *gs_p;    /* point to grace group being looked at */
+       struct GRPSYL *prev_p;  /* point to nongrace group preceding gs_p */
+       struct GRPSYL *next_p;  /* point to nongrace group following gs_p */
+       float beamthick;        /* total thickness of beams and space between*/
+       float ycross;           /* where grace stem would hit nongrace beam */
+
+
+       /*
+        * Loop through all the grace groups that are embedded somewhere
+        * between the first and last groups of this nongrace beamed set.
+        * If their stems point the opposite way, there is no problem.  But
+        * if not, we may need to move the main beam(s) out of the way.
+        */
+       for (gs_p = start_p; gs_p->grpvalue == GV_ZERO ||
+                               gs_p->beamloc != ENDITEM; gs_p = gs_p->next) {
+               if (gs_p->grpvalue == GV_NORMAL)
+                       continue;       /* ignore nongrace groups */
+
+               /*
+                * Find the preceding and following nongrace group.  Whichever
+                * has the least (slowest) basictime, that determines how many
+                * full beams will connect those two groups.  (You take log2 of
+                * it and subtract 2.)
+                */
+               prev_p = prevnongrace(gs_p);
+               next_p = nextnongrace(gs_p);
+
+               /* thickness of relevant beams at right side of grace */
+               beamthick = beamoff(next_p, PB_LEFT, gs_p->c[AE], start_p);
+
+               /*
+                * Find the AX and RY coords of the end of the grace group
+                * stem that is nearest the nongrace beam(s).  Then, if this
+                * point would run into or beyond the nongrace beam(s), change
+                * the Y intercept (b0) so that it won't.
+                */
+               ycross = b1 * gs_p->c[AE] + b0;
+               if (start_p->stemdir == UP) {
+                       if (ycross - beamthick < gs_p->c[RN])
+                               b0 += gs_p->c[RN] - (ycross - beamthick);
+               } else {        /* stemdir == DOWN */
+                       if (ycross + beamthick > gs_p->c[RS])
+                               b0 -= (ycross + beamthick) - gs_p->c[RS];
+               }
+
+               /* thickness of relevant beams at left side of grace */
+               beamthick = beamoff(prev_p, PB_RIGHT, gs_p->c[AW], start_p);
+
+               ycross = b1 * gs_p->c[AW] + b0;
+               if (start_p->stemdir == UP) {
+                       if (ycross - beamthick < gs_p->c[RN])
+                               b0 += gs_p->c[RN] - (ycross - beamthick);
+               } else {        /* stemdir == DOWN */
+                       if (ycross + beamthick > gs_p->c[RS])
+                               b0 -= (ycross + beamthick) - gs_p->c[RS];
+               }
+       }
+
+       return (b0);    /* new (possibly changed) Y intercept */
+}
+\f
+/*
+ * Name:        embedclef()
+ *
+ * Abstract:    Change the Y intercept if necessary for embedded clefs.
+ *
+ * Returns:     new y intercept value (may be no change)
+ *
+ * Description: When clef changes occur before groups in a beamed set, the
+ *             beam(s) for the set may have to be put farther away from their
+ *             note heads, so that these beams won't collide with the clefs.
+ *             This function returns the new Y intercept for the equation of
+ *             the nongraces' main beam, which accomplishes this.  When there
+ *             aren't any embedded clefs, or they are in certain positions,
+ *             this Y intercept will be the same as the old Y intercept.
+ */
+
+static double
+embedclef(start_p, b1, b0)
+
+struct GRPSYL *start_p;        /* first group in nongrace beamed set */
+double b1;             /* slope */
+double b0;             /* y intercept */
+
+{
+       struct GRPSYL *gs_p;    /* point to group being looked at */
+       struct GRPSYL *pbgs_p;  /* group whose partial beams may impact us */
+       float north, south;     /* top and bottom edge of a clef */
+       float horizontal;       /* left or right edge of a clef */
+       float beamthick;        /* total thickness of beams and space between*/
+       float ycross;           /* where grace stem would hit nongrace beam */
+
+
+       /*
+        * Loop through all the groups between the first and last groups of
+        * this nongrace beamed set, including the last but not the first, and
+        * including any embedded graces.  If any are preceded by a clef, we
+        * may need to move the beam(s) out of the way.
+        */
+       for (gs_p = start_p->next; gs_p != 0 && ! (gs_p->prev->grpvalue ==
+                       GV_NORMAL && gs_p->prev->beamloc == ENDITEM);
+                       gs_p = gs_p->next) {
+
+               if (gs_p->clef == NOCLEF) {
+                       continue;       /* ignore groups with no clef */
+               }
+
+               /* find the vertical edges of the clef */
+               (void)clefvert(gs_p->clef, YES, &north, &south);
+               north *= Staffscale;
+               south *= Staffscale;
+
+               /*
+                * Make sure the right side of the clef doesn't collide with
+                * the beams.
+                */
+               /* find right side of the clef */
+               horizontal = gs_p->c[AW] - CLEFPAD * Staffscale;
+
+               /* group whose partial beams we need to worry about */
+               pbgs_p = gs_p->grpvalue == GV_ZERO ? nextnongrace(gs_p) : gs_p;
+
+               /* thickness of relevant beams at right side of clef */
+               beamthick = beamoff(pbgs_p, PB_LEFT, horizontal, start_p);
+
+               /* Find RY where right edge of clef would hit the main beam. If
+                * that edge of clef would hit any beam, change Y intercept. */
+               ycross = b1 * horizontal + b0;
+               if (start_p->stemdir == UP) {
+                       if (ycross - beamthick < north) {
+                               b0 += north - (ycross - beamthick);
+                       }
+               } else {        /* stemdir == DOWN */
+                       if (ycross + beamthick > south) {
+                               b0 -= (ycross + beamthick) - south;
+                       }
+               }
+
+               /*
+                * Make sure the left side of the clef doesn't collide with
+                * the beams.
+                */
+               /* find left side of the clef */
+               horizontal -= clefwidth(gs_p->clef, YES) * Staffscale;
+
+               /* group whose partial beams we need to worry about */
+               pbgs_p = prevnongrace(gs_p);
+
+               /* thickness of relevant beams at left side of clef */
+               beamthick = beamoff(pbgs_p, PB_RIGHT, horizontal, start_p);
+
+               /* Find RY where left edge of clef would hit main beam.  If
+                * that edge of clef would hit any beam, change Y intercept. */
+               ycross = b1 * horizontal + b0;
+               if (start_p->stemdir == UP) {
+                       if (ycross - beamthick < north) {
+                               b0 += north - (ycross - beamthick);
+                       }
+               } else {        /* stemdir == DOWN */
+                       if (ycross + beamthick > south) {
+                               b0 -= (ycross + beamthick) - south;
+                       }
+               }
+       }
+
+       return (b0);    /* new (possibly changed) Y intercept */
+}
+\f
+/*
+ * Name:        beamoff()
+ *
+ * Abstract:    On one side of group, get height of beams and spaces between.
+ *
+ * Returns:     height in inches
+ *
+ * Description: This function is called with a nongrace group in beamed set, to
+ *             find out how many beams it has on one side of it and how high
+ *             they are.  If the group is the first or last in the set, the
+ *             side must be the interior side.  Partial beams are also figured
+ *             in, if they might extend far enough to reach the "boundary"
+ *             coordinate.
+ */
+
+static double
+beamoff(gs_p, side, boundary, start_p)
+
+struct GRPSYL *gs_p;   /* group we are concerned with */
+int side;              /* which side of the group, PB_LEFT or PB_RIGHT */
+double boundary;       /* X coord of edge of thing that must not collide */
+struct GRPSYL *start_p;        /* first group in nongrace beamed set */
+
+{
+       struct GRPSYL *ogs_p;   /* nongrace group on "side" side of gs_p */
+       struct GRPSYL *o2gs_p;  /* nongrace group on other side of gs_p */
+       int beams;              /* number of beams for figuring collision */
+       int minbasic;           /* minimum (longest) basictime */
+
+
+       /*
+        * If it's the left side of this group we're worried about, set ogs_p
+        * to the previous nongrace, and o2gs_p to the next.  If right, do the
+        * opposite.
+        */
+       if (side == PB_LEFT) {
+               ogs_p = prevnongrace(gs_p);
+               o2gs_p = nextnongrace(gs_p);
+       } else {
+               ogs_p = nextnongrace(gs_p);
+               o2gs_p = prevnongrace(gs_p);
+       }
+
+       /*
+        * Whichever of the two groups {this group, the group on the side
+        * that we're worried about} has the least (slowest) basictime, that
+        * determines how many full beams will connect those two groups.  (You
+        * take log2 of it and subtract 2.)
+        */
+       minbasic = MIN(gs_p->basictime, ogs_p->basictime);
+       if (minbasic >= 8) {
+               beams = drmo(MIN(gs_p->basictime, ogs_p->basictime)) - 2;
+       } else {
+               beams = 0;      /* must be an alternation */
+       }
+
+       /* add the number of alternation beams, if any */
+       if (gs_p->slash_alt < 0) {
+               beams -= gs_p->slash_alt;
+       }
+
+       /*
+        * If our group needs more beams than the group on the requested side,
+        * and the stem is in the direction where partial beams would stick out
+        * beyond our GRPSYL boundary and the partial beams are long enough to
+        * possibly collide with the thing we're trying to avoid . . .
+        */
+       if (gs_p->basictime > ogs_p->basictime &&
+                       (side == PB_LEFT && gs_p->stemdir == DOWN &&
+                               gs_p->c[AW] - 5.0 * Stepsize < boundary ||
+                       side == PB_RIGHT && gs_p->stemdir == UP &&
+                               gs_p->c[AE] + 5.0 * Stepsize > boundary)) {
+               /*
+                * If we are the start or end of this beamed set, or we need
+                * more beams than the group on the other side . . .
+                */
+               if (gs_p->beamloc == STARTITEM || gs_p->beamloc == ENDITEM ||
+                               gs_p->basictime > o2gs_p->basictime) {
+                       /*
+                        * We have partial beam(s); if on the side that matters
+                        * to us, reset the number of beams to include partials.
+                        */
+                       if (pbeamside(gs_p, start_p) == side) {
+                               beams = drmo(gs_p->basictime) - 2;
+                       }
+               }
+       }
+
+       /*
+        * To get total beam thickness, multiply the size of one beam by the
+        * number of beams.  Also add in a small fudge factor.
+        */
+       return (Flagsep * beams + Stepsize / 2.0);
+}
+\f
+/*
+ * Name:        embedrest()
+ *
+ * Abstract:    Set relative vertical coords of rests embedded in beamed sets.
+ *
+ * Returns:     void
+ *
+ * Description: Rests' vertical coords were set in restsyl.c.  But when a rest
+ *             is embedded in a beamed set, its coords may have to be changed
+ *             now so that it fits well.
+ */
+
+static void
+embedrest(start_p, last_p, b1, b0)
+
+struct GRPSYL *start_p;        /* first group in nongrace beamed set */
+struct GRPSYL *last_p; /* last group in nongrace beamed set */
+double b1;             /* slope */
+double b0;             /* y intercept */
+
+{
+       struct GRPSYL *gs_p;    /* point to group in the set */
+       struct GRPSYL *gp_p, *gpp_p; /* prev nongrace note, and prev to that */
+       struct GRPSYL *gn_p, *gnn_p; /* next nongrace note, and next to that */
+       int bp, bn;             /* beams on gp_p and gn_p */
+       int partial;            /* partial beams in our way */
+       char rchar;             /* char for the rest */
+       int size;               /* font size */
+       float asc, des;         /* ascent and descent of a rest */
+       float beamthick;        /* total thickness of beams and space between*/
+       float ycross;           /* where rest would hit beam */
+       int beams;              /* number of beams joining two groups */
+
+
+       /*
+        * Loop through the interior groups of this set, setting relative
+        * vertical coords of rest groups.  (Outer groups are never rests.)
+        */
+       for (gs_p = start_p->next; gs_p != last_p; gs_p = gs_p->next) {
+
+               /* skip nonrests */
+               if (gs_p->grpcont != GC_REST)
+                       continue;
+
+               /* skip cases where the user is forcing the coords */
+               if (gs_p->restdist != NORESTDIST)
+                       continue;
+
+               rchar = restchar(gs_p->basictime);
+               size = (gs_p->grpsize == GS_NORMAL ? DFLT_SIZE : SMALLSIZE);
+               asc = ascent(FONT_MUSIC, size, rchar) * Staffscale;
+               des = descent(FONT_MUSIC, size, rchar) * Staffscale;
+
+
+               /* find prev nongrace note group; will be in this beamed set */
+               for (gp_p = gs_p->prev; gp_p->grpcont != GC_NOTES ||
+                               gp_p->grpvalue == GV_ZERO; gp_p = gp_p->prev)
+                       ;
+
+               /* find prev nongrace note group to that, if any */
+               for (gpp_p = gp_p->prev; gpp_p != 0 && (gpp_p->grpcont !=
+                               GC_NOTES || gpp_p->grpvalue == GV_ZERO);
+                               gpp_p= gpp_p->prev)
+                       ;
+               /* but if it's not in this beamed set, forget it */
+               if (gpp_p != 0 && gpp_p->beamloc != INITEM &&
+                                 gpp_p->beamloc != STARTITEM)
+                       gpp_p = 0;
+
+
+               /* find next nongrace note group; will be in this beamed set */
+               for (gn_p = gs_p->next; gn_p->grpcont != GC_NOTES ||
+                               gn_p->grpvalue == GV_ZERO; gn_p = gn_p->next)
+                       ;
+
+               /* find next nongrace note group to that, if any */
+               for (gnn_p = gn_p->next; gnn_p != 0 && (gnn_p->grpcont !=
+                               GC_NOTES || gnn_p->grpvalue == GV_ZERO);
+                               gnn_p= gnn_p->next)
+                       ;
+               /* but if it's not in this beamed set, forget it */
+               if (gnn_p != 0 && gnn_p->beamloc != INITEM &&
+                                 gnn_p->beamloc != ENDITEM)
+                       gnn_p = 0;
+
+
+               /* get number of beams needed by prev and next */
+               bp = numbeams(gp_p->basictime);
+               bn = numbeams(gn_p->basictime);
+
+               partial = 0;    /* init to no partial beams */
+
+               /*
+                * If the group just before our rest is notes, and this beamed
+                * set's stems are up, and the prev note needs more beams than
+                * the next note, we may have to deal with partial beams.
+                */
+               if (gs_p->prev->grpcont == GC_NOTES && start_p->stemdir == UP
+                               && bp > bn) {
+                       if (gpp_p == 0) {
+                               /* definitely partial beams on this side */
+                               partial = bp - bn;
+                       } else {
+                               /* maybe partial beams on this side */
+                               if (numbeams(gpp_p->basictime) < bp &&
+                               pbeamside(gp_p, start_p) == PB_RIGHT)
+                                       partial = bp - bn;
+                       }
+                       /* but if far enough away horizontally, we can ignore */
+                       if (gs_p->c[AW] - gp_p->c[AE] > 1.5 * Stepsize)
+                               partial = 0;
+               }
+
+               /*
+                * If the group just after our rest is notes, and this beamed
+                * set's stems are down, and the next note needs more beams than
+                * the prev note, we may have to deal with partial beams.  If
+                * the next group is grace, we might fall into this block, but
+                * that's okay; the next nongrace (gn_p) will be far enough
+                * away that partial will (correctly) be forced back to 0.
+                */
+               if (gs_p->next->grpcont == GC_NOTES && start_p->stemdir == DOWN
+                               && bn > bp) {
+                       if (gnn_p == 0) {
+                               /* definitely partial beams on this side */
+                               partial = bn - bp;
+                       } else {
+                               /* maybe partial beams on this side */
+                               if (numbeams(gnn_p->basictime) < bn &&
+                               pbeamside(gn_p, start_p) == PB_LEFT)
+                                       partial = bn - bp;
+                       }
+                       /* but if far enough away horizontally, we can ignore */
+                       if (gn_p->c[AW] - gs_p->c[AE] > 1.5 * Stepsize)
+                               partial = 0;
+               }
+
+               /* full beams joining prev and next, plus relevant partials */
+               beams = MIN(bp, bn) + partial;
+
+               /*
+                * To get total beam thickness, multiply the size of one beam
+                * by the number of beams.
+                */
+               beamthick = Flagsep * beams;
+
+               /* find where outer beam hits our rest's X coord */
+               ycross = b1 * gs_p->c[AX] + b0;
+
+               /* find vertical coord, quantizing the results */
+               if (start_p->stemdir == UP) {
+                       gs_p->c[RY] = nearestline(ycross - beamthick -
+                                       asc - Stepsize);
+               } else {        /* stemdir == DOWN */
+                       gs_p->c[RY] = nearestline(ycross + beamthick +
+                                       des + Stepsize);
+               }
+
+               gs_p->c[RN] = gs_p->c[RY] + asc;
+               gs_p->c[RS] = gs_p->c[RY] - des;
+       }
+}
+\f
+/*
+ * Name:        avoidothervoice()
+ *
+ * Abstract:    Change the Y intercept if necessary to avoid the other voice.
+ *
+ * Returns:     new y intercept value (may be no change)
+ *
+ * Description: When there is another voice, its groups might collide with our
+ *             voice's beams, unless we lengthen our groups' stems.  This
+ *             function returns the new Y intercept for the equation of the
+ *             our voice's main beam, which accomplishes this.  When there is
+ *             no other voice, or its groups don't interfere with our beam,
+ *             this Y intercept will be the same as the old Y intercept.
+ *             When it changes, embedded rests' coords need to be changed too.
+ */
+
+static double
+avoidothervoice(start_p, last_p, b1, b0, ogs_p)
+
+struct GRPSYL *start_p;        /* first group in nongrace beamed set */
+struct GRPSYL *last_p; /* last group in nongrace beamed set */
+double b1;             /* slope */
+double b0;             /* y intercept */
+struct GRPSYL *ogs_p;  /* first group in the other voice */
+
+{
+       struct GRPSYL *prev_p;  /* point to nongrace group preceding gs_p */
+       struct GRPSYL *prev2_p; /* point to nongrace group before that one */
+       struct GRPSYL *next_p;  /* point to nongrace group following gs_p */
+       struct GRPSYL *next2_p; /* point to nongrace group after that one */
+       struct GRPSYL *gs_p;    /* point to group being looked at */
+       float beamthick;        /* total thickness of beams and space between*/
+       float ycross;           /* where grace stem would hit nongrace beam */
+       float fary;             /* farthest y coord of other voice's group */
+       int beams;              /* number of beams joining two nongrace groups*/
+       float thismove;         /* how far one item requires the beam to move*/
+       float move;             /* distance to move intercept */
+
+
+       move = 0.0;             /* init to no move */
+
+       /*
+        * Loop through all the groups in the other voice.  (If there is no
+        * other voice, this loop will execute zero times.)  If any of its
+        * groups land on or beyond our beam, move our beam farther away so
+        * they don't.
+        */
+       for (gs_p = ogs_p; gs_p != 0; gs_p = gs_p->next) {
+
+               /* spaces and rests can't interfere with anything */
+               if (gs_p->grpcont != GC_NOTES)
+                       continue;
+
+               /* if this group is outside our beamed set, ignore it */
+               if (gs_p->c[AX] <= start_p->c[AX] ||
+                   gs_p->c[AX] >=  last_p->c[AX])
+                       continue;
+
+               /*
+                * Find which groups in our set immediately preceed and follow
+                * the other voice's group.  These will be prev_p and next_p.
+                */
+               for (prev_p = next_p = start_p;
+                    next_p->c[AX] < gs_p->c[AX];
+                    prev_p = next_p, next_p = nextnongrace(next_p))
+                       ;
+
+               /*
+                * If next_p is lined up with gs_p, and is a note group, that
+                * means these groups were "compatible" (see setgrps.c), and so
+                * there can be no way that we would have to move our beam.
+                * But if next_p is a rest, handle the situation and continue.
+                */
+               if (next_p->c[AX] == gs_p->c[AX]) {
+                       if (next_p->grpcont == GC_NOTES)
+                               continue;       /* compatible, no problem */
+
+                       /*
+                        * Find the AX and RY coords of the outer edge of the
+                        * outer note of the other voice's group that is the
+                        * farthest in the direction of our beam.  Then, if
+                        * this point would run into or beyond the rest, find
+                        * how far to move the Y intercept (b0) so that it
+                        * won't.  Remember the farthest move needed.
+                        */
+                       if (start_p->stemdir == UP) {
+                               fary = gs_p->notelist[0].c[RN] + Stdpad;
+                               if (next_p->c[RS] < fary) {
+                                       thismove = fary - next_p->c[RS];
+                                       move = MAX(move, thismove);
+                               }
+                       } else { /* stemdir == DOWN */
+                               fary = gs_p->notelist[ gs_p->nnotes-1 ].c[RS]
+                                               - Stdpad;
+                               if (next_p->c[RN] > fary) {
+                                       thismove = fary - next_p->c[RN];
+                                       move = MIN(move, thismove);
+                               }
+                       }
+
+                       continue;
+               }
+
+               /*
+                * Find which of prev_p and next_p has the least (slowest)
+                * basictime.  That determines how many full beams will connect
+                * those two groups.  (You take log2 of it and subtract 2.)
+                * Then add in any alternation beams.
+                */
+               if (prev_p->basictime >= 8)
+                       beams = drmo(MIN(prev_p->basictime, next_p->basictime))
+                                       - 2;
+               else
+                       beams = 0;
+
+               if (prev_p->slash_alt < 0)
+                       beams -= prev_p->slash_alt;
+
+               /*
+                * Find out if there are partial beams on the left side of the
+                * following group or right side of the preceding group.  If
+                * so, that group's basictime may determine the total number of
+                * beams that could interfere with our group, if it's close
+                * enough.
+                */
+               if (prev_p->basictime < next_p->basictime && next_p->stemdir ==
+                   DOWN && next_p->c[AX] - gs_p->c[AX] < 5 * Stepsize) {
+
+                       /* find nongrace group after "next", if one exists */
+                       next2_p = nextnongrace(next_p);
+
+                       /* if "next" group has partial beams . . . */
+                       if (next2_p == 0 || next_p->beamloc == ENDITEM ||
+                               next_p->basictime > next2_p->basictime) {
+
+                               /* if on its left side, reset total beams */
+                               if (pbeamside(next_p, start_p) == PB_LEFT)
+                                       beams = drmo(next_p->basictime) - 2;
+                       }
+               } else if (prev_p->basictime > next_p->basictime && prev_p->
+               stemdir == UP && gs_p->c[AX] - prev_p->c[AX] < 5 * Stepsize) {
+
+                       /* find nongrace group before "prev", if one exists */
+                       prev2_p = prevnongrace(prev_p);
+
+                       /* if "prev" group has partial beams . . . */
+                       if (prev2_p == 0 || prev_p->beamloc == STARTITEM ||
+                               prev_p->basictime > prev2_p->basictime) {
+
+                               /* if on its right side, reset total beams */
+                               if (pbeamside(prev_p, start_p) == PB_RIGHT)
+                                       beams = drmo(prev_p->basictime) - 2;
+                       }
+               }
+
+               beamthick = Flagsep * beams + Stepsize;
+
+               /*
+                * Find the AX and RY coords of the outer edge of the outer
+                * note of the other voice's group that is the farthest in the
+                * direction of our beam.  Then, if this point would run into
+                * or beyond the nongrace beam(s), find how much the Y
+                * intercept (b0) would have to move to avoid the collision.
+                * Remember the farthest move found so far.
+                */
+               ycross = b1 * gs_p->c[AX] + b0;
+               if (start_p->stemdir == UP) {
+
+                       fary = gs_p->notelist[0].c[RN] + Stdpad;
+                       if (ycross - beamthick < fary) {
+                               thismove = fary - (ycross - beamthick);
+                               move = MAX(move, thismove);
+                       }
+
+               } else { /* stemdir == DOWN */
+
+                       fary = gs_p->notelist[ gs_p->nnotes-1 ].c[RS] - Stdpad;
+                       if (ycross + beamthick > fary) {
+                               thismove = fary - (ycross + beamthick);
+                               move = MIN(move, thismove);
+                       }
+               }
+       }
+
+       if (move == 0.0)
+               return (b0);            /* no change; return old intercept */
+
+       /*
+        * If our beamed set has any embedded rests, we want to move the rests
+        * too.  We really only have to move rests that the other voice is
+        * bumping into, but it will probably look better to move them all.
+        * We need to move everything by a multiple of 2 stepsizes, since rests
+        * should be positioned that way.
+        */
+       for (gs_p = start_p->next; gs_p != last_p; gs_p = gs_p->next) {
+               /* break out if we find a rest */
+               if (gs_p->grpcont == GC_REST)
+                       break;
+       }
+       if (gs_p != last_p) {
+               /*
+                * We found a rest.  Round the amount the intercept moved up to
+                * a multiple of 2 stepsizes.
+                */
+               move = (move < 0.0 ? -1.0 : 1.0) * 2.0 * Stepsize *
+                       ((int)(fabs(move) / (2.0 * Stepsize)) + 1);
+
+               /* move every embedded rest by this amount */
+               for (gs_p = start_p->next; gs_p != last_p; gs_p = gs_p->next) {
+                       if (gs_p->grpcont == GC_REST) {
+                               gs_p->c[RN] += move;
+                               gs_p->c[RY] += move;
+                               gs_p->c[RS] += move;
+                       }
+               }
+       }
+
+       return (b0 + move);     /* new Y intercept */
+}
+\f
+/*
+ * Name:        setgroupvert()
+ *
+ * Abstract:    Set RN and RS for each group of given type in a linked list.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through the linked list of groups for one
+ *             voice for one measure.  It handles either grace groups or non-
+ *             grace groups, whichever it is told to do.  It sets the RN and
+ *             RS for the groups.
+ */
+
+static void
+setgroupvert(grpvalue, firstgs_p, ogs_p)
+
+int grpvalue;                  /* should we do grace groups or normal groups?*/
+struct GRPSYL *firstgs_p;      /* point to first group in a linked list */
+struct GRPSYL *ogs_p;          /* point to first group in other linked list */
+
+{
+       struct GRPSYL *gs_p;    /* point along groups in a linked list */
+       float outstem;  /* the part of the stemlen outside notes of group */
+       float stemtip;  /* coord of the end of the stem */
+       float old;              /* old group boundary */
+       float delta;            /* change in group boundary */
+
+
+       debug(32, "setgroupvert file=%s line=%d grpvalue=%d",
+                       firstgs_p->inputfile, firstgs_p->inputlineno, grpvalue);
+       /*
+        * Loop through every group, skipping rests, spaces, and groups of the
+        * wrong type (grace vs. nongrace), setting the relative vertical
+        * coordinates.
+        */
+       for (gs_p = firstgs_p; gs_p != 0; gs_p = gs_p->next) {
+               if (gs_p->grpcont != GC_NOTES)
+                       continue;
+               if (gs_p->grpvalue != grpvalue)
+                       continue;
+
+               /*
+                * Back in setnotes.c, we set RY to 0, the center line of the
+                * staff.  N was set to the top of the highest note, plus
+                * padding, excluding any CSS notes.  S is the analogous thing,
+                * below.  But if all notes are CSS, N and S were set to 0.
+                */
+
+               /*
+                * Now we want to set the stemlen, as well as we can.  For
+                * groups whose step tips are not affected by CSS, we do it in
+                * the non-CSS pass; otherwise we do it in the CSS pass.
+                */
+               if (css_affects_stemtip(gs_p) == CSSpass) {
+
+                       /*
+                        * If the group has a stem or pseudostem, we do this
+                        * work.  Extend the appropriate group boundary to
+                        * reach to the end of the stem.  Do this for all
+                        * groups with real stems or pseudostems, excluding
+                        * cross staff beaming (where we don't know yet how
+                        * long the stems will be and we don't want to include
+                        * them in the group boundary anyway, since it would
+                        * prevent stem overlapping that we want).  That means
+                        * half notes or shorter (excluding grace quarter
+                        * notes), or anything with slash/alternations.
+                        */
+                       if (gs_p->beamto == CS_SAME &&
+                          (gs_p->basictime >= 2 || gs_p->slash_alt != 0) &&
+                           gs_p->stemlen != 0.0) {
+
+                               outstem = gs_p->stemlen
+                                       - (gs_p->notelist[0].c[RY]
+                                       - gs_p->notelist[gs_p->nnotes-1].c[RY]);
+                               /*
+                                * In the CSS pass we also have to adjust the
+                                * absolute coords, by the same amount as the
+                                * relative, since those have been set by now.
+                                */
+                               if (gs_p->stemdir == UP) {
+                                       stemtip = gs_p->notelist[0].c[RY]
+                                               + outstem;
+                                       old = gs_p->c[RN];
+                                       gs_p->c[RN] = MAX(stemtip, gs_p->c[RN])
+                                               + Stdpad;
+                                       if (CSSpass == YES) {
+                                               delta = gs_p->c[RN] - old;
+                                               gs_p->c[AN] += delta;
+                                       }
+                               } else {
+                                       stemtip = gs_p->notelist[gs_p->nnotes-1]
+                                               .c[RY] - outstem;
+                                       old = gs_p->c[RS];
+                                       gs_p->c[RS] = MIN(stemtip, gs_p->c[RS])
+                                               - Stdpad;
+                                       if (CSSpass == YES) {
+                                               delta = gs_p->c[RS] - old;
+                                               gs_p->c[AS] += delta;
+
+                                       }
+                               }
+                       }
+               }
+
+               if (CSSpass == NO) {
+                       /*
+                        * Increase RN and decrease RS based on "with" lists.
+                        * Do this only in the first pass.  This depends on the
+                        * fact that "with" lists are always put on the side
+                        * away from the other staff, when CSS is involved.
+                        */
+                       expgroup(gs_p, ogs_p);
+               } else {
+                       /*
+                        * In the CSS pass, various group boundaries need more
+                        * adjustment.
+                        */
+                       if (gs_p->stemdir == UP) {
+                               if (gs_p->stemto == CS_ABOVE && NNN(gs_p) == 0){
+                                       gs_p->c[RS] = gs_p->notelist[
+                                               gs_p->nnotes-1].c[RS] - Stdpad;
+                                       gs_p->c[AS] += gs_p->c[RS];
+                               }
+                               if (gs_p->stemto == CS_BELOW && NNN(gs_p) == 0){
+                                       gs_p->c[RN] = gs_p->notelist[
+                                               gs_p->nnotes-1].c[RY] +
+                                               gs_p->stemlen;
+                                       expgroup(gs_p, ogs_p);
+                                       gs_p->c[AN] = gs_p->c[AY] + gs_p->c[RN];
+                               }
+                               if (gs_p->stemto == CS_SAME &&
+                                               gs_p->stemlen > 0) {
+                                       gs_p->c[RN] = gs_p->notelist
+                                       [gs_p->nnotes-1].c[RY] + gs_p->stemlen
+                                       + Stdpad;
+
+                                       gs_p->c[AN] = gs_p->notelist
+                                       [gs_p->nnotes-1].c[AY] + gs_p->stemlen
+                                       + Stdpad;
+                               }
+                               if (gs_p->stemto == CS_ABOVE &&
+                                               gs_p->stemlen == 0) {
+                                       gs_p->c[RN] = gs_p->notelist[0].c[RN]
+                                               + Stdpad;
+                                       gs_p->c[AN] = gs_p->notelist[0].c[AN]
+                                               + Stdpad;
+                               }
+                       } else {
+                               if (gs_p->stemto == CS_BELOW && NNN(gs_p) == 0){
+                                       gs_p->c[RN] = gs_p->notelist[0].c[RN]
+                                               + Stdpad;
+                                       gs_p->c[AN] += gs_p->c[RN];
+                               }
+                               if (gs_p->stemto == CS_ABOVE && NNN(gs_p) == 0){
+                                       gs_p->c[RS] = gs_p->notelist[0].c[RY] -
+                                               gs_p->stemlen;
+                                       expgroup(gs_p, ogs_p);
+                                       gs_p->c[AS] = gs_p->c[AY] + gs_p->c[RS];
+                               }
+                               if (gs_p->stemto == CS_SAME &&
+                                               gs_p->stemlen > 0) {
+                                       gs_p->c[RS] = gs_p->notelist[0].c[RY]
+                                               - gs_p->stemlen - Stdpad;
+
+                                       gs_p->c[AS] = gs_p->notelist[0].c[AY]
+                                               - gs_p->stemlen - Stdpad;
+                               }
+                               if (gs_p->stemto == CS_BELOW &&
+                                               gs_p->stemlen == 0) {
+                                       gs_p->c[RS] = gs_p->notelist
+                                               [gs_p->nnotes-1].c[RS] - Stdpad;
+                                       gs_p->c[AS] = gs_p->notelist
+                                               [gs_p->nnotes-1].c[AS] - Stdpad;
+                               }
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        settuplet()
+ *
+ * Abstract:    Figure out where tuplet bracket goes and change RN and RS.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given a pointer to the first GRPSYL in a
+ *             tuplet whose bracket is to be printed.  It figures out where
+ *             the tuplet bracket and number should go, and sets tupextend for
+ *             all the groups, to show where the tuplet bracket would go.
+ *             Even if the bracket ends up not getting printed, this is needed
+ *             for placing the number.
+ */
+
+static void
+settuplet(start_p, staff_p)
+
+struct GRPSYL *start_p;                /* first group in the tuplet */
+struct STAFF *staff_p;         /* staff the tuplet is on */
+
+{
+       struct GRPSYL *gs_p;    /* loop through the groups in the tuplet */
+       struct GRPSYL *last_p;  /* point the last group in the tuplet */
+       struct GRPSYL *end_p;   /* point beyond the last group in the tuplet */
+       struct NOTE *note_p;    /* pointer to an outside note of a group */
+       float sx, sy;           /* sum of x and y coords of north or south */
+       float xbar, ybar;       /* average x and y coords of north or south */
+       float top, bottom;      /* numerator & denominator for finding b1 */
+       float temp;             /* scratch variable */
+       float startx, endx;     /* x coord of first and last north or south */
+       float starty, endy;     /* y coord of first and last north or south */
+       float b0, b1;           /* y intercept and slope */
+       float maxb0, minb0;     /* max and min y intercepts */
+       float shift;            /* x dist bracket reaches beyond end groups */
+       float acceast, accwest; /* horizontal coords of an accidental */
+       float accvert;          /* north or south of an accidental */
+       float asc, des, wid;    /* ascent, descent, and width of an acc */
+       float numeast, numwest; /* horizontal coords of the tuplet number */
+       float numvert;          /* vertical edge of number closest to staff */
+       float height;           /* height of the tuplet number */
+       int css_affects_tup;    /* does CSS affect any group in the tuplet? */
+       int coord;              /* RN or RS, depending on where bracket goes */
+                               /* or AN or AS if CSSpass == YES */
+       int halfstaff;          /* half the height of staff, in stepsizes */
+       int num;                /* number of groups in tuplet */
+       float vert[2];          /* vertical coords of two groups */
+       int n;                  /* loop variable */
+
+
+       debug(32, "settuplet file=%s line=%d", start_p->inputfile,
+                       start_p->inputlineno);
+       /*
+        * If start_p is pointing at a grace group that precedes the first real
+        * group of the tuplet, move start_p forward to the first real group.
+        * Actually, this shouldn't be necessary; the parser is doing it now.
+        */
+       while (start_p->grpvalue == GV_ZERO)
+               start_p = start_p->next;
+
+       /*
+        * Find out which side the tuplet number (and bracket, if needed)
+        * should go on.  That determines which coord we pay attention to.
+        * The other determining factor is whether this is the CSS pass.
+        */
+       if (tupdir(start_p, staff_p) == PL_ABOVE) {
+               coord = CSSpass == YES ? AN : RN;
+       } else {
+               coord = CSSpass == YES ? AS : RS;
+       }
+
+       /* find whether CSS affects any group in the set */
+       css_affects_tup = NO;
+       if (CSSused == YES) {   /* don't waste time looking if CSS not used */
+               for (gs_p = start_p; gs_p != 0 && ! (gs_p != start_p &&
+                                       gs_p->prev->tuploc == ENDITEM);
+                                       gs_p = gs_p->next) {
+                       if (gs_p->stemto == CS_ABOVE &&
+                                               (coord == AN || coord == AN) ||
+                           gs_p->stemto == CS_BELOW &&
+                                               (coord == AS || coord == AS)) {
+                               css_affects_tup = YES;
+                               break;
+                       }
+               }
+       }
+
+       /*
+        * If no groups are affected by CSS, handle this tuplet on the
+        * first pass only.  If some are affected, handle it on the second
+        * pass only.
+        */
+       if (css_affects_tup != CSSpass) {
+               return;
+       }
+
+       last_p = 0;     /* prevent useless 'used before set' warnings */
+
+       /*
+        * If the first group is STARTITEM, there are multiple groups in the
+        * tuplet.  If it is LONEITEM, there is only one.
+        */
+       if (start_p->tuploc == STARTITEM) {
+               /*
+                * Use linear regression to find the best-fit line through the
+                * RN or RS, or AN or AS, of the groups, as the case may be.
+                * The X coords used are absolute, but the Y coords are, in the
+                * normal (non-CSSpass case) relative to the center line of the
+                * staff, since we don't know the absolute Y coords yet, and it
+                * wouldn't affect the result anyway.  But if this is the CSS
+                * pass, we do know the absolute vertical coords, and we have
+                * to use them, since we are dealing with two staffs.
+                *
+                * First get sum of x and y coords, to find averages.  Remember
+                * where last valid group is.  Only nongrace groups can be
+                * tuplet members, although there could be grace groups before
+                * a tuplet member.  We ignored any grace group before the
+                * first real tuplet member, but any others must be dealt with.
+                */
+               sx = sy = 0;
+               num = 0;
+               for (gs_p = start_p; gs_p != 0 && ! (gs_p != start_p &&
+                                       gs_p->prev->tuploc == ENDITEM);
+                                       gs_p = gs_p->next) {
+                       sx += gs_p->c[AX];
+                       sy += gs_p->c[coord];
+                       num++;                  /* count number of groups */
+                       last_p = gs_p;
+               }
+               /* last_p now points at last valid group */
+
+               end_p = gs_p;   /* point end_p beyond last tuplet member */
+
+               xbar = sx / num;
+               ybar = sy / num;
+
+               /* accum numerator & denominator of regression formula for b1 */
+               top = bottom = 0;
+               for (gs_p = start_p; gs_p != end_p; gs_p = gs_p->next) {
+                       temp = gs_p->c[AX] - xbar;
+                       top += temp * (gs_p->c[coord] - ybar);
+                       bottom += temp * temp;
+               }
+
+               b1 = top / bottom;              /* slope */
+               /*
+                * We could also figure:
+                *      b0 = ybar - b1 * xbar;          y intercept
+                * to get the equation of the regression line:  y = b0 + b1 * x
+                * but we're going to change b0 later anyway.  Now, there are
+                * certain cases where we want to override the slope determined
+                * by regression, so revise b1 if that is the case.
+                */
+
+               /* if first and last groups are equal, force horizontal */
+               if (start_p->c[coord] == last_p->c[coord])
+                       b1 = 0.0;
+
+               /* if repeating pattern of two coords, force horizontal */
+               if (b1 != 0.0 && num >= 4 && num % 2 == 0) {
+                       vert[0] = start_p->c[coord];
+                       vert[1] = start_p->next->c[coord];
+                       for (n = 0, gs_p = start_p; n < num;
+                                       n++, gs_p = gs_p->next) {
+                               if (n >= 2 && gs_p->c[coord] != vert[n % 2])
+                                       break;
+                       }
+                       if (n == num)
+                               b1 = 0.0;
+               }
+
+       } else {        /* LONEITEM */
+               /*
+                * There's only one group, so there's no need to apply linear
+                * regression.  But we need to set up certain variables so that
+                * later code in this function can treat both cases the same.
+                */
+               last_p = start_p;       /* point at last tuplet member */
+               end_p = start_p->next;  /* point beyond last tuplet member */
+               b1 = 0;                 /* set horizontal slope */
+               b0 = start_p->c[coord]; /* y intercept based on this group */
+       }
+
+       /*
+        * Find half the width of a note head; the end of the tuplet bracket
+        * reaches that far beyond the X coords of the outer groups.  Set
+        * the X positions for these ends.
+        */
+       shift = getstemshift(last_p);
+       startx = start_p->c[AX] - shift;        /* start of tuplet bracket */
+       endx = last_p->c[AX] + shift;           /* end of tuplet bracket */
+
+       /*
+        * The original line derived by linear regression must be adjusted in
+        * certain ways.  First, don't let the slope exceed plus or minus 0.7,
+        * since that would look bad.
+        */
+       if (b1 > 0.7)
+               b1 = 0.7;
+       else if (b1 < -0.7)
+               b1 = -0.7;
+
+       /*
+        * Calculate a new y intercept (b0).  First pass parallel lines
+        * through each group's extremity, and record the maximum and minimum
+        * y intercepts that result.
+        */
+       b0 = start_p->c[coord] - b1 * start_p->c[AX];
+       maxb0 = minb0 = b0;             /* init to value for first group */
+       /* look at rest of them */
+       for (gs_p = start_p; gs_p != end_p; gs_p = gs_p->next) {
+               b0 = gs_p->c[coord] - b1 * gs_p->c[AX];
+               if (b0 > maxb0)
+                       maxb0 = b0;
+               else if (b0 < minb0)
+                       minb0 = b0;
+       }
+
+       /*
+        * The outer edge of the tuplet bracket, including the number, should
+        * be TUPHEIGHT away from the group that sticks out the farthest.
+        */
+       if (coord == RN || coord == AN) {
+               b0 = maxb0 + Tupheight;
+       } else {        /* RS or AS */ 
+               b0 = minb0 - Tupheight;
+       }
+
+       /*
+        * Calculate the Y positions of the start and end of the bracket from
+        * the X positions, and the slope and Y intercept we have tentatively
+        * chosen.  If, however, the bracket is going to fall within the staff,
+        * make adjustments so it won't.
+        */
+       starty = b0 + b1 * startx;      /* y coord near left end of beam */
+       endy = b0 + b1 * endx;          /* y coord near right end of beam */
+       halfstaff = svpath(staff_p->staffno, STAFFLINES)->stafflines == 5
+                       ? 4 : 1;
+
+       if (coord == RN) {
+               if (starty < halfstaff * Stepsize + Tupheight)
+                       starty = halfstaff * Stepsize + Tupheight;
+               if (endy < halfstaff * Stepsize + Tupheight)
+                       endy = halfstaff * Stepsize + Tupheight;
+       } else if (coord == RS) {
+               if (starty > -halfstaff * Stepsize - Tupheight)
+                       starty = -halfstaff * Stepsize - Tupheight;
+               if (endy > -halfstaff * Stepsize - Tupheight)
+                       endy = -halfstaff * Stepsize - Tupheight;
+       }
+
+       /*
+        * If y at the ends of the bracket only differs by less than 2 points,
+        * set end equal to the start to avoid a jagged look.
+        */
+       if (endy - starty < 2 * POINT && endy - starty > -2 * POINT) {
+               endy = (starty + endy) / 2.;
+               starty = endy;
+       }
+
+       /* recalculate slope and y intercept from (possibly) new endpoints */
+       b1 = (endy - starty) / (endx - startx);         /* slope */
+       b0 = starty - b1 * startx;                      /* y intercept */
+
+       /*
+        * The vertical extension of accidentals is not included in group
+        * boundaries, and so the calculation of the tuplet bracket's equation
+        * has ignored them so far.  In general, this is no problem.  If an
+        * accidental touches or slightly crosses that line, who cares?  But we
+        * would like to keep it from running into the tuplet number.  So scan
+        * through the notes closest to the bracket, checking for accidentals.
+        * (Notes a step or more from there would never really be a problem.)
+        * Also, accidentals on the first group can never be a problem.
+        */
+       (void)tupnumsize(start_p, &numwest, &numeast, &height, staff_p);
+       numvert = (starty + endy) / 2 + (coord == RN || coord == AN ?
+                       -height : height) / 2;
+
+       for (gs_p = start_p->next; gs_p != end_p; gs_p = gs_p->next) {
+
+               if (gs_p->grpcont != GC_NOTES)
+                       continue;
+
+               note_p = &gs_p->notelist[ coord == RN || coord == AN ?
+                               0 : gs_p->nnotes - 1 ];
+               if (note_p->accidental == '\0')
+                       continue;
+
+               /*
+                * The note of this group nearest the bracket has an acci-
+                * dental.  Find its horizontal midpoint, and vertical coord
+                * nearest the bracket.  Add padding to the vertical coord.
+                */
+               accdimen(note_p, &asc, &des, &wid);
+               asc *= Staffscale;
+               des *= Staffscale;
+               wid *= Staffscale;
+
+               accwest = gs_p->c[AX] + note_p->waccr;
+               acceast = accwest + wid;
+
+               if (coord == RN || coord == AN) {
+                       accvert = note_p->c[CSSpass == YES ? AY : RY]
+                                       + asc + Stepsize;
+               } else {
+                       accvert = note_p->c[CSSpass == YES ? AY : RY]
+                                       - des - Stepsize;
+               }
+
+               /* if acc is completely to the left of the number, try next */
+               if (acceast < numwest)
+                       continue;
+
+               /* if acc is completely to the right, get out */
+               if (accwest > numeast)
+                       break;
+
+               /*
+                * If acc sticks out beyond the edge of the number, change the
+                * y intercept by that amount to prevent it.  Then get out,
+                * since no later groups could be that nearby.
+                */
+               if ((coord == RN || coord == AN) && accvert > numvert ||
+                   (coord == RS || coord == AS) && accvert < numvert) {
+                       b0 += accvert - numvert;
+                       break;
+               }
+       }
+
+       /*
+        * At this point we know where to put the tuplet bracket.  Set
+        * tupextend in all the groups, to reach the tuplet bracket.
+        */
+       for (gs_p = start_p; gs_p != end_p; gs_p = gs_p->next)
+               gs_p->tupextend = (b0 + b1 * gs_p->c[AX]) - gs_p->c[coord];
+}
+\f
+/*
+ * Name:        expgroup()
+ *
+ * Abstract:    Decide side for "with" list & expand vertical group vertically.
+ *
+ * Returns:     void
+ *
+ * Description: This function decides which side of the group a "with" list
+ *             should be put, and calls applywith() to alter the group's
+ *             vertical boundaries accordingly.
+ */
+
+static void
+expgroup(gs_p, ogs_p)
+
+struct GRPSYL *gs_p;   /* the group to be worked on */
+struct GRPSYL *ogs_p;  /* the other group */
+
+{
+       struct GRPSYL *g_p;     /* earlier GRPSYLs in *gs_p's list */
+       RATIONAL vtime;         /* time preceding this group in measure */
+       int side;               /* side to put things on (1=top, -1=bottom) */
+
+
+       side = 0;       /* prevent useless 'used before set' warnings */
+
+       /*
+        * Define a chunk of code for the cases where the stem may be allowed
+        * to go either way.  It goes opposite the stem for normal, with the
+        * stem for tab.
+        */
+#define FREESTEM                                                       \
+       {                                                               \
+               if (is_tab_staff(gs_p->staffno) == YES) {               \
+                       side = -1;      /* we know stemdir is DOWN */   \
+                       gs_p->normwith = NO;                            \
+               } else {                                                \
+                       side = gs_p->stemdir == UP ? -1 : 1;            \
+                       gs_p->normwith = YES;                           \
+               }                                                       \
+       }
+
+       /*
+        * Define a chunk of code for the cases where the stem has to go a
+        * certain way, determined by which voice this is, unless forced by the
+        * user.  The "with" items are always above a voice acting as voice 1,
+        * and below a voice acting as voice 2.
+        */
+#define FIXEDSTEM                                                      \
+       {                                                               \
+               if (gs_p->pvno == 1) {                                  \
+                       side = 1;                                       \
+                       gs_p->normwith = gs_p->stemdir == UP ? NO : YES;\
+               } else {                                                \
+                       side = -1;                                      \
+                       gs_p->normwith = gs_p->stemdir == DOWN ? NO : YES;\
+               }                                                       \
+       }
+
+       /*
+        * If there is cross staff stemming, that consideration overrides all
+        * others.  We want to keep the "with" items towards our staff, hoping
+        * they will be less likely to collide with something there.
+        */
+       if (gs_p->stemto != CS_SAME) {
+               if (gs_p->stemto == CS_ABOVE) {
+                       gs_p->normwith = gs_p->stemdir == UP ? YES : NO;
+                       side = -1;
+               } else {        /*  CS_BELOW */
+                       gs_p->normwith = gs_p->stemdir == UP ? NO : YES;
+                       side = 1;
+               }
+               applywith(gs_p, side);
+               return;
+       }
+
+       /*
+        * Switch on vscheme to decide which side of the group the "with"
+        * things will be put on.
+        */
+       switch (svpath(gs_p->staffno, VSCHEME)->vscheme) {
+       case V_1:
+               FREESTEM
+               break;
+
+       case V_2OPSTEM:
+               FIXEDSTEM
+               break;
+
+       case V_2FREESTEM:
+               /*
+                * Figure out where this group starts by adding up the time
+                * values of all previous groups in the measure.  Then, treat
+                * this like V_1 or V_2OPSTEM, based on whether the other
+                * voice has space here.
+                */
+               vtime = Zero;
+               for (g_p = gs_p->prev; g_p != 0; g_p = g_p->prev)
+                       vtime = radd(vtime, g_p->fulltime);
+
+               if (hasspace(ogs_p, vtime, radd(vtime, gs_p->fulltime))) {
+                       FREESTEM
+               } else {
+                       FIXEDSTEM
+               }
+               break;
+
+       case V_3OPSTEM:
+               if (gs_p->pvno == 3) {
+                       FREESTEM        /* voice 3 is always like V_1 */
+               } else {
+                       FIXEDSTEM
+               }
+               break;
+
+       case V_3FREESTEM:
+               if (gs_p->pvno == 3) {
+                       FREESTEM        /* voice 3 is always like V_1 */
+               } else {
+                       /* voices 1 and 2 act like V_2FREESTEM */
+                       vtime = Zero;
+                       for (g_p = gs_p->prev; g_p != 0; g_p = g_p->prev)
+                               vtime = radd(vtime, g_p->fulltime);
+
+                       if (hasspace(ogs_p, vtime, radd(vtime, gs_p->fulltime))) {
+                               FREESTEM
+                       } else {
+                               FIXEDSTEM
+                       }
+               }
+               break;
+       }
+
+       /*
+        * If there is cross staff beaming and the "with" items are to be on
+        * the beam side, we can't do anything yet since we don't know yet
+        * where the beam will be.
+        */
+       if (gs_p->beamto != CS_SAME && gs_p->normwith == NO) {
+               return;
+       }
+
+       applywith(gs_p, side);
+}
+\f
+/*
+ * Name:        applywith()
+ *
+ * Abstract:    Expand vertical boundaries of group, based on "with" list.
+ *
+ * Returns:     void
+ *
+ * Description: This function adds to the RN coord of a group and/or subtracts
+ *             from the RS coord, if a "with" list is present.
+ */
+
+static void
+applywith(gs_p, side)
+
+struct GRPSYL *gs_p;   /* the group to be worked on */
+int side;              /* side to put things on (1=top, -1=bottom) */
+
+{
+       int n;                  /* loop variable */
+       float hi;               /* height of a list item */
+
+
+       /*
+        * Loop through all the "with" items, expanding the N or S coord of
+        * the group.  Each item is allowed enough space for its height, or
+        * MINWITHHEIGHT, whichever is greater.  In the print phase, items of
+        * height less than MINWITHHEIGHT will be placed so as to avoid staff
+        * lines as much as possible.
+        */
+       for (n = 0; n < gs_p->nwith; n++) {
+               hi = strheight(gs_p->withlist[n]);
+               hi = MAX(hi, Staffscale * MINWITHHEIGHT);
+               if (side == 1)
+                       gs_p->c[RN] += hi;
+               else
+                       gs_p->c[RS] -= hi;
+       }
+}
diff --git a/mup/mup/brac.c b/mup/mup/brac.c
new file mode 100644 (file)
index 0000000..44ca1f1
--- /dev/null
@@ -0,0 +1,1017 @@
+
+/* Copyright (c) 1995, 1997, 1999, 2000, 2001, 2002, 2003, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions to deal with brace/bracket lists, to make sure they don't
+ * overlap, and then to place the labels to minimize the space they use. */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+/* padding between labels in inches. **** eventually should adjust padding
+ * based on size??? ***/
+#define LABELPAD       0.125
+
+/* information to be able to determine overlaps in the brace/bracket lists */
+static struct BRAC_INFO {
+       struct STAFFSET *staffset_p;    /* bracelist or bracklist item */
+       int bractype;                   /* BRACELIST or BRACKLIST */
+       struct BRAC_INFO *nested_p;     /* pointer to another brace/bracket
+                                        * item, which has its top on the
+                                        * same staff, and presumably
+                                        * is nested inside this one */
+       struct BRAC_INFO *nested_by_p;  /* if this one is nested, pointer
+                                        * to what it is nested by, else NULL */
+       short nestlevel;                /* how many levels deep */
+       short topvisstaff;              /* top visible staff in range */
+       short botvisstaff;              /* bottom visible staff in range */
+} *Brac_info_p [MAXSTAFFS + 1];
+
+
+/* information about a label, either for a staff or group. */
+struct LABELINFO {
+       char    *label;         /* text of the label */
+       float   width;          /* strwidth(label) */
+       float   west;           /* relative distance of left edge of label
+                                * from the line between the labels and the
+                                * braces/brackets. This will be negative */
+       int     is_staff_label; /* YES for staff label, NO for group */
+       struct LABELINFO *next;/* linked list of labels at same y location */
+};
+
+/* information about all the labels that end up being printed left of a
+ * specific staff or between that staff and the one below it. */
+struct LABELLIST {
+       short staffno;                  /* which staff */
+       struct LABELINFO *label_p;      /* list of labels to be printed to
+                                        * the left of this staff */
+       struct LABELINFO *btwnlabel_p;  /* list of labels to be printed
+                                        * between this staff and the one
+                                        * below this staff */
+       short pad;                      /* how many levels of labels 
+                                        * have been put on this staff, either
+                                        * on the staff itself or on one or
+                                        * more other staffs that are
+                                        * grouped with this one */
+};
+static struct LABELLIST Labellist[MAXSTAFFS + 1];
+
+static short Numvis;           /* how many staffs currently visible */
+static short Maxlevels;                /* maximum number of nesting levels */
+static float Nested_brace_adjust = 0.0;        /* brace outside a bracket needs
+                                * some extra space to look good. */
+
+
+/* static functions */
+static void free_brac_info P((struct BRAC_INFO *brac_info_p));
+static void set_brac_info P((struct STAFFSET *staffset_p, int bractype));
+static int check_brac_overlap P((struct BRAC_INFO *brac_info_p));
+static void setnestlevel P((struct BRAC_INFO *brac_p,
+               struct BRAC_INFO *nested_by_p));
+static void place_labels P((struct MAINLL *mll_p,
+               struct MAINLL *prev_feed_mll_p));
+static void init_labellist P((void));
+static void free_label P((struct LABELINFO *label_p));
+static struct LABELINFO *newlabelinfo P((char *label, int is_staff_label));
+static void grouplabel P((struct BRAC_INFO *brac_p, int do_nested,
+               struct MAINLL *mll_p, struct MAINLL *prev_feed_mll_p));
+static double west_adjust P((struct MAINLL *mll_p,
+               struct MAINLL *prev_feed_mll_p));
+static struct MAINLL *find_prev_feed_mll_p P((struct MAINLL *mll_p));
+static char * label4staff P((struct MAINLL *mll_p, int s,
+               struct MAINLL *prev_feed_mll_p));
+static char * label4group P((struct MAINLL *mll_p, struct BRAC_INFO *brac_p,
+               struct MAINLL *prev_feed_mll_p));
+static double dflt_label_width P((struct MAINLL *mll_p,
+               struct MAINLL *prev_feed_mll_p));
+
+\f
+
+/* check for overlap between brace and bracket lists. Return YES if okay, NO
+ * if there is something illegal */
+
+int
+brac_check (bracelist_p, nbrace, bracklist_p, nbrack)
+
+struct STAFFSET *bracelist_p;
+int nbrace;                    /* how many items in bracelist_p */
+struct STAFFSET *bracklist_p;
+int nbrack;                    /* how many items in bracklist_p */
+
+{
+       register int s;         /* staff index into Brac_info_p */
+       register int n;         /* index into staffset */
+       int retval = 0;         /* return from check_brac_overlap() */
+       static int first_time = YES;    /* flag for if first time this function
+                                        * has been called */
+
+
+       debug(4, "brac_check");
+
+       /* initialize table */
+       for (s = 1; s <= Score.staffs; s++) {
+               if (first_time == NO) {
+                       /* only try to free if we know item has been properly
+                        * initialized, in case this is ever run on some system
+                        * that doesn't initialize pointer arrays to null ptrs */
+                       free_brac_info(Brac_info_p[s]);
+               }
+               Brac_info_p[s] = (struct BRAC_INFO *) 0;
+       }
+       first_time = NO;
+       Maxlevels = 0;
+
+       /* Go through each list, attaching each to table slot of its top staff.
+        */
+       for (n = 0; n < nbrace; n++) {
+               set_brac_info( &(bracelist_p[n]), BRACELIST);
+       }
+       for (n = 0; n < nbrack; n++) {
+               set_brac_info( &(bracklist_p[n]), BRACKLIST);
+       }
+
+       /* now check each staff for possible overlap */
+       for (s = 1; s <= Score.staffs; s++) {
+               if (Brac_info_p[s] == (struct BRAC_INFO *) 0) {
+                       /* no braces or brackets, so can't be any overlap */
+                       continue;
+               }
+
+               retval += check_brac_overlap (Brac_info_p[s]);
+       }
+
+       return(retval == 0 ? YES : NO);
+}
+\f
+
+/* recursively free a linked list of BRAC_INFO structs */
+
+static void
+free_brac_info(brac_info_p)
+
+struct BRAC_INFO *brac_info_p; /* the list to free */
+
+{
+       if (brac_info_p == (struct BRAC_INFO *) 0) {
+               return;
+       }
+
+       free_brac_info(brac_info_p->nested_p);
+       FREE(brac_info_p);
+}
+\f
+
+/* save information about a brace/bracket STAFFSET and link onto list for its
+ * top staff */
+
+static void
+set_brac_info (staffset_p, bractype)
+
+struct STAFFSET *staffset_p;   /* staffs to group together */
+int bractype;                  /* BRACELIST or BRACKLIST */
+
+{
+       struct BRAC_INFO *new_p;        /* info to be saved */
+       int s;                          /* staff num of top staff of staffset */
+
+
+       /* record information */
+       MALLOC(BRAC_INFO, new_p, 1);
+       new_p->staffset_p = staffset_p;
+       new_p->bractype = bractype;
+       new_p->nested_by_p = (struct BRAC_INFO *) 0;
+       new_p->nestlevel = 0;
+
+       /* link into list off of table */
+       s = staffset_p->topstaff;
+       new_p->nested_p = Brac_info_p[s];
+       Brac_info_p[s] = new_p;
+}
+\f
+
+/* check the brace/bracket information for one staff for overlap. Return
+ * number of errors found */
+
+static int
+check_brac_overlap (brac_info_p)
+
+struct BRAC_INFO *brac_info_p;
+
+{
+       register int s;
+
+
+       if (brac_info_p == (struct BRAC_INFO *) 0) {
+               /* end recursion */
+               return(0);
+       }
+
+       /* if no nesting, don't need to do those checks */
+       if (brac_info_p->nested_p != (struct BRAC_INFO *) 0) {
+
+               /* braces can't have anything nested inside them */
+               if (brac_info_p->bractype == BRACELIST) {
+                       yyerror("nesting inside a brace not allowed");
+                       return(1);
+               }
+
+               /* brace on top of bracket needs extra space */
+               if (brac_info_p->nested_p->bractype == BRACELIST) {
+                       Nested_brace_adjust = STEPSIZE;
+               }
+
+               /* check that nested range is a proper subset */
+               if (brac_info_p->nested_p->staffset_p->botstaff
+                                       >= brac_info_p->staffset_p->botstaff) {
+                       yyerror("nested brackets must be subsets of other brackets");
+                       return(1);
+               }
+
+               setnestlevel(brac_info_p->nested_p, brac_info_p);
+       }
+
+       /* see if this one overlaps with groups
+        * defined previously */
+       for (s = brac_info_p->staffset_p->topstaff + 1;
+                               s <= brac_info_p->staffset_p->botstaff; s++) {
+
+               if (Brac_info_p[s] == (struct BRAC_INFO *) 0) {
+                       continue;
+               }
+
+               /* if brace is being nested by something else,
+                * overlap is illegal */
+               if (brac_info_p->bractype == BRACELIST) {
+                       yyerror("brace overlap not allowed");
+                       return(1);
+               }
+
+               /* if bottom of this staffset is greater than bottom of the one
+                * we are checking, there is illegal overlap */
+               if (Brac_info_p[s]->staffset_p->botstaff 
+                                       > brac_info_p->staffset_p->botstaff) {
+                       yyerror("overlapping brackets are not nested");
+                       return(1);
+               }
+
+               /* remember who nests this one */
+               setnestlevel(Brac_info_p[s], brac_info_p);
+       }
+
+       /* recurse */
+       return (check_brac_overlap (brac_info_p->nested_p));
+}
+\f
+
+/* when one bracket is nested inside another, record that fact */
+
+static void
+setnestlevel(brac_p, nested_by_p)
+
+struct BRAC_INFO *brac_p;      /* set nesting here */
+struct BRAC_INFO *nested_by_p; /* brac_p is nested by this one */
+
+{
+       brac_p->nested_by_p = nested_by_p;
+       brac_p->nestlevel = nested_by_p->nestlevel + 1;
+
+       /* keep track of deepest nesting level */
+       if (brac_p->nestlevel > Maxlevels) {
+               Maxlevels = brac_p->nestlevel;
+       }
+}
+\f
+
+/*
+ * for each label
+ *     find which staff the label should go on based on visible
+ *
+ * Determine placement of staff labels, then nested, then outer.
+ */
+
+static void
+place_labels(mll_p, prev_feed_mll_p)
+
+struct MAINLL *mll_p;  /* current place in main list, used to determine
+                        * whether to use label or label2. */
+struct MAINLL *prev_feed_mll_p;        /* actual or proposed location of prev FEED */
+
+{
+       int s;                  /* index through staffs */
+       int count;              /* how many labels */
+       char *label;            /* the label being processed */
+       struct LABELINFO *lab_p;/* info about label */
+
+
+       init_labellist();
+       lab_p = (struct LABELINFO *) 0;
+
+       /* put the staff labels on the label list. While we're at it, count
+        * up the number of staffs that are currently visible */
+       for (count = Numvis = 0, s = 1; s <= Score.staffs; s++) {
+               if (svpath(s, VISIBLE)->visible == NO) {
+                       continue;
+               }
+
+               /* use label or label2 as appropriate */
+               if ((label = label4staff(mll_p, s, prev_feed_mll_p)) != 0) {
+                       lab_p = newlabelinfo(label, YES);
+               }
+
+               /* if there was a label, save info about it */
+               if (lab_p != (struct LABELINFO *) 0) {
+
+                       /* staff labels always go as far east as possible */
+                       /* Adjust by staffscale, but get from SSV, since
+                        * Stepsize won't be up to date. */
+                       lab_p->west = (-(lab_p->width) - STEPSIZE)
+                                       * svpath(s, STAFFSCALE)->staffscale;
+
+                       /* link onto list */
+                       lab_p->next = Labellist[Numvis].label_p;
+                       Labellist[Numvis].label_p = lab_p;
+
+                       /* count up number of staff labels */
+                       count++;
+
+                       /* re-init for next trip through loop */
+                       lab_p = (struct LABELINFO *) 0;
+               }
+
+               Labellist[Numvis].staffno = (short) s;
+
+               /* we now know there is one more staff visible */
+               Numvis++;
+       }
+
+       /* if there were any labels, mark all staffs as needing padding
+        * before placing another label. If there were no staff labels,
+        * group labels will go as far east as possible, otherwise the
+        * group labels will be leftward a bit. */
+       if (count > 0) {
+               for (s = 0; s < Numvis; s++) {
+                       (Labellist[s].pad)++;
+               }
+       }
+
+       /* do all nested group labels */
+       for (s = 1; s <= Score.staffs; s++) {
+               grouplabel(Brac_info_p[s], YES, mll_p, prev_feed_mll_p);
+       }
+
+       /* do all non-nested group labels */
+       for (s = 1; s <= Score.staffs; s++) {
+               grouplabel(Brac_info_p[s], NO, mll_p, prev_feed_mll_p);
+       }
+}
+\f
+
+/* initialize label list. Free any information currently in the list and
+ * mark everything as empty */
+
+static void
+init_labellist()
+
+{
+       register int s;         /* index through label list */
+
+
+       for (s = 0; s <= Numvis; s++) {
+               free_label(Labellist[s].label_p);
+               free_label(Labellist[s].btwnlabel_p);
+               Labellist[s].label_p = Labellist[s].btwnlabel_p
+                                               = (struct LABELINFO *) 0;
+               Labellist[s].pad = 0;
+       }
+       Numvis = 0;
+}
+\f
+
+/* recursively free linked list of LABELINFO structs */
+
+static void
+free_label(label_p)
+
+struct LABELINFO *label_p;     /* free this list */
+
+{
+       if (label_p == (struct LABELINFO *) 0) {
+               return;
+       }
+
+       free_label(label_p->next);
+       FREE(label_p);
+}
+\f
+
+/* allocate a new LABELINFO struct and fill in the label and width. Initialize
+ * west to zero */
+
+static struct LABELINFO *
+newlabelinfo(label, is_staff_label)
+
+char *label;           /* text of the label */
+int is_staff_label;    /* YES or NO */
+
+{
+       struct LABELINFO *new_p;        /* newly allocate place to save info */
+
+
+       MALLOC(LABELINFO, new_p, 1);
+       new_p->label = label;
+       new_p->west = 0.0;
+       new_p->width = strwidth(label);
+       new_p->is_staff_label = is_staff_label;
+       new_p->next = (struct LABELINFO *) 0;
+       return(new_p);
+}
+\f
+
+/* do placement of group labels */
+
+static void
+grouplabel(brac_p, do_nested, mll_p, prev_feed_mll_p)
+
+struct BRAC_INFO *brac_p;      /* info about group of staffs to do */
+int do_nested;                 /* if YES, process nested staff group. If NO,
+                                * process non-nested */
+struct MAINLL *mll_p;          /* used to decide if to use label or label2 */
+struct MAINLL *prev_feed_mll_p;        /* actual or proposed previous FEED */
+
+{
+       struct STAFFSET *staffset_p;    /* staffs/label in group */
+       char *label;                    /* label for group */
+       int index;                      /* into Labellist */
+       int topindex, botindex;         /* index into Labellist of where
+                                        * group range top & bottom visible
+                                        * staffs are */
+       int labindex;                   /* index into Labellist of staff where
+                                        * label should go */
+       struct LABELINFO *lab_p;        /* information about group label */
+       struct LABELINFO **lab_p_p;     /* where to insert label info */
+
+
+       if (brac_p == (struct BRAC_INFO *) 0) {
+               /* end recursion */
+               return;
+       }
+
+       if (do_nested == YES) {
+               /* recurse */
+               grouplabel(brac_p->nested_p, do_nested, mll_p, prev_feed_mll_p);
+               if (brac_p->nested_by_p == (struct BRAC_INFO *) 0) {
+                       return;
+               }
+       }
+       else if (brac_p->nested_by_p != (struct BRAC_INFO *) 0) {
+               return;
+       }
+
+       /* we'll probably need the staffset info a lot, so get pointer to it */
+       staffset_p = brac_p->staffset_p;
+
+       /* Find index in Labellist of top
+        * and bottom visible staffs of the range */
+       for (topindex = botindex = -1, index = 0;  index < Numvis; index++) {
+               if (topindex == -1 && staffset_p->topstaff
+                                               <= Labellist[index].staffno) {
+                       topindex = index;
+               }
+               if (staffset_p->botstaff >= Labellist[index].staffno) {
+                       botindex = index;
+               }
+       }
+
+       /* see if there were some visible staffs in this group */
+       if (topindex != -1 && botindex != -1 && botindex >= topindex) {
+
+               brac_p->topvisstaff = Labellist[topindex].staffno;
+               brac_p->botvisstaff = Labellist[botindex].staffno;
+
+               /* figure out which label to use, if any */
+               if ((label = label4group(mll_p, brac_p, prev_feed_mll_p))
+                                                       == (char *) 0) {
+                       return;
+               }
+
+               /* find index in list of visible staffs where label should
+                * go. If even number of visible staffs in range, label
+                * goes between two staffs */
+               labindex = (topindex + botindex) / 2;
+               if ((botindex - topindex) & 1) {
+                       lab_p_p = &(Labellist[labindex].btwnlabel_p);
+               }
+               else {
+                       lab_p_p = &(Labellist[labindex].label_p);
+               }
+
+               lab_p = newlabelinfo(label, NO);
+
+               /* put as far east as possible */
+               lab_p->west = - (lab_p->width);
+
+               lab_p->west -= Labellist[labindex].pad * LABELPAD;
+
+               /* link onto list */
+               lab_p->next = *lab_p_p;
+               *lab_p_p = lab_p;
+
+               /* add padding to all visible staffs in the group range */
+               for (    ; topindex <= botindex; topindex++) {
+                       Labellist[topindex].pad++;
+               }
+       }
+       else {
+               /* all staffs in group are invisible */
+               brac_p->topvisstaff = 0;
+       }
+}
+\f
+
+/* determine total width of labels. This is how much to add to
+ * relative west to get absolute location from left margin */
+
+static double
+west_adjust(mll_p, prev_feed_mll_p)
+
+struct MAINLL *mll_p;          /* actual or proposed FEED location,
+                                * used to decide if to use label or label2 */
+struct MAINLL *prev_feed_mll_p;        /* actual or proposed location of preceeding
+                                * FEED, used for label/label2 decision */
+
+{
+       register int s;         /* index */
+       double minwest = 0.0;   /* farthest west distance */
+
+
+       /* find westernmost label */
+       for (s = 0; s < Numvis; s++) {
+               if (Labellist[s].label_p != (struct LABELINFO *) 0) {
+                       if (Labellist[s].label_p->west < minwest) {
+                               minwest = Labellist[s].label_p->west;
+                       }
+               }
+               if (Labellist[s].btwnlabel_p != (struct LABELINFO *) 0) {
+                       if (Labellist[s].btwnlabel_p->west < minwest) {
+                               minwest = Labellist[s].btwnlabel_p->west;
+                       }
+               }
+       }
+
+       /* check for need to use default label on first score.
+        * If default label is needed, it creates an indent. */
+       if (minwest == 0.0) {
+               return(dflt_label_width(mll_p, prev_feed_mll_p));
+       }
+
+       return( - minwest);
+}
+\f
+
+/* return width of braces/brackets and their labels */
+
+double
+width_left_of_score(mll_p)
+
+struct MAINLL *mll_p;  /* FEED, used to decide if to use label or label2 */
+
+{
+       return(pwidth_left_of_score(mll_p, find_prev_feed_mll_p(mll_p)));
+}
+
+double
+pwidth_left_of_score(mll_p, prev_feed_mll_p)
+
+struct MAINLL *mll_p;          /* actual or proposed location of current FEED,
+                                * used to decide if to use label or label2 */
+struct MAINLL *prev_feed_mll_p;        /* actual or proposed location of prev FEED */
+
+{
+       double westadj;
+       int n;                  /* index through brac*lists */
+       int s;                  /* staff index */
+       int hasbracs;           /* YES if there are visible brackets/braces */
+
+
+       if (brac_check(Score.bracelist, Score.nbrace, Score.bracklist,
+                                       Score.nbrack) == NO) {
+               /* we should have exited before */
+               pfatal("illegal brace/bracket ranges");
+       }
+       /* call functions to determine the placement of all labels and
+        * save that information in the Labellist, then determine how
+        * wide the labels plus braces and brackets are */
+       place_labels(mll_p, prev_feed_mll_p);
+       westadj = west_adjust(mll_p, prev_feed_mll_p);
+
+       /* total is space for the labels (the westadj),
+        * the braces/brackets themselves (based on  Maxlevels),
+        * and 2 stepsizes of padding to left of score before brace/brack,
+        * plus special adjustment for brace on top of bracket, if any */
+       /* See if there are any visible brackets/braces.
+        * If so, we'll need to allow space for them, otherwise not. */
+       hasbracs = NO;
+       for (n = 0; n < Score.nbrace && hasbracs == NO; n++) {
+               for (s = Score.bracelist[n].topstaff;
+                                       s <= Score.bracelist[n].botstaff; s++){
+                       if (svpath(s, VISIBLE)->visible == YES) {
+                               hasbracs = YES;
+                               break;
+                       }
+               }
+       }
+       for (n = 0; n < Score.nbrack && hasbracs == NO; n++) {
+               for (s = Score.bracklist[n].topstaff;
+                                       s <= Score.bracklist[n].botstaff; s++){
+                       if (svpath(s, VISIBLE)->visible == YES) {
+                               hasbracs = YES;
+                               break;
+                       }
+               }
+       }
+
+       if (hasbracs == YES) {
+               return(westadj + ((Maxlevels + 2) * 2.0 * STDPAD)
+                               + (2.0 * STEPSIZE) + Nested_brace_adjust);
+       }
+       else {
+               return(westadj);
+       }
+}
+\f
+
+/* print braces/brackets and their labels, Return YES if there were braces or
+ * brackets, NO if not. */
+
+int
+pr_brac(is_restart, x_offset, mll_p)
+
+int is_restart;                /* YES if being called due to restart */
+double x_offset;       /* where to print, if is_restart == YES */
+struct MAINLL *mll_p;  /* for FEED for possible margin override, and to
+                        * decide if to use label or label2 */
+
+{
+       register int li;                /* index into Labellist */
+       register int s;                 /* staff index */
+       struct LABELINFO *lab_p;        /* info about a label */
+       struct LABELINFO *l_p;          /* for finding y adjust for overlaps */
+       double y_adjust;                /* for overlapping labels */
+       struct BRAC_INFO *brac_p;       /* info about brace or bracket */
+       double adj;                     /* how much to adjust relative west */
+       double x, y, y1;
+       int eff_stafflines;             /* how many stafflines there effectively
+                                        * are, counting the extra space around
+                                        * staffs with a very small number
+                                        * of stafflines */
+       double tab_adjust;              /* to adjust for TABRATIO */
+       double eff_stepsize;            /* STEPSIZE adjusted for staffscale */
+       char *label;
+       int printed_brac = NO;          /* if printed any braces/brackets */
+       struct MAINLL *prev_feed_mll_p; /* previous FEED */
+
+
+       debug(512, "pr_brac");
+
+       /* figure out where to place everything */
+       (void) brac_check(Score.bracelist, Score.nbrace, Score.bracklist,
+                                                               Score.nbrack);
+       prev_feed_mll_p = find_prev_feed_mll_p(mll_p);
+       place_labels(mll_p, prev_feed_mll_p);
+       if (is_restart == NO) {
+               adj = west_adjust(mll_p, prev_feed_mll_p)
+                                               + eff_leftmargin(mll_p);
+
+               /* print labels on visible staffs */
+               for (li = 0; li < Numvis; li++) {
+
+                       /* print labels to go by this staff */
+                       for (lab_p = Labellist[li].label_p;
+                                       lab_p != (struct LABELINFO *) 0;
+                                       lab_p = lab_p->next) {
+                               if (lab_p->is_staff_label == YES) {
+                                       /* Have to adjust by staffscale.
+                                        * We can't change the label
+                                        * in the SSV itself because that
+                                        * would cause problems, so make a copy
+                                        * and adjust that, then free it
+                                        * when we are done with it.
+                                        * Have to get size out of SSV,
+                                        * because Staffscale won't be
+                                        * up to date. */
+                                       MALLOCA(char, label, strlen(lab_p->label) + 1);
+                                       memcpy(label, lab_p->label,
+                                               strlen(lab_p->label) + 1);
+                                       resize_string(label,
+                                               svpath(Labellist[li].staffno,
+                                               STAFFSCALE)->staffscale,
+                                               (char *) 0, -1);
+                               }
+                               else {
+                                       label = lab_p->label;
+                               }
+
+                               x = lab_p->west + adj;
+                               /* Move above any other inner labels.
+                                * The very inner-most stays centered on the
+                                * staff, so ones above that have to be adjusted
+                                * by its ascent. This label itself has to
+                                * have enough room for half its height,
+                                * since it was originally centered,
+                                * for any between there, we need to skip
+                                * past their entire height.
+                                */
+                               for (y_adjust = 0.0, l_p = lab_p->next;
+                                               l_p != 0; l_p = l_p->next) {
+                                       if (l_p->next == 0) {
+                                               y_adjust += strascent(
+                                                       l_p->label) + STDPAD;
+                                       }
+                                       else {
+                                               y_adjust += strheight(
+                                                       l_p->label) + STDPAD;
+                                       }
+                               }
+                               if (lab_p->next != 0) {
+                                       y_adjust += strheight(lab_p->label)
+                                                       / 2.0 + STDPAD;
+                               }
+                               y = Staffs_y[ Labellist[li].staffno ]
+                                               + (strheight(label) / 2.0)
+                                               - strascent(label)
+                                               + y_adjust;
+                               pr_string(x, y, label, J_CENTER, (char *) 0, -1);
+                               if (lab_p->is_staff_label == YES) {
+                                       FREE(label);
+                               }
+                       }
+
+                       /* do labels that fall between staffs */
+                       for (lab_p = Labellist[li].btwnlabel_p;
+                                       lab_p != (struct LABELINFO *) 0;
+                                       lab_p = lab_p->next) {
+                               label = lab_p->label;
+                               x = lab_p->west + adj;
+                               /* y is the midpoint between the staffs,
+                                * adjusted by the height/ascent of the label,
+                                * and for any other labels. */
+                               for (y_adjust = 0.0, l_p = lab_p->next;
+                                               l_p != 0; l_p = l_p->next) {
+                                       if (l_p->next == 0) {
+                                               y_adjust += strascent(
+                                                       l_p->label) + STDPAD;
+                                       }
+                                       else {
+                                               y_adjust += strheight(
+                                                       l_p->label) + STDPAD;
+                                       }
+                               }
+                               if (lab_p->next != 0) {
+                                       y_adjust += strheight(lab_p->label)
+                                                       / 2.0 + STDPAD;
+                               }
+                               y = (Staffs_y[ Labellist[li].staffno ] +
+                                       Staffs_y[ Labellist[li+1].staffno ])/2.0
+                                       + (strheight(label) / 2.0)
+                                       - strascent(label) + y_adjust;
+                               pr_string(x, y, label, J_CENTER, (char *) 0, -1);
+                       }
+               }
+       }
+       else {
+               adj = - (Maxlevels * 2.0 * STDPAD);
+       }
+
+       /* print the braces and brackets themselves */
+       for (s = 1; s <= Score.staffs; s++) {
+               for (brac_p = Brac_info_p[s]; brac_p != (struct BRAC_INFO *) 0;
+                                               brac_p = brac_p->nested_p) {
+                       x = x_offset + adj + (Maxlevels - brac_p->nestlevel + 1)
+                                       * (2.0 * STDPAD) + (2.0 * STEPSIZE)
+                                       + Nested_brace_adjust;
+                       if (brac_p->bractype == BRACELIST) {
+                               if (brac_p->nested_by_p == 0) {
+                                       x += (0.5 * STEPSIZE);
+                               }
+                               else {
+                                       x -= (0.5 * STEPSIZE);
+                               }
+                       }
+                       if (brac_p->topvisstaff > 0) {
+                               /* figure out y (the top). Start at the y
+                                * of the top staff, then adjust as needed. */
+                               y = Staffs_y [brac_p->topvisstaff];
+
+                               /* figure out how tall the staff is effectively.
+                                * Staffs with only a few stafflines are
+                                * effectively taller than the number of
+                                * stafflines. */
+                               if ((eff_stafflines = svpath(
+                                               brac_p->topvisstaff, STAFFLINES)                                                ->stafflines) < 3) {
+                                       eff_stafflines = 3;
+                               }
+                               /* stepsizes are taller on tab staffs */
+                               tab_adjust = (is_tab_staff(brac_p->topvisstaff)
+                                                       ? TABRATIO : 1.0);
+
+                               /* adjust for height of staff */
+                               eff_stepsize = svpath(brac_p->topvisstaff,
+                                               STAFFSCALE)->staffscale
+                                               * STEPSIZE;
+                               y += (eff_stafflines - 1) * eff_stepsize
+                                               * tab_adjust;
+
+                               /* nested brackets should be a little shorter
+                                * vertically to fit inside their parent.
+                                * But beyond about 4 levels, if there is
+                                * only a single staff, things look
+                                * pretty bad, so limit to 4. */
+                               y -= (eff_stepsize * (brac_p->nestlevel < 5
+                                       ? brac_p->nestlevel : 4));
+
+                               /* brackets are 1 stepsize taller than braces */
+                               if (brac_p->bractype == BRACKLIST) {
+                                       y += eff_stepsize;
+                               }
+
+                               /* now calculate y1 (the bottom) by similar
+                                * means */
+                               y1 = Staffs_y [brac_p->botvisstaff];
+               
+                               /* figure out how tall the staff is effectively.
+                                * Staffs with only a few stafflines are
+                                * effectively taller than the number of
+                                * stafflines. */
+                               if ((eff_stafflines = svpath(
+                                               brac_p->botvisstaff, STAFFLINES)                                                ->stafflines) < 3) {
+                                       eff_stafflines = 3;
+                               }
+                               /* stepsizes are taller on tab staffs */
+                               tab_adjust = (is_tab_staff(brac_p->botvisstaff)
+                                                       ? TABRATIO : 1.0);
+
+                               /* adjust for height of staff */
+                               eff_stepsize = svpath(brac_p->botvisstaff,
+                                               STAFFSCALE)->staffscale
+                                               * STEPSIZE;
+                               y1 -= (eff_stafflines - 1) * eff_stepsize
+                                               * tab_adjust;
+
+                               /* nested brackets should be a little shorter
+                                * vertically to fit inside their parent.
+                                * But beyond about 4 levels, if there is
+                                * only a single staff, things look
+                                * pretty bad, so limit to 4. */
+                               y1 += (eff_stepsize * (brac_p->nestlevel < 5
+                                       ? brac_p->nestlevel : 4));
+
+                               /* brackets are 1 stepsize taller than braces */
+                               if (brac_p->bractype == BRACKLIST) {
+                                       y1 -= eff_stepsize;
+                               }
+
+                               /* now do the actual printing */
+                               do_pr_brac(x, y, y1, brac_p->bractype);
+                               printed_brac = YES;
+                       }
+               }
+       }
+
+       return(printed_brac);
+}
+\f
+
+/* Given one MAINLL pointing to a FEED, find the previous one.
+ * Many functions in this file need the previous feed. At abshorz time,
+ * there may not be an actual FEED yet, it might just be proposed,
+ * so functions at that time need to provide that proposed FEED place.
+ * Once all the FEEDs are determined, we can use this function to
+ * find the previous one.
+ */
+
+static struct MAINLL *
+find_prev_feed_mll_p(mll_p)
+
+struct MAINLL *mll_p;
+
+{
+       for (mll_p = mll_p->prev; mll_p != 0; mll_p = mll_p->prev) {
+               if (IS_CLEFSIG_FEED(mll_p)) {
+                       break;
+               }
+       }
+       return(mll_p);
+}
+\f
+
+/* Determine which label to use for a given staff.
+ * Goes backwards from mll_p, finding if label has been changed more recently
+ * than the previous feed. If so, use that label, else use label2.
+ */
+
+static char *
+label4staff(mll_p, s, prev_feed_mll_p)
+
+struct MAINLL *mll_p;  /* should point to an actual or proposed FEED location */
+int s;
+struct MAINLL *prev_feed_mll_p;        /* should point to an actual or proposed FEED location */
+
+{
+       for (mll_p = mll_p->prev; mll_p != 0; mll_p = mll_p->prev) {
+               if (mll_p == prev_feed_mll_p) {
+                       break;
+               }
+               if (mll_p->str == S_SSV) {
+                       struct SSV *ssv_p = mll_p->u.ssv_p;
+
+                       /* If user changed label for this staff in staff
+                        * context more recently that the previous feed,
+                        * then that's the label we need. */
+                       if (ssv_p->context == C_STAFF && ssv_p->staffno == s
+                                               && ssv_p->used[LABEL] == YES) {
+                               return(ssv_p->label);
+                       }
+
+                       /* If user changed the score-wide label
+                        * more recently than the previous feed,
+                        * but there isn't any label set in staff context for
+                        * this staff to override the score level label,
+                        * then the score level label is the one we need. */
+                       if (ssv_p->context == C_SCORE &&
+                                               ssv_p->used[LABEL] == YES &&
+                                               Staff[s-1].used[LABEL] == NO) {
+                               return(ssv_p->label);
+                       }
+               }
+       }
+       if (mll_p != 0) {
+               /* Hit another feed before any relevent label changes,
+                * so we need to use label2 */
+               return(svpath(s, LABEL2)->label2);
+       }
+       /* Ran off the top of the song. Use label */
+       return(svpath(s, LABEL)->label);
+}
+\f
+
+/* Given information about a set of grouped staffs,
+ * return the appropriate label to use: label or label2.
+ */
+
+static char *
+label4group(mll_p, brac_p, prev_feed_mll_p)
+
+struct MAINLL *mll_p;
+struct BRAC_INFO *brac_p;
+struct MAINLL *prev_feed_mll_p;
+
+{
+       for (mll_p = mll_p->prev; mll_p != 0; mll_p = mll_p->prev) {
+               if (mll_p == prev_feed_mll_p) {
+                       /* Hasn't changed since previous feed, so label2 */
+                       return(brac_p->staffset_p->label2);
+               }
+               if (mll_p->str == S_SSV && mll_p->u.ssv_p->context == C_SCORE &&
+                               mll_p->u.ssv_p->used[brac_p->bractype] == YES) {
+                       /* found SSV where brace/bracket was changed */
+                       break;
+               }
+       }
+       /* Either changed since previous feed or is the first feed in song,
+        * so use label. */
+       return(brac_p->staffset_p->label);
+}
+\f
+
+/* Return width of default label if the default label is needed (for
+ * indent of first score. Returns 0.0 if default label should not be used.
+ */
+
+static double
+dflt_label_width(mll_p, prev_feed_mll_p)
+
+struct MAINLL *mll_p;          /* points to FEED or proposed place
+                                * where current FEED will be */
+struct MAINLL *prev_feed_mll_p;        /* points to previous FEED, or proposed
+                                * place where prev FEED will be */
+
+{
+       char dfltlabel[16];
+
+
+       for (mll_p = mll_p->prev; mll_p != 0; mll_p = mll_p->prev) {
+               if (mll_p == prev_feed_mll_p) {
+                       /* not the first; so don't use default for first */
+                       return(0.0);
+               }
+
+               if (mll_p->str == S_SSV && mll_p->u.ssv_p->context == C_SCORE &&
+                                       mll_p->u.ssv_p->used[LABEL] == YES) {
+                       /* explicit label for first, so don't use default */
+                       return(0.0);
+               }
+       }
+       (void) sprintf(dfltlabel, "%c%c            ", FONT_TR, DFLT_SIZE);
+       return(strwidth(dfltlabel));
+}
diff --git a/mup/mup/charinfo.c b/mup/mup/charinfo.c
new file mode 100644 (file)
index 0000000..7f010f4
--- /dev/null
@@ -0,0 +1,3081 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions related to characters: information about the size and shape of
+ * characters to be printed, to initialize the internal tables
+ * to tell how big each character is, etc.
+ */
+
+#include <string.h>
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+/* code for invalid music character */
+#define BAD_CHAR       '\377'
+/* code for invalid number in user input string */
+#define BAD_NUMBER     -30000
+
+/* machine-generated sorted list for translating
+ * music character names to internal code numbers. */
+/* The +1 is because there is an "end-of-list" entry with charname == 0 */
+extern struct SPECCHAR Mus_char_table[NUM_MFONTS][CHARS_IN_FONT+1];
+#ifdef EXTCHAR
+extern struct SPECCHAR Ext_char_table[];
+#endif
+
+
+/* save information about characters in string as we go, in order to be
+ * able to backspace back over them */
+struct BACKSPACEINFO {
+       char    code;
+       char    font;
+};
+
+
+#ifndef __STDC__
+extern char *bsearch();        /* binary search library function */
+#endif
+extern long strtol();
+
+/* static functions */
+static char *get_font P((char *string, int *font_p, int prev_font, char *fname,
+               int lineno));
+static char *get_num P((char *string, int *num_p));
+static int sc_compare P((const void *item1_p, const void *item2_p));
+#ifdef EXTCHAR
+static unsigned char ext_name2num P((char *name));
+#endif
+static int starts_piled P((char *string, int *font_p, int *size_p,
+               char **pile_start_p_p));
+static int str_cmd P((char *str, int *size_p, int *in_pile_p));
+static int get_accidental P((unsigned char *str, char *accidental_p,
+               int *acc_size_p, int trans_natural, int *escaped_p));
+static int add_accidental P((char *buff, int acc_character, int acc_size,
+               int escaped));
+static int dim_tri P((unsigned char *str, char *replacement,
+               int size, int is_chord));
+static int smallsize P((int size));
+static int accsize P((int size));
+\f
+
+/* return the height (in inches) of a character of specified font and size */
+
+double
+height(font, size, ch)
+
+int font;
+int size;
+int ch;                /* which character */
+
+{
+       int chval;
+
+       chval = ch & 0xff;
+
+       /* control characters have no height */
+       if (chval < FIRST_CHAR) {
+               return(0.0);
+       }
+
+       return((Fontinfo[ font_index(font) ].ch_height[ CHAR_INDEX(chval) ] 
+               / FONTFACTOR) * ((float)size / (float)DFLT_SIZE) );
+}
+\f
+
+/* return the width (in inches) of a character of specified font and size */
+
+double
+width(font, size, ch)
+
+int font;
+int size;
+int ch;                /* which character */
+
+{
+       int chval;
+
+       chval = ch & 0xff;
+
+       /* control characters have no width */
+       if (chval < FIRST_CHAR) {
+               return(0.0);
+       }
+
+       return((Fontinfo[ font_index(font) ].ch_width[ CHAR_INDEX(chval) ] 
+               / FONTFACTOR) * ((float)size / (float)DFLT_SIZE) );
+}
+\f
+
+/* return the ascent (in inches) of a character of specified font and size */
+
+double
+ascent(font, size, ch)
+
+int font;
+int size;
+int ch;                /* which character */
+
+{
+       int chval;
+
+       chval = ch & 0xff;
+
+       /* control characters have no ascent */
+       if (chval < FIRST_CHAR) {
+               return(0.0);
+       }
+
+       return((Fontinfo[ font_index(font) ].ch_ascent[ CHAR_INDEX(chval) ]
+               / FONTFACTOR) * ((float) size / (float)DFLT_SIZE) );
+}
+\f
+
+/* return the descent (in inches) of a character of specified font and size */
+
+double
+descent(font, size, ch)
+
+int font;
+int size;
+int ch;                /* which character */
+
+{
+       return ( height(font, size, ch) - ascent(font, size, ch) );
+}
+\f
+
+/* given a user input string, normalize it. This means:
+ * Put the default font in [0] and default size in [1] of the string.
+ * Change backslashed things to internal format. Each starts with a
+ * hyper-ASCII code byte and is followed by one or more data bytes.
+ * Note that in all cases in internal format is no longer than the
+ * incoming format.
+ * Change any \f(XX) to          STR_FONT font_number
+ * Change any \s(NN) to   STR_SIZE actual_size
+ *     Note that NN might have a sign to indicate relative size change.
+ * Change any \v(NN) to   STR_VERTICAL vertical_offset
+ *     Note that NN might have a sign to indicate direction,
+ *     negative means downward.
+ * Change any \/ to      STR_SLASH
+ * Change any \| to       STR_L_ALIGN (piled mode only)
+ * Change any \^ to       STR_C_ALIGN (piled mode only)
+ * Change any backslashed space to space when in piled mode
+ * Change any space to newline while in piled mode
+ * Change \(xxxx) to      STR_MUS_CHAR size mus_char_code
+ * Change \% to           STR_PAGENUM %
+ * Change \# to                  STR_NUMPAGES #
+ * Change \n to newline
+ * Change \b to           STR_BACKSPACE n
+ *      where n is how much to back up for the
+ *     default size, in BACKSP_FACTORths of an inch
+ * Change backslashed backslash or double quote to just be themselves.
+ * Reject any other control characters or illegal backslash escapes.
+ * The string is null-terminated.
+ *
+ * The normalized string is put back into the original string buffer
+ * that was passed in, and a pointer to it is returned.
+ *
+ * Note that some functions in lyrics.c, and prntdata.c
+ * also have knowledge of the escape conventions,
+ * so if these change, check there too. But it is intended
+ * that all the rest of the code gets at strings indirectly
+ * via functions in this file, so the details can be hidden here.
+ */
+
+char *
+fix_string(string, font, size, fname, lineno)
+
+char *string;  /* original string */
+int font;      /* default font for string */
+int size;      /* default size for string */
+char *fname;   /* file name, for error messages */
+int lineno;    /* input line number, for error messages */
+
+{
+       char *tmpbuff;                  /* for normalized string */
+       int leng;                       /* strlen(string) + 1 */
+       char *inp_p, *out_p;            /* walk thru orig & normalized string */
+       int nsize;                      /* new size */
+       int prevsize;                   /* previous size */
+       int msize;                      /* size for music character */
+       int vert;                       /* argument to \v without sign */
+       int vertval = 0;                /* signed argument to \v */
+       int has_vertical = NO;          /* YES if \v or pile found */
+       int has_newline = NO;           /* YES if \n somewhere in string */
+       int pile_mode = NO;
+       int align_points = 0;           /* how many aligments points found */
+       int error;                      /* YES if have found an error */
+       char spec_name[100], *sc_p;     /* name of special music character, or
+                                        * extended character set character */
+       unsigned char extchar;          /* value for extended character */
+       unsigned char muschar;          /* value for music character */
+       int now_font;                   /* current font */
+       int newfont;                    /* proposed new font */
+       int prevfont;                   /* previous font */
+       int mfont;                      /* music font */
+       struct BACKSPACEINFO *backspaceinfo;    /* font/size for backspacing */
+       int backspaceindex = 0;         /* index into backspaceinfo */
+       float backup;                   /* backspace distance in inches
+                                        * for default size */
+       int backupval;                  /* value to store for backspace
+                                        * distance */
+
+
+       /* fill in default font and size */
+       string[0] = (char) font;
+       if (rangecheck(size, MINSIZE, MAXSIZE, "size") == NO) {
+               size = MAXSIZE;
+       }
+       string[1] = (char) size;
+       now_font = prevfont = font;
+       prevsize = size;
+
+       leng = strlen(string) + 1;
+       MALLOCA(char, tmpbuff, leng);
+       MALLOC(BACKSPACEINFO, backspaceinfo, leng);
+       /* walk through incoming string, creating normalized string */
+       for (error = NO, out_p = tmpbuff + 2, inp_p = string + 2;
+                                       (error == NO) && (*inp_p != '\0');
+                                       inp_p++, out_p++) {
+
+               /* handle backslashed stuff */
+               if (*inp_p == '\\') {
+
+                       /* skip past the backslash */
+                       inp_p++;        
+
+                       switch( *inp_p) {
+
+                       case '\n':
+                               /* ignore the backslashed newline */
+                               out_p--;
+                               break;
+
+                       case '\r':
+                               if (*(inp_p) == '\n') {
+                                       inp_p++;
+                               }
+                               out_p--;
+                               break;
+
+                       case 'f':
+                               /* font change */
+                               inp_p = get_font(++inp_p, &newfont, prevfont,
+                                                       fname, lineno);
+                               if (newfont == FONT_UNKNOWN) {
+                                       error = YES;
+                               }
+                               else {
+                                       *out_p++ = (char) STR_FONT;
+                                       *out_p = (char) newfont;
+                                       prevfont = now_font;
+                                       now_font = newfont;
+                               }
+                               break;
+
+                       case 's':
+                               /* size change */
+                               if (*++inp_p == '(') {
+                                       switch (*++inp_p) {
+                                       case '+':
+                                               inp_p = get_num(++inp_p, &nsize);
+                                               if (nsize > 0) {
+                                                       nsize += size;
+                                               }
+                                               break;
+                                       case '-':
+                                               inp_p = get_num(++inp_p, &nsize);
+                                               if (nsize > 0) {
+                                                       nsize = size - nsize;
+                                               }
+                                               break;
+                                       case 'P':
+                                               if (strncmp(inp_p, "PV)", 3) == 0) {
+                                                       nsize = prevsize;
+                                                       inp_p += 2;
+                                               }
+                                               else {
+                                                       nsize = BAD_NUMBER;
+                                               }
+                                               break;
+                                       case 'p':
+                                               if (strncmp(inp_p, "previous)", 9) == 0) {
+                                                       nsize = prevsize;
+                                                       inp_p += 8;
+                                               }
+                                               else {
+                                                       nsize = BAD_NUMBER;
+                                               }
+                                               break;
+                                       default:
+                                               inp_p = get_num(inp_p, &nsize);
+                                               break;
+                                       }
+                               }
+                               else {
+                                       nsize = BAD_NUMBER;
+                               }
+
+                               /* if got valid size, store it */
+                               if (nsize == BAD_NUMBER) {
+                                       l_yyerror(fname, lineno,
+                                               "Invalid format for size value");
+                                       error = YES;
+                               }
+                               else if (rangecheck(nsize, MINSIZE,
+                                               MAXSIZE, "size") == YES) {
+                                       *out_p++ = (char) STR_SIZE;
+                                       *out_p = (char) nsize;
+                                       /* save new size */
+                                       prevsize = size;
+                                       size = nsize;
+                               }
+                               else {
+                                       error = YES;
+                               }
+
+                               break;
+
+                       case 'v':
+                               /* vertical motion */
+                               if (*++inp_p == '(') {
+                                       switch (*++inp_p) {
+                                       case '-':
+                                               inp_p = get_num(++inp_p, &vert);
+                                               if (vert >= 0) {
+                                                       vertval = -vert;
+                                               }
+                                               break;
+
+                                       case '+':
+                                               ++inp_p;
+                                               /* fall through */
+                                       default:
+                                               inp_p = get_num(inp_p, &vert);
+                                               if (vert >= 0) {
+                                                       vertval = vert;
+                                               }
+                                               break;
+                                       }
+                               }
+                               else {
+                                       vert = BAD_NUMBER;
+                               }
+
+                               if (vert == BAD_NUMBER) {
+                                       l_yyerror(fname, lineno,
+                                               "Invalid format for vertical motion value");
+                                       error = YES;
+                               }
+                               else if (rangecheck(vertval, -100, 100,
+                                               "vertical") == YES) {
+                                       /* if motion is zero, don't even bother
+                                        * to save it, else do */
+                                       if (vertval != 0) {
+                                               /* convert percentage to 
+                                                * STR_VERTICAL units */
+                                               if (vertval > 0) {
+                                                       vertval = vertval *
+                                                               MAXVERTICAL/100;
+                                               }
+                                               else {
+                                                       vertval = -vertval *
+                                                               MINVERTICAL/100;
+                                               }
+                                               *out_p++ = (char) STR_VERTICAL;
+                                               *out_p = (char) ENCODE_VERT(
+                                                       vertval );
+                                       }
+                               }
+                               else {
+                                       error = YES;
+                               }
+
+                               /* we don't allow backspacing to something
+                                * before a vertical motion--this is almost
+                                * like a newline. */
+                               backspaceindex = 0;
+
+                               has_vertical = YES;
+                       
+                               break;
+                               
+                       case ':':
+                               /* If this begins a pile, and the next thing
+                                * in input ends the pile, just ignore them
+                                * both to keep things simpler later. */
+                               if (pile_mode == NO && *(inp_p+1) == '\\'
+                                                       && *(inp_p+2) == ':') {
+                                       inp_p += 2;
+                                       /* no output character */
+                                       out_p--;
+                               }
+                               else {
+                                       *out_p = (char) STR_PILE;
+                                       has_vertical = YES;
+                                       pile_mode = (pile_mode == YES ? NO : YES);
+                               }
+                               align_points = 0;
+                               break;
+
+                       case '|':
+                       case '^':
+                               if (pile_mode == NO) {
+                                       l_yyerror(fname, lineno,
+                                               "alignment point only allowed in piled mode");
+                                       *out_p =  *inp_p;
+                               }
+
+                               else if (++align_points > 1) {
+                                       l_yyerror(fname, lineno,
+                                               "only one alignment point allowed per line");
+                                       *out_p =  *inp_p;
+                               }
+
+                               else if (*inp_p == '^') {
+                                       int next_ch;
+                                       *out_p = (char) STR_C_ALIGN;
+                                       next_ch = *(inp_p+1) & 0xff;
+                                       /* it's too much trouble to handle
+                                        * things like font changes between
+                                        * the \^ and the character that
+                                        * will be allowed, so disallow them,
+                                        * since user can easily put them
+                                        * before the \^ anyway. */
+                                       if ( (IS_STR_COMMAND(next_ch)
+                                               && next_ch != STR_MUS_CHAR)
+                                               || *(inp_p+1) == ' '
+                                               || iscntrl(*(inp_p+1)) ) {
+                                          l_yyerror(fname, lineno,
+                                               "\\^ must be followed by normal character");
+                                       }
+                               }
+                               else {
+                                       *out_p = (char) STR_L_ALIGN;
+                               }
+                               has_vertical = YES;
+                               break;
+
+                       case ' ':
+                               if (pile_mode == NO) {
+                                       l_yyerror(fname, lineno,
+                                               "backslashed space only allowed in piled mode");
+                               }
+                               *out_p = ' ';
+                               break;
+
+                       case '/':
+                               /* This is only allowed after one
+                                * or more digits */
+                               if ( inp_p - string < 4 ||
+                                               ! isdigit( *(inp_p - 2)) ) {
+                                       l_yyerror(fname, lineno,
+                                               "slash can only be used after digit(s)");
+                               }
+                               *out_p = (char) STR_SLASH;
+                               break;
+                       case '\\':
+                       case '"':
+                               /* real backslash or embedded quote, copy it */
+                               backspaceinfo[backspaceindex].code = *inp_p;
+                               backspaceinfo[backspaceindex++].font
+                                                       = (char) now_font;
+                               *out_p = *inp_p;
+                               break;
+
+                       case '(':
+                               /* special music character or extended
+                                * character set character */
+                               /* make copy of name */
+                               for ( sc_p = spec_name, inp_p++;
+                                               *inp_p != ')' && *inp_p != '\0';
+                                               sc_p++, inp_p++) {
+                                       *sc_p = *inp_p;
+                               }
+                               *sc_p = '\0';
+
+#ifdef EXTCHAR
+                               /* first see if it is a character in the
+                                * extended character set */
+                               if ((extchar = ext_name2num(spec_name))
+                                                       != (unsigned char) BAD_CHAR) {
+                                       /* temporarily change to the extended
+                                        * character set font that corresponds
+                                        * to the current normal ASCII font,
+                                        * and output the extended character
+                                        * set code for the desired character.
+                                        * Then go back to original font */
+                                       *out_p++ = (char) STR_FONT;
+                                       *out_p++ = (char)
+                                               (now_font + EXT_FONT_OFFSET);
+                                       *out_p++ = extchar;
+                                       *out_p++ = (char) STR_FONT;
+                                       *out_p = (char) now_font;
+                                       backspaceinfo[backspaceindex].code
+                                                               = extchar;
+                                       backspaceinfo[backspaceindex++].font
+                                               = now_font + EXT_FONT_OFFSET;
+
+                                       /* mark that this extended character
+                                        * set font has been used */
+                                       Font_used[now_font + EXT_FONT_OFFSET] = YES;
+
+                                       break;
+                               }
+#endif
+                               /* look up music character with this name */
+                               msize = size;
+                               if ((muschar = mc_name2num(spec_name, fname,
+                                               lineno, &msize, &mfont))
+                                               != (unsigned char) BAD_CHAR) {
+                                       *out_p++ = (char) mfont2str(mfont);
+                                       *out_p++ = (char) msize;
+                                       *out_p = muschar;
+                                       backspaceinfo[backspaceindex].code
+                                                               = muschar;
+                                       backspaceinfo[backspaceindex++].font
+                                                               = FONT_MUSIC;
+                               }
+                               break;
+
+                       case '[':
+                               /* start of boxed text. We only allow this at
+                                * the beginning of a string */
+                               if (inp_p != string + 3) {
+                                       l_yyerror(fname, lineno,
+                                               "\\[ only allowed at beginning of string");
+                                       error = YES;
+                               }
+                               else {
+                                       *out_p = (char) STR_BOX;
+                               }
+                               break;
+
+                       case ']':
+                               /* end of boxed text. Only allowed at end of
+                                * string, and only if the string began
+                                * with a box start. */
+                               if (*(inp_p + 1) != '\0') {
+                                       l_yyerror(fname, lineno,
+                                               "\\] only allowed at end of string");
+                                       error = YES;
+                               }
+                               else if (IS_BOXED(tmpbuff) == NO) {
+                                       l_yyerror(fname, lineno,
+                                               "no matching \\[ for \\]");
+                                       error = YES;
+                               }
+                               else {
+                                       *out_p = (char) STR_BOX_END;
+                               }
+                               break;
+
+                       case '{':
+                               /* start of circled text. We only allow this at
+                                * the beginning of a string */
+                               if (inp_p != string + 3) {
+                                       l_yyerror(fname, lineno,
+                                               "\\{ only allowed at beginning of string");
+                                       error = YES;
+                               }
+                               else {
+                                       *out_p = (char) STR_CIR;
+                               }
+                               break;
+
+                       case '}':
+                               /* end of circled text. Only allowed at end of
+                                * string, and only if the string began
+                                * with a circle start. */
+                               if (*(inp_p + 1) != '\0') {
+                                       l_yyerror(fname, lineno,
+                                               "\\} only allowed at end of string");
+                                       error = YES;
+                               }
+                               else if (IS_CIRCLED(tmpbuff) == NO) {
+                                       l_yyerror(fname, lineno,
+                                               "no matching \\{ for \\}");
+                                       error = YES;
+                               }
+                               else {
+                                       *out_p = (char) STR_CIR_END;
+                               }
+                               break;
+
+                       case '%':
+                               /* too hard to deal with inside a pile... */
+                               if (pile_mode == YES) {
+                                       l_yyerror(fname, lineno,
+                                               "\\%c not allowed inside a pile\n", '%');
+                               }
+
+                               /* page number -- change to STR_PAGENUM-% */
+                               *out_p++ = (char) STR_PAGENUM;
+                               *out_p = '%';
+                               /* we really don't know at this point how far
+                                * to backspace over pagenum because we don't
+                                * know yet how many digits it is, etc, so we
+                                * punt and just use the % character
+                                * for width */
+                               backspaceinfo[backspaceindex].code = '%';
+                               backspaceinfo[backspaceindex++].font
+                                                       = (char) now_font;
+                               break;
+
+                       case '#':
+                               /* code basically the same as for % */
+                               if (pile_mode == YES) {
+                                       l_yyerror(fname, lineno,
+                                               "\\# not allowed inside a pile\n");
+                               }
+
+                               /* number of pages -- change to STR_NUMPAGES-# */
+                               *out_p++ = (char) STR_NUMPAGES;
+                               *out_p = '#';
+                               /* We really don't know at this point how far
+                                * to backspace, because we don't know yet
+                                * how many digits it is, etc, so we punt
+                                * and just use the # character for width. */
+                               backspaceinfo[backspaceindex].code = '#';
+                               backspaceinfo[backspaceindex++].font
+                                                       = (char) now_font;
+                               break;
+
+                       case 'n':
+                               /* newline */
+                               *out_p = '\n';
+                               /* can't back up to previous line */
+                               backspaceindex = 0;
+                               has_newline = YES;
+                               break;
+
+                       case 'b':
+                               /* can't back up past beginning of string */
+                               if (backspaceindex == 0) {
+                                       if (has_newline == YES || has_vertical == YES) {
+                                               l_yyerror(fname, lineno,
+                                                       "can't backspace before newline or vertical motion");
+                                       }
+                                       else {
+                                               l_yyerror(fname, lineno,
+                                                       "can't backspace before beginning of line");
+                                       }
+                                       error = YES;
+                               }
+                               else {
+                                       backspaceindex--;
+                                       backup = width(backspaceinfo
+                                                       [backspaceindex].font,
+                                                       DFLT_SIZE, backspaceinfo
+                                                       [backspaceindex].code);
+                                       *out_p++ = (char) STR_BACKSPACE;
+                                       /* calculate backup value to store */
+                                       backupval = (int) (backup * BACKSP_FACTOR);
+                                       if (backupval < 1) {
+                                               backupval = 1;
+                                       }
+                                       else if (backupval > 127) {
+                                               backupval = 127;
+                                       }
+                                       *out_p = (char) backupval;
+                               }
+                               break;
+
+                       default:
+                               yyerror("illegal \\ escape");
+                               error = YES;
+                               break;
+                       }
+               }
+
+               else if (iscntrl(*inp_p) ) {
+                       if (*inp_p == '\n') {
+                               backspaceindex = 0;
+                               has_newline = YES;
+                               *out_p = *inp_p;
+                       }
+                       else if (*inp_p == '\r' && *(inp_p+1) == '\n') {
+                               /* ignore DOS's extraneous \r */
+                               out_p--;
+                       }
+                       else {
+                               /* We don't support any other control
+                                * characters, but just convert others to
+                                * space and continue. That way user at least
+                                * gets something. Tab is something user may
+                                * expect to work, so we give a more clear
+                                * and specific error for that.
+                                */
+                               l_warning(fname, lineno,
+                                       "unsupported control character '\\0%o' %sin string replaced with space",
+                                       *inp_p, *inp_p =='\t' ? "(tab) ": "");
+                               *out_p = ' ';
+                       }
+               }
+               else if  (pile_mode == YES && *inp_p == ' ') {
+                       /* in piled mode, space means move down for next
+                        * item in pile. */
+                       *out_p = '\n';
+                       
+                       align_points = 0;
+                       backspaceindex = 0;
+               }
+               else {
+                       /* normal character -- copy as is */
+                       *out_p = *inp_p;
+                       backspaceinfo[backspaceindex].code = *inp_p;
+                       backspaceinfo[backspaceindex++].font = (char) now_font;
+               }
+       }
+       /* If we got an error, we would not have put anything into the
+        * final output position before incrementing out_p in the 'for' loop,
+        * so compensate, so we don't leave a garbage character. */
+       if (error == YES) {
+               out_p--;
+       }
+       *out_p = '\0';
+
+       if (error == NO && IS_BOXED(tmpbuff) == YES &&
+                               (*(out_p - 1) & 0xff) != (STR_BOX_END & 0xff)) {
+               l_yyerror(fname, lineno, "no matching \\] for \\[");
+       }
+
+       if (error == NO && IS_CIRCLED(tmpbuff) == YES &&
+                               (*(out_p - 1) & 0xff) != (STR_CIR_END & 0xff)) {
+               l_yyerror(fname, lineno, "no matching \\} for \\{");
+       }
+
+       /* to keep things simple, we don't allow
+        * mixing newlines with vertical motion */
+       if (has_vertical == YES && has_newline == YES) {
+               l_yyerror(fname, lineno,
+                       "can't have newline in same string with vertical motion or alignment");
+       }
+
+       /* now copy normalized string back onto original */
+       (void) strcpy(string + 2, tmpbuff + 2);
+       FREE(tmpbuff);
+       FREE(backspaceinfo);
+       return(string);
+}
+\f
+
+/* given pointer into a string, read a font name exclosed in parentheses.
+ * Return the corresponding font number, or
+ * FONT_UNKNOWN if name is invalid. Return pointer to last character
+ * processed in string */
+
+static char *
+get_font(string, font_p, prev_font, fname, lineno)
+
+char *string;  /* get font from this string */
+int *font_p;   /* return new font via this pointer */
+int prev_font; /* previous font */
+char *fname;   /* file name for errors */
+int lineno;    /* line number, for error messages */
+
+{
+       char fontname[BUFSIZ];
+       int font = FONT_UNKNOWN;
+       char *endparen;         /* where ')' is in string */
+       int length;             /* of font name */
+
+
+       if (*string == '(') {
+               string++;
+               if ((endparen = strchr(string, ')')) != (char *) 0) {
+                       length = endparen - string;
+                       (void) strncpy(fontname, string, (unsigned) length);
+                       fontname[length] = '\0';
+                       string += length;
+                       if (strcmp(fontname, "PV") == 0
+                                       || strcmp(fontname, "previous") == 0) {
+                               /* special case of "previous" font */
+                               font = prev_font;
+                       }
+                       else {
+                               font = lookup_font(fontname);
+                       }
+               }
+       }
+
+       *font_p = font;
+       if (font == FONT_UNKNOWN) {
+               l_yyerror(fname, lineno, "unknown font specified");
+       }
+       return(string);
+}
+\f
+
+/* given a pointer into a string, get a number followed by close parenthesis.
+ * Return the number via pointer, or BAD_NUMBER on error.
+ * Return pointer to the last character processed
+ * in the incoming string */
+
+static char *
+get_num(string, num_p)
+
+char *string;  /* get number from this string */
+int *num_p;    /* return number via this pointer, or -1 on error */
+
+{
+       if (isdigit(*string)) {
+               *num_p = strtol(string, &string, 10);
+               if (*string != ')') {
+                       *num_p = BAD_NUMBER;
+               }
+       }
+       else {
+               *num_p = BAD_NUMBER;
+       }
+       return(string);
+}
+\f
+
+/* compare the charname fields of 2 SPECCHAR structs and return
+ * their proper order, for comparison by bsearch() */
+
+static int
+sc_compare(item1_p, item2_p)
+
+#ifdef __STDC__
+const void *item1_p;   /* there are really struct SPECCHAR *, but bsearch
+                        * passes them as char * and we have to
+                        * cast appropriately */
+const void *item2_p;
+#else
+char *item1_p; /* there are really struct SPECCHAR *, but bsearch passes them
+                * as char * and we have to cast appropriately */
+char *item2_p;
+#endif
+
+{
+       return(strcmp( ((struct SPECCHAR *)(item1_p))->charname,
+                               ((struct SPECCHAR *)(item2_p))->charname));
+}
+\f
+
+/* given the name of a music character, return its code number.
+ * If the name is not a valid name, return BAD_CHAR.
+ * Just do a binary search in the name-to-code translation table.
+ */
+
+unsigned char
+mc_name2num(name, fname, lineno, size_p, font_p)
+
+char *name;    /* name for a music character */
+char *fname;   /* file name for error messages */
+int lineno;    /* input line number for error messages */
+int *size_p;   /* points to current size, proper size for music character
+                * is returned through here */
+int *font_p;   /* FONT_MUSIC* is returned here */
+
+{
+       struct SPECCHAR *info_p;/* translation entry for the given name */
+       struct SPECCHAR key;    /* what to look for */
+       int f;                          /* font index */
+       static unsigned int numch[NUM_MFONTS];  /* how many items in font */
+
+
+       /* first time through, find size of name-to-code table */
+       if (numch[0] == 0) {
+               for (f = 0; f < NUM_MFONTS; f++) {
+                       for ( ; Mus_char_table[f][numch[f]].charname != (char *)0;
+                                                       (numch[f])++) {
+                               ;
+                       }
+               }
+       }
+
+       /* check for "small" characters */
+       if (name[0] == 's' && name[1] == 'm') {
+               key.charname = name + 2;
+               *size_p = smallsize(*size_p);
+       }
+       else {
+               key.charname = name;
+       }
+
+       /* do binary search for code */
+       for (f = 0; f < NUM_MFONTS; f++) {
+               if ((info_p = (struct SPECCHAR *) bsearch((char *) &key, Mus_char_table[f],
+                               numch[f], sizeof(struct SPECCHAR), sc_compare))
+                               != (struct SPECCHAR *) 0) {
+                       *font_p = FONT_MUSIC + f;
+                       return( (unsigned char) info_p->code);
+               }
+       }
+
+       l_yyerror(fname, lineno, "unknown music character '%s'", name);
+       *font_p = FONT_MUSIC;
+       return( (unsigned char) BAD_CHAR);
+}
+#ifdef EXTCHAR
+\f
+
+/* given the name of an extended character set character,
+ * return its code number.
+ * If the name is not a valid name, return BAD_CHAR.
+ * Just do a binary search in the name-to-code translation table.
+ */
+
+static unsigned char
+ext_name2num(name)
+
+char *name;    /* name for an extended character set character */
+
+{
+       struct SPECCHAR *info_p;/* translation entry for the given name */
+       struct SPECCHAR key;    /* what to look for */
+       static unsigned int numch = 0;  /* how many items in xlation table */
+       char shortcut[12];      /* full name of shortcutted character */
+
+
+       /* find size of name-to-code table */
+       if (numch == 0) {
+               for (   ; Ext_char_table[numch].charname != (char *) 0;
+                                                       numch++) {
+                       ;
+               }
+       }
+
+       key.charname = name;
+
+       /* allow some shortcuts for common diacritical marks. A letter
+        * followed by one of '`^~:/,vo represents acute, grave, circumflex,
+        * tilde, dieresis, slash, cedilla, caron, and ring.
+        * And as a special case, ss represents germandbls */
+       if (strlen(name) == 2 && isalpha(name[0])) {
+               switch (name[1]) {
+               case '\'':
+                       (void) sprintf(shortcut, "%cacute", name[0]);
+                       key.charname = shortcut;
+                       break;
+               case '`':
+                       (void) sprintf(shortcut, "%cgrave", name[0]);
+                       key.charname = shortcut;
+                       break;
+               case '^':
+                       (void) sprintf(shortcut, "%ccircumflex", name[0]);
+                       key.charname = shortcut;
+                       break;
+               case '~':
+                       (void) sprintf(shortcut, "%ctilde", name[0]);
+                       key.charname = shortcut;
+                       break;
+               case ':':
+                       (void) sprintf(shortcut, "%cdieresis", name[0]);
+                       key.charname = shortcut;
+                       break;
+               case '/':
+                       (void) sprintf(shortcut, "%cslash", name[0]);
+                       key.charname = shortcut;
+                       break;
+               case ',':
+                       (void) sprintf(shortcut, "%ccedilla", name[0]);
+                       key.charname = shortcut;
+                       break;
+               case 'v':
+                       (void) sprintf(shortcut, "%ccaron", name[0]);
+                       key.charname = shortcut;
+                       break;
+               case 'o':
+                       (void) sprintf(shortcut, "%cring", name[0]);
+                       key.charname = shortcut;
+                       break;
+               case 's':
+                       if (name[0] == 's') {
+                               (void) sprintf(shortcut, "germandbls");
+                               key.charname = shortcut;
+                       }
+                       break;
+               default:
+                       /* not a special shortcut, leave as is */
+                       break;
+               }
+       }
+       /* Some more special case shortcuts: `` and '' are shortcuts for
+        * quotedblleft and quotedblright, and << and >> for guillemots */
+       if (strcmp(name, "``") == 0) {
+               key.charname = "quotedblleft";
+       }
+       else if (strcmp(name, "''") == 0) {
+               key.charname = "quotedblright";
+       }
+       else if (strcmp(name, "<<") == 0) {
+               key.charname = "guillemotleft";
+       }
+       else if (strcmp(name, ">>") == 0) {
+               key.charname = "guillemotright";
+       }
+
+       /* do binary search for code */
+       if ((info_p = (struct SPECCHAR *) bsearch((char *) &key, Ext_char_table,
+                       numch, sizeof(struct SPECCHAR), sc_compare))
+                       != (struct SPECCHAR *) 0) {
+               return( (unsigned char) info_p->code);
+       }
+
+       else {
+               /* don't do error message here, because it could just be a
+                * music character rather than an extended character set char */
+               return( (unsigned char) BAD_CHAR);
+       } 
+}
+#endif
+\f
+
+/* given the C_XXX code value for a music character, return the
+ * user name for the character. The first time this function gets
+ * called it sets up a translation array. Then it can just look up
+ * the name by using the code as an index into the array */
+
+char *
+mc_num2name(code, font)
+
+int code;      /* the code for the music character */
+int font;      /* FONT_MUSIC*   */
+
+{
+       static int xlate_tbl[NUM_MFONTS][CHARS_IN_FONT + FIRST_CHAR];
+                                       /* translate music char #define
+                                        * values to offset in Mus_char_table
+                                        * array */
+       int f;                          /* font index */
+       static int called = NO;         /* boolean, YES if this function
+                                        * has been called before */
+       register int numch;             /* how many music characters to do */
+
+
+       if (called == NO) {
+               called = YES;
+               /* first time. need to build table */
+
+               /* For each item in the Mus_char_table, fill in the
+                * element of the xlate_tbl array with its offset,
+                * or fill in -1 if no valid character with that code. */
+               for (f = 0; f < NUM_MFONTS; f++) {
+                       for ( numch = 0; numch < CHARS_IN_FONT + FIRST_CHAR; numch++) {
+                               xlate_tbl[f][numch] = -1;
+                       }
+               }
+               for (f = 0; f < NUM_MFONTS; f++) {
+                       for ( numch = 0; numch < CHARS_IN_FONT + FIRST_CHAR; numch++) {
+                               if (Mus_char_table[f][numch].charname != 0) {
+                                       xlate_tbl [f] [ Mus_char_table[f][numch].code & 0xff ] =
+                                       numch;
+                               }
+                               else {
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       /* now we just look up the name */
+       if ((numch = xlate_tbl[font - FONT_MUSIC][code & 0xff]) < 0) {
+               pfatal("bad music character [%d][%d] in mc_num2name",
+                                               font - FONT_MUSIC, code & 0xff);
+       }
+
+       return( Mus_char_table[font - FONT_MUSIC][numch].charname );
+}
+#ifdef EXTCHAR
+\f
+
+/* given the C_XXX code value for an extended character set char, return the
+ * user name for the character. The first time this function gets
+ * called it sets up a translation array. Then it can just look up
+ * the name by using the code as an index into the array */
+
+char *
+ext_num2name(code)
+
+int code;      /* the code for the extended character set character */
+
+{
+       static int xlate_tbl[CHARS_IN_FONT + FIRST_CHAR];
+                                       /* translate extended char
+                                        * #define values to offset in
+                                        * Ext_char_table array */
+       static int called = NO;         /* boolean, YES if this function
+                                        * has been called before */
+       register int numch;             /* how many extended characters to do */
+
+
+       if (called == NO) {
+               called = YES;
+               /* first time. need to build table */
+
+               /* initialize table to have nothing set */
+               for ( numch = 0; numch < CHARS_IN_FONT + FIRST_CHAR; numch++) {
+                       xlate_tbl[numch] = -1;
+               }
+
+               /* for each item in the Ext_char_table, fill in the
+                * element of the xlate_tbl array with its offset */
+               for (numch = 0; Ext_char_table[numch].charname != (char *) 0;
+                                                       numch++) {
+                       xlate_tbl [ Ext_char_table[numch].code & 0xff ] =
+                                       numch;
+               }
+       }
+
+       /* now we just look up the name */
+       if ((numch = xlate_tbl[code & 0xff]) < 0) {
+               pfatal("bad extended character set character (%d) in ext_num2name", code & 0xff);
+       }
+
+       return( Ext_char_table[numch].charname );
+}
+#endif
+\f
+
+/* return YES if string passed in consists solely of a music symbol, otherwise
+ * return NO */
+
+int
+is_music_symbol(str)
+
+char *str;             /* which string to check */
+
+{
+       char *string;
+       int font;
+       int size;
+
+
+       if (str == (char *) 0) {
+               return(NO);
+       }
+
+       font = str[0];
+       size = str[1];
+       string = str + 2;
+
+       /* has to be music char followed by null to be YES */
+       if (next_str_char(&string, &font, &size) == '\0') {
+               return(NO);
+       }
+       if ( ! IS_MUSIC_FONT(font)) {
+               return(NO);
+       }
+       if (next_str_char(&string, &font, &size) == '\0') {
+               return(YES);
+       }
+       return(NO);
+}
+\f
+
+/* return the ascent of a string in inches. This is the largest ascent of any
+ * character in the string */
+
+double
+strascent(str)
+
+char *str;     /* which string to process */
+
+{
+       float max_ascent, a;    /* tallest and current ascent */
+       char *s;                /* to walk through string */
+       int font, size, code;
+       int textfont;
+       double vertical, horizontal;
+       float baseline_offset;  /* to account for vertical motion */
+       int in_pile;
+       int only_mus_sym;       /* YES if string consists solely
+                                * of a music char */
+
+
+       if (str == (char *) 0) {
+               return(0.0);
+       }
+
+       only_mus_sym = is_music_symbol(str);
+
+       /* first 2 bytes are font and size. */
+       font = str[0];
+       size = str[1];
+
+       /* Walk through the string. */
+       for (max_ascent = 0.0, baseline_offset = 0.0, s = str + 2;
+                       (code = nxt_str_char(&s, &font, &size, &textfont,
+                       &vertical, &horizontal, &in_pile, NO)) > 0;    ) {
+
+               /* A newline goes to following line, so we probably won't
+                * get any higher ascent than we have so far, but if
+                * user gives enough vertical motion, we might, so continue. */
+               if (code == '\n') {
+                       baseline_offset -= fontheight(font, size);
+               }
+
+               /* adjust for any vertical motion */
+               if (vertical != 0.0) {
+                       baseline_offset += vertical;
+               }
+
+               /* music characters inside strings get moved up to the baseline,
+                * so use their height as ascent.
+                * Regular characters use the
+                * ascent of the character */
+               if ((IS_MUSIC_FONT(font))  && (only_mus_sym == NO)) {
+                       a = height(font, size, code);
+               }
+               else {
+                       a = ascent(font, size, code);
+               }
+               a += baseline_offset;
+
+               /* if tallest seen save this height */
+               if (a > max_ascent) {
+                       max_ascent = a;
+               }
+       }
+
+       /* if boxed, allow space for that */
+       if (IS_BOXED(str) == YES) {
+               max_ascent += 2.5 * STDPAD;
+       }
+       /* similarly, allow space for circle */
+       if (IS_CIRCLED(str) == YES) {
+               float ascent_adjust;
+               max_ascent += circled_dimensions(str, (float *) 0, (float *) 0,
+                                       &ascent_adjust, (float *) 0);
+               max_ascent += ascent_adjust;
+       }
+       return(max_ascent);
+}
+\f
+
+/* return the descent of a string in inches. This is the largest descent of any
+ * character in the string */
+
+double
+strdescent(str)
+
+char *str;     /* which string to process */
+
+{
+       float max_descent, d;   /* largest and current descent */
+       float line_descent;     /* descent caused by newlines */
+       double vertical, horizontal;
+       int in_pile;
+       char *s;                /* to walk through string */
+       int font, size, code;
+       int textfont;
+       int only_mus_sym;       /* YES if string consists solely
+                                * of a music char */
+
+
+       if (str == (char *) 0) {
+               return(0.0);
+       }
+
+       only_mus_sym = is_music_symbol(str);
+
+       /* first 2 bytes are font and size. */
+       font = str[0];
+       size = str[1];
+
+       /* walk through the string. */
+       for (max_descent = line_descent = 0.0, s = str + 2;
+                       (code = nxt_str_char(&s, &font, &size, &textfont,
+                       &vertical, &horizontal, &in_pile, NO)) > 0
+                       || vertical != 0.0;  ) {
+
+               /* Adjust for vertical motion. Since line_descent is
+                * measured downward and vertical is upward, have to
+                * substract the vertical, then adjust max_descent
+                * to compensate. */
+               if (vertical != 0.0) {
+                       line_descent -= vertical;
+                       max_descent += vertical;
+                       if (code == 0) {
+                               /* motion only */
+                               continue;
+                       }
+               }
+
+               if (code == '\n') {
+                       /* at newline, descent goes down to next baseline,
+                        * which will be down from current baseline
+                        * by height of font */
+                       line_descent += fontheight(font, size);
+                       max_descent = 0.0;
+                       continue;
+               }
+
+               /* music characters inside strings get moved up to the
+                * baseline, so have no descent. */
+               if ( ! (IS_MUSIC_FONT(font)) || (only_mus_sym == YES)) {
+                       d = descent(font, size, code);
+               }
+               else {
+                       d = 0.0;
+               }
+
+               /* if largest descent seen, save this descent */
+               if (d > max_descent) {
+                       max_descent = d;
+               }
+       }
+
+       /* if boxed, allow space for that */
+       if (IS_BOXED(str) == YES) {
+               max_descent += 3.5 * STDPAD;
+       }
+       /* similarly, allow space for circle */
+       if (IS_CIRCLED(str) == YES) {
+               max_descent += circled_dimensions(str, (float *) 0, (float *) 0,
+                                               (float *) 0, (float *) 0);
+       }
+       return(max_descent + line_descent);
+}
+\f
+
+/* return the height of a string in inches. This is the maximum ascent plus the
+ * maximum descent */
+
+double
+strheight(str)
+
+char *str;             /* which string to process */
+{
+       /* Since letters may not
+        * align because of ascent/descent, we get the tallest extent
+        * by adding the largest ascent to the largest descent */
+       return( strascent(str) + strdescent(str));
+}
+\f
+
+/* return the width of a string. This is the sum of the widths of the
+ * individual characters in the string */
+
+double
+strwidth(str)
+char *str;
+{
+       float tot_width;
+       float widest_line;      /* for multi-line strings */
+       float curr_width;
+       double horizontal, vertical;
+       int was_in_pile;        /* if in pile last time through loop */
+       int in_pile_now;        /* if current character is inside a pile */
+       char *s;                /* to walk through string */
+       int font, size, code;
+       int textfont;
+
+
+       if (str == (char *) 0) {
+               return(0.0);
+       }
+
+       /* first 2 bytes are font and size. */
+       font = str[0];
+       size = str[1];
+
+       /* walk through string */
+       was_in_pile = NO;
+       for (curr_width = tot_width = widest_line = 0.0, s = str + 2;
+                       (code = nxt_str_char(&s, &font, &size, &textfont,
+                       &vertical, &horizontal, &in_pile_now, NO)) > 0;
+                       was_in_pile = in_pile_now) {
+
+               /* Piles are handled specially. As soon as we enter a pile,
+                * we call the function to get its entire width. Then for
+                * the rest of the pile, we just skip past everything */
+               if (in_pile_now == YES) {
+                       if (was_in_pile == NO) {
+                               curr_width += pile_width();
+                               if (curr_width > tot_width) {
+                                       tot_width = curr_width;
+                               }
+                       }
+                       continue;
+               }
+
+               /* the horizontal movement coming out of a pile doesn't count,
+                * since it was included in the pile, otherwise it does */
+               if (was_in_pile == NO) {
+                       curr_width += horizontal;
+               }
+               if (curr_width > tot_width) {
+                       tot_width = curr_width;
+               }
+
+               if (code == '\n') {
+                       /* keep track of width line of multi-line string */
+                       if (tot_width > widest_line) {
+                               widest_line = tot_width;
+                       }
+                       tot_width = 0.0;
+                       curr_width = 0.0;
+                       continue;
+               }
+
+               if (code == '\b') {
+                       /* backspace */
+                       tot_width -= backsp_width(size);
+                       curr_width -= backsp_width(size);
+                       continue;
+               }
+
+               /* If we have the special "page number" character,
+                * or special "total number of pages" character,
+                * we deal with that here. */
+               if ( (code == '%' || code == '#') && (s > str + 3)
+                                       && ( (*(s-2) & 0xff) == STR_PAGENUM
+                                       || (*(s-2) & 0xff) == STR_NUMPAGES) ) {
+
+                       char pgnumbuff[8], *pgnum_p;
+
+                       /* convert page number to a string and
+                        * add the width of each character in
+                        * that string. */
+                       (void) sprintf(pgnumbuff, "%d",
+                                       code == '%' ? Pagenum : Last_pagenum);
+
+                       for ( pgnum_p = pgnumbuff; *pgnum_p != '\0';
+                                                               pgnum_p++) {
+                               curr_width += width(font, size, *pgnum_p);
+                       }
+               }
+
+               else {
+                       /* Oh good. This is a normal case. Just add
+                        * width of this character to width so far */
+                       curr_width += width(font, size, code);
+               }
+
+               if (curr_width > tot_width) {
+                       tot_width = curr_width;
+               }
+       }
+       if (tot_width < widest_line) {
+               tot_width = widest_line;
+       }
+       /* if string is boxed, allow space for the box */
+       if (IS_BOXED(str) == YES) {
+               tot_width += 6.0 * STDPAD;
+       }
+       /* similarly, allow space for circled */
+       if (IS_CIRCLED(str) == YES) {
+               (void) circled_dimensions(str, (float *) 0, &tot_width,
+                                               (float *) 0, (float *) 0);
+       }
+       return(tot_width);
+}
+\f
+
+/* Return the width to the "anchor" point of a string. For most strings,
+ * this will be half the width of the first character. But for a string
+ * that begins with things piled atop one another, it is the alignment point.
+ * And for boxed or circled strings, the box or circle must be considered.
+ */
+
+double
+left_width(string)
+
+char *string;
+
+{
+       int font;
+       int size;
+       char *pile_start_p;     /* where pile begins, if any */
+
+       if (starts_piled(string, &font, &size, &pile_start_p) == YES) {
+               return(align_distance(pile_start_p, font, size));
+       }
+       else {
+               int ch;
+               float extra;            /* space for box or circle, if any */
+
+               /* For boxed or circled strings,
+                * the space for the box or circle must be added in */
+               if (IS_BOXED(string) == YES) {
+                       extra = 3.5 * STDPAD;
+               }
+               else if (IS_CIRCLED(string) == YES) {
+                       (void) circled_dimensions(string, (float *) 0,
+                                       (float *) 0, (float *) 0, &extra);
+               }
+               else {
+                       extra = 0.0;
+               }
+
+               /* Get half the width of the first character in the string */
+               font = *string++;
+               size = *string++;
+               ch = next_str_char(&string, &font, &size);
+               return(width(font, size, ch) / 2.0 + extra);
+       }
+}
+\f
+
+/* If string begins with piled text, return YES, otherwise NO,
+ * If YES, also return via pointers the start of the pile and the
+ * font and size at that point. */
+
+static int
+starts_piled(string, font_p, size_p, pile_start_p_p)
+
+char *string;
+int *font_p;
+int *size_p;
+char **pile_start_p_p;
+
+{
+       *font_p = *string++;
+       *size_p = *string++;
+
+       /* walk through string, skipping any leading box/size/font */
+       for (  ; *string != '\0'; string++) {
+               if (IS_STR_COMMAND(*string)) {
+                       switch(*string & 0xff) {
+
+                       case STR_FONT:
+                               *font_p = *(++string);
+                               break;
+
+                       case STR_SIZE:
+                               *size_p = *(++string);
+                               break;
+
+                       case STR_BOX:
+                       case STR_CIR:
+                               break;
+
+                       case STR_PILE:
+                               /* The first thing we found that was not to be
+                                * ignored is the beginning of a pile */
+                               *pile_start_p_p = string;
+                               return(YES);
+               
+                       default:
+                               return(NO);
+                       }
+               }
+               else {
+                       break;
+               }
+       }
+       return(NO);
+}
+\f
+
+/* given a string representing a chord mark, transpose it. For each letter
+ * 'A' to 'G' optionally followed by an accidental, call function to
+ * get transposed value. Build new string with transposed values. Free up
+ * the old string and return the new one. Also, if the accidental was
+ * of the form &, #, x, or && instead of \(smflat) etc, change to proper
+ * music symbol. Also handles translation of o, o/ and ^ to dim, halfdim,
+ * and triangle symbols, and does translation of unescaped accidentals. */
+
+char *
+tranchstr(chordstring, staffno)
+
+char *chordstring;     /* untransposed string */
+int staffno;           /* which staff it is associated with */
+                       /* A staffno of -1 means no transpose, just translate */
+
+{
+       char tmpbuff[128];      /* temporary copy of transposed string */
+       char replacement[4];    /* for dim/halfdim/triangle */
+       short i;                /* index into tmpbuff */
+       unsigned char *str;     /* walk through chordstring */
+       char *transposed;       /* new version of letter[accidental] */
+       char tranbuff[4];       /* to point 'transposed' at if not really
+                                * transposing */
+       char letter;            /* A to G */
+       char accidental;
+       int escaped;            /* YES is accidental was escaped */
+       char literal_accidental;        /* what would normally be translated */
+       int nprocessed;         /* how many character processed by subroutine */
+       char *newstring;        /* final copy of transposed string */
+       int n;
+       int size;
+       int in_pile;            /* YES if inside a pile */
+       int acc_size;           /* size for accidentals */
+
+
+       /* get font/size info */
+       tmpbuff[0] = chordstring[0];
+       tmpbuff[1] = chordstring[1];
+       size = chordstring[1];
+       in_pile = NO;
+       str = (unsigned char *) (chordstring + 2);
+       literal_accidental = '\0';  /* avoids bogus "used before set" warning */
+
+       /* walk through original string */
+       for (i = 2; *str != '\0'; str++) {
+
+               /* Be safe. Bail out a little before we reach end,
+                * because some things take several bytes,
+                * and it's easiest to just check once per loop. */
+               if (i > sizeof(tmpbuff) - 8) {
+                       ufatal("chord string too long: '%s'", chordstring + 2);
+               }
+
+               acc_size = accsize(size);
+
+               /* If a STR_*, deal with that */
+               if ((n = str_cmd((char *) str, &size, &in_pile)) > 0) {
+                       strncpy(tmpbuff + i, (char *) str, (unsigned) n);
+                       i += n;
+                       str += n - 1;
+               }
+
+               /* handle backslashed o and ^ */
+               else if (*str == '\\' && ( *(str+1) == 'o' || *(str+1) == '^' ) ) {
+                       str++;
+                       tmpbuff[i++] = *str;
+               }
+
+               else if (*str >= 'A' && *str <= 'G') {
+
+                       /* Aha! Something to transpose. */
+                       letter = *str;
+
+                       str += get_accidental( (unsigned char *) (str + 1),
+                                       &accidental, &acc_size, NO, &escaped);
+                       if (escaped == YES) {
+                               /* not *really* an accidental, so save to
+                                * print later. */
+                               literal_accidental = accidental;
+                               accidental = '\0';
+                       }
+                       if (staffno == -1) {
+                               /* not to be transposed, so make a string
+                                * that would be like what tranchnote() would
+                                * return, but with no transposition. */
+                               tranbuff[0] = letter;
+                               tranbuff[1] = accidental;
+                               tranbuff[2] = '\0';
+                               transposed = tranbuff;
+                       }
+                       else {
+                               /* get the transposed value */
+                               transposed = tranchnote(letter, accidental, staffno);
+                       }
+
+                       /* put transposed letter into output */
+                       tmpbuff[i++] = *transposed;
+
+                       /* now add accidental if any */
+                       i += add_accidental(tmpbuff + i, (int) *++transposed,
+                                                       acc_size, NO);
+
+                       /* add on any escaped pseudo-accidental */
+                       if (escaped == YES) {
+                               i += add_accidental(tmpbuff + i,
+                                       (int) literal_accidental,
+                                       acc_size, YES);
+                               escaped = NO;
+                       }
+
+                       /* handle dim/halfdim/triangle transformations */
+                       if ((n = dim_tri(str + 1, replacement, size, YES)) > 0) {
+                               strcpy(tmpbuff + i, replacement);
+                               i += strlen(replacement);
+                               str += n;
+                       }
+               }
+               else {
+                       /* Originally we only translated things like # and &
+                        * in chords to musical accidental symbols if they
+                        * immediately followed a letter A-G. But due to
+                        * popular demand, they are now translated everywhere,
+                        * unless escaped. */
+                       nprocessed = get_accidental( (unsigned char *) str,
+                                       &accidental, &acc_size, NO, &escaped);
+                       if (nprocessed > 0) {
+                               i += add_accidental(tmpbuff + i,
+                                       (int) accidental,
+                                       acc_size, escaped);
+                               /* the -1 is because str will get incremented
+                               * at the top of the 'for' */
+                               str += nprocessed - 1;
+                       }
+                       else {
+                               /* something boring. Just copy */
+                               tmpbuff[i++] = *str;
+                       }
+               }
+       }
+
+       /* need to make permanent copy of new string */
+       tmpbuff[i++] = '\0';
+       MALLOCA(char, newstring, i + 1);
+       (void) memcpy(newstring, tmpbuff, (unsigned) i);
+
+       /* free original version */
+       FREE(chordstring);
+
+       /* return new, transposed version */
+       return(newstring);
+}
+\f
+
+/* If there is a STR_* command in chord/analysis/figbass, return how
+ * many characters long it is. Also update the size if the
+ * command was one to change size, and update pile status if necessary. */
+
+static int
+str_cmd(str, size_p, in_pile_p)
+
+char *str;     /* check string starting here */
+int *size_p;
+int *in_pile_p;        /* YES if in pile, may be updated */
+
+{
+       if (IS_STR_COMMAND(*str)) {
+               switch(*str & 0xff) {
+
+               case STR_SIZE:
+                       /* update size */
+                       *size_p = *(str + 1);
+                       /* command plus 1 argument byte */
+                       return(2);
+
+               case STR_PAGENUM:
+               case STR_NUMPAGES:
+               case STR_FONT:
+               case STR_BACKSPACE:
+               case STR_VERTICAL:
+                       /* command plus 1 argument byte */
+                       return(2);
+
+               case STR_MUS_CHAR:
+                       /* command plus 2 argument bytes */
+                       return(3);
+
+               case STR_PILE:
+                       /* entering/leaving a pile alters the size */
+                       *size_p = pile_size(*size_p, *in_pile_p);
+                       *in_pile_p = (*in_pile_p ? NO : YES);
+                       break;
+
+               default:
+                       /* others have no argument bytes */
+                       return(1);
+               }
+       }
+       return(0);
+}
+\f
+
+/* Check the first character of the given string to see if it is an accidental
+ * or something that should be translated to an accidental (# & x && and
+ * maybe n). If so, fill in the accidental. If the accidental was specified
+ * via a STR_MUS_CHAR, also update the accidental size.
+ * If no accidental, accidental_p will will filled in
+ * with '\0'. In any case return how many bytes were processed.
+ */
+
+static int
+get_accidental(string, accidental_p, acc_size_p, trans_natural, escaped_p)
+
+unsigned char *string; /* check this for an accidental */
+char *accidental_p;    /* return the accidental here, or \0 if none */
+int *acc_size_p;       /* return the accidental size here */
+int trans_natural;     /* if YES, translate n to natural, else leave as n */
+int *escaped_p;                /* Return value: YES if the symbol was backslashed */
+
+{
+       unsigned char *str_p;
+
+       str_p = string;
+       /* assume no accidental */
+       *accidental_p = '\0';
+
+       /* check if escaped */
+       if (*str_p == '\\') {
+               *escaped_p = YES;
+               str_p++;
+       }
+       else {
+               *escaped_p = NO;
+       }
+
+       /* See if the following character is an accidental */
+       switch (*str_p) {
+
+       case '#':
+       case 'x':
+               *accidental_p = *str_p++;
+               break;
+       case '&':
+               *accidental_p = *str_p++;
+               /* have to peek ahead to check for double flat,
+                * but not if escaped, so person can get a literal
+                * ampersand followed by a flat. */
+               if (*escaped_p == NO && *str_p == '&') {
+                       /* double flat is 'B' internally */
+                       *accidental_p = 'B';
+                       str_p++;
+               }
+               break;
+
+       case 'n':
+               /* naturals are not translated in chords, but are
+                * in analysis and figbass */
+               if (trans_natural == YES) {
+                       *accidental_p = *str_p++;
+               }
+               break;
+
+       case STR_MUS_CHAR:
+               if (*escaped_p == YES) {
+                       break;
+               }
+               /* Check if user put in \(flat) or something
+                * similar. If so, use that. */
+               switch (*(str_p + 2)) {
+               case C_FLAT:
+                       *acc_size_p = *(str_p + 1);
+                       *accidental_p = '&';
+                       str_p += 3;
+                       break;
+
+               case C_SHARP:
+                       *acc_size_p = *(str_p + 1);
+                       *accidental_p = '#';
+                       str_p += 3;
+                       break;
+
+               case C_DBLFLAT:
+                       *acc_size_p = *(str_p + 1);
+                       *accidental_p = 'B';
+                       str_p += 3;
+                       break;
+
+               case C_DBLSHARP:
+                       *acc_size_p = *(str_p + 1);
+                       *accidental_p = 'x';
+                       str_p += 3;
+                       break;
+
+               case C_NAT:
+                       /* Always translate the natural symbol,
+                        * even when trans_natural is NO. That really
+                        * applies just to the use of 'n' which is
+                        * likely to be wanted as a real n, whereas
+                        * a music symbol natural is unambiguous. */
+                       *acc_size_p = *(str_p + 1);
+                       *accidental_p = 'n';
+                       str_p += 3;
+                       break;
+
+               default:
+                       /* false alarm. Some other
+                        * music character. */
+                       break;
+               }
+               break;
+
+       default:
+               /* nothing special */
+               break;
+       }
+
+       /* If all we saw was a backslash,
+        * then there wasn't really an accidental */
+       if (*escaped_p == YES && str_p == string + 1) {
+               *escaped_p = NO;
+               str_p = string;
+       }
+
+       return(str_p - string);
+}
+\f
+
+/* Write the given accidental in the given size to the given string.
+ * Return how many bytes were added. */
+
+static int
+add_accidental(buff, acc_character, acc_size, escaped)
+
+char *buff;            /* write into this buffer */
+int acc_character;     /* write this accidental */
+int acc_size;          /* make accidental this big */
+int escaped;           /* if YES, was escaped, so not really an accidental;
+                        * print it as a normal character */
+
+{
+       if (acc_character != '\0') {
+
+               /* if escaped, just treat like normal character. */
+               if (escaped == YES) {
+                       buff[0] = acc_character;
+                       return(1);
+               }
+
+               /* sharps and naturals are tall enough that they can
+                * make things not line up, so move them down some */
+               if (acc_character == '#' || acc_character == 'n') {
+                       buff[0] = (char) STR_VERTICAL;
+                       buff[1] = (char) ENCODE_VERT(-4);
+                       buff += 2;
+               }
+               /* has accidental. Add STR_MUS_CHAR-size-code */
+               buff[0] = (char) STR_MUS_CHAR;
+
+               /* double sharp is special. It is too small,
+                * so make it bigger */
+               if (acc_character == 'x') {
+                       acc_size = (int) ( (float) acc_size
+                                                       * 1.25);
+               }
+               buff[1] = (char) acc_size;
+
+               /* use accidental of appropriate type */
+               switch (acc_character) {
+
+               case '#':
+                       buff[2] = C_SHARP;
+                       break;
+
+               case '&':
+                       buff[2] = C_FLAT;
+                       break;
+
+               case 'x':
+                       buff[2] = C_DBLSHARP;
+                       break;
+
+               case 'B':
+                       buff[2] = C_DBLFLAT;
+                       break;
+
+               case 'n':
+                       buff[2] = C_NAT;
+                       break;
+
+               default:
+                       pfatal("illegal accidental on transposed chord");
+                       break;
+               }
+               if (acc_character == '#' || acc_character == 'n') {
+                       buff[3] = (char) STR_VERTICAL;
+                       buff[4] = (char) ENCODE_VERT(4);
+                       /* We added 3 bytes for the accidental, plus
+                        * 2 bytes before and after for vertical motion. */
+                       return(7);
+               }
+               else {
+                       return(3);      /* we added 3 bytes */
+               }
+       }
+
+       return (0);
+}
+\f
+
+/* In chords and such, "o" becomes \(dim), "o/" becomes \(halfdim)
+ * unless followed by [A-G] in which case it becomes "\(dim)/",
+ * and "^" becomes \(triangle). Return number of characters processed.
+ */
+
+static int
+dim_tri(str_p, replacement, size, is_chord)
+
+unsigned char *str_p;          /* check string at this point */
+char *replacement;             /* return the replacement in this buffer,
+                                * which needs to be at least 4 bytes long */
+int size;                      /* use this size for music character */
+int is_chord;                  /* YES for chord, NO for analysis/figbass */
+
+{
+       if (*str_p == '^') {
+               replacement[0] = (char) STR_MUS_CHAR;
+               replacement[1] = size;
+               replacement[2] = C_TRIANGLE;
+               replacement[3] = '\0';
+               return(1);
+       }
+       else if (*str_p == 'o') {
+               replacement[0] = (char) STR_MUS_CHAR;
+               replacement[1] = size;
+               replacement[3] = '\0';
+               if ( *(str_p+1) == '/' && (is_chord == NO ||
+                               (*(str_p+2) < 'A' || *(str_p+2) > 'G'))) {
+                       replacement[2] = C_HALFDIM;
+                       return(2);
+               }
+               else {
+                       replacement[2] = C_DIM;
+                       return(1);
+               }
+       }
+       return(0);
+}
+\f
+
+/* Given a string for analysis or figbass, transform the accidentals
+ * & # && x n to their music characters.
+ */
+
+char *
+acc_trans(string)
+
+char *string;
+
+{
+       char buffer[128];       /* output buffer for transformed string */
+       char *out_p;            /* current location in output buffer */
+       char replacement[4];    /* space for dim, halfdim, etc */
+       int n;
+       int size, acc_size;
+       char accidental;        /* #, &, x, etc */
+       int escaped;            /* YES is accidental was escaped */
+       int in_pile;            /* YES if inside a pile */
+
+
+       buffer[0] = string[0];
+       buffer[1] = string[1];
+       size = string[1];
+       in_pile = NO;
+
+       /* walk through string, transforming any accidentals along the way */
+       for ( string += 2, out_p = buffer + 2; *string != '\0'; ) {
+               /* Be safe. Bail out a little before we reach end,
+                * because some things take several bytes,
+                * and it's easiest to just check once per loop. */
+               if (out_p - buffer > sizeof(buffer) - 8) {
+                       l_ufatal(Curr_filename, yylineno,
+                               "analysis or figbass string too long");
+               }
+
+               acc_size = accsize(size);
+               if ((n = get_accidental((unsigned char *) string,
+                               &accidental, &acc_size, YES, &escaped)) > 0 ) {
+                       out_p += add_accidental(out_p, (int) accidental,
+                                               acc_size, escaped);
+                       string += n;
+               }
+               else if (*string == '\\' && ( *(string+1) == 'o' || *(string+1) == '^') ) {
+                       *out_p++ = *++string;
+                       string++;
+               }
+               else if ((n = dim_tri((unsigned char *) string, replacement,
+                                                       size, NO)) > 0) {
+                       strcpy(out_p, replacement);
+                       out_p += strlen(replacement);
+                       string += n;
+               }
+               else if ((n = str_cmd(string, &size, &in_pile)) > 0) {
+                       strncpy(out_p, string, (unsigned) n);
+                       out_p += n;
+                       string += n;
+               }
+               else {
+                       *out_p++ = *string++;
+               }
+       }
+       *out_p = '\0';
+
+       return(copy_string(buffer + 2, buffer[0], buffer[1]));
+}
+\f
+/* Given a chord, analysis or figbass string,
+ * transform according to their special rules:
+ *     - : gets translated to \: and vice-versa
+ *     - figbass starts in piled mode
+ *     - in figbass, a / gets translated to \/ and vice-versa
+ * This string will be in half transformed state: the first 2 bytes
+ * are font/size, but the rest is still all ASCII, not internal format.
+ */
+
+char *
+modify_chstr(string, modifier)
+
+char *string;
+int modifier;
+
+{
+       int length;     /* of modified string */
+       char *s;        /* walk through string */
+       char *newstring;
+       char *new_p;    /* walk through newstring */
+       int need_new;   /* if we need to make a new string */
+
+
+       length = strlen(string);
+       if (modifier == TM_FIGBASS) {
+               /* We'll need two extra bytes for
+                * the leading \: for pile mode. */
+               length += 2;
+               need_new = YES;
+       }
+       else {
+               /* Only need a new string if the original has colons,
+                * so assume for now we won't need a new string */
+               need_new = NO;
+       }
+
+       /* Figure out how much space we'll need for the modified string.
+        * Any unbackslashed colons will take up an extra byte once
+        * we backslash it. But any backslashed one will take up one
+        * less when we unescape it. Similar for slashes in figbass. */
+       for (s = string + 2; *s != '\0'; s++) {
+               if (*s == ':') {
+                       length++;
+                       need_new = YES;
+               }
+               else if (modifier == TM_FIGBASS && *s == '/') {
+                       /* o/ means half diminished so that doesn't count */
+                       if (s > string + 2 && *(s-1) == 'o') {
+                               continue;
+                       }
+                       length++;
+                       need_new = YES;
+               }
+               else if (*s == '\\') {
+                       s++;
+                       /* things that occur inside \(...) don't count */
+                       if (*s == '(') {
+                               for (s++; *s != '\0' && *s != ')'; s++) {
+                                       ;
+                               }
+                               /* If no closing parenthesis, return as is;
+                                * later code will catch that */
+                               if (*s == '\0') {
+                                       return(string);
+                               }
+                       }
+                       else if (*s == ':') {
+                               length--;
+                               need_new = YES;
+                       }
+                       else if (modifier == TM_FIGBASS && *s == '/') {
+                               length--;
+                               need_new = YES;
+                       }
+               }
+       }
+
+       /* If string is okay as is, we are done here */
+       if (need_new == NO) {
+               return(string);
+       }
+
+       /* get enough space for new string */
+       MALLOCA(char, newstring, length + 1);
+
+       /* copy font/size */
+       newstring[0] = string[0];
+       newstring[1] = string[1];
+
+       new_p = newstring + 2;
+       s = string + 2;
+       if (modifier == TM_FIGBASS) {
+               /* add \: but after box, if any */
+               if (string[2] == '\\' && string[3] == '[') {
+                       *new_p++ = *s++;
+                       *new_p++ = *s++;
+               }
+               *new_p++ = '\\';
+               *new_p++ = ':';
+       }
+
+       /* walk through rest of string, copying, but transforming
+        * any slashes and colons along the way */
+       for (  ; *s != '\0'; s++, new_p++) {
+
+               /* handle colons */
+               if (*s == ':') {
+                       /* add a backslash */
+                       *new_p++ = '\\';
+               }
+               else if (*s == '\\' && *(s+1) == ':') {
+                       /* skip past the backslash */
+                       s++;
+               }
+
+               /* handle slashes in figbass */
+               else if (modifier == TM_FIGBASS) {
+                       if (*s == '/') {
+                               /* o/ means half diminished
+                                * so that doesn't count */
+                               if (s <= string + 2 || *(s-1) != 'o') {
+                                       /* add a backslash */
+                                       *new_p++ = '\\';
+                               }
+                       }
+                       else if (*s == '\\' && *(s+1) == '/') {
+                               /* skip past the backslash */
+                               s++;
+                       }
+               }
+
+               /* copy from original string to new one */
+               *new_p = *s;
+       }
+
+       /* original is now no longer needed */
+       FREE(string);
+
+       /* terminate and return the modified string */
+       *new_p = '\0';
+       return(newstring);
+}
+\f
+
+/* given an integer point size, return the integer point size appropriate
+ * for a "small" version. This is SM_FACTOR times the size, rounded, but
+ * not less than 1. */
+
+static int
+smallsize(size)
+
+int size;
+
+{
+       size = (int) ( (float) size * SM_FACTOR);
+       if (size < 1) {
+               size = 1;
+       }
+       return(size);
+}
+\f
+
+/* accidentals in chords need to be scaled. Given a size, return the size
+ * that an accidental should be. This is 60% of given size, rounded to
+ * an integer, but no smaller than 1. */
+
+static int
+accsize(size)
+
+int size;
+
+{
+       size = (int) ( (float) size * 0.6);
+       if (size < 1) {
+               size = 1;
+       }
+       return(size);
+}
+\f
+
+/* return which character to use for rest, based on basictime */
+
+int
+restchar(basictime)
+
+int basictime;
+
+{
+       if (basictime < -1) {
+               pfatal("tried to get rest character for multirest");
+               /*NOTREACHED*/
+               return(0);
+       }
+
+       else if (basictime == -1) {
+               /* quad rest */
+               return (C_QWHREST);
+       }
+
+       else if (basictime == 0) {
+               /* double whole rest */
+               return (C_DWHREST);
+       }
+
+       else {
+               /* other non-multirest */
+               return (Resttab [ drmo(basictime) ] );
+       }
+}
+\f
+
+/* return YES if given font is an italic font (includes boldital too) */
+
+int
+is_ital_font(font)
+
+int font;
+
+{
+       return(Fontinfo[ font_index(font) ].is_ital);
+}
+\f
+
+/* given a string, return, via pointers the font and size in effect at the
+ * end of the string */
+
+void
+end_fontsize(str, font_p, size_p)
+
+char *str;             /* check this string */
+int *font_p;           /* return font at end of str via this pointer */
+int *size_p;           /* return size at end of str via this pointer */
+
+{
+       if (str == (char *) 0) {
+               /* empty string, use defaults */
+               *font_p = FONT_TR;
+               *size_p = DFLT_SIZE;
+               return;
+       }
+
+       /* find the font/size in effect at end of given string */
+       *font_p = *str++;
+       *size_p = *str++;
+       while (next_str_char(&str, font_p, size_p) != '\0') {
+               ;
+       }
+}
+\f
+
+/* given a string, return a string made up of a dash in the font and size
+ * of the end of the given string. However, if the string ends with a ~ or _
+ * return a string containing that instead */
+
+char *
+dashstr(str)
+
+char *str;     /* return dash with same font/size as end of this string */
+
+{
+       int font, size;
+       char *newstring;
+       int ch;         /* character to use */
+
+
+       end_fontsize(str, &font, &size);
+       ch = last_char(str);
+       if (ch != '~' && ch != '_') {
+               ch = '-';
+       }
+
+       /* allocate space for dash string and fill it in */
+       MALLOCA(char, newstring, 4);
+       newstring[0] = (char) font;
+       newstring[1] = (char) size;
+       newstring[2] = (char) ch;
+       newstring[3] = '\0';
+       return(newstring);
+}
+\f
+
+/* Given an internal format string, create an ASCII-only string. Flags
+ * tell how complete a conversion to do. If verbose is YES, try to convert
+ * everything back to user's original input, otherwise ignore special things
+ * other than music characters, extended characters, and backspace.
+ * If pagenum is YES, interpolate the current page number rather than using %.
+ *
+ * Recreating the original user string is not perfect, but is usually right.
+ * Where there are shortcuts, we can't tell if user used them or not.
+ * Extended characters are output by name even if user put them in as single
+ * Latin-1 characters. But we couldn't use the Latin-1 hyper-ASCII in midi
+ * anyway, because they have high bit set.
+ *
+ * Returns the ASCII-ized string, which is stored in an area that will get
+ * overwritten on subsequent calls, so if caller needs a permanent copy,
+ * they have to make it themselves.
+ */
+
+/* This is how much to malloc at a time to hold the ASCII-ized string */
+#define ASCII_BSIZE    512
+
+char *
+ascii_str(string, verbose, pagenum, textmod)
+
+char *string;  /* internal format string to convert */
+int verbose;   /* If YES, try to reproduce user's original input */
+int pagenum;   /* YES (interpolate number for \%) or NO (leave \% as is) */
+int textmod;   /* TM_ value */
+
+{
+       static char *buff = 0;          /* for ASCII-ized string */
+       static unsigned buff_length = 0;/* how much is malloc-ed */
+       int i;                          /* index into ASCII-ized string */
+       char *musname;                  /* music character name */
+       int in_pile = NO;
+       char *str;                      /* walk through string */
+       int musfont;                    /* FONT_MUSIC*    */
+
+
+       /* first time, get some space */
+       if (buff_length == 0) {
+               buff_length = ASCII_BSIZE;
+               MALLOCA(char, buff, buff_length);
+       }
+
+       /* walk through string */
+       i = 0;
+       /* special case: normally we implicitly begin a figbass with a
+        * pile start, but if users cancels that, it won't be there */
+       if (textmod == TM_FIGBASS &&
+                       (((unsigned char) *(string+2)) & 0xff) != STR_PILE) {
+               buff[i++] = ':';
+       }
+       for (str = string + 2;  *str != '\0'; str++) {
+               switch ( ((unsigned char) *str) & 0xff) {
+
+               case STR_FONT:
+                       str++;
+#ifdef EXTCHAR
+                       if ( (int) *str > EXT_FONT_OFFSET) {
+                               str++;
+                               /* translate to Mup name */
+                               (void) sprintf(buff + i, "\\(%s)",
+                                               ext_num2name((int) *str));
+                               while (buff[i] != '\0') {
+                                       i++;
+                               }
+                               /* skip past the return to original font */
+                               str += 2;
+                       }
+                       else if (verbose == YES) {
+#else
+                       if (verbose == YES) {
+#endif
+                               (void) sprintf(buff + i, "\\f(%s)",
+                                               fontnum2name((int) *str));
+                               while (buff[i] != '\0') {
+                                       i++;
+                               }
+                       }
+                       break;
+
+               case STR_SIZE:
+                       str++;
+                       if (verbose == YES) {
+                               (void) sprintf(buff + i, "\\s(%d)", (int) *str);
+                               while (buff[i] != '\0') {
+                                       i++;
+                               }
+                       }
+                       break;
+
+               case STR_VERTICAL:
+                       str++;
+                       if (verbose == YES) {
+                               (void) sprintf(buff + i, "\\v(%d)",
+                                               DECODE_VERT((int) *str) * 100
+                                               / MAXVERTICAL);
+                               while (buff[i] != '\0') {
+                                       i++;
+                               }
+                       }
+                       break;
+               
+               case STR_MUS_CHAR:
+               case STR_MUS_CHAR2:
+                       musfont = str2mfont( ((unsigned char) *str) & 0xff);
+
+                       /* skip past the size byte,
+                        * and on to the character code. */
+                       str += 2;
+                       /* In chordlike stuffs, we translate things like
+                        * # and &&, so translate them back. It's possible
+                        * the user used the names explicitly rather than us
+                        * translating, in which case this won't be
+                        * strictly what they put in, but it will be
+                        * consistent, so that a caller of this function
+                        * can easily sort or compare values
+                        * without having to know (for example)
+                        * that '#' and \(smsharp) are the same thing.  */
+                       musname = 0;
+                       if (IS_CHORDLIKE(textmod) == YES
+                                               && musfont == FONT_MUSIC) {
+                               switch( ((unsigned char) *str) & 0xff) {
+                               case C_SHARP:
+                                       musname = "#";
+                                       break;
+                               case C_FLAT:
+                                       musname = "&";
+                                       break;
+                               case C_DBLSHARP:
+                                       musname = "x";
+                                       break;
+                               case C_DBLFLAT:
+                                       musname = "&&";
+                                       break;
+                               case C_NAT:
+                                       if (textmod != TM_CHORD) {
+                                               musname = "n";
+                                       }
+                                       break;
+                               case C_DIM:
+                                       musname = "o";
+                                       break;
+                               case C_HALFDIM:
+                                       musname = "o/";
+                                       break;
+                               case C_TRIANGLE:
+                                       musname = "^";
+                                       break;
+                               default:
+                                       break;
+                               }
+                       }
+                       if (musname != 0) {
+                               (void) sprintf(buff + i, musname);
+                       }
+                       else {
+                               (void) sprintf(buff + i, "\\(%s)", 
+                                       mc_num2name((int) *str, musfont));
+                       }
+                       while (buff[i] != '\0') {
+                               i++;
+                       }
+                       
+                       break;
+
+               case STR_BACKSPACE:
+                       if (verbose == YES) {
+                               buff[i++] = '\\';
+                               buff[i++] = 'b';
+                       }
+                       /* ignore this and following char */
+                       str++;
+                       break;
+
+               case STR_PRE:
+               case STR_PST:
+                       if (verbose == YES) {
+                               buff[i++] = '<';
+                       }
+                       break;
+
+               case STR_U_PRE:
+               case STR_U_PST:
+                       if (verbose == YES) {
+                               buff[i++] = '<';
+                               buff[i++] = '^';
+                       }
+                       break;
+
+               case STR_PRE_END:
+               case STR_PST_END:
+                       if (verbose == YES) {
+                               buff[i++] = '>';
+                       }
+                       break;
+
+               case STR_BOX:
+                       if (verbose == YES) {
+                               buff[i++] = '\\';
+                               buff[i++] = '[';
+                       }
+                       break;
+
+               case STR_BOX_END:
+                       if (verbose == YES) {
+                               buff[i++] = '\\';
+                               buff[i++] = ']';
+                       }
+                       break;
+
+               case STR_CIR:
+                       if (verbose == YES) {
+                               buff[i++] = '\\';
+                               buff[i++] = '{';
+                       }
+                       break;
+
+               case STR_CIR_END:
+                       if (verbose == YES) {
+                               buff[i++] = '\\';
+                               buff[i++] = '}';
+                       }
+                       break;
+
+               case STR_C_ALIGN:
+                       if (verbose == YES) {
+                               buff[i++] = '\\';
+                               buff[i++] = '^';
+                       }
+                       break;
+
+               case STR_L_ALIGN:
+                       if (verbose == YES) {
+                               buff[i++] = '\\';
+                               buff[i++] = '|';
+                       }
+                       break;
+
+               case STR_PILE:
+                       if (verbose == YES) {
+                               /* On figbass, we implictly add a pile start */
+                               if (textmod == TM_FIGBASS && string + 2 == str) {
+                                       ;
+                               }
+                               /* if this is at the end of a padded string,
+                                * there is a high probability it is one
+                                * we added implicitly, so skip it */
+                               else if (in_pile == YES && *(str+1) == ' ' &&
+                                               *(str+2) == '\0') {
+                                       ;
+                               }
+                               else {
+                                       /* in chordlike things, user didn't
+                                        * use a backslash, else they did */
+                                       if (IS_CHORDLIKE(textmod) == NO) {
+                                               buff[i++] = '\\';
+                                       }
+                                       buff[i++] = ':';
+                               }
+                       }
+                       /* keep track of toggle state */
+                       in_pile = (in_pile == YES ? NO : YES);
+                       break;
+
+               case STR_SLASH:
+                       if (verbose == YES && textmod != TM_FIGBASS) {
+                               buff[i++] = '\\';
+                       }
+                       buff[i++] = '/';
+                       break;
+
+               case STR_PAGENUM:
+               case STR_NUMPAGES:
+                       if (pagenum == YES) {
+                               /* Write page number and update length.
+                                * Actually, we don't have the correct values
+                                * for this until late in program execution,
+                                * and for MIDI, there are no pages at all,
+                                * and this can be called from MIDI, so
+                                * this is probably not really very useful,
+                                * but this is the best we can do... */
+                               (void) sprintf(buff + i, "%d",
+                                       (((unsigned char) *str) & 0xff)
+                                       == STR_PAGENUM ?
+                                       Pagenum : Last_pagenum);
+                               while (buff[i] != '\0') {
+                                       i++;
+                               }
+                       }
+                       else {
+                               buff[i++] = '\\';
+                               buff[i++] = *(str+1);
+                       }
+                       str++;
+                       break;
+
+               case '\\':
+                       buff[i++] = '\\';
+                       buff[i++] = '\\';
+                       break;
+
+               default:
+                       if (*str == '\n') {
+                               if (in_pile == YES) {
+                                       if ( *(str+1) != '\0') {
+                                               buff[i++] = ' ';
+                                       }
+                               }
+                               else {
+                                       buff[i++] = '\\';
+                                       buff[i++] = 'n';
+                               }
+                       }
+                       else if (IS_CHORDLIKE(textmod) == YES && *str == ':') {
+                               buff[i++] = '\\';
+                               buff[i++] = ':';
+                       }
+                       else if (textmod == TM_FIGBASS && *str == '/') {
+                               buff[i++] = '\\';
+                               buff[i++] = '/';
+                       }
+                       else if (*str == ' ' && *(str+1) == '\0') {
+                               /* This is probably a space padding
+                                * that we added implicitly,
+                                * so don't print it. If this is
+                                * called on a 'with' item or 'print' item
+                                * where user explicitly added a space,
+                                * this will strip that off, which, strictly
+                                * speaking, it shouldn't. But that would
+                                * only be for debugging anyway, and a
+                                * strange case, so don't worry about it. */
+                               ;
+                       }
+                       else {
+                               /* ordinary character */
+                               buff[i++] = *str;
+                       }
+               }
+
+               /* If running low on space, get some more. Could probably
+                * just truncate, since this is used for things like error
+                * messages, but alloc-ing more is easy enough. */
+               if (i > buff_length - 20) {
+                       buff_length += ASCII_BSIZE;
+                       REALLOCA(char, buff, buff_length);
+               }
+       }
+       buff[i++] = '\0';
+
+       return(buff);
+}
+\f
+
+/*
+ * Given a text string and a maximum desired width, try adding newlines at
+ * white space to bring the width down under the desired width. If that's
+ * not possible, do the best we can. Return pointer to the possibly
+ * altered string.
+ */
+
+char *
+split_string(string, desired_width)
+
+char *string;
+double desired_width;
+
+{
+       char *last_white_p;     /* where last white space was */
+       char *curr_white_p;     /* white space we're dealing with now */
+       char *str;              /* to walk through string */
+       double proposed_width;  /* width of string so far */
+       int font, size;
+       int c;                  /* the current character in string */
+       int save_c;             /* temporary copy of c */
+       int save_str;           /* temporary copy of character from string */
+
+
+       /* Piles are incompatible with newlines, so we don't want to
+        * even attempt to split a string with a pile in it. */
+       for (str = string + 2; *str != '\0'; str++) {
+               if ((*str & 0xff) == STR_PILE) {
+                       /* string has a pile, so return it as is */
+                       return(string);
+               }
+       }
+
+       /* Go through the string, until we hit white space. */
+       last_white_p = (char *) 0;
+       font = string[0];
+       size = string[1];
+       str = string + 2;
+       while ((c = next_str_char(&str, &font, &size)) != '\0') {
+
+               /* Are we at white space? */
+               if ( ! IS_MUSIC_FONT(font) && (c == ' ' || c == '\t')) {
+
+                       /* Temporarily replace with newline, and terminate
+                        * to get width so far if we were to add a newline */
+                       curr_white_p = str - 1;
+                       save_c = c;
+                       save_str = *str;
+                       *curr_white_p = '\n';
+                       *str = '\0';
+                       proposed_width = strwidth(string);
+                       *curr_white_p = save_c;
+                       *str = save_str;
+
+                       if (proposed_width > desired_width) {
+                               if (last_white_p != (char *) 0) {
+                                       /* reduce the width of the string by
+                                        * changing the most recent white space
+                                        * to a newline */
+                                       *last_white_p = '\n';
+
+                                       /* if the overall string is now short
+                                        * enough, we are done */
+                                       if (strwidth(string) <= desired_width) {
+                                               return(string);
+                                       }
+                                       last_white_p = curr_white_p;
+                               }
+                               else {
+                                       /* No previous white space, so we
+                                        * can't make it short enough. So change
+                                        * this current white space to a
+                                        * newline, since that's the best we
+                                        * can do. But also set the desired
+                                        * width to our current width,
+                                        * because we know we're
+                                        * going to have to be at least this
+                                        * wide anyway, so we might as well use
+                                        * this much space on future lines */
+                                       *curr_white_p = '\n';
+                                       desired_width = proposed_width;
+
+                                       /* no longer have a previous
+                                        * white space on the current line,
+                                        * because we just started a new
+                                        * line */
+                                       last_white_p = (char *) 0;
+                               }
+
+                       }
+                       else {
+                               /* not too wide yet. Remember where this white
+                                * space is, in case the next word makes us
+                                * too wide and we have to change it to a
+                                * newline */
+                               last_white_p = curr_white_p;
+                       }
+               }
+       }
+
+       /* If last word went over the edge, move to next line if possible. */
+       if (strwidth(string) > desired_width && last_white_p != (char *) 0) {
+               *last_white_p = '\n';
+       }
+
+       /* Return the (possibly altered) string */
+       return(string);
+}
+\f
+
+/* Given a point size and an adjustment factor, return a new point size.
+ * If size would be less than MINSIZE, return MINSIZE.
+ * If it would be greater than MAXSIZE, print error and return MAXSIZE.
+ * Since we only use integer sizes, there may be some roundoff error.
+ * While it would be possible to dream up a pathological case
+ * where this roundout might be big enough to notice,
+ * for any sane scenario you would probably need
+ * an extremely high resolution printer and a microscope to notice.
+ */
+
+int
+adj_size(size, scale_factor, filename, lineno)
+
+int size;              /* original point size */
+double scale_factor;   /* multiply original size by this factor */
+char *filename;                /* filename and lineno are for error messages */
+int lineno;
+
+{
+       size = (int) ((double) size * scale_factor + 0.5);
+       if (size < MINSIZE) {
+               return(MINSIZE);
+       }
+       if (size > MAXSIZE) {
+               l_warning(filename, lineno,
+                       "Adjusted size of string would be bigger than %d", MAXSIZE);
+               return(MAXSIZE);
+       }
+       return(size);
+}
+\f
+
+/* Given a string that is in internal format, and a scale factor by which to
+ * resize that string, adjust all size bytes in the string.
+ */
+
+char *
+resize_string(string, scale_factor, filename, lineno)
+
+char *string;          /* this is the string to adjust */
+double scale_factor;   /* adjust sizes in string by this factor */
+char *filename;                /* for error messages */
+int lineno;            /* for error messages */
+
+{
+       char *s;        /* to walk through string */
+
+
+       /* if string is empty, nothing to do */
+       if (string == (char *) 0 || *string == '\0') {
+               return(string);
+       }
+
+       /* if factor is sufficiently close to 1.0 that it's very clear
+        * we won't be making any changes (since we only use integer
+        * point sizes), don't bother */
+       if ( fabs( (double) (scale_factor - 1.0)) < 0.01) {
+               return(string);
+       }
+
+       /* second byte is size byte, so adjust that */
+       string[1] = (char) adj_size( (int) string[1], scale_factor,
+                                                       filename, lineno);
+
+       /* Go through the string. For each size byte, replace it with an
+        * adjusted size. Size bytes occur immediately after STR_SIZE
+        * and STR_MUS_CHAR commands. Everything else can get copied as
+        * is: STR_BACKSPACE is in terms of the default size, so it is
+        * unaffected by this resizing, and the other special string commands
+        * are unrelated to size and thus unaffected. */
+       for (s = string + 2; *s != '\0'; s++) {
+               switch ( (unsigned char) *s ) {
+               case STR_SIZE:
+               case STR_MUS_CHAR:
+                       s++;
+                       *s = (char) adj_size( (int) *s, scale_factor,
+                                                       filename, lineno);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return(string);
+}
+\f
+
+/* Given a circled string, return how much to add to its ascent and
+ * descent to give room for the circle.  If pointer arguments are non-zero,
+ * return additional values via those pointers.
+ */
+
+double
+circled_dimensions(str, height_p, width_p, ascent_adjust, x_offset_p)
+
+char *str;                     /* a circled string */
+float *height_p;               /* if non-zero, return circled height here */
+float *width_p;                        /* if non-zero, return circled width here */
+float *ascent_adjust;          /* if non-zero, return amount we added to
+                                * ascent to bring up to minimum height */
+float *x_offset_p;             /* if non-zero, return where to print the
+                                * actual string relative to circle edge */
+
+{
+       int font, size;
+       float min_height;
+       float adjust;                   /* amount to bring up to min height */
+       float uncirc_height, uncirc_width;/* dimensions of uncircled str */
+       float circ_height;              /* height including circle */
+       float circ_width;               /* width including circle */
+       float circ_extra;               /* how much to add to top and
+                                        * bottom to allow space for circle */
+
+
+       /* temporarily make the string uncircled */
+       size = str[2] = str[1];
+       font = str[1] = str[0];
+       /* Note that there is at least one circumstance (in split_string())
+        * where a circled string is temporarily lacking the trailing END_CIR,
+        * and strheight and strwidth don't need it, so we don't need
+        * to blank that out. */
+
+       /* get the dimensions of the uncircled version */
+       uncirc_height = strheight(str+1);
+       uncirc_width = strwidth(str+1);
+
+       /* put the circle back */
+       str[1] = str[2];
+       str[2] = (char) STR_CIR;
+
+       /* If string is unusually short vertically, treat as at least as tall
+        * as the font's ascent. That way if there are a bunch of
+        * circled things and one is tiny, like a dot, that circle
+        * won't be vastly smaller than the others. */
+       min_height = fontascent(font, size);
+       if (uncirc_height < min_height) {
+               adjust = min_height - uncirc_height;
+               uncirc_height = min_height;
+       }
+       else {
+               adjust = 0.0;
+       }
+
+       /* Allow 25% of the height above and below as space for the circle. */
+       circ_extra = 0.25 * uncirc_height;
+       circ_height = 2.0 * circ_extra + uncirc_height;
+
+       /* If width is up to 110% of the height, use the circled
+        * height as the circled width as well. */
+       if (uncirc_width <= 1.1 * uncirc_height) {
+               circ_width = circ_height;
+       }
+       else {
+               /* make a little taller to compensate for the width */
+               circ_extra += circ_height * .03 * (uncirc_width / uncirc_height);
+               circ_height = 2.0 * circ_extra + uncirc_height;
+
+               /* Use 50% of the circled height as the amount to add
+                * to the width, 25% on each end. */
+               circ_width = uncirc_width + 0.5 * circ_height;
+       }
+       if (height_p != 0) {
+               *height_p = circ_height;
+       }
+       if (width_p != 0) {
+               *width_p = circ_width;
+       }
+       if (x_offset_p != 0) {
+               *x_offset_p = (circ_width - uncirc_width) / 2.0;
+       }
+       if (ascent_adjust != 0) {
+               *ascent_adjust = adjust;
+       }
+
+       return(circ_extra);
+}
+\f
+
+/* Return proper version of rehearsal mark string, based on staff number.
+ * It may be circled, boxed, or plain. If circled or boxed, a new string
+ * is returned. If plain, the string is returned as is.
+ */
+
+char *
+get_reh_string(string, staffnum)
+
+char *string;  /* the plain rehearsal mark string */
+int staffnum;  /* which staff it is for */
+
+{
+       char reh_buffer[100];   /* if not okay as it is, copy is put here */
+       int style;
+
+       style = svpath(staffnum, REHSTYLE)->rehstyle;
+
+       if (style == RS_PLAIN) {
+               return(string);
+       }
+
+       if (strlen(string) + 3 > sizeof(reh_buffer)) {
+               /* Usually reh marks are very short,
+                * so if this one is really long, too bad.
+                */
+               ufatal("rehearsal mark is too long");
+       }
+
+       (void) sprintf(reh_buffer, "%c%s%c",
+               style == RS_CIRCLED ? STR_CIR : STR_BOX,
+               string + 2,
+               style == RS_CIRCLED ? STR_CIR_END : STR_BOX_END);
+       return(copy_string(reh_buffer, string[0], string[1]));
+}
+\f
+
+/* Map STR_MUS_CHAR* to FONT_MUSIC*  */
+
+int
+str2mfont(str)
+
+int str;       /* STR_MUS_CHAR*  */
+
+{
+       switch (str) {
+       case STR_MUS_CHAR:
+               return(FONT_MUSIC);
+       case STR_MUS_CHAR2:
+               return(FONT_MUSIC2);
+       default:
+               pfatal("impossible str 0x%x in str2mfont", str);
+               /*NOTREACHED*/
+               return(FONT_MUSIC);
+       }
+}
+
+/* Map FONT_MUSIC* to STR_MUS_CHAR*  */
+
+int
+mfont2str(mfont)
+
+int mfont;     /* FONT_MUSIC*  */
+
+{
+       switch (mfont) {
+       case FONT_MUSIC:
+               return(STR_MUS_CHAR);
+       case FONT_MUSIC2:
+               return(STR_MUS_CHAR2);
+       default:
+               pfatal("impossible mfont %d in mfont2str", mfont);
+               /*NOTREACHED*/
+               return(STR_MUS_CHAR);
+       }
+}
diff --git a/mup/mup/check.c b/mup/mup/check.c
new file mode 100644 (file)
index 0000000..e329b9c
--- /dev/null
@@ -0,0 +1,1994 @@
+
+/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions for checking for various classes of errors such as
+ * values out of range, or trying to do something in an illegal context.
+ * Also contains the code to combine multiple measures of rests into
+ * multirests. */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+static struct MAINLL *add_pre_meas P((struct MAINLL *insert_p, int start,
+               int end, int add_bar));
+static int check_all_rests P((struct STAFF *staff_p, int count));
+static void do_combine P((struct MAINLL *begin_p, struct MAINLL *end_p,
+               int nummeas, int min_combine));
+static int valid_mark_item P((int mark, int place));
+static void mv_accs P((struct MAINLL *mll_p));
+static void move_xoct P((struct STUFF *stuff_p, struct MAINLL *newfirst_p,
+               int staffno, int bars, int start));
+static void addped P((struct STUFF *pedal_p, struct MAINLL *mll_p));
+
+
+\f
+
+/* give error message if given number is not within specified range. */
+/* return NO if out of range, YES if okay */
+
+/* once upon a time, there was the rangecheck function, and it got called
+ * many times. Then midi support was added and that code needed to do lots
+ * of rangechecks, but with the filename and line number something other
+ * than Curr_filename, and yylineno, so the l_rangecheck function was
+ * created, and rangecheck just calls that. There isn't an l_frangecheck
+ * to go with frangecheck, because nothing needed it. Another case where
+ * C++ would have been nice, so we could default added arguments....
+ */
+
+int
+rangecheck(n, min, max, name)
+
+int n;         /* the number to check */
+int min;       /* has to be at least this big */
+int max;       /* can be no bigger than this */
+char *name;    /* describes what n represents, to use in error message */
+
+{
+       return(l_rangecheck(n, min, max, name, Curr_filename, yylineno));
+}
+
+int
+l_rangecheck(n, min, max, name, fname, lineno)
+
+int n;         /* the number to check */
+int min;       /* has to be at least this big */
+int max;       /* can be no bigger than this */
+char *name;    /* describes what n represents, to use in error message */
+char *fname;   /* file name */
+int lineno;    /* line number */
+
+{
+       if ( (n < min) || (n > max) ) {
+               l_yyerror(fname, lineno,
+                               "%s (%d) is out of range (must be between %d and %d)",
+                               name, n, min, max);
+               return(NO);
+       }
+       return(YES);
+}
+
+
+/* This function is rather like rangecheck, except it also allows a special
+ * "empty" value. */
+
+int
+erangecheck(n, min, max, empty_value, name)
+
+int n;         /* the number to check */
+int min;       /* has to be at least this big */
+int max;       /* can be no bigger than this */
+int empty_value;       /* this is also a legal value */
+char *name;    /* describes what n represents, to use in error message */
+
+{
+       if (n == empty_value) {
+               /* value is okay--means user set to empty */
+               return(YES);
+       }
+       if ( (n < min) || (n > max) ) {
+               l_yyerror(Curr_filename, yylineno,
+                               "%s (%d) out of range (must be between %d to %d or set to nothing at all)",
+                               name, n, min, max);
+               return(NO);
+       }
+       return(YES);
+}
+\f
+
+/* just like rangecheck except for a float instead of int */
+
+int
+frangecheck(n, min, max, name)
+
+float n;       /* the number to check */
+float min;     /* has to be at least this big */
+float max;     /* can be no bigger than this */
+char *name;    /* describes what n represents, to use in error message */
+
+{
+       if ( (n < min) || (n > max) ) {
+               l_yyerror(Curr_filename, yylineno,
+                               "%s (%.3f) is out of range (must be between %.3f and %.3f)",
+                               name, n, min, max);
+               return(NO);
+       }
+       return(YES);
+}
+\f
+
+/* give error and return NO if given number is not a power of 2 */
+
+int
+power_of2check(n, name)
+
+int n;         /* number to verify */
+char *name;    /* what n represents, for error message */
+
+{
+       if ( (n <= 0) || ((n & (n - 1)) != 0)) {
+               l_yyerror(Curr_filename, yylineno,
+                               "%s (%d) not a power of 2", name, n);
+               return(NO);
+       }
+       return(YES);
+}
+\f
+
+/* check that current action is valid in current context. */
+/* If so, return YES, otherwise print message and return NO */
+
+int
+contextcheck(validcontext, action)
+
+int validcontext;      /* bitmap of valid contexts */
+char *action;          /* what action is to be done, for error messages */
+
+{
+       static int shouldBmusic; /* count of how many consecutive times
+                               * we were called when we should have been
+                               * in music context, but weren't
+                               */
+
+       /* Forgetting to say 'music' can cause tons of errors,
+        * which may confuse the user. So try to deduce what they meant.
+        */
+       if (validcontext == C_MUSIC) {
+               if (Context != C_MUSIC) {
+                       if (++shouldBmusic > 5) {
+                               
+                               l_yyerror(Curr_filename, yylineno, "guessing you forgot to specify 'music'; changing to music context to try to recover");
+                               Context = C_MUSIC;
+                       }
+               }
+               else {
+                       shouldBmusic = 0;
+               }
+       }
+       else {
+               shouldBmusic = 0;
+       }
+
+       if ((validcontext & Context) == 0) {
+               l_yyerror(Curr_filename, yylineno, "%s not valid in %s context",
+                       action, contextname(Context));
+               return(NO);
+       }
+       return(YES);
+}
+\f
+
+/* convert context number back to name */
+
+char *
+contextname(cont)
+
+int cont;      /* context number */
+
+{
+       switch(cont)  {
+       case C_MUSIC:
+               return("music");
+       case C_SCORE:
+               return("score");
+       case C_STAFF:
+               return("staff");
+       case C_VOICE:
+               return("voice");
+       case C_HEADER:
+               return("header");
+       case C_FOOTER:
+               return("footer");
+       case C_HEAD2:
+               return("header2");
+       case C_FOOT2:
+               return("footer2");
+       case C_TOP:
+               return("top");
+       case C_TOP2:
+               return("top2");
+       case C_BOT:
+               return("bottom");
+       case C_BOT2:
+               return("bottom2");
+       case C_BLOCK:
+               return("block");
+       default:
+               return("unknown");
+       }
+}
+\f
+
+/* check that at least one staff is visible, print error message if not */
+
+void
+check_at_least1visible()
+
+{
+       int staffno;
+
+       /* go through list of staffs, if we find a visible one, fine */
+       for (staffno = Score.staffs; staffno > 0; staffno--) {
+               if ( (svpath(staffno, VISIBLE))->visible == YES) {
+                       return;
+               }
+       }
+
+       yyerror("no staffs visible");
+       return;
+}
+\f
+
+/* if there is a change in visibility status, need to have a scorefeed after
+ * that. So go through main list. If there is a change in visibility, or
+ * in number of staffs, or stafflines, or staffscale, go
+ * backwards in list till hit FEED, BAR, or beginning of list. If hit FEED
+ * first, throw it away. Then search forward from the SSV until we hit
+ * FEED or STAFF.  If FEED, fine. If STAFF, insert
+ * a FEED. If we discarded the user FEED because it was in the wrong place,
+ * mark the pagefeed field as they had it.
+ * This function also adds a measure of space to the beginning of the song
+ * if we are doing MIDI. If a song begins with a grace note,
+ * we want to move that back into the "previous" measure, so this will
+ * create that measure. It's easier to deal with that here, before
+ * makechords() is called, than to try to add it in later.
+ */
+
+void
+chk_vis_feed()
+
+{
+       struct MAINLL *mll_p, *m_p;     /* to walk through main list */
+       struct MAINLL *new_feed_p;
+       short set_pagefeed = NO;        /* if to set pagefeed field */
+       short s;                        /* staff index */
+       short vis[MAXSTAFFS + 1];       /* which staffs are currently visible */
+       short stlines[MAXSTAFFS + 1];   /* stafflines for each staff */
+       float stscale[MAXSTAFFS + 1];   /* staffscale for each staff */
+       short num_staffs;               /* number of staffs */
+       short add_extra;                /* if to add extra space measure */
+
+
+       debug(4, "chk_vis_feed");
+
+       /* If doing MIDI, we want to add an extra space measure to the
+        * beginning */
+       add_extra = Doing_MIDI;
+
+       /* go through main list looking for visibility changes */
+       initstructs();
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->next) {
+
+               if (mll_p->str == S_SSV) {
+                       /* SSV can only follow a BAR or BLOCKHEAD or another
+                        * SSV. If it follows a LINE/CURVE/PRHEAD,
+                        * then user must have entered music context,
+                        * but not entered any music,
+                        * just line/curve/print things. This violates our
+                        * mainlist rules, so we have to disallow */
+                       if (mll_p->prev != 0 && mll_p->prev->str != S_BAR &&
+                                       mll_p->prev->str != S_BLOCKHEAD &&
+                                       mll_p->prev->str != S_SSV) {
+                               l_yyerror(mll_p->inputfile, mll_p->inputlineno,
+                                       "music context containing only lines/curves/print statements is not allowed");
+                       }
+
+                       /* Only want to insert a FEED if there truly was
+                        * a change in the number of staffs to be printed.
+                        * User may have set visible when it was already set,
+                        * or just changed voice visibility which didn't
+                        * cause the visibily of staffs to change, or
+                        * something like that, which doesn't count.
+                        * So see what visiblity, stafflines,
+                        * and staffscale are set to now,
+                        * then assign the SSV and see if things changed.
+                        */
+                       for (s = 1; s <= MAXSTAFFS; s++) {
+                               /* save current values of interest */
+                               vis[s] = svpath(s, VISIBLE)->visible;
+                               stlines[s] = svpath(s, STAFFLINES)->stafflines;
+                               stscale[s] = svpath(s, STAFFSCALE)->staffscale;
+                       }
+                       num_staffs = Score.staffs;
+
+                       /* make any updates */
+                       asgnssv(mll_p->u.ssv_p);
+
+                       /* now compare with previous values */
+                       for (s = 1; s <= MAXSTAFFS; s++) {
+                               if (vis[s] != svpath(s, VISIBLE)->visible ||
+                                               stlines[s] != svpath(s,
+                                               STAFFLINES)->stafflines ||
+                                               stscale[s] != svpath(s,
+                                               STAFFSCALE)->staffscale) {
+                                       /* something changed */
+                                       break;
+                               }
+                       }
+
+                       if (s <= MAXSTAFFS || Score.staffs != num_staffs) {
+
+                               /* found a change. Go backwards. If find a
+                                * FEED, discard it. Otherwise ok */
+                               for (m_p = mll_p->prev;
+                                               m_p != (struct MAINLL *) 0;
+                                               m_p = m_p->prev) {
+
+                                       if (IS_CLEFSIG_FEED(m_p)) {
+                                               /* feed in wrong place. Discard
+                                                * this one. We'll put one in
+                                                * the proper place later */
+                                               set_pagefeed =
+                                                       m_p->u.feed_p->pagefeed;
+                                               unlinkMAINLL(m_p);
+                                               FREE(m_p);
+                                               break;
+                                       }
+
+                                       else if (m_p->str == S_BAR) {
+                                               break;
+                                       }
+                               }
+
+                               /* now look forwards. If find FEED, fine.
+                                * If not, insert one */
+                               for (m_p = mll_p->next;
+                                               m_p != (struct MAINLL *) 0;
+                                               m_p = m_p->next) {
+
+                                       if (m_p->str == S_FEED) {
+                                               /* user already put one in */
+                                               break;
+                                       }
+
+                                       else if (m_p->str == S_STAFF) {
+                                               /* user neglected to put in an
+                                                * explicit feed, so we add
+                                                * one for them */
+                                               new_feed_p =
+                                                       newMAINLLstruct(S_FEED,
+                                                       -1);
+                                               new_feed_p->u.feed_p->pagefeed
+                                                               = set_pagefeed;
+                                               insertMAINLL(new_feed_p,
+                                                               m_p->prev);
+                                               break;
+                                       }
+                               }
+                               set_pagefeed = NO;
+                       }
+               }
+
+               else if (add_extra == YES && mll_p->str == S_STAFF) {
+                       /* For MIDI purposes, add a measure space to the
+                        * beginning of the song, in case we need to move
+                        * grace notes back into it. Strictly speaking,
+                        * we probably don't need to do this unless there
+                        * truly is a grace note at the beginning, but
+                        * it should never hurt to add it, and it doesn't
+                        * seem worth the effort to check. */
+                       add_pre_meas(mll_p->prev, 1, Score.staffs, YES);
+
+                       add_extra = NO;
+               }
+       }
+}
+\f
+
+/* For MIDI, we add a measure of space preceeding what the user put in.
+ * This is used in case they start the piece with grace notes that we need
+ * to move back in the preceeding measure, since this guarantees there will
+ * be a preceeding measure. Also, for when taking a "slice" of the piece,
+ * skipping measures at the beginning, this is where we attach any MIDI
+ * STUFFs that happened during the skipped part.
+ * Returns the last MAINLL added.
+ */
+
+static struct MAINLL *
+add_pre_meas(insert_p, start, end, add_bar)
+
+struct MAINLL *insert_p;       /* insert after here */
+int start;                     /* staff number of first STAFF to create */
+int end;                       /* staff number of last STAFF to create */
+int add_bar;                   /* if YES, add an invisible bar too */
+
+{
+       int staff;              /* loop through staffs to be created */
+       struct MAINLL *new_p;   /* new STAFFs */
+       int numvoices;          /* number of voices on current staff */
+       int v;                  /* voice index */
+
+       /* Create a staff with measure space for all
+        * defined staffs/voices, and link onto main list */
+       for (staff = start; staff <= end; staff++) {
+
+               /* create the STAFF struct itself */
+               new_p = newMAINLLstruct(S_STAFF, -1);
+               new_p->u.staff_p->staffno = staff;
+               new_p->u.staff_p->visible = svpath(staff, VISIBLE)->visible;
+
+               numvoices = vscheme_voices(svpath(staff, VSCHEME)->vscheme);
+               for (v = 0; v < numvoices; v++) {
+                       add_meas_space( &(new_p->u.staff_p->groups_p[v]),
+                                               staff, v + 1);
+               }
+
+               /* link onto main list, and arrange to
+                * link the next thing after this one */
+               insertMAINLL(new_p, insert_p);
+               insert_p = new_p;
+       }
+       if (add_bar == YES) {
+               /* add an invisible bar line */
+               new_p = newMAINLLstruct(S_BAR, -1);
+               new_p->u.bar_p->bartype = INVISBAR;
+               insertMAINLL(new_p, insert_p);
+               insert_p = new_p;
+       }
+       return(insert_p);
+}
+\f
+
+/* check for valid interval. Unison, octave, fourths and fifths can not be
+ * major or minor. The others cannot be perfect. */
+
+void
+chk_interval(inttype, intnum)
+
+int inttype;   /* PERFECT, MINOR, etc */
+int intnum;    /* e.g., 4 for fourth */
+
+{
+       if (intnum <= 0) {
+               yyerror("transposition interval must be > 0");
+               return;
+       }
+
+       /* collapse into 1 octave. It's okay that a 7th will come out zero
+        * because of the way things are checked below. */
+       intnum %= 7;
+
+       switch (inttype) {
+
+       case  PERFECT:
+               switch (intnum) {
+               case 1: 
+               case 4:
+               case 5:
+                       break;
+               default:
+                       yyerror("specified interval cannot be perfect");
+                       break;
+               }
+               break;
+
+       case MAJOR:
+       case MINOR:
+               switch(intnum) {
+               case 1:
+               case 4:
+               case 5:
+                       yyerror("specified interval cannot be major or minor");
+                       break;
+               default:
+                       break;
+               }
+               break;
+
+       default:
+               /* everything else is okay */
+               break;
+       }
+}
+\f
+
+/* if specified used[] field is set to YES, print warning that its value is
+ * being overridden. This is to let user know they set the same parameter
+ * twice in the same SSV context */
+
+void
+used_check(mll_p, var, name)
+
+struct MAINLL *mll_p;  /* check used[] in the SSV pointed to by this */
+int var;               /* check this index in the used[] array */
+char *name;            /* name of variable, for warning message */
+
+{
+       if (mll_p == (struct MAINLL *) 0) {
+               l_yyerror(Curr_filename, yylineno,
+                       "can't set %s in %s context", name, contextname(Context));
+               return;
+       }
+
+       if (mll_p->str != S_SSV) {
+               pfatal("bad argument passed to used_check()");
+       }
+
+       if (mll_p->u.ssv_p->used[var] == YES) {
+               l_warning(Curr_filename, yylineno,
+                       "setting of '%s' parameter overrides previous setting",
+                       name);
+       }
+}
+\f
+
+/* go through list and combine multiple consecutive rests into multi-rests */
+
+void
+combine_rests(c)
+
+int c; /* argument to -c command line option;
+        * only combine when there are at least
+        * this many rest measures in a row.
+        * Set to NORESTCOMBINE if user didn't use -c option. */
+
+{
+       struct MAINLL *mll_p;   /* walk through main list */
+       struct MAINLL *begin_p = (struct MAINLL *) 0;   /* where section to
+                                                        * combine begins */
+       struct MAINLL *end_p = (struct MAINLL *) 0;
+       int all_rests = YES;
+       int n;                  /* how many measures minimum to combine */
+       int count = 0;          /* how many measures of all rests */
+       int begin_valid = NO;   /* if begin_p has been set. Can't just check to
+                                * see if it is null, because null is valid */
+       struct SSV *ssv_p;
+       char *timerep;          /* current time signature representation */
+
+
+       debug(2, "combine_rests");
+
+       /* go through main list */
+       initstructs();
+       n = c;  /* init to value of -c option */
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->next) {
+
+               if (Doing_MIDI == YES && mll_p == Mainllhc_p) {
+                       /* Don't want to combine the "extra" measure
+                        * we added in for MIDI, so skip it. */
+                       for (  ; mll_p != 0; mll_p = mll_p->next) {
+                               if (mll_p->str == S_BAR) {
+                                       mll_p = mll_p->next;
+                                       break;
+                               }
+                       }
+                       if (mll_p == 0) {
+                               /* Must be no valid music data in the file.
+                                * check4barline_at_end() should have already
+                                * reported this to user, so we can just
+                                * return silently here. */
+                               return;
+                       }
+               }
+
+               /* for each STAFF that is visible, see if it is all rests */
+               if (mll_p->str == S_STAFF) {
+                       /* remember where we are, in case this is the beginning
+                        * of section that needs to be combined */
+                       if (begin_valid == NO) {
+                               begin_p = mll_p->prev;
+                               begin_valid = YES;
+                       }
+
+                       /* if we have all rests so far, check this staff */
+                       if (all_rests == YES) {
+                               if ((all_rests = check_all_rests
+                                               (mll_p->u.staff_p, count))
+                                               == NO) {
+                                       /* this measure was not all rests.
+                                        * Check to see if before that we
+                                        * had seen a run of
+                                        * all rests. If so, combine them */
+                                       do_combine(begin_p, end_p, count, n);
+                               }
+                       }
+               }
+
+               else if (mll_p->str == S_BAR) {
+                       if (all_rests == YES) {
+                               /* this measure was all rests, so
+                                * bump counter */
+                               if (mll_p->u.bar_p->bartype != INVISBAR) {
+                                       count++;
+                               }
+                               end_p = mll_p;
+                               /* if not an ordinary bar, end the combining */
+                               if ( (mll_p->u.bar_p->reh_type != REH_NONE) ||
+                                               (mll_p->u.bar_p->endingloc
+                                               != NOITEM &&
+                                               mll_p->u.bar_p->endingloc
+                                               != INITEM) ||
+                                               ( (mll_p->u.bar_p->bartype
+                                               != SINGLEBAR) &&
+                                               (mll_p->u.bar_p->bartype !=
+                                               INVISBAR) ) ) {
+                                       if (mll_p->u.bar_p->bartype == RESTART) {
+                                               /* There is an empty "measure"
+                                                * of space before restarts */
+                                               count--;
+                                               /* need to end combining at
+                                                * the previous bar line */
+                                               if (count >= n) {
+                                                       for (end_p = end_p->prev;
+                                                       end_p != 0 &&
+                                                       end_p->str != S_BAR;
+                                                       end_p = end_p->prev) {
+                                                               ;
+                                                       }
+                                               }
+                                       }
+
+                                       do_combine(begin_p, end_p, count, n);
+
+                                       /* re-initialize */
+                                       count = 0;
+                                       begin_p = (struct MAINLL *) 0;
+                                       all_rests = YES;
+                                       begin_valid = NO;
+                               }
+                       }
+                       else {
+                               /* re-init for next measure */
+                               all_rests = YES;
+                               count = 0;
+                               begin_p = (struct MAINLL *) 0;
+                               begin_valid = NO;
+                       }
+               }
+
+               else if (mll_p->str == S_SSV) {
+
+                       ssv_p = mll_p->u.ssv_p;
+
+                       /* If -c option was not used, we use the value of
+                        * the restcombine parameter. */
+                       if (c == NORESTCOMBINE &&
+                                       ssv_p->used[RESTCOMBINE] == YES) {
+                               n = ssv_p->restcombine;
+                       }
+
+                       /* if there is a change in visibility or a relevant
+                        * change on an already-visible score,
+                        * that is grounds to end the combination */
+                       if ( ssv_p->used[VISIBLE] == YES ||
+                                       ((((mll_p->u.ssv_p->staffno == 0) ||
+                                       (svpath(mll_p->u.ssv_p->staffno,
+                                       VISIBLE))->visible == YES)) &&
+                                       (ssv_p->used[CLEF] == YES
+                                       || ssv_p->used[SHARPS] == YES
+                                       || ssv_p->used[TIME] == YES
+                                       || ssv_p->used[TRANSPOSITION] == YES
+                                       || ssv_p->used[ADDTRANSPOSITION] == YES
+                                       || ssv_p->used[VISIBLE] == YES))) {
+                               do_combine(begin_p, end_p, count, n);
+
+                               /* re-initialize */
+                               count = 0;
+                               begin_p = (struct MAINLL *) 0;
+                               all_rests = YES;
+                               begin_valid = NO;
+                       }
+
+                       /* keep track of visibility */
+                       asgnssv(mll_p->u.ssv_p);
+               }
+               else if (mll_p->str == S_FEED) {
+                       do_combine(begin_p, end_p, count, n);
+                       count = 0;
+                       begin_p = (struct MAINLL *) 0;
+                       all_rests = YES;
+                       begin_valid = NO;
+               }
+       }
+
+       /* do final combination if any */
+       do_combine(begin_p, end_p, count, n);
+
+       /* If there were case of TS_ALWAYS with alternating time
+        * signatures, we had to save the entire time signature list for
+        * every measure in case it turned out to be a multirest.
+        * Now we can shorten down to one for those that aren't,
+        * and need to do this so later code works.
+        */
+       initstructs();
+       timerep = 0;
+       for (mll_p = Mainllhc_p; mll_p != 0; mll_p = mll_p->next) {
+               struct MAINLL * nmll_p;
+
+               if (mll_p->str != S_SSV) {
+                       continue;
+               }
+               asgnssv(mll_p->u.ssv_p);
+               if (Score.timevis != PTS_ALWAYS) {
+                       continue;
+               }
+
+               /* If we need to change the current timerep,
+                * need to do the permanent copy in the main list,
+                * not the one current in Score, so save pointer to current
+                * one in main list. */
+               if (mll_p->u.ssv_p->used[TIME]) {
+                       timerep = mll_p->u.ssv_p->timerep;
+               }
+
+               for (nmll_p = mll_p->next; nmll_p != 0;
+                                               nmll_p = nmll_p->next) {
+                       if (nmll_p->str == S_STAFF) {
+                               if (nmll_p->u.staff_p->groups_p[0]->basictime >= -1) {
+                                       /* not followed by multi-rest,
+                                        * can truncate time sig */
+                                       char * t;
+                                       for (t = timerep; t != 0 && *t != 0; t++) {
+                                               if (*t == TSR_ALTERNATING) {
+                                                       *t = TSR_END;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               break;
+                       }
+               }
+       }
+}
+\f
+
+/* given a STAFF, return NO if the staff is visible and has at least one
+ * voice which contains notes, or has lyrics or STUFF (except if stuff is on
+ * or before the first beat of the first measure. Otherwise return YES */
+
+static int
+check_all_rests(staff_p, count)
+
+struct STAFF *staff_p; /* which staff info to check */
+int count;             /* how many measures of all rest so far */
+
+{
+       int v;                  /* index through voices */
+       struct GRPSYL *gs_p;    /* walk through grpsyl list */
+       struct STUFF *stuff_p;  /* walk through stuff list */
+
+
+       /* if not visible, then okay to treat as all rests */
+       if ( (svpath(staff_p->staffno, VISIBLE))->visible == NO) {
+               return(YES);
+       }
+
+       /* if has lyrics, consider that not rests */
+       if (staff_p->nsyllists > 0) {
+               return(NO);
+       }
+
+       /* having STUFF is usually grounds for not being treated as all rests */
+       /***** what to do about earlier stuff that happens to spill into
+        *** this measure???????? *****/
+       if (staff_p->stuff_p != (struct STUFF *) 0) {
+               /* special case. If this is the first measure of rests, and     
+                * all STUFFs occur on or before beat 1 and have no til clause,
+                * then that's okay.
+                * This allows user to change tempo or something similar at
+                * the beginning of a combined multirest. */
+               if (count > 0) {
+                       /* Combining only applies to printing, not MIDI,
+                        * so MIDI STUFFs can be ignored */
+                       for (stuff_p = staff_p->stuff_p; stuff_p != 0;
+                                               stuff_p = stuff_p->next) {
+                               if (stuff_p->stuff_type != ST_MIDI) {
+                                       return(NO);
+                               }
+                       }
+                       /* all the STUFFs must have been MIDI */
+                       return(YES);
+               }
+               for (stuff_p = staff_p->stuff_p; stuff_p != (struct STUFF *) 0;
+                                       stuff_p = stuff_p->next) {
+                       if (stuff_p->stuff_type == ST_MIDI) {
+                               continue;
+                       }
+                       if (stuff_p->start.count > 1.0 || stuff_p->end.bars > 0
+                                       || stuff_p->end.count > 0.0) {
+                               return(NO);
+                       }
+               }
+       }
+
+       for (v = 0; v < MAXVOICES; v++) {
+               for (gs_p = staff_p->groups_p[v]; gs_p != (struct GRPSYL *) 0;
+                                                       gs_p = gs_p->next) {
+                       /* if voice is invisible, treat like all rests */
+                       if (vvpath(staff_p->staffno, v + 1, VISIBLE)->visible == NO) {
+                               continue;
+                       }
+
+                       if (gs_p->grpcont == GC_NOTES) {
+                               return(NO);
+                       }
+
+                       else if (gs_p->is_meas == NO) {
+                               /* We only combine mr and ms. If user entered
+                                * one or more rests/spaces that fill the
+                                * entire measure, we don't combine,
+                                * because the user may have had some reason
+                                * for explicitly specifying time values rather
+                                * than using a measure duration. */
+                               return(NO);
+                       }
+                       else if (gs_p->basictime < -1) {
+                               /* already multirest! */
+                               return(NO);
+                       }
+               }
+       }
+       return(YES);
+}
+\f
+
+/* effect the combination of several measures of rests into a multirest. */
+
+static void
+do_combine(begin_p, end_p, nummeas, min_combine)
+
+struct MAINLL *begin_p;        /* start combining from here */
+struct MAINLL *end_p;  /* stop here */
+int nummeas;           /* hom many measures are being combined */
+int min_combine;       /* minimum number to combine, or NORESTCOMBINE */
+
+{
+       struct MAINLL *new_p;
+       struct MAINLL *old_p;           /* first of items to discard */
+       struct GRPSYL *gs_p;            /* for multirest */
+       struct MAINLL *mll_p;           /* to find staff for transferring stuffs */
+       short s;                        /* index through staffs */
+       short numvoices;
+
+
+       if (min_combine == NORESTCOMBINE || nummeas < min_combine) {
+               /* don't bother to combine */
+               return;
+       }
+
+       /* discard everything in main list between the given points.
+        * It will be either STAFFs with all rests to be replaced or
+        * BARs to be discarded, or things associated with invisible staffs.
+        * I guess maybe we should free up the space rather than merely
+        * unhitching it from the list, but it hardly seems worth the bother,
+        * especially since we'd have to be careful not to delete the STUFFs
+        * on the first one in case they were needed at the end of this
+        * function.
+        */
+       if (begin_p == (struct MAINLL *) 0) {
+               old_p = Mainllhc_p;
+               Mainllhc_p = end_p;
+       }
+       else {
+               old_p = begin_p->next;
+               begin_p->next = end_p;
+       }
+       if (end_p != (struct MAINLL *) 0) {
+               end_p->prev = begin_p;
+       }
+
+       /* add multirest to list */
+       for (s = Score.staffs; s > 0; s--) {
+               new_p = newMAINLLstruct(S_STAFF, -1);
+               gs_p = newGRPSYL(GS_GROUP);
+               gs_p->grpcont = GC_REST;
+               gs_p->basictime = -nummeas;
+               gs_p->fulltime = Score.time;
+               gs_p->staffno = s;
+               gs_p->vno = 1;
+
+               new_p->u.staff_p->groups_p[0] = gs_p;
+               numvoices = vscheme_voices(svpath(s, VSCHEME)->vscheme);
+               if (numvoices > 1) {
+                       add_meas_space( &(new_p->u.staff_p->groups_p[1]), s, 2);
+                       new_p->u.staff_p->groups_p[1]->basictime = -nummeas;
+                       /* if the first voice was invisible,
+                        * but the second voice is visible, need to convert
+                        * the space just created into a rest. */
+                       if (vvpath(s, 1, VISIBLE)->visible == NO &&
+                                       vvpath(s, 2, VISIBLE)->visible == YES) {
+                               new_p->u.staff_p->groups_p[1]->grpcont = GC_REST;
+                       }
+               }
+               if (numvoices > 2) {
+                       add_meas_space( &(new_p->u.staff_p->groups_p[2]), s, 3);
+                       new_p->u.staff_p->groups_p[2]->basictime = -nummeas;
+                       /* if only the third voice is visible, need to convert
+                        * the space just created into a rest. */
+                       if (vvpath(s, 1, VISIBLE)->visible == NO &&
+                                       vvpath(s, 2, VISIBLE)->visible == NO &&
+                                       vvpath(s, 3, VISIBLE)->visible == YES) {
+                               new_p->u.staff_p->groups_p[2]->grpcont = GC_REST;
+                       }
+               }
+               new_p->u.staff_p->staffno = s;
+               new_p->u.staff_p->visible = svpath(s, VISIBLE)->visible;
+               insertMAINLL(new_p, begin_p);
+
+               /* if there were any STUFFs on or before the first beat of the
+                * first measure, we have to transfer them to the stufflist of
+                * the multirest. We can transfer the entire list, because if
+                * there were any items that shouldn't be transferred, we
+                * wouldn't have allowed the multirest combination in the
+                * first place. */
+               for (mll_p = old_p; mll_p != (struct MAINLL *) 0
+                               && mll_p != end_p; mll_p = mll_p->next) {
+                       if (mll_p->str == S_STAFF
+                                       && mll_p->u.staff_p->staffno == s) {
+                               new_p->u.staff_p->stuff_p =
+                                               mll_p->u.staff_p->stuff_p;
+                               break;
+                       }
+               }
+       }
+}
+\f
+
+/* translate MK_* to printable name */
+
+char *
+markname(mark)
+
+int mark;      /* MK_* value */
+
+{
+       switch(mark) {
+       case MK_MUSSYM:
+               return("mussym");
+       case MK_OCTAVE:
+               return("octave");
+       case MK_DYN:
+               return("dyn");
+       case MK_OTHERTEXT:
+               return("othertext");
+       case MK_CHORD:
+               return("chord");
+       case MK_LYRICS:
+               return("lyrics");
+       case MK_ENDING:
+               return("ending");
+       case MK_REHEARSAL:
+               return("rehearsal");
+       case MK_PEDAL:
+               return("pedal");
+       default:
+               pfatal("markname(): missing case");
+               /*NOTREACHED*/
+               return("");
+       }
+}
+\f
+
+/* verify that a mark order list is valid */
+
+void
+chk_order(ssv_p, place)
+
+struct SSV *ssv_p;     /* check the markorder list in here */
+int place;             /* PL_*, which list to check */
+
+{
+       int m, n;       /* index through MK_* */
+       int level;      /* value in markorder table */
+
+       for (m = 0; m < NUM_MARK; m++) {
+               if (ssv_p->markorder[place][m] == 0) {
+                       /* no level set for this mark, so skip it */
+                       continue;
+               }
+
+               /* some mark types cannot be equal with any other types */
+               switch (m) {
+
+               case MK_LYRICS:
+               case MK_ENDING:
+               case MK_REHEARSAL:
+               case MK_PEDAL:
+                       level = ssv_p->markorder[place][m];
+                       for (n = 0; n < NUM_MARK; n++) {
+                               if (n == m) {
+                                       continue;
+                               }
+                               if (ssv_p->markorder[place][n] == level) {
+                                       l_yyerror(Curr_filename, yylineno,
+                                               "%s cannot be at same level as %s",
+                                               markname(m), markname(n));
+                               }
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+
+               if (valid_mark_item(m, place) == NO) {
+                       char *placename;
+                       switch (place) {
+                       case PL_ABOVE:
+                               placename = "above";
+                               break;
+                       case PL_BELOW:
+                               placename = "below";
+                               break;
+                       case PL_BETWEEN:
+                               placename = "between";
+                               break;
+                       default:
+                               pfatal("chk_order: invalid place %d", place);
+                               /* not reached; it just avoids bogus
+                                * "used before set" warning */
+                               placename = "";
+                       }
+                       l_warning(Curr_filename, yylineno,
+                                       "%s not valid in %sorder list",
+                                       markname(m), placename);
+               }
+       }
+}
+\f
+
+/* return YES if MK_* item is valid at given place, NO if not */
+
+static int
+valid_mark_item(mark, place)
+
+int mark;      /* MK_* */
+int place;     /* PL_* */
+
+{
+       if (mark == MK_OCTAVE && place == PL_BETWEEN) {
+               return(NO);
+       }
+       if ((mark == MK_ENDING || mark == MK_REHEARSAL)
+                                               && place != PL_ABOVE) {
+               return(NO);
+       }
+       if (mark == MK_PEDAL && place != PL_BELOW) {
+               return(NO);
+       }
+
+       /* everything else is okay */
+       return(YES);
+}
+\f
+
+/*
+ * User can specify that only a portion of the song is to be processed.
+ * This is done via one or two numbers, the first measure to include and
+ * the last.
+ * Positive numbers are relative to the beginning of the song, negative
+ * are relative to the end. So, as examples:
+ *     1       // the whole song (default)
+ *     1,-1    // another way to say the whole song
+ *     5       // start at measure 5, through the end
+ *     6,7     // only measures 6 and 7
+ *     1,10    // measures 1 through 10
+ *     1,-8    // skip the last 7 measures
+ *     -12,-3  // only process from 12 measures from the end through
+ *             // the third from the end
+ *
+ * When counting measures for this, invisbar bars do not count.
+ * It is measured by the number of bars encountered in input, not in
+ * performance: the bars are not double counted in sections
+ * between repeat signs. 
+ *
+ * A value of zero is not allowed.
+ * A positive start larger than the number of measures in the song
+ *     is a user error.
+ * A negative start that would result in starting before the beginning
+ *     starts at the beginning (with a warning)
+ * A positive end larger than the number of measures in the song goes to
+ *     end of song (with a warning)
+ * An end value that would result in starting before the beginning of the
+ *     song or before the start value is a user error.
+ *
+ * Only one slice is supported. I.e., you can't ask for something
+ * like measures 4-10, 17-24, and 46-80.
+ * You can only ask for one of those ranges.
+ * (You could get that effect by making 3 files and playing them one after
+ * another, although there might be slight pauses in between.)
+ *
+ * A possible future enhancement might be
+ * to also be able to specify by rehearsal mark.
+ * If a rehearsal mark string is specified rather than a number,
+ * the rehearsal mark  having that string (ASCII-ized by removing font, size,
+ * and other special things) would be used as the marked place. In this case,
+ * the end place would be only up to the rehearsal mark, not through the
+ * measure that starts there.
+ */
+
+void
+chk_x_arg(x_arg, start_p, end_p)
+
+char *x_arg;   /* arg to -x option specified by user */
+int *start_p;  /* start gets returned here */
+int *end_p;    /* end gets returned here */
+
+{
+       char *arg_p;    /* pointer to where end starts in x_arg */
+
+       /* set to defaults */
+       *start_p = 1;
+       *end_p = -1;
+
+       if (x_arg == 0 || *x_arg == '\0') {
+               /* No -x option, use whole song as normal */
+               return;
+       }
+
+       *start_p = (int) strtol(x_arg, &arg_p, 0);
+       if (arg_p == x_arg) {
+               if (Mupmate == YES) {
+                       l_yyerror(0, -1, "Run > Set Options > Extract Measures: value must be one or two numbers.");
+               }
+               else {
+                       l_yyerror(0, -1, "argument for %cx option must be one or two numbers", Optch);
+               }
+       }
+
+       /* If there is a comma, get the "end" argument as well */
+       if (*arg_p == ',') {
+               *end_p = (int) strtol(arg_p + 1, &arg_p, 0);
+       }
+
+       /* We should be at end of string, either after first arg if there
+        * was only one arg, or after second if there were two. */
+       if (*arg_p != '\0') {
+               if (Mupmate == YES) {
+                       l_yyerror(0, -1, "Run > Set Options > Extract Measures: value must be one or two numbers.");
+               }
+               else {
+                       l_yyerror(0, -1, "argument for %cx option must be one or two numbers", Optch);
+               }
+       }
+}
+\f
+
+/* This function does the slicing to extract selected measures from the input */
+
+void
+extract(start, end)
+
+int start;     /* Start at this measure number.  A negative
+                * number means count from the end of the piece,
+                * so -3 would mean the last 3 bars. */
+int end;       /* Play only through this measure number.
+                * Negative is relative to the end of the piece. */
+
+{
+       int pickup;                             /* YES if song begins
+                                                * with pickup measure */
+       int numbars;                            /* total number of bars */
+       int bars;                               /* how many processed so far */
+       int mrbars;                             /* how many bars of multirest */
+       struct MAINLL *topstaff_mll_p = 0;      /* "all" MIDI STUFFS will
+                                                * be attached here */
+       struct MAINLL *mll_p;                   /* loop through list */
+       struct MAINLL *m_p;                     /* to look ahead in list */
+       struct MAINLL *next_p;                  /* saved next */
+       struct STUFF *nextstuff_p;              /* saved next of a STUFF */
+       struct MAINLL *first_p;                 /* first STAFF at start */
+       struct STUFF *stuff_p;                  /* loop through STUFF list */
+       struct STUFF *pedal[MAXSTAFFS+1];       /* YES if pedal is down */
+       struct STUFF *saveped[MAXSTAFFS+1];     /* YES if pedal was down                                                         * at entry to set of endings */
+       int in_endings;                         /* YES if inside endings */
+       int i;                                  /* index */
+
+
+       pickup = has_pickup();
+       if ( ( (pickup == YES && start == 0) || (pickup == NO && start == 1) )
+                       && end == -1) {
+               /* Use whole song as normal; nothing to do here */
+               return;
+       }
+
+       /* If song has a pickup measure, compensate for that.
+        * This function treats the partial measure as a measure.
+        * So if user specified 0 for start, they want to start at the pickup,
+        * which will be effectively measure 1 here. If they specified 1,
+        * they want to skip the pickup, which means they want to start at
+        * what will be considered measure 2. And so forth.
+        */
+       if (pickup == YES) {
+               if (start >= 0) {
+                       start++;
+               }
+               if (end >= 0) {
+                       end++;
+               }
+       }
+       else {
+               /* It's not clear if these should be warnings or errors,
+                * but it seems friendlier to be just warnings.
+                * That way, if someone wants the beginning,
+                * but can't remember if the piece has a pickup or not,
+                * they can use 0, and it will always work,
+                * albeit possibly with a warning.
+                */
+               if (start == 0) {
+                       warning("x option start of 0 is only valid if there is a pickup measure; using 1");
+                       start = 1;
+               }
+               if (end == 0) {
+                       warning("x option end of 0 is only valid if there is a pickup measure; using 1");
+                       end = 1;
+               }
+       }
+
+       /* Count total number of bars in song */
+       for (numbars = 0, mll_p= Mainllhc_p; mll_p != 0; mll_p = mll_p->next) {
+               if (mll_p->str == S_BAR && mll_p->u.bar_p->bartype != INVISBAR) {
+                       numbars++;
+               }
+               /* Multirests count as multiple bars */
+               else if (mll_p->str == S_STAFF
+                               && mll_p->u.staff_p->groups_p[0] != 0) {
+                       if (mll_p->u.staff_p->groups_p[0]->basictime < -1) {
+                               numbars += -(mll_p->u.staff_p->groups_p[0]->basictime) - 1 ;
+                       }
+                       /* skip the rest of the STAFFs till BAR */
+                       while (mll_p->next != 0 && mll_p->next->str == S_STAFF) {
+                               mll_p = mll_p->next;
+                       }
+               }
+       }
+       if (numbars == 0) {
+               /* Only non-invisible bars count. If there aren't any
+                * identifiable measures, -x is pointless. */
+               ufatal("can't use -x on song with no visible bar lines");
+       }
+
+       /* If user specified things relative to the end, convert
+        * the relative-to-end negative values to relative-to-beginning
+        * positive values.
+        */
+       if (start < 0) {
+               start = numbars + start + 1;
+       }
+       if (end < 0) {
+               end = numbars + end + 1;
+       }
+
+       if (start > numbars) {
+               ufatal("Attempt to start beyond end of song");
+       }
+       if (end < start) {
+               ufatal("Attempt to end before start");
+       }
+       if (end <= 0) {
+               ufatal("Attempt to end before beginning of song");
+       }
+       if (start < 1) {
+               warning("attempt to start before beginning; ignoring");
+               start = 1;
+       }
+       if (end > numbars) {
+               warning("attempt to go past end; ignoring");
+               end = numbars;
+       }
+
+       if (start == 1 && end == numbars) {
+               /* After all the conversions, we ended up with
+                * the entire song. Nothing more to do here. */
+               return;
+       }
+       /* compensate for bar being at end of measure */
+       start--;
+
+
+       /* First find the bar where we're going to start.
+        * Find out if there are any notes tied into that measure
+        * that have an accidental. If so, move the accidental
+        * into the new starting measure.
+        * Note: the 'mll_p != 0' checks are defensive; shouldn't happen.
+        */
+       initstructs();
+       for (bars = 0, mll_p = Mainllhc_p; mll_p != 0 && bars < start;
+                                                       mll_p = mll_p->next){
+               if (mll_p->str == S_SSV) {
+                       /* need to keep things like keysig up to date */
+                       asgnssv(mll_p->u.ssv_p);
+               }
+               else if (mll_p->str == S_BAR && mll_p->u.bar_p->bartype != INVISBAR) {
+                       bars++;
+               }
+               else if (mll_p->str == S_STAFF
+                               && mll_p->u.staff_p->groups_p[0] != 0) {
+                       if (mll_p->u.staff_p->groups_p[0]->basictime < -1) {
+                               bars += -(mll_p->u.staff_p->groups_p[0]->basictime) - 1 ;
+                       }
+                       /* skip the rest of the STAFFs till BAR */
+                       while (mll_p->next->str == S_STAFF) {
+                               mll_p = mll_p->next;
+                       }
+               }
+       }
+       first_p = 0;
+       for (  ; mll_p != 0 && mll_p->str != S_BAR; mll_p = mll_p->next) {
+               if (mll_p->str == S_STAFF) {
+                       mv_accs(mll_p);
+                       if (first_p == 0) {
+                               first_p = mll_p;
+                       }
+               }
+       }
+       /* Fix up the measure number to account for what was chopped off.
+        * The pickup part may be a bit counter-intuitive...
+        * It's because when there was a pickup, we've already added 1 to
+        * "start" for that partial measure; with no pickup, we didn't.
+        * As an example, if user specified -x2, then the measure number
+        * at the barline at the end of the first printed measure should be 3.
+        * "start" will have value 1 if there was no pickup,
+        * but 2 if there was a pickup. So....
+        *
+        *                      start + 1 + (pickup ? 0 : 1);
+        *                      -----------------------------
+        *    no pickup:          1   + 1 +               1     = 3
+        *    pickup:             2   + 1 +           0         = 3
+        */
+       Meas_num = mll_p->u.bar_p->mnum = start + 1 + (pickup ? 0 : 1);
+
+       /* Find the top visible staff on the new effective "first" measure,
+        * We will be moving MIDI STUFFs into the special "extra"
+        * space measure that exists for MIDI right before the first real
+        * measure entered by the user.
+        * The current top visible tells us which staff to use for "all" items.
+        * We leave everything on the list up through the "extra" measure */
+       if (Doing_MIDI) {
+               int staffs_needed;      /* number of staffs at new first meas */
+               struct MAINLL *laststaffmll_p = 0;      /* last staff of the extra meas
+                        * added at the beginning for MIDI.
+                        * Initialization just to avoid "used before set." */
+
+               for (mll_p = Mainllhc_p; mll_p->str != S_BAR; mll_p = mll_p->next) {
+                       if (mll_p->str == S_STAFF && svpath(
+                                       mll_p->u.staff_p->staffno, VISIBLE)
+                                       ->visible == YES) {
+                               topstaff_mll_p = mll_p;
+                               break;
+                       }
+               }
+
+               /* The number of staffs in the "extra" added measure might be
+                * smaller than the number of staffs on the new
+                * effective first measure.
+                */
+               staffs_needed = Score.staffs;
+               for (mll_p = Mainllhc_p; mll_p->str != S_BAR; mll_p = mll_p->next){
+                       if (mll_p->str == S_STAFF) {
+                               laststaffmll_p = mll_p;
+                       }
+               }
+               if (laststaffmll_p == 0){
+                       pfatal("extract failed to find last staff in extra measure");
+               }
+               if (laststaffmll_p->u.staff_p->staffno < staffs_needed) {
+                       (void) add_pre_meas(laststaffmll_p,
+                                       laststaffmll_p->u.staff_p->staffno,
+                                       staffs_needed, NO);
+               }
+
+               /* We want to start discarding things after the extra measure,
+                * so skip past that. */
+               for (mll_p = Mainllhc_p; mll_p->str != S_BAR; mll_p = mll_p->next) {
+                       ;
+               }
+               mll_p = mll_p->next;
+       }
+       else {
+               mll_p = Mainllhc_p;
+       }
+
+       /* Pedal is off at the start */
+       for (i = 1; i <= MAXSTAFFS; i++) {
+               pedal[i] = 0;
+               saveped[i] = 0;
+       }
+
+       /* Now go through and discard anything irrelevant before the
+        * start measure. We save all SSVs. If doing MIDI, we save any
+        * MIDI directives that matter.
+        * Everything else gets discarded.
+        */
+       mrbars = 0;
+       next_p = 0;
+       in_endings = NO;
+       for (bars = 0; bars < start; mll_p = next_p) {
+               if (mll_p == 0) {
+                       pfatal("got null mll_p when finding starting measure");
+               }
+               next_p = mll_p->next;
+
+               switch (mll_p->str) {
+
+               case S_BAR:
+                       if (mll_p->u.bar_p->bartype != INVISBAR) {
+                               bars++;
+                       }
+                       if (mrbars > 0) {
+                               bars += mrbars - 1;
+                               if (bars > start || (mll_p->u.bar_p->bartype
+                                               == INVISBAR && bars == start)) {
+                                       /* New first bar is or was a multirest,
+                                        * so we need to retain this bar line.
+                                        */
+                                       continue;
+                               }
+                       }
+                       mrbars = 0;
+
+                       /* Keep track of if we're in a first ending. */
+                       if (mll_p->u.bar_p->endingloc == STARTITEM) {
+                               in_endings = YES;
+                       }
+                       else if (mll_p->u.bar_p->endingloc == ENDITEM) {
+                               in_endings = NO;
+                       }
+                       break;
+
+               case S_STAFF:
+                       /* Keep track of current pedal state for this staff.
+                        * If we find a C_ENDPED the pedal is up, otherwise
+                        * it's down (because even with a bounce, at the end
+                        * of the bounce, the pedal is down).
+                        * Also deal with an octave marks that might spill
+                        * over into the new first measure.
+                        */
+                       for (stuff_p = mll_p->u.staff_p->stuff_p; stuff_p != 0;
+                                               stuff_p = nextstuff_p) {
+                               /* In a previous implementation,
+                                * stuff_p->next could be invalid after call
+                                * to move_xoct, so we had to save it here.
+                                * With the current implementation, this
+                                * shouldn't be strictly necessary, but
+                                * it doesn't hurt. */
+                               nextstuff_p = stuff_p->next;
+
+                               /* Note that the only time string should be
+                                * null is on pedal carried over from a
+                                * previous score, so that isn't really a
+                                * change in pedal state, so we can ignore it.
+                                */
+                               if (stuff_p->stuff_type == ST_PEDAL &&
+                                                       stuff_p->string != 0) {
+                                       pedal[mll_p->u.staff_p->staffno] =
+                                                               stuff_p;
+                               }
+                               if (stuff_p->stuff_type == ST_OCTAVE) {
+                                       move_xoct(stuff_p, first_p,
+                                               mll_p->u.staff_p->staffno,
+                                               bars, start);
+                               }
+                       }
+
+                       if (Doing_MIDI) {
+                               mv_midi_items(mll_p, topstaff_mll_p);
+                       }
+
+                       /* Deal with multirest */
+                       if (mll_p->u.staff_p->groups_p[0]->basictime < -1) {
+                               mrbars = -(mll_p->u.staff_p->groups_p[0]->basictime);
+                               if (bars + mrbars > start) {
+                                       /* Slice starts in middle of multirest.
+                                        * This multirest will be the new
+                                        * first measure, but we need
+                                        * to adjust the number of
+                                        * measures worth of multirest to
+                                        * account for starting in the middle
+                                        * of it.
+                                        */
+                                   mll_p->u.staff_p->groups_p[0]->basictime =
+                                               -((bars + mrbars) - start);
+
+                                   /* If the end of the slice is also inside
+                                    * this same multirest, shorten it down
+                                    * to end there. It's slightly silly to
+                                    * be saving only a part of a multirest,
+                                    * but it's better to handle it than
+                                    * to core dump...
+                                    */
+                                  if (bars + mrbars > end) {
+                                       mll_p->u.staff_p->groups_p[0]->basictime
+                                               += (end - bars - mrbars + 2);
+                                  }
+
+                                   /* If down to single measure, have to
+                                    * convert from multirest to meas rest */
+                                   if (mll_p->u.staff_p->groups_p[0]->basictime == -1) {
+                                       mll_p->u.staff_p->groups_p[0]->is_meas = YES;
+                                       mll_p->u.staff_p->groups_p[0]->basictime = 1;
+                                       mll_p->u.staff_p->groups_p[0]->fulltime = Score.time;
+                                   }
+                                   continue;
+                               }
+                       }
+                       break;
+
+               case S_SSV:
+                       /* Need to keep all the SSVs. Not sure they
+                        * really need to be assigned, but shouldn't hurt. */
+                       asgnssv(mll_p->u.ssv_p);
+                       continue;
+
+               default:
+                       break;
+
+               }
+
+               /* Get rid of this MAINLL. User wants it skipped. */
+               unlinkMAINLL(mll_p);
+       }
+
+       /* Make sure there is a bar after where mll_p currently is.
+        * If song consists of just a multirest, followed by
+        * blocks, prints, lines, or curves, but no more music,
+        * we need to force mll_p to get set to the bar at the end of
+        * the multirest.
+        */
+       for (m_p = mll_p; m_p != 0 && m_p->str != S_BAR; m_p = m_p->next) {
+               ;
+       }
+       if (m_p == 0) {
+               /* No bar.  Force into hitting the next 'if' */
+               mll_p = 0;
+       }
+
+       /* If start was in a multirest, mll_p could be zero,
+        * so we have to use the beginning bar. */
+       if (mll_p == 0) {
+               for (mll_p = Mainllhc_p; mll_p != 0 && mll_p->str != S_BAR;
+                                                       mll_p = mll_p->next) {
+                       ;
+               }
+               if (mll_p == 0) {
+                       pfatal("-x option failed to find beginning bar correctly");
+               }
+       }
+
+       /* Add pedal starts if necessary. Go through the new effective
+        * first measure. For any staff that had the pedal down coming
+        * into that measure, make sure the measure starts with a BEGPED.
+        * Also, if there are any measure repeats, ufatal.
+        * Trying to start at a measure repeat doesn't really make a lot of
+        * sense, and it would be work to allow it, so don't bother.
+        * Using mrpt is discouraged anyway.
+        */
+       for ( ; mll_p->str != S_BAR; mll_p = mll_p->next) {
+               if (mll_p->str == S_STAFF) {
+                       int v;          /* voice index */
+                       /* check for mrpt */
+                       for (v = 0; v < MAXVOICES; v++) {
+                               if (is_mrpt(mll_p->u.staff_p->groups_p[v]) == YES) {
+                                       l_ufatal(mll_p->inputfile, mll_p->inputlineno,
+                                       "-x option not allowed to start at a mrpt");
+                               }
+                       }
+
+                       addped(pedal[mll_p->u.staff_p->staffno], mll_p);
+               }       
+       }
+
+       /* If slice starts inside an ending, we disallow that.
+        * It turns out there a number of pathological cases,
+        * particularly regarding pedal. If the pedal was down going into
+        * the first ending, but up at the beginning of the slice, then
+        * what should the pedal state be at the start of subsequent endings?
+        * It should normally be based on the state coming into the ending,
+        * but that no longer exists and conflicts with the new "beginning
+        * of the ending" state. And more fundamentally, where do you go back
+        * to when you reach the end of a non-final ending?
+        * There's nothing there to go back to!
+        * I suppose if someone has a really long ending and wants
+        * just the middle of it, this restriction will be annoying,
+        * but that shouldn't happen too often, and trying to handle this
+        * was just getting too complicated!
+        */
+       if (in_endings == YES) {
+               ufatal("-x section not allowed to begin inside an ending");
+       }
+
+       /* If the new first measure is in the middle of an ending,
+        * patch up the endingloc. */
+       if (mll_p->u.bar_p->endingloc == ENDITEM ||
+                                       mll_p->u.bar_p->endingloc == INITEM) {
+               struct MAINLL *prevmll_p;
+               struct MAINLL *topstaffmll_p = 0;
+
+               for (prevmll_p = mll_p->prev; prevmll_p != 0;
+                                               prevmll_p = prevmll_p->prev) {
+                       if (prevmll_p->str == S_STAFF) {
+                               topstaffmll_p = prevmll_p;
+                       }
+                       else if (prevmll_p->str == S_BAR) {
+                               prevmll_p->u.bar_p->endingloc = STARTITEM;
+                               break;
+                       }
+               }
+               if (prevmll_p == 0) {
+                       if (topstaffmll_p == 0) {
+                               pfatal("unexpected null topstaffmll_p");
+                       }
+                       prevmll_p = add_pre_meas(
+                               topstaffmll_p->prev, 1, Score.staffs, YES);
+                       prevmll_p->u.bar_p->endingloc = STARTITEM;
+               }
+       }
+
+       /* Now chop off end if needed */
+       if (end < numbars) {
+               for (  ; mll_p != 0 && (bars < end || mrbars > 0);
+                                                       mll_p = mll_p->next) {
+                       if (mll_p->str == S_BAR && mll_p->u.bar_p->bartype != INVISBAR) {
+                               bars++;
+                               mrbars = 0;
+                       }
+                       if (mll_p->str == S_STAFF &&
+                                       mll_p->u.staff_p->groups_p[0] != 0 &&
+                                       mll_p->u.staff_p->groups_p[0]->basictime < -1) {
+                               /* It's a multirest */
+                               mrbars = -(mll_p->u.staff_p->groups_p[0]->basictime);
+                               bars += mrbars - 1;
+                               if (bars >= end) {
+                                       /* Slice ends inside the multirest.
+                                        * Adjust its length. If down to a
+                                        * single measure, convert */
+                                       for (  ; mll_p->str == S_STAFF;
+                                                       mll_p = mll_p->next) {
+                                           mll_p->u.staff_p->groups_p[0]->basictime
+                                                       += bars - end + 1;
+                                           if (mll_p->u.staff_p->groups_p[0]->basictime == -1) {
+                                               mll_p->u.staff_p->groups_p[0]->is_meas = YES;
+                                               mll_p->u.staff_p->groups_p[0]->basictime = 1;
+                                               mll_p->u.staff_p->groups_p[0]->fulltime = Score.time;
+                                           }
+                                       }
+                                       bars -= bars - end;
+                               }
+                               /* multi-rest has been handled; skip over
+                                * the rest of the staffs in this measure */
+                               while (mll_p->next != 0 &&
+                                               mll_p->next->str == S_STAFF) {
+                                       mll_p = mll_p->next;
+                               }
+                       }
+               }
+               if (mll_p != 0) {
+                       /* If didn't get all the way to end of main list,
+                        * chop off the rest.
+                        * We don't bother to free the space.
+                        */
+                       mll_p->prev->next = 0;
+                       Mainlltc_p = mll_p->prev;
+               }
+
+               /* Remove ties/slurs going into the chopped-off part. */
+               for (mll_p = Mainlltc_p->prev; mll_p != 0; mll_p = mll_p->prev) {
+                       if (mll_p->str == S_STAFF) {
+                               int v;          /* voice index */
+                               for (v = 0; v < MAXVOICES; v++) {
+                                       struct GRPSYL *g_p;
+                                       int n;          /* note index */
+                                       if (mll_p->u.staff_p->groups_p[v] == 0) {
+                                               /* this voice doesn't exist */
+                                               continue;
+                                       }
+                                       /* find last group in this voice */
+                                       for (g_p = mll_p->u.staff_p->groups_p[v];
+                                                       g_p->next != 0;
+                                                       g_p = g_p->next) {
+                                               ;
+                                       } 
+                                       /* only notes can have tie/slur */
+                                       if (g_p->grpcont != GC_NOTES) {
+                                               continue;
+                                       }
+                                       g_p->tie = NO;
+                                       for (n = 0; n < g_p->nnotes; n++) {
+                                               g_p->notelist[n].tie = NO;
+                                               if (g_p->notelist[n].nslurto > 0) {
+                                                       g_p->notelist[n].nslurto = 0;
+                                                       FREE(g_p->notelist[n].slurtolist);
+                                               }
+                                       }
+                               }
+
+                               if (mll_p->u.staff_p->staffno == 1) {
+                                       /* No more staffs in the final bar */
+                                       break;
+                               }
+                       }
+               }
+
+               /* If end is in the middle of an ending, or with a restart,
+                * fix that */
+               for (mll_p = Mainlltc_p; mll_p != 0; mll_p = mll_p->prev) {
+                       if (mll_p->str == S_BAR) {
+                               if (mll_p->u.bar_p->endingloc == INITEM) {
+                                       mll_p->u.bar_p->endingloc = ENDITEM;
+                               }
+                               else if (mll_p->u.bar_p->endingloc == STARTITEM) {
+                                       struct MAINLL *pmll_p;
+
+                                       /* If there is a previous bar and it's
+                                        * in an ending, we need to change this
+                                        * one to an ENDITEM, else to NOITEM.
+                                        */
+                                       mll_p->u.bar_p->endingloc = NOITEM;
+                                       for (pmll_p = mll_p->prev; pmll_p != 0;
+                                                       pmll_p = pmll_p->prev) {
+                                               if (pmll_p->str == S_BAR) {
+                                                       if (pmll_p->u.bar_p->endingloc == INITEM ||
+                                                       pmll_p->u.bar_p->endingloc == STARTITEM) {
+                                                               mll_p->u.bar_p->endingloc = ENDITEM;
+                                                       }
+                                                       break;
+                                               }
+                                       }
+                               }
+                               if (mll_p->u.bar_p->bartype == RESTART) {
+                                       /* Not exactly clear what to do here.
+                                        * Could ufatal. We'll convert to
+                                        * an invisible bar. */
+                                       mll_p->u.bar_p->bartype = INVISBAR;
+                               }
+                               break;
+                       }
+               }
+               
+               /* Note: it shouldn't be necessary to do anything
+                * about location tags in chopped-off areas.
+                * Locvar code runs much later, so doesn't know
+                * about what was deleted, and that code has to be able
+                * to handle tags pointing to invisible things anyway
+                * for other reasons. Similarly, it is not necessary to
+                * shorten til clauses, since any that spill into the
+                * chopped-off part will still be handled okay, since a
+                * staff could be made invisible in the middle of a til
+                * clause, and this is a similar case.
+                */
+       }
+}
+\f
+
+/* When using -x option, if there is a tie across the beginning split point,
+ * we need to check if there was an accidental on the note being tied from,
+ * and if so, move the accidental to the new effective first measure.
+ */
+
+static void
+mv_accs(mll_p)
+
+struct MAINLL *mll_p;
+
+{
+       int v;                  /* voice index */
+       int n;                  /* note index */
+       int staffno;
+       int ea;                 /* effective accidental */
+       struct GRPSYL *gs_p;
+       struct NOTE *note_p;
+
+       staffno = mll_p->u.staff_p->staffno;
+       for (v = 0; v < MAXVOICES; v++) {
+               if ((gs_p = mll_p->u.staff_p->groups_p[v]) == 0) {
+                       /* voice doesn't exist on this staff */
+                       continue;
+               }
+               /* Only non-grace note groups can be tied to */
+               if (gs_p->grpcont == GC_NOTES && gs_p->grpvalue != GV_ZERO) {
+                       /* check all notes for being tied to */
+                       for (n = 0; n < gs_p->nnotes; n++) {
+                               note_p = &(gs_p->notelist[n]);
+                               /* Only need to check if doesn't already
+                                * have an accidental. If effective accidental
+                                * differs from what note would get from        
+                                * key sig, need to add explicit accidental. */
+                               if (note_p->accidental == '\0') {
+                                       ea = eff_acc(gs_p, note_p, mll_p);
+                                       if (ea != acc_from_keysig(
+                                         note_p->letter, staffno, mll_p)) {
+                                               note_p->accidental
+                                                       = Acclets[ea+2];
+                                       }
+                               }
+                       }
+               }
+       }
+}
+\f
+
+/* If there is an octave mark whose til clause goes into the new
+ * effective first measure due to -x option, we need to move that octave mark
+ * to that new first measure, with its til clause appropriately shortened.
+ */
+
+static void
+move_xoct(stuff_p, newfirst_p, staffno, bars, start)
+
+struct STUFF *stuff_p;         /* the STUFF to potentially move */
+struct MAINLL *newfirst_p;     /* points to first STAFF in new first meas */
+int staffno;                   /* which STAFF this STUFF is for */
+int bars;                      /* how many bars into song the STUFF is */
+int start;                     /* start bar number from -x option */
+
+{
+       struct STAFF *staff_p;  /* where to move the STUFF */
+       struct MAINLL *mll_p;   /* to search for proper STAFF */
+       struct STUFF *newstuff_p;       /* moved STUFF */
+
+
+       /* See if this STUFF is an octave that spills into new first measure */
+       if (stuff_p->stuff_type == ST_OCTAVE &&
+                                       bars + stuff_p->end.bars >= start) {
+               /* Make a new STUFF, adjusting length of til clause
+                * to compensate for -x, and starting at count 1 */
+               newstuff_p = newSTUFF(stuff_p->string,
+                                       stuff_p->dist,
+                                       stuff_p->dist_usage,
+                                       1.0, 0.0, 0,
+                                       bars + stuff_p->end.bars - start,
+                                       stuff_p->end.count,
+                                       ST_OCTAVE,
+                                       stuff_p->modifier,
+                                       stuff_p->place,
+                                       stuff_p->inputfile,
+                                       stuff_p->inputlineno);
+
+               /* Find corresponding STAFF in new first measure */
+               staff_p = 0;
+               for (mll_p = newfirst_p; mll_p != 0 && mll_p->str == S_STAFF;
+                                                       mll_p = mll_p->next) {
+                       if (mll_p->u.staff_p->staffno == staffno) {
+                               staff_p = mll_p->u.staff_p;
+                               break;
+                       }
+               }
+               if (staff_p == 0) {
+                       /* Staff apparently doesn't exist here,
+                        * so we can ignore the octave mark. */
+                       return;
+               }
+
+               /* Make the octave stuff into a 1-element stufflist,
+                * and call the function to merge that list with the
+                * existing list. */
+               newstuff_p->next = 0;
+               connect_stuff(staff_p, newstuff_p);
+       }
+}
+\f
+
+/* If the passed-in pedal_p points to a pedal stuff that indicates the
+ * pedal state needs to be altered at the beginning of the STAFF passed in,
+ * then do that. This is for -x, for like when the slice begins where the
+ * pedal was held down from the previous measure, so we have to add a begped.
+ */
+
+static void
+addped(pedal_p, mll_p)
+
+struct STUFF *pedal_p; /* last pedal state of previous measures */
+struct MAINLL *mll_p;  /* points to a STAFF, to add pedal to */
+
+{
+       int s;          /* staff number */
+       struct STUFF *stuff_p;  /* walk through stuff list */
+       struct STUFF **prev_p_p; /* This holds the address
+                                * of the previous' next,
+                                * which is where we will need
+                                * to update if we need to delete
+                                * or insert a STUFF.
+                                */
+
+       s = mll_p->u.staff_p->staffno;
+       if (pedal_p == 0 || pedal_p->string == 0) {
+               /* There is no pedal carrying over into this measure,
+                * so no need to add anything. */
+               return;
+       }
+
+       /* If last pedal mark was an endped, we don't need to move one in,
+        * because pedal is off; otherwise we do. */
+       if (pedal_p->string[4] != C_ENDPED) {
+
+               /* Need to add a pedal STUFF at count 1 if
+                * there isn't already one at or before there.
+                * See if there's already one there.
+                */
+               for (stuff_p = mll_p->u.staff_p->stuff_p,
+                               prev_p_p = &(mll_p->u.staff_p->stuff_p);
+                               stuff_p != 0;
+                               prev_p_p = &(stuff_p->next),
+                               stuff_p = stuff_p->next) {
+                       if (stuff_p->stuff_type == ST_PEDAL &&
+                                       stuff_p->start.count
+                                       <= 1.0) {
+                               /* Already had a pedal at beginning of measure.
+                                * If it's an ENDPED,
+                                * that negates the one coming in,
+                                * and it ought to be removed.
+                                * If it's a PEDAL, need to change to a BEGPED.
+                                * In any case, we don't need
+                                * to check any more STUFFs for this STAFF.
+                                */
+                               if (stuff_p->string[4] == C_ENDPED) {
+                                       /* delete it */
+                                       *prev_p_p = stuff_p->next;
+                               }
+                               else if (stuff_p->string[4] == C_PEDAL) {
+                                       stuff_p->string[4] = C_BEGPED;
+                               }
+                               break;
+                       }
+               }
+               if (stuff_p == 0) {
+                       /* There wasn't a pedal at the
+                        * beginning of the new first measure,
+                        * so we will need to add one.
+                        */
+                       struct STUFF *newped_p;
+
+                       newped_p = newSTUFF(pedal_p->string,
+                                       pedal_p->dist,
+                                       pedal_p->dist_usage,
+                                       1.0, 0.0, 0, 0, 0.0,
+                                       ST_PEDAL,
+                                       pedal_p->modifier,
+                                       pedal_p->place,
+                                       pedal_p->inputfile,
+                                       pedal_p->inputlineno);
+                       newped_p->string[4] = C_BEGPED;
+
+                       /* figure out where to insert it */
+                       for (stuff_p = mll_p->u.staff_p->stuff_p,
+                                       prev_p_p = &(mll_p->u.staff_p->stuff_p);
+                                       stuff_p != 0;
+                                       prev_p_p = &(stuff_p->next),
+                                       stuff_p = stuff_p->next) {
+                               if (stuff_p->place == PL_ABOVE) {
+                                       /* not far enough yet */
+                                       continue;
+                               }
+                               if (pedal_p->all == YES && stuff_p->all == NO){
+                                       continue;
+                               }
+                               if (stuff_p->start.count < 1.0) {
+                                       continue;
+                               }
+                               /* found right place */
+                               break;
+                       }
+                       if (prev_p_p == 0) {
+                               pfatal("failed to find place to insert pedal for -x");
+                       }
+
+                       /* insert into STUFF list */
+                       newped_p->next = *prev_p_p;
+                       *prev_p_p = newped_p;
+               }
+       }
+}
diff --git a/mup/mup/debug.c b/mup/mup/debug.c
new file mode 100644 (file)
index 0000000..101eff0
--- /dev/null
@@ -0,0 +1,888 @@
+
+/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+
+
+
+/* routines for printing info for debugging purposes */
+/* It would be nicer to write a program to read the header files and
+ * generate most of these routines from there to keep them up to date,
+ * but this will do for now. */
+
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+/* for number-to-English name translations, if we fall off the bottom of
+ * a switch without a match, need to return something, so use "unknown" */
+static char Unknown[] = "unknown";
+
+
+/* static functions */
+static void print_ssv P((struct SSV *ssv_p));
+static void print_markorder P((struct SSV *ssv_p, int place));
+static void print_printdata P((struct PRINTDATA *printdata_p));
+static void print_bar P((struct BAR *bar_p));
+static void print_chhead P((struct CHORD *ch_p));
+static void print_staff P((struct STAFF *staff_p));
+static void print_grpsyl P((struct GRPSYL *g_p, char *gstype, int vno));
+static void print_slurtolist P((struct NOTE *note_p));
+static void pr_stuff P((struct STUFF *stuff_p));
+static char *xlate_place P((int place));
+static char *xlate_stufftype P((int stuff_type));
+static char * xlate_linetype P((int ltype));
+static char *xlate_gvalue P((int grpvalue));
+static char *xlate_gsize P((int grpsize));
+static char *xlate_gcont P((int gcont));
+static char *xlate_item P((int item));
+static char *xlate_dir P((int dir));
+static void print_curve P((struct CURVE *curve_p));
+static char *xlate_coordtype P((int coordtype));
+\f
+
+/* tell what is in the main linked list. Walk down the list and print
+ * things of interest. */
+
+void
+print_mainll()
+
+{
+       struct MAINLL *mll_p;           /* to walk through list */
+       register int i;                 /* count number of items in list */
+       int s;                          /* walk through staffs */
+
+
+       /* only do this stuff if debug level 128 is on */
+       if (debug_on(128) == 0) {
+               return;
+       }
+
+       debug(128, "\n\t\t==== Contents of main linked list ====\n");
+
+       /* walk down the main linked list, printing things about each struct
+        * in it */
+       for (i = 0, mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
+                               mll_p = mll_p->next, i++) {
+
+               debug(128, "\nmainll %d: type %s", i, stype_name(mll_p->str));
+               if (mll_p->inputfile != (char *) 0 && mll_p->inputlineno > 0) {
+                       debug(128, "from file %s inputlineno %d",
+                               mll_p->inputfile, mll_p->inputlineno);
+               }
+
+               /* print info of interest based on struct type */
+               switch (mll_p->str) {
+
+               case S_SSV:
+                       print_ssv(mll_p->u.ssv_p);
+                       break;
+
+               case S_BAR:
+                       print_bar(mll_p->u.bar_p);
+                       break;
+
+               case S_CURVE:
+                       print_curve(mll_p->u.curve_p);
+                       break;
+
+               case S_LINE:
+                       if (mll_p->u.line_p->linetype != L_NORMAL) {
+                               debug(128, "\t%s\n",
+                               xlate_linetype(mll_p->u.line_p->linetype));
+                       }
+                       break;
+
+               case S_PRHEAD:
+                       print_printdata(mll_p->u.prhead_p->printdata_p);
+                       break;
+
+               case S_FEED:
+                       debug(128, "\tfeed at (%f, %f) with%s pagefeed\n\tnorth %f, south %f, west %f, east %f",
+                               mll_p->u.feed_p->c[AX], mll_p->u.feed_p->c[AY],
+                               mll_p->u.feed_p->pagefeed ? "" : "out",
+                               mll_p->u.feed_p->c[AN], mll_p->u.feed_p->c[AS],
+                               mll_p->u.feed_p->c[AW], mll_p->u.feed_p->c[AE]);
+                       debug(128, "\tleftmargin %f rightmargin %f",
+                               mll_p->u.feed_p->leftmargin,
+                               mll_p->u.feed_p->rightmargin);
+                       if (mll_p->u.feed_p->top_p != 0) {
+                               debug(128, "\ttop block: height %f",
+                                               mll_p->u.feed_p->top_p->height);
+                               print_printdata(mll_p->u.feed_p->top_p->printdata_p);
+                       }
+                       if (mll_p->u.feed_p->bot_p != 0) {
+                               debug(128, "\tbot block: height %f",
+                                               mll_p->u.feed_p->bot_p->height);
+                               print_printdata(mll_p->u.feed_p->bot_p->printdata_p);
+                       }
+                       /* Note: after placment top2/bot2 are only meaningful
+                        * on final FEED when doing gridsatend with more than
+                        * one page worth of grids. */
+                       if (mll_p->u.feed_p->top2_p != 0) {
+                               debug(128, "\ttop2 block: height %f",
+                                               mll_p->u.feed_p->top2_p->height);
+                               print_printdata(mll_p->u.feed_p->top2_p->printdata_p);
+                       }
+                       if (mll_p->u.feed_p->bot2_p != 0) {
+                               debug(128, "\tbot2 block: height %f",
+                                               mll_p->u.feed_p->bot2_p->height);
+                               print_printdata(mll_p->u.feed_p->bot2_p->printdata_p);
+                       }
+                       break;
+
+               case S_CLEFSIG:
+                       debug(128, "\twest at %f, prtimesig %d, hide %d",
+                               mll_p->u.clefsig_p->wclefsiga,
+                               mll_p->u.clefsig_p->prtimesig,
+                               mll_p->u.clefsig_p->hide);
+                       if (mll_p->u.clefsig_p->bar_p != (struct BAR *) 0) {
+                               debug(128, " clefsig includes pseudo bar:");
+                               print_bar(mll_p->u.clefsig_p->bar_p);
+                       }
+                       for (s = 1; s <= Score.staffs; s++) {
+                               debug(128, "  staff %d: prclef %d, %d sharps, %d naturals",
+                                       s, mll_p->u.clefsig_p->prclef[s],
+                                       mll_p->u.clefsig_p->sharps[s],
+                                       mll_p->u.clefsig_p->naturals[s]);
+                       }
+                       break;
+
+               case S_CHHEAD:
+                       print_chhead(mll_p->u.chhead_p->ch_p);
+                       break;
+
+               case S_STAFF:
+                       print_staff(mll_p->u.staff_p);
+                       break;
+
+               case S_BLOCKHEAD:
+                       debug(128, "height %f\n", mll_p->u.blockhead_p->height);
+                       print_printdata(mll_p->u.blockhead_p->printdata_p);
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+\f
+
+/* translate S_* numbers used for the str field of MAINLL struct to names */
+
+char *
+stype_name(stype)
+
+int stype;     /* the S_* number to translate */
+
+{
+       switch(stype) {
+       case S_SSV:
+               return("S_SSV");
+       case S_CHHEAD:
+               return("S_CHHEAD");
+       case S_PRHEAD:
+               return("S_PRHEAD");
+       case S_LINE:
+               return("S_LINE");
+       case S_CURVE:
+               return("S_CURVE");
+       case S_BAR:
+               return("S_BAR");
+       case S_CLEFSIG:
+               return("S_CLEFSIG");
+       case S_FEED:
+               return("S_FEED");
+       case S_STAFF:
+               return("S_STAFF");
+       case S_BLOCKHEAD:
+               return("S_BLOCKHEAD");
+       default:
+               return(Unknown);
+       }
+}
+\f
+
+/* print some useful info from SSV struct */
+
+static void
+print_ssv(ssv_p)
+
+struct SSV *ssv_p;             /* which struct to report on */
+
+{
+       debug(128, "\tcontext = %s", contextname(ssv_p->context));
+       debug(128, "\tstaffno = %d", ssv_p->staffno);
+       debug(128, "\tvoiceno = %d", ssv_p->voiceno);
+       if (ssv_p->strinfo != (struct STRINGINFO *) 0) {
+               int i;
+
+               for (i = 0; i < ssv_p->stafflines; i++) {
+                       debug(128, "\t\ttab string %d: %c%c nticks=%d, oct=%d",
+                               i, ssv_p->strinfo[i].letter,
+                               ssv_p->strinfo[i].accidental == '\0'
+                               ? ' ' : ssv_p->strinfo[i].accidental,
+                               ssv_p->strinfo[i].nticks,
+                               ssv_p->strinfo[i].octave);
+               }
+       }
+       if (ssv_p->used[ABOVEORDER] == YES) {
+               print_markorder(ssv_p, PL_ABOVE);
+       }
+       if (ssv_p->used[BELOWORDER] == YES) {
+               print_markorder(ssv_p, PL_BELOW);
+       }
+       if (ssv_p->used[BETWEENORDER] == YES) {
+               print_markorder(ssv_p, PL_BETWEEN);
+       }
+}
+
+static void
+print_markorder(ssv_p, place)
+
+struct SSV *ssv_p;
+int place;
+
+{
+       int m;
+
+       debug(128, "\tmarkorder %s: ", xlate_place(place));
+       for (m = 0; m < NUM_MARK; m++) {
+               debug(128, "\t\t%d ", ssv_p->markorder[place][m]);
+       }
+       debug(128, "\n");
+}
+\f
+
+/* print useful info from STAFF struct */
+
+static void
+print_staff(staff_p)
+
+struct STAFF *staff_p;         /* which to report on */
+
+{
+       register int i;         /* index to walk down a list */
+
+
+       debug(128, "\tstaffno = %d, visible = %s", staff_p->staffno,
+                                       staff_p->visible == YES ? "y" : "n");
+
+       /* print each group */
+       for ( i = 0; i < MAXVOICES; i++) {
+               if (staff_p->groups_p[i] != (struct GRPSYL *) 0) {
+                       print_grpsyl(staff_p->groups_p[i], "GROUP", i + 1);
+               }
+       }
+
+       /* print each lyrics syllable */
+       for (i = 0; i < staff_p->nsyllists; i++) {
+               debug(128, "\n\tsylplace = %s",
+                                       xlate_place(staff_p->sylplace[i]));
+               print_grpsyl(staff_p->syls_p[i], "SYLLABLE",
+                                       staff_p->syls_p[i]->vno);
+       }
+
+       pr_stuff(staff_p->stuff_p);
+}
+\f
+
+/* print info from a list of GRPSYL structs */
+
+static void
+print_grpsyl(g_p, gstype, vno)
+
+struct GRPSYL *g_p;    /* which GRPSYL */
+char *gstype;          /* "GROUP" or "SYLLABLE" */
+int vno;               /* voice number or verse number */
+
+{
+       register int i;         /* index through list */
+       char *sylbuff;          /* syllable with all ASCII characters */
+
+
+       if (debug_on(128) == 0) {
+               return;
+       }
+
+       (void) fprintf(stderr, "\tgrpsyl = %s, vno = %d\n", gstype, vno);
+
+       /* print info about the stuff in GRPSYL structs */
+       for (   ; g_p != (struct GRPSYL *) 0; g_p = g_p->next) {
+
+               (void) fprintf(stderr, "\n\t\tbasictime = %d, dots = %d, fulltime = %ld/%ld\n",
+                                       g_p->basictime, g_p->dots,
+                                       g_p->fulltime.n, g_p->fulltime.d);
+               (void) fprintf(stderr, "\t\tc[AX] = %f, c[AY] = %f\n",
+                                       g_p->c[AX], g_p->c[AY]);
+               (void) fprintf(stderr, "\t\tc[AW] = %f, c[AE] = %f\n",
+                                       g_p->c[AW], g_p->c[AE]);
+               (void) fprintf(stderr, "\t\tc[AN] = %f, c[AS] = %f\n",
+                                       g_p->c[AN], g_p->c[AS]);
+               if (g_p->ho_usage != HO_NONE) {
+                       (void) fprintf(stderr, "\t\tho_usage = %d", g_p->ho_usage);
+                       if (g_p->ho_usage == HO_VALUE) {
+                               (void) fprintf(stderr, ", ho_value = %f",
+                                                       g_p->ho_value);
+                       }
+                       (void) fprintf(stderr, "\n");
+               }
+
+               /* if group, print info about it, including the list of
+                * notes if any */
+               if (g_p->grpsyl == GS_GROUP) {
+
+                       (void) fprintf(stderr, "\t\tclef = %d, xdotr = %f, stemx = %f\n",
+                               g_p->clef, g_p->xdotr, g_p->stemx);
+                       (void) fprintf(stderr, "\t\tgrpvalue = %s, grpsize = %s, headshape = %d,\n\t\tgrpcont = %s, beamloc = %s, beamslope=%f\n",
+                               xlate_gvalue(g_p->grpvalue),
+                               xlate_gsize(g_p->grpsize),
+                               g_p->headshape,
+                               xlate_gcont(g_p->grpcont),
+                               xlate_item(g_p->beamloc),
+                               g_p->beamslope);
+                       if (g_p->roll != NOITEM) {
+                               (void) fprintf(stderr, "\t\troll = %s, rolldir = %s\n",
+                               xlate_item(g_p->roll),
+                               xlate_dir(g_p->rolldir));
+                       }
+
+                       if( g_p->padding != 0.0) {
+                               (void) fprintf(stderr, "\t\tpadding=%f\n", g_p->padding);
+                       }
+                       (void) fprintf(stderr, "\t\tis_meas=%d, uncompressible=%d\n",
+                               g_p->is_meas, g_p->uncompressible);
+
+                       (void) fprintf(stderr, "\t\tstemlen=%f, stemdir=%s\n",
+                               g_p->stemlen, xlate_dir(g_p->stemdir));
+                       (void) fprintf(stderr, "\t\ttie=%d, slash_alt=%d\n",
+                               g_p->tie, g_p->slash_alt);
+
+                       /* if part of tuplet, print info about that */
+                       if (g_p->tuploc != NOITEM) {
+                               (void) fprintf(stderr, "\t\ttuploc=%s, tupcont=%d\n",
+                                       xlate_item(g_p->tuploc), g_p->tupcont);
+                               (void) fprintf(stderr, "\t\tprinttup=%d, tupside=%s, tupextend=%f\n",
+                                       g_p->printtup, xlate_place(g_p->tupside),
+                                       g_p->tupextend);
+                       }
+
+                       /* print a bit about "with" lists */
+                       if (g_p->nwith) {
+                               int w;
+                               (void) fprintf(stderr, "\t\t%d items in 'with' list (normwith=%d):\n",
+                                               g_p->nwith, g_p->normwith);
+                               for (w = 0; w < g_p->nwith; w++) {
+                                       (void) fprintf(stderr, "\t\t\t\"%s\"\n",
+                                               ascii_str(g_p->withlist[w],
+                                               YES, NO, TM_NONE));
+                               }
+                       }
+
+                       (void) fprintf(stderr, "\t\tnnotes = %d, beamto = %d, stemto = %d, stemto_idx = %d\n",
+                                       g_p->nnotes, g_p->beamto,
+                                       g_p->stemto, g_p->stemto_idx);
+                       for (i = 0; i < g_p->nnotes; i++) {
+                               if (is_tab_staff(g_p->staffno) == YES) {
+                                       (void) fprintf(stderr, "\t\t\tstring %d, fret %d, bend %d %d/%d, fret_paren %d\n",
+                                               g_p->notelist[i].STRINGNO,
+                                               g_p->notelist[i].FRETNO,
+                                               BENDINT(g_p->notelist[i]),
+                                               BENDNUM(g_p->notelist[i]),
+                                               BENDDEN(g_p->notelist[i]),
+                                               g_p->notelist[i].FRET_HAS_PAREN);
+                                       continue;
+                               }
+                               (void) fprintf(stderr, "\t\t\t%c %c %d steps %d",
+                                       g_p->notelist[i].letter,
+                                       g_p->notelist[i].accidental == '\0'
+                                       ? ' ' : g_p->notelist[i].accidental,
+                                       g_p->notelist[i].octave,
+                                       g_p->notelist[i].stepsup);
+                               if (g_p->notelist[i].note_has_paren == YES) {
+                                       (void) fprintf(stderr, " note_paren (%f, %f)",
+                                               g_p->notelist[i].wlparen,
+                                               g_p->notelist[i].erparen);
+                               }
+                               if (g_p->notelist[i].acc_has_paren == YES) {
+                                       (void) fprintf(stderr, " acc_paren");
+                               }
+                               if (g_p->notelist[i].tie == YES) {
+                                       (void) fprintf(stderr, " tie(style %d)",
+                                               g_p->notelist[i].tiestyle);
+                               }
+
+                               (void) fprintf(stderr, "   (headshape %d, headchar %d, headfont %d)",
+                                       g_p->notelist[i].headshape,
+                                       g_p->notelist[i].headchar,
+                                       g_p->notelist[i].headfont);
+                               if (g_p->notelist[i].notesize != GS_NORMAL) {
+                                       (void) fprintf(stderr, " (size %s)",
+                                               xlate_gsize(g_p->notelist[i]
+                                               .notesize));
+                               }
+                               if (g_p->notelist[i].is_bend == YES) {
+                                       fprintf(stderr, " is_bend");
+                               }
+                               if (g_p->notelist[i].smallbend == YES) {
+                                       fprintf(stderr, " smallbend");
+                               }
+                               print_slurtolist( &(g_p->notelist[i]) );
+                               (void) fprintf(stderr, "\n");
+                       }
+               }
+
+
+               /* if syllable, print it */
+               if (g_p->syl != (char *) 0) {
+                       sylbuff = ascii_str(g_p->syl, YES, NO, TM_NONE);
+                       (void) fprintf(stderr, "\t\tsyllable = '%s', font %d, size %d\n",
+                               sylbuff, g_p->syl[0], g_p->syl[1]);
+               }
+       }
+}
+\f
+
+/* print any slurtolist entries */
+
+static void
+print_slurtolist(note_p)
+
+struct NOTE *note_p;
+
+{
+       register int n;
+
+       if ( (note_p->nslurto == 0) || (debug_on(128) == 0) ) {
+               return;
+       }
+
+       (void) fprintf(stderr, "    slurred to:");
+       for (n = note_p->nslurto - 1; n >= 0; n--) {
+               switch (note_p->slurtolist[n].octave) {
+               case IN_UPWARD:
+                       (void) fprintf(stderr, " IN_UPWARD");
+                       break;
+               case IN_DOWNWARD:
+                       (void) fprintf(stderr, " IN_DOWNWARD");
+                       break;
+               case OUT_UPWARD:
+                       (void) fprintf(stderr, " OUT_UPWARD");
+                       break;
+               case OUT_DOWNWARD:
+                       (void) fprintf(stderr, " OUT_DOWNWARD");
+                       break;
+               default:
+                       (void) fprintf(stderr, " %c%d",
+                                       note_p->slurtolist[n].letter,
+                                       note_p->slurtolist[n].octave);
+               }
+       }
+}
+\f
+
+/* given a GV_* value, return its English name */
+
+static char *
+xlate_gvalue(grpvalue)
+
+int grpvalue;
+
+{
+       switch (grpvalue) {
+       case GV_NORMAL:
+               return("NORMAL");
+       case GV_ZERO:
+               return("ZERO");
+       default:
+               return(Unknown);
+       }
+}
+\f
+
+/* given a GS_* value, return its English name */
+
+static char *
+xlate_gsize(grpsize)
+
+int grpsize;
+
+{
+       switch(grpsize) {
+       case GS_NORMAL:
+               return("NORMAL");
+       case GS_SMALL:
+               return("SMALL");
+       default:
+               return(Unknown);
+       }
+}
+\f
+
+/* given a GC_* grpcont value, return its English name */
+
+static char *
+xlate_gcont(grpcont)
+
+int grpcont;
+
+{
+       switch(grpcont) {
+       case GC_NOTES:
+               return("NOTES");
+       case GC_REST:
+               return("REST");
+       case GC_SPACE:
+               return("SPACE");
+       default:
+               return(Unknown);
+       }
+}
+\f
+
+/* given an "ITEM" value, return its English name */
+
+static char *
+xlate_item(item)
+
+int item;
+
+{
+       switch(item) {
+       case NOITEM:
+               return("NOITEM");
+       case INITEM:
+               return("INITEM");
+       case STARTITEM:
+               return("STARTITEM");
+       case ENDITEM:
+               return("ENDITEM");
+       case LONEITEM:
+               return("LONEITEM");
+       default:
+               return(Unknown);
+       }
+}
+\f
+
+/* translate direction to name */
+
+static char *
+xlate_dir(dir)
+
+int dir;
+
+{
+       switch(dir) {
+       case UP:
+               return("UP");
+       case DOWN:
+               return("DOWN");
+       default:
+               return("UNKNOWN");
+       }
+}
+\f
+
+/* recursively print info from a list of PRINTDATA structs */
+
+static void
+print_printdata(printdata_p)
+
+struct PRINTDATA *printdata_p;
+
+{
+       char *buff;     /* for all-ASCII version. */
+
+
+       if (printdata_p == (struct PRINTDATA *) 0) {
+               /* we're at the end of the line... */
+               return;
+       }
+
+       buff = ascii_str(printdata_p->string, YES, NO, TM_NONE);
+       debug(128, "\tprint (isPostScript %d, justify %d, width %.2f, font %d, size %d) '%s'",
+               printdata_p->isPostScript, printdata_p->justifytype,
+               printdata_p->width, (int) printdata_p->string[0],
+               (int) printdata_p->string[1], buff);
+
+       /* recurse down the list */
+       print_printdata(printdata_p->next);
+}
+\f
+
+/* print useful info from a bar struct */
+
+static void
+print_bar(bar_p)
+
+struct BAR *bar_p;
+
+{
+       char *type;
+       struct TIMEDSSV *tssv_p;        /* list of mid-meas param changes */
+
+       switch(bar_p->bartype) {
+       case INVISBAR:
+               type = "INVISBAR";
+               break;
+       case SINGLEBAR:
+               type = "SINGLEBAR";
+               break;
+       case DOUBLEBAR:
+               type = "DOUBLEBAR";
+               break;
+       case REPEATSTART:
+               type = "REPEATSTART";
+               break;
+       case REPEATEND:
+               type = "REPEATEND";
+               break;
+       case REPEATBOTH:
+               type = "REPEATBOTH";
+               break;
+       case ENDBAR:
+               type = "ENDBAR";
+               break;
+       case RESTART:
+               type = "RESTART";
+               break;
+       default:
+               type = Unknown;
+               break;
+       }
+
+       debug(128, "\tbartype = %d (%s), endingloc=%d", bar_p->bartype, type,
+                               bar_p->endingloc);
+       debug(128, "\tx = %f, y = %f, mnum = %d",  bar_p->c[AX], bar_p->c[AY],
+                               bar_p->mnum);
+       if (bar_p->reh_string != 0) {
+               debug(128, "\treh_string = '%s'",
+                               ascii_str(bar_p->reh_string, YES, NO, TM_NONE));
+       }
+
+       for (tssv_p = bar_p->timedssv_p; tssv_p != 0; tssv_p = tssv_p->next) {
+               debug(128, "\tTimed SSV, time_off %d/%d\n", tssv_p->time_off.n,
+                                               tssv_p->time_off.d);
+               print_ssv(&tssv_p->ssv);
+       }
+}
+\f
+
+/* recursively print coord info about chords in chord list */
+
+static void
+print_chhead(ch_p)
+
+struct CHORD *ch_p;
+
+{
+       struct GRPSYL * gs_p;
+
+
+       if (ch_p != (struct CHORD *) 0) {
+               debug(128, "\tchord at (%f, %f), width %f, fullwidth %f",
+                       ch_p->c[AX], ch_p->c[AY], ch_p->width, ch_p->fullwidth);
+               debug(128, "\tc[RW] = %f, c[RE] = %f", ch_p->c[RW], ch_p->c[RE]);
+               debug(128, "\tstarttime %d/%d, duration %d/%d, pseudodur %f",
+                       ch_p->starttime.n, ch_p->starttime.d,
+                       ch_p->duration.n, ch_p->duration.d,
+                       ch_p->pseudodur);
+               for (gs_p = ch_p->gs_p; gs_p != (struct GRPSYL *) 0;
+                                                       gs_p = gs_p->gs_p) {
+                       debug(128, "\t\t%s, staff %d, vno %d",
+                                       gs_p->grpsyl == GS_GROUP ? "GROUP"
+                                       : "SYLLABLE", gs_p->staffno,
+                                       gs_p->vno);
+               }
+               print_chhead(ch_p->ch_p);
+       }
+}
+\f
+
+/* print information about a STUFF list */
+
+static void
+pr_stuff(stuff_p)
+
+struct STUFF *stuff_p;
+
+{
+       char *buff;     /* for all-ASCII version */
+
+
+       for (   ; stuff_p != (struct STUFF *) 0; stuff_p = stuff_p->next) {
+
+               debug(128, "\nSTUFF: %s %s %s: start=%f (%d) [%f], end=%dm+%f, all=%d, x=%f, y=%f",
+                       xlate_stufftype(stuff_p->stuff_type),
+                       (stuff_p->stuff_type == ST_PHRASE
+                         ? xlate_linetype(stuff_p->modifier)
+                         : stuff_modifier(stuff_p->modifier)),
+                       xlate_place(stuff_p->place), stuff_p->start.count,
+                       stuff_p->gracebackup, stuff_p->start.steps,
+                       stuff_p->end.bars, stuff_p->end.count, stuff_p->all,
+                       stuff_p->c[AX], stuff_p->c[AY]);
+
+               if (stuff_p->string != (char *) 0) {
+                       buff = ascii_str(stuff_p->string, YES, NO, stuff_p->modifier);
+                       debug(128, "\tstring = \"%s\"", buff);
+               }
+       }
+}
+\f
+
+/* given a PL_* place value, return its English name */
+
+static char *
+xlate_place(place)
+
+int place;
+
+{
+       switch(place) {
+       case PL_ABOVE:
+               return("above");
+       case PL_BELOW:
+               return("below");
+       case PL_BETWEEN:
+               return("between");
+       case PL_UNKNOWN:
+               return("unknown");
+       default:
+               return("invalid place");
+       }
+}
+\f
+
+/* given a ST_* stufftype, return its English name */
+
+
+static char *
+xlate_stufftype(stuff_type)
+
+int stuff_type;
+
+{
+       switch (stuff_type) {
+       case ST_ROM:
+               return("rom");
+       case ST_BOLD:
+               return("bold");
+       case ST_ITAL:
+               return("ital");
+       case ST_BOLDITAL:
+               return("boldital");
+       case ST_CRESC:
+               return("cresc");
+       case ST_DECRESC:
+               return("decresc");
+       case ST_MUSSYM:
+               return("mussym");
+       case ST_PHRASE:
+               return("phrase");
+       case ST_PEDAL:
+               return("pedal");
+       case ST_OCTAVE:
+               return("octave");
+       case ST_MIDI:
+               return("MIDI");
+       case ST_TIESLUR:
+               return("TIESLUR");
+       case ST_TABSLUR:
+               return("TABSLUR");
+       case ST_BEND:
+               return("BEND");
+       default:
+               return("unknown stuff_type");
+       }
+}
+\f
+
+/* Translate L_ line type to name */
+
+static char *
+xlate_linetype(ltype)
+
+int ltype;     /* L_* value */
+
+{
+       switch(ltype) {
+       case L_NORMAL:
+               return("");
+       case L_MEDIUM:
+               return("medium");
+       case L_WIDE:
+               return("wide");
+       case L_DOTTED:
+               return("dotted");
+       case L_DASHED:
+               return("dashed");
+       case L_WAVY:
+               return("wavy");
+       default:
+               return("unknown");
+       }
+}
+\f
+
+static void
+print_curve(curve_p)
+
+struct CURVE *curve_p;
+
+{
+       struct COORD_INFO *cinfo_p;
+       int n;
+
+       if (debug_on(128) == 0) {
+               return;
+       }
+
+       for (n = 0; n < curve_p->ncoord; n++) {
+               if ((cinfo_p = find_coord(curve_p->coordlist[n].hor_p)) != 0) {
+                       debug(128, "\thor_p = 0x%lx, page = %d, score = %d, pseudo_bar_p = %lx",
+                               curve_p->coordlist[n].hor_p,
+                               cinfo_p->page, cinfo_p->scorenum,
+                               cinfo_p->pseudo_bar_p);
+               }
+               debug(128, "\thtype = %s, hsteps = %f, counts = %f",
+                               xlate_coordtype(curve_p->coordlist[n].htype),
+                               curve_p->coordlist[n].hsteps,
+                               curve_p->coordlist[n].counts);
+               if ((cinfo_p = find_coord(curve_p->coordlist[n].vert_p)) != 0) {
+                       debug(128, "\tvert_p = 0x%lx, page = %d, score = %d, pseudo_bar_p = %lx",
+                               curve_p->coordlist[n].vert_p,
+                               cinfo_p->page, cinfo_p->scorenum,
+                               cinfo_p->pseudo_bar_p);
+               }
+               debug(128, "\tvtype = %s, vsteps = %f\n",
+                               xlate_coordtype(curve_p->coordlist[n].vtype),
+                               curve_p->coordlist[n].vsteps);
+       }
+}
+
+/* given an absolute coordinate type like AX, return its name */
+
+static char
+*xlate_coordtype(coordtype)
+
+int coordtype;
+
+{
+       switch(coordtype) {
+       case AX:
+               return("AX");
+       case AY:
+               return("AY");
+       case AN:
+               return("AN");
+       case AS:
+               return("AS");
+       case AE:
+               return("AE");
+       case AW:
+               return("AW");
+       default:
+               return(Unknown);
+       }
+}
diff --git a/mup/mup/defines.h b/mup/mup/defines.h
new file mode 100644 (file)
index 0000000..560516b
--- /dev/null
@@ -0,0 +1,1327 @@
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ * 2006 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ *     defines.h
+ *
+ *     This file defines the constants needed for the music publication
+ *     program.
+ */
+
+#include <math.h>
+#ifndef _DEFINES
+#define _DEFINES
+#include "muschar.h"
+
+/*
+ * Define the environment =============================================
+ */
+
+/* for all forms of DOS we've tried, make sure __DOS__ is defined */
+#if defined(__TURBOC__) || defined(__WATCOMC__) || defined(__MINGW32__)
+#ifndef __DOS__
+#define __DOS__
+#endif
+#endif
+
+/* if you are short on memory or know you'll never use the extended character
+ * set (with accented characters, etc) you can undefine EXTCHAR
+ */
+#ifndef __TURBOC__
+#define EXTCHAR
+#endif
+#include "extchar.h"
+
+/* the following is needed for the DOS port of the GNU C compiler */
+#ifdef __DJGPP__
+#define __DOS__
+#undef unix
+#endif
+
+/*
+ * Based on system type, #define or don't #define various symbols, as follows:
+ *
+ * UNIX_LIKE_FILES     If defined, files can be simultaneously read from and
+ *                     written to and invisibly unlinked.
+ * UNIX_LIKE_PATH_RULES        If defined, use these rules for MUPPATH.
+ * DOS_LIKE_PATH_RULES If defined, use these rules for MUPPATH.
+ * CORE_MESSAGE                If defined, then a creating core error message will be
+ *                     printed in debug mode.
+ * NEED_GETOPT         If defined, the getopt suite is not available,
+ *                     therefore use the limited one in main.c.
+ * MAGIC_FILE_HOME     If defined, check for magic file in $HOME.
+ * MAGIC_FILE_NAME     Name of magic file.
+ * OPTION_MARKER       The char which preceeds command line options.
+ */
+#ifdef unix
+#define UNIX_LIKE_FILES
+#define        UNIX_LIKE_PATH_RULES
+#define CORE_MESSAGE
+#define MAGIC_FILE_HOME
+#define MAGIC_FILE_NAME        ".mup"
+#define OPTION_MARKER  '-'
+#endif
+
+#ifdef VMS
+#define MAGIC_FILE_HOME
+#define MAGIC_FILE_NAME        ".mup"
+#define OPTION_MARKER  '-'
+#endif
+
+#ifdef AMIGA
+#undef UNIX_LIKE_FILES
+#define NEED_GETOPT
+#define MAGIC_FILE_HOME
+#define MAGIC_FILE_NAME        ".mup"
+#define OPTION_MARKER  '-'
+#endif
+
+#ifdef __DOS__
+#define        DOS_LIKE_PATH_RULES
+#define NEED_GETOPT
+#define MAGIC_FILE_NAME        "mup.ok"
+#define OPTION_MARKER  '/'
+#endif
+
+#ifdef Mac_BBEdit
+#undef  UNIX_LIKE_FILES
+#define NEED_GETOPT
+/* skip length byte of Pascal string literal */
+#define MAGIC_FILE_NAME        (char *)(MupRegFileName + 1);
+#define OPTION_MARKER  '-'
+#endif
+
+#ifdef __EMX__
+#undef UNIX_LIKE_FILES
+#define        DOS_LIKE_PATH_RULES
+#define MAGIC_FILE_HOME
+#define MAGIC_FILE_NAME        ".mup"
+#define OPTION_MARKER  '-'
+#endif
+
+#ifndef OPTION_MARKER
+/* use - as default if nothing has been defined for it */
+#define OPTION_MARKER '-'
+#endif
+
+/*
+ * Define ranges for variables =============================================
+ */
+
+/*
+ * Define maximum value for exit code from Mup. Must be less than 128
+ * to be able to distinguish from WAIT_ABANDONED value on Windows.
+ */
+#define        MAX_ERRORS      (127)
+
+/* text point sizes */
+#define MINSIZE        (1)
+#define MAXSIZE        (100)
+
+/* key signatures */
+#define MINSHARPS      (-7)
+#define MAXSHARPS      (7)
+#define DEFSHARPS      (0)
+
+/* octave */
+#define MINOCTAVE      (0)
+#define MAXOCTAVE      (9)
+#define DEFOCTAVE      (4)
+
+/* staves */
+#define MINSTAFFS      (1)
+#define MAXSTAFFS      (40)
+#define DEFSTAFFS      (1)
+
+/* voices */
+#define MINVOICES      (1)
+#define NORMVOICES     (2)
+#define MAXVOICES      (3)
+
+/* number of lines in a tablature staff */
+#define        MINTABLINES     (1)
+#define        DEFTABLINES     (6)     /* see Guitar[] in globals.c */
+#define        MAXTABLINES     (9)
+
+/* number of ticks on a string designation for tablature */
+#define        MINTICKS        (0)
+#define        MAXTICKS        (MAXTABLINES - 1)
+
+#define TABDEFOCT      (4)
+
+/* tablature fret numbers, including pseudo fret numbers */
+#define MINFRET                (0)
+#define MAXFRET                (99)
+#define DEFFRET                (0)
+#define NOFRET         (MAXFRET + 1)
+#define IN_UPWARD      (MAXFRET + 2)   /* slur from nowhere, going up */
+#define IN_DOWNWARD    (MAXFRET + 3)   /* slur from nowhere, going down */
+#define OUT_UPWARD     (MAXFRET + 4)   /* slur to nowhere, going up */
+#define OUT_DOWNWARD   (MAXFRET + 5)   /* slur to nowhere, going down */
+#define IS_NOWHERE(fret) ((fret) >= IN_UPWARD && (fret) <= OUT_DOWNWARD)
+
+/* range of frets that can be printed by a chord grid */
+#define        MINGRIDFRET     (2)
+#define        MAXGRIDFRET     (MAXFRET)
+#define        DEFGRIDFRET     (4)
+#define        NOGRIDFRET      (-1)    /* must be negative so user can't enter it */
+
+/* USE_DFLT_OCTAVE has to be number that is not a valid octave, nor a */
+/* valid fret number.  But it has to be positive and small enough to be */
+/* able to add MAX_OCTAVE to it */
+#define USE_DFLT_OCTAVE        (MAXFRET + 6)
+
+/* min and max numbers for bend integers, numerators, and denominators */
+#define BENDINTBITS    (4)
+#define MINBENDINT     (0)
+#define MAXBENDINT     ((1 << BENDINTBITS) - 1)
+#define BENDNUMBITS    (6)
+#define MINBENDNUM     (0)
+#define MAXBENDNUM     ((1 << BENDNUMBITS) - 1)
+#define BENDDENBITS    (6)
+#define MINBENDDEN     (1)
+#define MAXBENDDEN     ((1 << BENDDENBITS) - 1)
+
+/* time unit */
+/* -1 means quadruple whole and 0 means double whole.  Actually, less than -1 */
+/* is allowed, and it's minus the number of measures in a multirest */
+#define MINBASICTIME   (-1)
+#define MAXBASICTIME   (256)
+
+/* the biggest number that is allowed on a multirest */
+#define MAXMULTINUM    (1000)
+
+/* limits for scaling the output */
+#define MINSCALE       (0.1)
+#define MAXSCALE       (10.0)
+#define DEFSCALE       (1.0)
+
+/* limits for scaling a staff relative to the output as a whole */
+#define MINSTFSCALE    (0.1)
+#define MAXSTFSCALE    (10.0)
+#define DEFSTFSCALE    (1.0)
+
+#define MINGRIDSCALE   (0.1)
+#define MAXGRIDSCALE   (10.0)
+#define DEFGRIDSCALE   (1.0)
+
+/* limits on min distance required between a chord and its staff (stepsizes) */
+#define        MINCHORDDIST    (0)
+#define        MAXCHORDDIST    (50)
+#define        DEFCHORDDIST    (3)
+
+/* limits on min dist required between other stuff and its staff (stepsizes) */
+#define        MINDIST         (0)
+#define        MAXDIST         (50)
+#define        DEFDIST         (2)
+
+/* limits on min distance required between a cresc and its staff (stepsizes) */
+#define        MINDYNDIST      (0)
+#define        MAXDYNDIST      (50)
+#define        DEFDYNDIST      (0)
+
+/* vertical space between staffs and scores, in units of stepsize */
+#define        MINMINSTSEP     (6)     /* min user-specified min between staffs */
+#define        DEFMINSTSEP     (10)    /* default min between staffs */
+#define        MINMINSCSEP     (6)     /* min user-specified min between scores */
+#define        DEFMINSCSEP     (12)    /* default min between scores */
+#define        MINMAXSCSEP     MINMINSCSEP /* min user-specified max between scores */
+#define        DEFMAXSCSEP     (20)    /* default max between scores */
+#define MAXSEPVAL      ((int)(PGHEIGHT / STEPSIZE)) /* max for either one */
+#define        MINSTPAD        (-MAXSEPVAL) /* min user-spec. white between staffs */
+#define        MAXSTPAD        (MAXSEPVAL) /* max user white between staffs */
+#define        DEFSTPAD        (0)     /* default white between staffs */
+#define        MINMINSCPAD     (-MAXSEPVAL) /* min user-spec. white between scores */
+#define        DEFMINSCPAD     (2)     /* default white between scores */
+#define        MINMAXSCPAD     (-MAXSEPVAL) /* min user-spec. white between scores */
+#define        DEFMAXSCPAD     (2)     /* default white between scores */
+#define        MAXPADVAL       (MAXSEPVAL) /* max user white between scores */
+
+/* distance from center line a rest should be forced to be */
+#define MINRESTDIST    (-50)
+#define MAXRESTDIST    (50)
+#define        NORESTDIST      (11111) /* this means it is not set */
+
+/* number of mr needed to combine into a multirest (like -c option) */
+#define        MINRESTCOMBINE  (2)
+#define        MAXRESTCOMBINE  (1000)
+#define        NORESTCOMBINE   (-1)    /* must be negative so user can't enter it */
+
+/* page number to be put on the first page (like -p option) */
+#define MINFIRSTPAGE   (1)
+#define MAXFIRSTPAGE   (5000)
+#define NOFIRSTPAGE    (0)     /* this means it is not set */
+
+/* number to multiply linear regression slope by to get beam's slope */
+#define MINBEAMFACT    (0.0)
+#define MAXBEAMFACT    (1.0)
+#define DEFBEAMFACT    (1.0)
+
+/* maximum beam angle allowed, in degrees */
+#define MINBEAMMAX     (0.0)
+#define MAXBEAMMAX     (45.0)
+#define DEFBEAMMAX     (20.0)
+
+/* angle of beam specified by the "slope" interchord attribute */
+#define        MINBEAMANGLE    (-MAXBEAMMAX)
+#define        MAXBEAMANGLE    (MAXBEAMMAX)
+#define        NOBEAMANGLE     (2 * MAXBEAMANGLE)      /* something out of range */
+
+/* padding to be applied on the left of every group (and the right of the */
+/* last group in the measure), in stepsizes */
+#define MINPAD         (-5.0)
+#define MAXPAD         (50.0)
+#define DEFPAD         (0.0)
+
+/* for setting and testing unknown stem length */
+#define        STEMLEN_UNKNOWN         (-1.0)
+#define        IS_STEMLEN_KNOWN(x)     ((x) >= 0.0)    /* avoid using "==" on floats */
+#define        IS_STEMLEN_UNKNOWN(x)   ((x) < 0.0)     /* avoid using "==" on floats */
+
+/* other stem length definitions */
+#define        MINSTEMLEN      (0.0)
+#define        DEFSTEMLEN      (7.0)
+#define        MAXSTEMLEN      (100.0)
+#define        SM_STEMFACTOR   (5.0 / 7.0)     /* grace/cue factor */
+
+/* number of stepsizes by which a beamed stem can be shortened */
+#define        MINSTEMSHORTEN  (0.0)
+#define        MAXSTEMSHORTEN  (2.0)
+#define        DEFSTEMSHORTEN  (1.0)
+
+/* what fraction of each lyrics syllable goes left of the center of chord */
+#define MINLYRICSALIGN (0.0)
+#define MAXLYRICSALIGN (1.0)
+#define DEFLYRICSALIGN (0.25)
+
+/* size of the paper */
+#define MINPAGEHEIGHT  (2.0)
+#define MAXPAGEHEIGHT  (24.0)
+#define DEFPAGEHEIGHT  (11.0)
+#define MINPAGEWIDTH   (2.0)
+#define MAXPAGEWIDTH   (24.0)
+#define DEFPAGEWIDTH   (8.5)
+
+/* top and bottom margins */
+#define MINVMARGIN     (0.0)
+#define MAXVMARGIN     (3.0)
+#define DEFVMARGIN     (0.5)
+
+/* left and right margins */
+#define MINHMARGIN     (0.0)
+#define MAXHMARGIN     (3.0)
+#define DEFHMARGIN     (0.5)
+
+/* panels per page */
+#define        MINPANELSPERPAGE        (1)
+#define        MAXPANELSPERPAGE        (2)
+#define        DEFPANELSPERPAGE        (1)
+
+/* how tightly to pack the stuff horizontally (default value) */
+#define MINPACKFACT    (0.0)
+#define DFLTPACKFACT   (1.0)
+#define MAXPACKFACT    (10.0)
+
+/* how much to expand long notes relative to short ones */
+#define MINPACKEXP     (0.0)
+#define DFLTPACKEXP    (0.8)
+#define MAXPACKEXP     (1.0)
+
+/* time signature */
+#define MINNUMERATOR   (1)
+#define MAXNUMERATOR   (99)
+
+#define MINDENOMINATOR (1)
+#define MAXDENOMINATOR (64)
+
+#define MINDIVISION    (1)
+#define DEFDIVISION    (192)
+#define MAXDIVISION    (3 * 512)
+
+/* define values for the "release" parameter, in milliseconds */
+#define MINRELEASE     (0)
+#define DEFRELEASE     (20)
+#define MAXRELEASE     (500)
+
+/* define values for the "sylposition" parameter, in points */
+#define        MINSYLPOSITION  (-100)
+#define        MAXSYLPOSITION  (100)
+#define        DEFSYLPOSITION  (-5)
+#define        NOSYLPOSITION   (11111) /* this means it is not set */
+
+
+/*
+ * Define sets of symbols which probably should have been done as enums,
+ * but in ANSI C enums aren't much good anyhow.  =============================
+ * Also define some macros for testing these enums.
+ */
+
+/*
+ * To limit the number of terminal symbols so that yacc won't blow up,
+ * several tokens map to the same terminal symbol, and we set a variable
+ * (yylval) to say which particular one was actually seen.
+ */
+#define F_STAFFS       (1)
+#define F_OCTAVE       (2)
+#define F_LYRSIZE      (3)
+#define F_VERTSPACE    (4)
+#define F_SIZE         (5)
+
+#define F_TOPMARGIN    (6)
+#define F_BOTMARGIN    (7)
+#define F_LEFTMARGIN   (8)
+#define F_RIGHTMARGIN  (9)
+
+#define F_TIMEUNIT     (10)
+#define F_VSCHEME      (11)
+
+#define F_BRACKET      (12)
+#define F_BRACE                (13)
+#define F_BARSTYLE     (14)
+
+#define F_LABEL                (15)
+#define F_LABEL2       (16)
+
+#define F_FONT         (17)
+#define F_LYRFONT      (18)
+
+#define F_VISIBLE      (19)
+#define F_VERSES       (20)
+
+/*
+ * Define all the types of context in the input.  Make each one a bit, so that
+ * we can also define a couple groupings of them.
+ */
+#define        C_HEADER        (0x1)   /* first page header */
+#define        C_FOOTER        (0x2)   /* first page footer */
+#define        C_HEAD2         (0x4)   /* later page header */
+#define        C_FOOT2         (0x8)   /* later page footer */
+#define        C_TOP           (0x10)  /* initial block at top */
+#define        C_BOT           (0x20)  /* initial block at bottom */
+#define        C_TOP2          (0x40)  /* later block at top */
+#define        C_BOT2          (0x80)  /* later block at bottom */
+#define        C_BLOCK         (0x100) /* other block */
+#define        C_SCORE         (0x200) /* the whole score */
+#define        C_STAFF         (0x400) /* a staff */
+#define        C_VOICE         (0x800) /* a voice */
+#define        C_MUSIC         (0x1000) /* notes, etc. */
+#define        C_GRIDS         (0x2000) /* chord grids */
+#define        C_HEADSHAPES    (0x4000) /* head shapes for notehead characters */
+
+/* context classes--combining things that mostly have the same rules */
+#define        C_BLOCKHEAD     (C_HEADER | C_FOOTER | C_HEAD2 | C_FOOT2 | \
+                       C_TOP | C_BOT | C_TOP2 | C_BOT2 | C_BLOCK)
+#define        C_SSV           (C_SCORE | C_STAFF | C_VOICE)
+
+/* define whether things are measured in inches or centimeters */
+#define INCHES         (0)
+#define CM             (1)
+
+/*
+ * Define the voice schemes.  V_1 means just one voice is on the staff;
+ * the program will decide the stem direction of each group.  V_2OPSTEM
+ * means there are two voices with opposing stems:  the first voice always
+ * points up, and the second one always points down.  V_2FREESTEM means there
+ * are two voices.  If, at any time, one has a space, the other one's stems
+ * can point either way (as with one voice).  Otherwise, the first voice
+ * points up and the second one down.
+ * V_3OPSTEM and V_3FREESTEM are just like the "2" ones, except that a third
+ * voice is allowed to exist.  Its stem direction is determined elsewhere.
+ */
+#define        V_1             (0)
+#define        V_2OPSTEM       (1)
+#define        V_2FREESTEM     (2)
+#define        V_3OPSTEM       (3)
+#define        V_3FREESTEM     (4)
+
+/*
+ * Define the modes of the voicecombine parameter.
+ */
+/* bottom note of high voice must be higher than top note of low voice */
+#define VC_NOOVERLAP   (0)
+/* bottom note of high voice must be no lower than top note of low voice */
+#define VC_SHAREONE    (1)
+/* no restrictions */
+#define VC_OVERLAP     (2)
+
+/*
+ * Define the staff style vis-a-vis printing of clefs, accidentals (in key
+ * signatures and otherwise), and tranposing.  WARNING:  SS_NOTHING must be
+ * defined to be 0 so that calloc inits the field to this.
+ */
+#define        SS_NOTHING      (0)     /* no transpose; print no clef, no accidentals*/
+#define        SS_NORMAL       (1)     /* normal printing */
+#define        SS_DRUM         (2)     /* like SS_NOTHING, but print a "drum clef" */
+
+/*
+ * Define the time signature types.  NUMERIC is the usual two-number
+ * signature.  INVISNUM is the same, except that it will not be printed.
+ * Common and cut time are noted here separately.  But for all other
+ * purposes they are treated as 4/4 and 2/2 respectively.
+ */
+#define        TS_NUMERIC      (0)
+#define        TS_INVISNUM     (1)
+#define        TS_COMMON       (2)
+#define        TS_CUT          (3)
+
+/*
+ * Special bytes used inside time signature representation.
+ * These values need to be outside the range of time signature numerators
+ * and denominators, but small enough to fit in a byte.
+ * Probably safer to keep them under 128 as well, to avoid any possible
+ * issues with negative chars.
+ *
+ * Here's how the encoding works:
+ * cut and common get stored as TSR_CUT and TSR_COMMON respectively.
+ * If a + is used between a denominator of one fraction
+ * and numerator of another, it is encoded as TSR_ADD.
+ * When a + is used inside a numerator, nothing is stored at all,
+ * since it is clear all numbers up to the slash
+ * must be components of the numerator.
+ * White space rather than + after a denominator
+ * means alternating time signatures, marked internally by TSR_ALTERNATING.
+ * Numbers are stored as their binary values.
+ * A TSR_END is placed at the end of everything to mark the end.
+ * A null is used for that, so one could use things like strlen or strcpy
+ * on a representation.
+ */
+#define TSR_CUT                (MAXNUMERATOR + 1)
+#define TSR_COMMON     (MAXNUMERATOR + 2)
+#define TSR_SLASH      (MAXNUMERATOR + 3)
+#define TSR_ADD                (MAXNUMERATOR + 4)
+#define TSR_ALTERNATING        (MAXNUMERATOR + 5)
+#define TSR_END                (0)
+
+/*
+ * This is the maximum length of an internal time signature representation.
+ * Note that the internal form is more compact than the input form,
+ * so even something so ridiculously complicated that it's doubtful any
+ * human could keep it straight, like
+ *   3+1+4/16 + cut + 7+11+41/2  9+2/64 + 5+7+31+29/1 + com
+ * would only take 28 bytes, so 40 should be plenty!
+ * The maximum number of numerator components 40 bytes could accomodate
+ * would be 37, so maximum theoretical effective time signature
+ * would be thirty-seven 99's or 3663 counts.
+ */
+#define MAXTSLEN       40
+
+/*
+ * Define when time signatures should be printed.  "Once" means when it
+ * changes.  "Always" makes sense only when there is an alternating time sig,
+ * and it means print it at each measure.
+ */
+#define PTS_NEVER      (0)     /* user input "n" */
+#define PTS_ONCE       (1)     /* user input nothing */
+#define PTS_ALWAYS     (2)     /* user input "y" */
+
+/*
+ * Define the clefs that are allowed.  The values are important, so that
+ * the program can conveniently figure note positions without having a
+ * separate case for each value.
+ */
+#define        TREBLE_8A       (-7)
+#define        FRENCHVIOLIN    (-2)
+#define        TREBLE          (0)
+#define        SOPRANO         (2)
+#define        MEZZOSOPRANO    (4)
+#define        ALTO            (6)
+#define        TREBLE_8        (7)
+#define        TENOR           (8)
+#define        BARITONE        (10)
+#define        BASS            (12)
+#define        TABCLEF         (-1)    /* tablature "clef" */
+#define NOCLEF         (-99)   /* no clef is present */
+
+/*
+ * Define what a GRPSYL structure can represent.
+ */
+#define        GS_GROUP        (0)
+#define        GS_SYLLABLE     (1)
+
+/*
+ * Define the different contents a group can have.
+ */
+#define        GC_NOTES        (0)
+#define        GC_REST         (1)
+#define        GC_SPACE        (2)
+
+/*
+ * Define the time values a group can have.  Only note groups can be other than
+ * normal (grace notes).  There are no grace rests or spaces.
+ */
+#define        GV_NORMAL       (0)
+#define        GV_ZERO         (1)
+
+/*
+ * Define the unknown value for headshapes.  The other values aren't defined
+ * here because they are established as headshapes are loaded at run time.
+ * There is a built-in set of these that are loaded, and then the user can use
+ * the "headshapes" context to load more.  Each headshape number corresponds to
+ * a headshape name, such as "norm", "xnote", "rect", etc., and stands for the
+ * set of music characters used to print note heads of the various basictimes.
+ */
+#define        HS_UNKNOWN      (0)
+
+/*
+ * Define the size of a group.  Spaces are always normal, but notes and rests
+ * can have different sizes.  For note groups, this can vary on a per-note
+ * basis.
+ */
+#define        GS_NORMAL       (0)
+#define        GS_SMALL        (1)
+
+/*
+ * Define position that you can be in relative to a list of objects.
+ */
+#define        NOITEM          (0)     /* not within a list */
+#define        STARTITEM       (1)     /* first item in a list */
+#define        INITEM          (2)     /* interior item in a list */
+#define        ENDITEM         (3)     /* last item in a list */
+#define        LONEITEM        (4)     /* only item in a list */
+
+
+/*
+ * Define the directions for various items.
+ */
+#define UNKNOWN        (0)
+#define        UP      (1)
+#define        DOWN    (2)
+
+
+/*
+ * Define values for controlling printing of tuplet numbers and brackets.
+ * For PT_DEFAULT, the bracket will be printed unless all the notes of the
+ * tuplet (and no other notes) form a beamed set.
+ */
+#define        PT_NEITHER      (0)     /* never print number or bracket */
+#define        PT_DEFAULT      (1)     /* always print number; maybe print bracket */
+#define        PT_BOTH         (2)     /* always print number and bracket */
+#define        PT_NUMBER       (3)     /* always print just the number */
+
+
+/*
+ * Coordinate types that can have location variables associated with them.
+ */
+#define CT_BUILTIN     (1)
+#define CT_GRPSYL      (2)
+#define CT_BAR         (4)
+#define CT_NOTE                (8)
+#define CT_INVISIBLE   (128)
+
+
+/*
+ * Define the types of STUFF structure.  "Stuff" is things that are to be
+ * printed other than the actual music and lyrics.
+ */
+#define        ST_ROM          (0)
+#define        ST_BOLD         (1)
+#define        ST_ITAL         (2)
+#define        ST_BOLDITAL     (3)
+#define        ST_CRESC        (4)
+#define        ST_DECRESC      (5)
+#define        ST_MUSSYM       (6)
+#define        ST_PEDAL        (7)
+#define        ST_TIESLUR      (8)
+#define        ST_TABSLUR      (9)
+#define        ST_BEND         (10)
+#define        ST_PHRASE       (11)
+#define        ST_OCTAVE       (12)
+#define        ST_MIDI         (13)
+
+#define IS_TEXT(stype) ((stype) == ST_ROM || (stype) == ST_ITAL ||     \
+                       (stype) == ST_BOLD || (stype) == ST_BOLDITAL)
+
+/*
+ * Define the places where the stuff can be printed, relative to staff(s).
+ */
+#define        PL_ABOVE        (0)
+#define        PL_BELOW        (1)
+#define        PL_BETWEEN      (2)
+#define        PL_UNKNOWN      (3)
+#define        NUM_PLACE       (3)     /* number of "good" places (exclude unknown) */
+
+/*
+ * Define the ways a user can specify the horizonal offset of a group from the
+ * chord's X coordinate.
+ */
+#define        HO_NONE         (0)     /* not specified */
+#define        HO_LEFT         (1)     /* "-" (next to other group(s), on the left) */
+#define        HO_RIGHT        (2)     /* "+" (next to other group(s), on the right) */
+#define        HO_VALUE        (3)     /* "+/-N" (offset given by GRPSYL.ho_value) */
+
+/*
+ * Define text modifiers:  different flavors of rom, bold, ital, and
+ * boldital.  TM_DYN also applies automatically to the hairpin stuffs, < and >.
+ */
+#define        TM_NONE         (0)
+#define        TM_CHORD        (1)
+#define        TM_ANALYSIS     (2)
+#define        TM_FIGBASS      (3)
+#define        TM_DYN          (4)
+
+#define IS_CHORDLIKE(x)        ((x) == TM_CHORD || (x) == TM_ANALYSIS ||       \
+                       (x) == TM_FIGBASS)
+
+/*
+ * Define values for dist_usage in STUFF.
+ */
+#define        SD_NONE         (0)     /* user did not specify */
+#define        SD_MIN          (1)     /* user specified minimum distance */
+#define        SD_FORCE        (2)     /* user is forcing this distance */
+
+/*
+ * Define all the types of marks that the user can request to be stacked in
+ * different orders.  This list is in increasing order of the default priority
+ * of stacking, except that by default MK_DYN, MK_OTHERTEXT, and MK_CHORD are
+ * of equal priority.  If this list changes, make sure that Defmarkorder[]
+ * is updated too.  For each place (above, below, between), the user can
+ * specify a different ordering of priority to be used.  There is a restriction
+ * that the last ones (MK_LYRICS, MK_ENDING, MK_REHEARSAL, MK_PEDAL) must
+ * have a different priority from each other and any of the other ones.  Also,
+ * MK_PEDAL is allowed only below; MK_ENDING and MK_REHEARSAL are allowed only
+ * above; and those three and MK_OCTAVE are not allowed between.
+ */
+#define        MK_MUSSYM       (0)     /* ST_MUSSYM */
+#define        MK_OCTAVE       (1)     /* ST_OCTAVE */
+#define        MK_DYN          (2)     /* ST_CRESC or ST_DECRESC; or ST_ROM, */
+                               /* ST_ITAL, ST_BOLD, ST_BOLDITAL with "dyn" */
+                               /* (TM_DYN is set for these and only these) */
+#define        MK_OTHERTEXT    (3)     /* ST_ROM, ST_ITAL, ST_BOLD, ST_BOLDITAL */
+                               /* without chord/analysis/figbass or dyn */
+#define        MK_CHORD        (4)     /* ST_ROM, ST_ITAL, ST_BOLD, ST_BOLDITAL */
+                               /* with chord, analysis, or figbass */
+                               /* (TM_CHORD is set for these and only these) */
+#define        MK_LYRICS       (5)     /* lyrics */
+#define        MK_ENDING       (6)     /* ending mark */
+#define        MK_REHEARSAL    (7)     /* rehearsal mark */
+#define        MK_PEDAL        (8)     /* ST_PEDAL */
+#define NUM_MARK       (9)     /* this must follow the last MK */
+
+/*
+ * While parsing, we need to temporarily store some things as pseudo-pitches.
+ * When the user does not specify any pitch for the first group of a measure,
+ * we temporarily use PP_NO_PITCH, since not specifying a pitch is legal iff it
+ * is for one or more 1-line staffs, but it's not easy to check on that until
+ * later.  We also need to save rest, space, and rpt as pseudo notes until we
+ * later map them to groups.
+ */
+#define PP_NO_PITCH    'h'
+#define PP_REST                'r'
+#define PP_SPACE       's'
+#define PP_RPT         'p'
+
+/*
+ * Define the other staff that a given staff's groups are beamed or stemmed to.
+ */
+#define CS_SAME                (0)
+#define CS_ABOVE       (1)
+#define CS_BELOW       (2)
+
+/*
+ * Define symbols for indexing coordinate arrays.  The first 12 are X, Y,
+ * north, south, east, and west, both relative and absolute.  Not all things
+ * that have coordinates bother to set all 12 of these.  There should be
+ * comments in structs.h saying which things get set for what.
+ *
+ * In GRPSYL, during the time that positions of phrase marks are being
+ * figured out, AN and AS are used in a strange way.  But later, they get
+ * set to their intended values.
+ *
+ * The 13th is a special number used by nongrace notes and GRPSYLs, and BARs
+ * only.  For notes and GRPSYLs, it has the following meaning.  It indicates
+ * how many inches of horizontal space would be allocated to this object
+ * if it were a whole note instead of whatever it actually is, but were
+ * allocated space proportionally.  That is, fulltime times this number
+ * is the amount of space between the X coordinates of this GRPSYL and
+ * the next one in the measure (or the bar line if this is the last GRPSYL
+ * in the measure).  Notice that even for notes, it's the X coordinate of
+ * the note's GRPSYL that count, even if the note head is on the "wrong"
+ * side of the stem.  For BARs, this 13th number has a similiar use.  If
+ * you pretend that a bar line is count 0 of the following measure, and
+ * the first GRPSYL of the measure is at count 1 (whichever type of note
+ * constitutes a "count"), this number is how many inches would be allocated
+ * to a whole note instead of the one count of space that is there.
+ */
+#define        RX      (0)
+#define        RY      (1)
+#define        RN      (2)
+#define        RS      (3)
+#define        RE      (4)
+#define        RW      (5)
+#define        AX      (6)
+#define        AY      (7)
+#define        AN      (8)
+#define        AS      (9)
+#define        AE      (10)
+#define        AW      (11)
+#define        INCHPERWHOLE    (12)
+#define NUMCTYPE       (13)
+
+
+/*
+ * AN and AS of group coordinates are used temporarily to store the distance
+ * from the group to any phrase marks, to be used to make sure nesting phrases
+ * don't impinge on that space. But if a group has a phrase ending on it and
+ * another beginning on it, those won't collide.  So use bitmap to keep track
+ * of whether the AN and AS values apply to east side, west side, or both.
+ * (phraseside in GRPSYL is a bit map.)
+ */
+#define EAST_SIDE      (1 << 0)
+#define WEST_SIDE      (1 << 1)
+
+
+/*
+ * Define the types of bar line.
+ */
+#define        INVISBAR        (0)
+#define        SINGLEBAR       (1)
+#define        DOUBLEBAR       (2)
+#define        REPEATSTART     (3)
+#define        REPEATEND       (4)
+#define        REPEATBOTH      (5)
+#define        ENDBAR          (6)
+#define        RESTART         (7)
+
+/*
+ * Define the types of font, leaving 0 unused to avoid ending up having
+ * null characters appear in strings where this number is stored,
+ * and to have something convenient to use to flag an unknown font.
+ * WARNING:  the getfontinfo.c program depends on all the font names
+ * beginning with "FONT_", and on MAXFONTS being at the end of the list.
+ */
+#define FONT_UNKNOWN   (0)
+#define FAMILY_DFLT    (-1)
+
+#define BASE_TIMES     (0)
+#define        FONT_TR         (1)
+#define        FONT_TI         (2)
+#define        FONT_TB         (3)
+#define        FONT_TX         (4)
+
+#define BASE_AVANTGARDE        (FONT_TX)
+#define FONT_AR                (BASE_AVANTGARDE + FONT_TR)
+#define FONT_AI                (BASE_AVANTGARDE + FONT_TI)
+#define FONT_AB                (BASE_AVANTGARDE + FONT_TB)
+#define FONT_AX                (BASE_AVANTGARDE + FONT_TX)
+
+#define BASE_COURIER   (FONT_AX)
+#define FONT_CR                (BASE_COURIER + FONT_TR)
+#define FONT_CI                (BASE_COURIER + FONT_TI)
+#define FONT_CB                (BASE_COURIER + FONT_TB)
+#define FONT_CX                (BASE_COURIER + FONT_TX)
+
+#define BASE_HELVETICA (FONT_CX)
+#define FONT_HR                (BASE_HELVETICA + FONT_TR)
+#define FONT_HI                (BASE_HELVETICA + FONT_TI)
+#define FONT_HB                (BASE_HELVETICA + FONT_TB)
+#define FONT_HX                (BASE_HELVETICA + FONT_TX)
+
+#define BASE_BOOKMAN   (FONT_HX)
+#define FONT_BR                (BASE_BOOKMAN + FONT_TR)
+#define FONT_BI                (BASE_BOOKMAN + FONT_TI)
+#define FONT_BB                (BASE_BOOKMAN + FONT_TB)
+#define FONT_BX                (BASE_BOOKMAN + FONT_TX)
+
+#define BASE_NEWCENTURY        (FONT_BX)
+#define FONT_NR                (BASE_NEWCENTURY + FONT_TR)
+#define FONT_NI                (BASE_NEWCENTURY + FONT_TI)
+#define FONT_NB                (BASE_NEWCENTURY + FONT_TB)
+#define FONT_NX                (BASE_NEWCENTURY + FONT_TX)
+
+#define BASE_PALATINO  (FONT_NX)
+#define FONT_PR                (BASE_PALATINO + FONT_TR)
+#define FONT_PI                (BASE_PALATINO + FONT_TI)
+#define FONT_PB                (BASE_PALATINO + FONT_TB)
+#define FONT_PX                (BASE_PALATINO + FONT_TX)
+
+#ifdef EXTCHAR
+/* extra fonts that contain the extended character set start here.
+ * They go in the same order as their corresponding standard ASCII fonts */
+#define EXT_FONT_OFFSET        (FONT_PX - BASE_TIMES)
+
+#define FONT_XTR       (FONT_TR + EXT_FONT_OFFSET)
+#define        FONT_XTI        (FONT_TI + EXT_FONT_OFFSET)
+#define        FONT_XTB        (FONT_TB + EXT_FONT_OFFSET)
+#define        FONT_XTX        (FONT_TX + EXT_FONT_OFFSET)
+
+#define FONT_XAR       (FONT_AR + EXT_FONT_OFFSET)
+#define FONT_XAI       (FONT_AI + EXT_FONT_OFFSET)
+#define FONT_XAB       (FONT_AB + EXT_FONT_OFFSET)
+#define FONT_XAX       (FONT_AX + EXT_FONT_OFFSET)
+
+#define FONT_XCR       (FONT_CR + EXT_FONT_OFFSET)
+#define FONT_XCI       (FONT_CI + EXT_FONT_OFFSET)
+#define FONT_XCB       (FONT_CB + EXT_FONT_OFFSET)
+#define FONT_XCX       (FONT_CX + EXT_FONT_OFFSET)
+
+#define FONT_XHR       (FONT_HR + EXT_FONT_OFFSET)
+#define FONT_XHI       (FONT_HI + EXT_FONT_OFFSET)
+#define FONT_XHB       (FONT_HB + EXT_FONT_OFFSET)
+#define FONT_XHX       (FONT_HX + EXT_FONT_OFFSET)
+
+#define FONT_XBR       (FONT_BR + EXT_FONT_OFFSET)
+#define FONT_XBI       (FONT_BI + EXT_FONT_OFFSET)
+#define FONT_XBB       (FONT_BB + EXT_FONT_OFFSET)
+#define FONT_XBX       (FONT_BX + EXT_FONT_OFFSET)
+
+#define FONT_XNR       (FONT_NR + EXT_FONT_OFFSET)
+#define FONT_XNI       (FONT_NI + EXT_FONT_OFFSET)
+#define FONT_XNB       (FONT_NB + EXT_FONT_OFFSET)
+#define FONT_XNX       (FONT_NX + EXT_FONT_OFFSET)
+
+#define FONT_XPR       (FONT_PR + EXT_FONT_OFFSET)
+#define FONT_XPI       (FONT_PI + EXT_FONT_OFFSET)
+#define FONT_XPB       (FONT_PB + EXT_FONT_OFFSET)
+#define FONT_XPX       (FONT_PX + EXT_FONT_OFFSET)
+
+#define BASE_MISC      (FONT_XPX)
+#else
+#define BASE_MISC      (FONT_PX)
+#endif
+#define FONT_ZD                (BASE_MISC + 1)
+#define FONT_ZI                (BASE_MISC + 2)
+#define        FONT_MUSIC      (BASE_MISC + 3)
+#define        FONT_MUSIC2     (BASE_MISC + 4)
+#define MAXFONTS       (BASE_MISC + 5)
+
+/* number of music fonts */
+#define NUM_MFONTS     (2)
+
+/* first printable character in a font */
+#define        FIRST_CHAR      (32)
+
+/*
+ * The following value plus FIRST_CHAR needs to be at least as large as
+ * one more than the largest value in either muschar.h or extchar.h
+ */
+#define CHARS_IN_FONT  (96)
+
+/*
+ * Find array offset into height, width, and ascent tables.  This is character
+ * code -FIRST_CHAR, to skip ASCII control characters.
+ */
+#define CHAR_INDEX(c)  ((c) - FIRST_CHAR)
+
+/*
+ * Test if a font is a "music" font.
+ */
+#define IS_MUSIC_FONT(f)       ((f) == FONT_MUSIC || (f) == FONT_MUSIC2)
+
+/*
+ * Special commands to use inside internal format of strings.
+ * All use high-bit==1 to indicate a command.
+ * Note that the low order bits of STR_MUS_CHAR* specify which music font it is.
+ */
+#define STR_MUS_CHAR           0x80    /* followed by 1-byte size and 1-byte \
+                                        * music character code */
+#define STR_MUS_CHAR2          0x81    /* same rules as above */
+#define STR_FONT               0xe0    /* followed by 1-byte font number */
+#define STR_SIZE               0xe1    /* followed by 1-byte size */
+#define STR_PAGENUM            0xe2    /* followed by '%' */
+#define STR_NUMPAGES           0xe3    /* followed by '#' */
+#define STR_PRE                        0xe4    /* pre-syl <--->, ignored in spacing */
+#define STR_U_PRE              0xe5    /* pre-syl <...>, used in spacing */
+#define STR_PRE_END            0xe6    /* end of pre-syllable <...> */
+#define STR_PST                        0xe7    /* post-syl <...>, ignored in spacing */
+#define STR_U_PST              0xe8    /* post-syl <...>, used in spacing */
+#define STR_PST_END            0xe9    /* end of post-syllable <...> */
+/*
+ * Backspace is a bit strange.  The amount to back up varies because of
+ * proportionally spaced fonts.  So we save the distance in terms of the width
+ * in 250ths of an inch in the default size.  The actual distance to back up is
+ * then that number times the ratio of the current actual size to the default
+ * size divided by 250.  250 was chosen because that means a range of 1-127
+ * (to make sure it is non-zero and with high-bit of zero)
+ * will give a range of .004 to 0.508 inches, which should cover all
+ * characters we have today (the widest of which is currently just over 1/4").
+ * This is done in floating point, so no reason to use a power of 2 like 256.
+ */
+#define STR_BACKSPACE          0xea    /* followed by how much to back up */
+
+#define BACKSP_FACTOR          (250.0)
+
+/* string commands for boxed text */
+#define STR_BOX                        0xeb
+#define STR_BOX_END            0xec
+#define IS_BOXED(string)   (((string[2] & 0xff) == (STR_BOX & 0xff)) ? YES : NO)
+
+#define        STR_VERTICAL            0xed    /* vert move followed by 1-byte dist */
+#define        STR_L_ALIGN             0xee    /* align at left edge of next char */
+#define        STR_C_ALIGN             0xef    /* align at center of next char */
+#define STR_PILE               0xf0    /* toggle for piling, \: */
+#define STR_SLASH              0xf1    /* slash used by figbass, \/ */
+
+/* string commands for circled text */
+#define STR_CIR                        0xf2
+#define STR_CIR_END            0xf3
+#define IS_CIRCLED(string) (((string[2] & 0xff) == (STR_CIR & 0xff)) ? YES : NO)
+
+/*
+ * Define macros relating to vertical movement within a string.  It is stored
+ * in points, offset by a bias so that the number will always be positive when
+ * stored in the byte after the STR_VERTICAL in a string.
+ */
+#define        MINVERTICAL     (-50)
+#define        MAXVERTICAL     (50)
+#define        VERT_BIAS       (1 - MINVERTICAL)
+#define        ENCODE_VERT(x)  (x + VERT_BIAS)
+#define        DECODE_VERT(x)  (x - VERT_BIAS)
+
+/*
+ * Macro to determine if a character in an internal-format string is a
+ * command character.
+ */
+#define IS_STR_COMMAND(c)      ((c) & 0x80)
+
+
+#define DFLT_SIZE      (12)
+#define SMALLSIZE      ((int)(DFLT_SIZE * SM_FACTOR))
+
+/*
+ * Define the default font size of a measure number.
+ */
+#define MNUM_SIZE      (11)
+
+/*
+ * Define types of lines and curves.
+ */
+#define        L_NORMAL        (0)
+#define        L_MEDIUM        (1)
+#define        L_WIDE          (2)
+#define        L_WAVY          (3)
+#define        L_DOTTED        (4)
+#define        L_DASHED        (5)
+
+/*
+ * Define the kinds of justification.
+ */
+#define        J_LEFT          (1)
+#define        J_RIGHT         (2)
+#define        J_CENTER        (3)
+#define        J_NONE          (4)
+#define        J_RAGPARA       (5)     /* ragged-right paragraph */
+#define        J_JUSTPARA      (6)     /* justified paragraph */
+
+/*
+ * Define the ending styles (which staffs 1st, 2nd, etc. endings are to
+ * be drawn on).
+ */
+#define ENDING_TOP     (0)     /* only above top visible staff */
+#define ENDING_BARRED  (1)     /* above each group of staffs barred together*/
+#define ENDING_GROUPED (2)     /* above each group of staffs grouped */
+                               /*  together by braces or brackets */
+
+/*
+ * Define types of rehearsal letters/numbers.
+ */
+#define REH_NONE       (0)     /* none at all */
+#define REH_STRING     (1)     /* user-supplied string */
+#define REH_NUM                (2)     /* consecutive numbers 1, 2, 3, . . . */
+#define REH_LET                (3)     /* consecutive letters A, B, C, . . . */
+#define REH_MNUM       (4)     /* use current measure number */
+
+/*
+ * Define the style of (ways of drawing) rehearsal letters/numbers.
+ */
+#define        RS_PLAIN        (0)     /* just the letter/number */
+#define        RS_BOXED        (1)     /* enclosed in a box */
+#define        RS_CIRCLED      (2)     /* enclosed in a circle */
+
+/*
+ * Define the ways to print pedal markings.
+ */
+#define P_LINE         (0)     /* draw a line under where the pedal is down */
+#define P_PEDSTAR      (1)     /* print "Ped." and the start and "*" at end */
+#define P_ALTPEDSTAR   (2)     /* like P_PEDSTAR but only "Ped." when bounce*/
+
+/*
+ * Define the side of a stem that a partial beam can be on.  There is code in
+ * prntdata.c that depends on these values, -1 and 1.
+ */
+#define PB_LEFT                (-1)
+#define PB_RIGHT       (1)
+
+/*
+ * Define types of intervals.  There is code that depends on these being in
+ * this order, starting from 0, counting up (like in trnspose.c).
+ */
+#define        DIMINISHED      (0)
+#define        MINOR           (1)
+#define        PERFECT         (2)
+#define        MAJOR           (3)
+#define        AUGMENTED       (4)
+
+/*
+ * Define the input style.
+ */
+#define IS_VOICE_INPUT  (0)     /* voice-at-a-time (must be zero) */
+#define IS_CHORD_INPUT  (1)    /* chord-at-a-time */
+
+/*
+ * Define the valid page sizes. The values must match the indexes of
+ * pagesztbl in gram.y.
+ */
+#define PS_LETTER      (0)
+#define PS_LEGAL       (1)
+#define PS_FLSA                (2)
+#define PS_HALFLETTER  (3)
+#define PS_A4          (4)
+#define PS_A5          (5)
+#define PS_A6          (6)
+
+/* Define page orientations */
+#define O_PORTRAIT     (0)
+#define O_LANDSCAPE    (1)
+
+/*
+ * Define various constants =============================================
+ */
+
+/* the number of PostScript points in one inch */
+#define PPI            (72.0)
+
+/* the size of a point in inches */
+#define POINT          (1.0 / PPI)
+
+/* the distance between a note and the next higher note */
+#define STEPSIZE       (3.0 * POINT)
+
+/* size of white space for surrounding things that should be padded thus */
+#define        STDPAD          (STEPSIZE / 3.0)
+
+/* (distance between tab staff lines) / (distance between normal staff lines)*/
+#define TABRATIO       (1.735)
+
+/* scaling factor giving size of "sm" (small) music chars relative to normal */
+#define SM_FACTOR      (0.65)
+
+/* scaling factor giving size of a grace fret number relative to normal */
+#define SMFRETSIZE     ((int)(0.80 * DFLT_SIZE))
+
+/* font character size information is stored in FONTFACTORs of an inch */
+#define FONTFACTOR     (1000.0)
+
+/* widths of various types of lines, in points */
+#define        W_NORMAL        (0.7)
+#define        W_MEDIUM        (1.5)
+#define        W_WIDE          (3.0)
+
+/* vertical distance between two flags or two beams */
+#define        FLAGSEP         (1.6 * STEPSIZE)        /* for normal notes */
+#define        SMFLAGSEP       (FLAGSEP * SM_FACTOR)   /* for cue or grace notes */
+
+/* minimum width to be given to a multirest */
+#define MINMULTIWIDTH  (0.7)
+
+/* temporary width for a measure rest, serves as a marker */
+#define        TEMPMRPTWIDTH   (0.02)
+
+/* half the width of a restart bar */
+#define HALF_RESTART_WIDTH     (12 * POINT)
+
+/* padding provided to force more room between groups for various reasons */
+#define        TIESLURPAD      (0.12)  /* ties and slurs */
+#define        SLASHPAD        (0.06)  /* slashes through stems */
+#define        ALTPAD          (0.12)  /* alternation beams between groups */
+#define ROLLPADDING    (12 * STDPAD)   /* a roll to the left of a group */
+
+/* padding to be put after a clef */
+#define CLEFPAD                (2.0 * STDPAD)
+
+/* how high certain things are */
+#define TUPHEIGHT      (10.0/3.0 * STEPSIZE)   /* tuplet bracket */
+#define OCTHEIGHT      (10.0/3.0 * STEPSIZE)   /* octave bracket */
+#define ENDINGHEIGHT   (13.0/3.0 * STEPSIZE)   /* ending bracket */
+#define MULTIHEIGHT    (12.0/3.0 * STEPSIZE)   /* multirest number */
+#define MINWITHHEIGHT  (2.2 * STEPSIZE)        /* minimum "with" list item */
+
+/* horizontal extent of a slash, in stepsizes */
+#define SLASHHORZ      (5.0 / 3.0)
+
+/*
+ * The maximum number of notes there could ever be in a "hand" (the notes of a
+ * chord that occur on a given staff) is the number of unique notes that can
+ * exist, C0 through B9.
+ */
+#define MAXHAND                ((MAXOCTAVE - MINOCTAVE + 1) * 7)
+
+/* the length in the X direction of a tabslur to or from nowhere */
+#define        SLIDEXLEN       (3.0 * STEPSIZE)
+
+/* define the default distance, in stepsizes, between the lines of a grid */
+#define        WHEREUSED_GS    (1.6)   /* when printed by the music */
+#define        ATEND_GS        (2.0)   /* when printed at the end of the song */
+
+#define        NO              (0)
+#define        YES             (1)
+
+/* the "used" field in input SSVs uses the following in addition to YES/NO */
+#define        UNSET           (2)
+
+#ifndef PI
+#define PI     (3.141592653589793)
+#endif
+
+#define        CMPERINCH       (2.54)          /* centimeters per inch */
+
+/*
+ * Define miscellaneous macros =============================================
+ */
+
+/* number of elements in an array */
+#define NUMELEM(a)     (sizeof(a) / sizeof((a)[0]))
+
+/*
+ * Define macros for allocating structures.
+ */
+#define        MALLOC(structtype, new_p, numelem) {                            \
+       if ((new_p = (struct structtype *)malloc((unsigned)             \
+                       (((numelem) == 0 ? 1 : (numelem)) *             \
+                       sizeof(struct structtype)))) == 0)              \
+               l_no_mem(__FILE__, __LINE__);                           \
+}
+#define        CALLOC(structtype, new_p, numelem) {                            \
+       if ((new_p = (struct structtype *)calloc(                       \
+                       (numelem) == 0 ? 1 : (numelem),                 \
+                       (unsigned)sizeof(struct structtype)))  == 0)    \
+               l_no_mem(__FILE__, __LINE__);                           \
+}
+#ifndef __STDC__
+#define        REALLOC(structtype, new_p, numelem) {                           \
+       if ((new_p = (struct structtype *)realloc((char *)(new_p),      \
+                       (unsigned)(((numelem) == 0 ? 1 : (numelem)) *   \
+                       sizeof(struct structtype)))) == 0)              \
+               l_no_mem(__FILE__, __LINE__);                           \
+}
+#else
+#define        REALLOC(structtype, new_p, numelem) {                           \
+       if ((new_p = (struct structtype *)realloc((void *)(new_p),      \
+                       (unsigned)(((numelem) == 0 ? 1 : (numelem)) *   \
+                       sizeof(struct structtype)))) == 0)              \
+               l_no_mem(__FILE__, __LINE__);                           \
+}
+#endif
+
+/*
+ * Define macros for allocating other arrays.
+ */
+#define        MALLOCA(type, new_p, numelem) {                                 \
+       if ((new_p = (type *)malloc((unsigned)                          \
+                       (((numelem) == 0 ? 1 : (numelem)) *             \
+                       sizeof(type)))) == 0)                           \
+               l_no_mem(__FILE__, __LINE__);                           \
+}
+#define        CALLOCA(type, new_p, numelem) {                                 \
+       if ((new_p = (type *)calloc((numelem) == 0 ? 1 : (numelem),     \
+                       (unsigned)sizeof(type)))  == 0)                 \
+               l_no_mem(__FILE__, __LINE__);                           \
+}
+#ifndef __STDC__
+#define        REALLOCA(type, new_p, numelem) {                                \
+       if ((new_p = (type *)realloc((char *)(new_p),                   \
+                       (unsigned)(((numelem) == 0 ? 1 : (numelem)) *   \
+                       sizeof(type)))) == 0)                           \
+               l_no_mem(__FILE__, __LINE__);                           \
+}
+#else
+#define        REALLOCA(type, new_p, numelem) {                                \
+       if ((new_p = (type *)realloc((void *)(new_p),                   \
+                       (unsigned)(((numelem) == 0 ? 1 : (numelem)) *   \
+                       sizeof(type)))) == 0)                           \
+               l_no_mem(__FILE__, __LINE__);                           \
+}
+#endif
+
+/* define macro for freeing memory */
+#ifdef __STDC__
+#define        FREE(mem_p)     free((void *)mem_p)
+#else
+#define        FREE(mem_p)     free((char *)mem_p)
+#endif
+
+/* convert a RATIONAL to a float */
+#define RAT2FLOAT(rat) ( (float)(rat).n / (float)(rat).d )
+
+/* the usual minimum and maximum macros */
+#define MAX(a, b)      ( (a) > (b) ? (a) : (b) )
+#define MIN(a, b)      ( (a) < (b) ? (a) : (b) )
+
+/* absolute value of the difference of a and b */
+#define ABSDIFF(a, b)  ( (a) > (b) ? (a) - (b) : (b) - (a) )
+
+/* even and odd numbers (positive, zero, or negative; works on any compiler) */
+#define        EVEN(a)         (abs(a) % 2 == 0)
+#define        ODD(a)          (abs(a) % 2 == 1)
+
+#define SQUARED(x)     ((x) * (x))
+#define NEARESTQUARTER(x) ( (int)((x) * 4.0 + 0.5) / 4.0 )
+
+/* half the height of a staff in stepsizes; use 1 for 1-line staffs */
+#define HALFSTAFF(s)   ((svpath(s, STAFFLINES)->stafflines == 5) ? 4 : 1)
+
+/* given ptr to a group, return the NOTE struct for note nearest to the beam */
+#define BNOTE(gs_p)    \
+       (gs_p)->notelist[ (gs_p)->stemdir == UP ? 0 : (gs_p)->nnotes - 1 ]
+
+/*
+ * Define indices into GRPSYL.notelist for the first (FNNI) and last (LNNI)
+ * non-cross-staff-stemmed notes.  Also define indices for the first (FCNI)
+ * and last (LCNI) cross-staff-stemmed notes.
+ *
+ * For FNNI and LNNI to work, there must be non-CSS notes, although even if
+ * not, it's still okay to have loops like 
+ *     for (n = FNNI(gs_p); n <= LNNI(gs_p); n++)
+ * and the NNN macro, which uses them, always works.
+ *
+ * LCNI and FCNI only work if there are CSS notes.
+ */
+#define        FNNI(gs_p)      ((gs_p)->stemto == CS_ABOVE ?   \
+                       (gs_p)->stemto_idx + 1 : 0)
+#define        LNNI(gs_p)      ((gs_p)->stemto == CS_BELOW ?   \
+                       (gs_p)->stemto_idx - 1 : (gs_p)->nnotes - 1)
+#define        FCNI(gs_p)      ((gs_p)->stemto == CS_ABOVE ?   \
+                       0 : (gs_p)->stemto_idx)
+#define        LCNI(gs_p)      ((gs_p)->stemto == CS_BELOW ?   \
+                       (gs_p)->nnotes - 1 : (gs_p)->stemto_idx)
+
+/* define the Number of Normal Notes (non-CSS notes) in a group */
+#define NNN(gs_p)      (LNNI(gs_p) - FNNI(gs_p) + 1)
+
+/* test whether the note given via the index is CSS */
+#define IS_CSS_NOTE(gs_p, idx) (                                       \
+       (((gs_p)->stemto == CS_ABOVE && idx <= (gs_p)->stemto_idx) ||   \
+        ((gs_p)->stemto == CS_BELOW && idx >= (gs_p)->stemto_idx))     \
+)
+
+/* test whether any CSS notes that exist would be on stem side of the group */
+#define STEMSIDE_CSS(gs_p)                                     \
+       ((gs_p)->stemto == CS_ABOVE && (gs_p)->stemdir == UP || \
+        (gs_p)->stemto == CS_BELOW && (gs_p)->stemdir == DOWN)
+
+/*
+ * Define CSS_STEPS to be an offset to be applied to "stepsup" when the note is
+ * on the other staff.  It needs to be at twice as big as the interval between
+ * the highest and lowest notes so that stepsup plus or minus half of it  will
+ * become a value that it could never be for a normal note (see doacc()), and
+ * it has to be an even number, because, for example, that matters for vertical
+ * dot placement.
+ */
+#define CSS_STEPS      (MAXHAND * 2)
+
+/* is this FEED followed by a CLEFSIG (music), not a block? */
+#define IS_CLEFSIG_FEED(mll_p) ((mll_p)->str == S_FEED && \
+               (mll_p)->next != 0 && (mll_p)->next->str == S_CLEFSIG)
+
+/*
+ * This macro is to be used as in this example:
+ *     extern int func P((int parm1, float parm2));
+ * The ANSI version will result in a function prototype.  The other version
+ * will result in a function declaration (no parameters).
+ */
+#ifdef __STDC__
+#define        P(parms)        parms
+#else
+#define        P(parms)        ()
+#endif
+
+#endif
diff --git a/mup/mup/errors.c b/mup/mup/errors.c
new file mode 100644 (file)
index 0000000..d00f8b9
--- /dev/null
@@ -0,0 +1,604 @@
+
+/* Copyright (c) 1995, 1997, 1999, 2000, 2001, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* various functions for printing error messages and exiting when
+ * things go wrong */
+
+#include "globals.h"
+#include "rational.h"
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef Mac_BBEdit
+#include <BBEdit_Streams.h>
+#endif
+
+extern void exit P((int status));
+
+       int debug_on P((int level));
+
+#ifdef __STDC__
+       extern void abort P((void));
+#else
+       extern int abort();
+#endif
+
+static void error_header P((char *filename, int lineno, char * errtype));
+
+/* Print a message for a user error, and exit with the value of Errorcount,
+ * or of MAX_ERRORS if > MAX_ERRORS */
+
+/*VARARGS1*/
+#ifdef __STDC__
+
+void
+ufatal(char *format, ...)
+
+#else
+
+void
+ufatal(format, va_alist)
+
+char *format;  /* printf style format */
+va_dcl
+
+#endif
+
+{
+       va_list args;
+
+       /* we now have one more error */
+       Errorcount++;
+
+       /* print the specified message with a newline */
+#ifdef __STDC__
+       va_start(args, format);
+#else
+       va_start(args);
+#endif
+
+#ifndef UNIX_LIKE_FILES
+       mac_cleanup();
+#endif
+
+       (void) fprintf(stderr, "\nfatal user error: ");
+       (void) vfprintf(stderr, format, args);
+       va_end(args);
+       (void) fprintf(stderr, "\n");
+
+       error_exit();
+}
+
+/* Print a message with filename and linenumber for a user error,
+ * and exit with the value of Errorcount, or of MAX_ERRORS if > MAX_ERRORS */
+
+/*VARARGS3*/
+#ifdef __STDC__
+
+void
+l_ufatal(char *filename, int lineno, char *format, ...)
+
+#else
+
+void
+l_ufatal(filename, lineno, format, va_alist)
+
+char *filename;
+int lineno;
+char *format;  /* printf style format */
+va_dcl
+
+#endif
+
+{
+       va_list args;
+
+       /* we now have one more error */
+       Errorcount++;
+
+       /* print the specified message with a newline */
+#ifdef __STDC__
+       va_start(args, format);
+#else
+       va_start(args);
+#endif
+
+#ifndef UNIX_LIKE_FILES
+       mac_cleanup();
+#endif
+
+       error_header(filename, lineno, "fatal user error");
+
+       (void) vfprintf(stderr, format, args);
+       va_end(args);
+       (void) fprintf(stderr, "\n");
+
+#ifdef Mac_BBEdit
+       AppendError(filename, lineno);
+#endif
+
+       error_exit();
+}
+\f
+
+/* Print a message for a program internal error and exit with MAX_ERRORS */
+
+
+/*VARARGS1*/
+
+#ifdef __STDC__
+
+void
+pfatal(char *format, ...)
+
+#else
+
+void
+pfatal(format, va_alist)
+
+char *format;
+va_dcl
+
+#endif
+
+{
+       va_list args;
+
+#ifdef __STDC__
+       va_start(args, format);
+#else
+       va_start(args);
+#endif
+
+#ifndef UNIX_LIKE_FILES
+       mac_cleanup();
+#endif
+
+       /* print specified message with newline */
+       (void) fprintf(stderr, "\nfatal internal error: ");
+       (void) vfprintf(stderr, format, args);
+       va_end(args);
+       (void) fprintf(stderr, "\n");
+
+#ifdef CORE_MESSAGE
+       (void) fprintf(stderr, "creating a core dump\n");
+#endif
+       abort();
+
+       Errorcount = MAX_ERRORS;
+       error_exit();
+}
+\f
+
+/* fatal error with line number and file name. Note that this should be the
+ * line number and file in the program, not the input file, ie, __LINE__
+ * and __FILE__. */
+
+/*VARARGS3*/
+
+#ifdef __STDC__
+
+void
+l_pfatal(char *filename, int lineno, char *format, ...)
+
+#else
+
+void
+l_pfatal(filename, lineno, format, va_alist)
+
+char *filename;                /* name of program file */
+int lineno;            /* pgm line where error was discovered */
+char *format;          /* printf format */
+va_dcl
+
+#endif
+
+{
+       va_list args;
+
+#ifdef __STDC__
+       va_start(args, format);
+#else
+       va_start(args);
+#endif
+
+       error_header(filename, lineno, "fatal internal error");
+       pfatal(format, args);
+       va_end(args);
+}
+\f
+
+/* error exit for the common problem of malloc failures */
+
+void
+l_no_mem(filename, lineno)
+
+char *filename;
+int lineno;
+
+{
+       l_pfatal(filename, lineno, "memory allocation failed");
+}
+\f
+
+/* error exit for common error of not being able to open a specified file */
+
+void
+cant_open(filename)
+
+char *filename;
+
+{
+       ufatal("can't open '%s'", filename);
+}
+\f
+
+/* Exit with exit code being the number of errors, unless there were
+ * too many of them to fit in an exit code, in which case MAX_ERRORS
+ * is used. MAX_ERRORS is used for internal errors. */
+
+void
+error_exit()
+
+{
+       exit(Errorcount > MAX_ERRORS ? MAX_ERRORS : Errorcount);
+}
+\f
+
+/* print a warning message */
+
+/*VARARGS1*/
+
+#ifdef __STDC__
+
+void
+warning(char *format, ...)
+
+#else
+
+void
+warning(format, va_alist)
+
+char *format;
+va_dcl
+
+#endif
+
+{
+       va_list args;
+
+       if (Score.warn == NO) {
+               return;
+       }
+#ifdef __STDC__
+       va_start(args, format);
+#else
+       va_start(args);
+#endif
+
+       (void) fprintf(stderr, "warning: ");
+       (void) vfprintf(stderr, format, args);
+       (void) fprintf(stderr, "\n");
+       va_end(args);
+
+#ifdef Mac_BBEdit
+       AppendWarning((char *) 0, -1);
+#endif
+}
+
+
+/* warning message with file name and line number */
+
+/*VARARGS3*/
+
+#ifdef __STDC__
+
+void
+l_warning(char * filename, int lineno, char *format, ...)
+
+#else
+
+void
+l_warning(filename, lineno, format, va_alist)
+
+char *filename;        /* name of program file */
+int lineno;            /* pgm line where error was discovered */
+char *format;          /* printf format */
+va_dcl
+
+#endif
+
+{
+       va_list args;
+
+       if (Score.warn == NO) {
+               return;
+       }
+#ifdef __STDC__
+       va_start(args, format);
+#else
+       va_start(args);
+#endif
+
+       error_header(filename, lineno, "warning");
+       (void) vfprintf(stderr, format, args);
+       (void) fprintf(stderr, "\n");
+       va_end(args);
+
+#ifdef Mac_BBEdit
+       AppendWarning(filename, lineno);
+#endif
+}
+\f
+
+/* varargs version of yyerror, passing a file and linenumber (or -1 for the
+ * lineno if you don't want a filename and linenumber printed) */
+
+/*VARARGS3*/
+
+#ifdef __STDC__
+
+void
+l_yyerror(char *fname, int lineno, char *format, ...)
+
+#else
+
+void
+l_yyerror(fname, lineno, format, va_alist)
+
+char *fname;
+int lineno;
+char *format;
+va_dcl
+
+#endif
+
+{
+       va_list args;
+
+
+       /* if linenumber is zero or negative, assume this is special case of
+        * not being associated with a specific line, so don't print
+        * a line number */
+       if (lineno > 0) {
+               /* There are cases where the parser has already looked ahead
+                * to find the newline in order to fully match a grammar
+                * rule. When that happens, the line number will already have
+                * been incremented and our message would be off by one.
+                * So catch that case and compensate. */
+               if ( (lineno == yylineno) && (fname == Curr_filename) &&
+                                               Last_was_newline == YES) {
+                       lineno--;
+               }
+               error_header(fname, lineno, "error");
+       }
+
+#ifdef __STDC__
+       va_start(args, format);
+#else
+       va_start(args);
+#endif
+
+       (void) vfprintf(stderr, format, args);
+       va_end(args);
+       (void) fprintf(stderr, "\n");
+
+       /* if doing macro expansion, also tell where macro was defined */
+       mac_error();
+
+#ifdef Mac_BBEdit
+       AppendError(fname, lineno);
+#endif
+
+       Errorcount++;
+}
+\f
+
+
+
+/* print a debugging message if corresponding debugging bit is on */
+
+/*VARARGS2*/
+
+#ifdef __STDC__
+
+void
+debug(int level, char *format, ...)
+
+#else
+
+void
+debug(level, format, va_alist)
+
+int level;             /* debugging flag bitmap */
+char *format;          /* printf style format */
+va_dcl
+
+#endif
+
+{
+       va_list args;
+
+       if (debug_on(level)) {
+#ifdef __STDC__
+               va_start(args, format);
+#else
+               va_start(args);
+#endif
+               (void) vfprintf(stderr, format, args);
+               va_end(args);
+               (void) fprintf(stderr, "\n");
+       }
+}
+\f
+
+/* return AND of Debuglevel and argument. Useful for other debug functions
+ * that want to see if a given debug level is currently turned on */
+
+int
+debug_on(level)
+
+int level;
+
+{
+       return(Debuglevel & level);
+}
+
+/* if we get an error while doing rational arithmetic, we are in deep
+ * trouble, so print message and get out. */
+
+void
+doraterr(code)
+
+int code;
+
+{
+       switch (code) {
+
+       case RATOVER:
+               pfatal("rational overflow");
+               /*NOTREACHED*/
+               break;
+
+       case RATDIV0:
+               pfatal("rational division by zero");
+               /*NOTREACHED*/
+               break;
+
+       case RATPARM:
+               pfatal("invalid rational number parameter");
+               /*NOTREACHED*/
+               break;
+
+       default:
+               pfatal("error in rational arithmetic routines");
+               /*NOTREACHED*/
+               break;
+       }
+}
+\f
+
+/* Print header for an error report. If the error is associated with a
+ * particular line, the file name and line number and the text of the line
+ * is printed, but only on the first of multiple errors for the same line.
+ * If not associated with any line, a blank line is produced.
+ */
+
+static void
+error_header(filename, lineno, errtype)
+
+char * filename;
+int lineno;
+char * errtype;                /* "warning" or "error" etc */
+
+{
+       static char *cached_filename = 0;
+       static int cached_lineno = -1;
+
+       if (filename == 0 || lineno <= 0) {
+               (void) fprintf(stderr, "\n");
+               return;
+       }
+
+       /* We print the text of the offending line, unless it is the
+        * same as the last error, in which case we could have already
+        * printed it, so no need to print again. */
+       if (cached_filename != filename || cached_lineno != lineno) {
+               (void) fprintf(stderr,"\n%s: line %d:\n", filename, lineno);
+               print_offending_line(filename, lineno);
+       }
+       (void) fprintf(stderr,"%s: ", errtype);
+       cached_filename = filename;
+       cached_lineno = lineno;
+}
+\f
+
+/* Print the text of input line where error was found. */
+
+void
+print_offending_line(filename, lineno)
+
+char *filename;
+int lineno;
+
+{
+       /* We cache file info to save time when multiple errors */
+       static FILE *f = 0;
+       static char *prev_filename = 0;
+       static int prev_lineno = 0;
+       int inp;        /* a byte read from file */
+       int skipcount;  /* how many lines to skip past */
+
+       /* We try to reuse already opened file to save time,
+        * but need to open new file when necessary. */
+       if (f == 0 || prev_filename != filename) {
+               /* close any previously open file */
+               if (f != 0) {
+                       (void) fclose(f);
+               }
+               /* Note that if Mup is reading from stdin, we will try to
+                * open a file entitled "stdin" here. That will almost
+                * certainly fail, but we can't easily get the line from
+                * stdin anyway, so user just won't get the context in that
+                * case. People who are having Mup read from stdin are probably
+                * savvy enough that this isn't a big problem. (We never used
+                * to print this context ever, and no one complained.)
+                * So the only weird case is if the user happens to have a
+                * file whose name is literally "stdin" but the actual stdin
+                * being read is some other file, in which case they'll get
+                * garbage. But anyone using stdin for a file name is probably
+                * smart enough to figure out the strange results in that case.
+                * In the case of include files found via $MUPPATH,
+                * filename will have already been expanded to a full path,
+                * so we don't have to do anything special here for them.
+                */
+               if ((f = fopen(filename, "r")) == 0) {
+                       return;
+               }
+               skipcount = lineno - 1;
+               prev_filename = filename;
+       }
+       else if (lineno > prev_lineno) {
+               /* We can continue where we left off in the file */
+               skipcount = lineno - prev_lineno - 1;
+       }
+       else {
+               /* Earlier line in same file; easiest to just start over.
+                * This could happen, because sometimes we don't realize
+                * there is an error until a later line (E.g., only when
+                * getting to bar line we find inconsistency in the 
+                * contents of the bar.) */
+               rewind(f);
+               skipcount = lineno - 1;
+       }
+
+       /* Skip to the line of interest and print it. */
+       for (inp = 0; skipcount > 0; skipcount--) {
+               /* We read byte-by-byte so we don't need to guess
+                * how big a buffer to use to hold a line.
+                */
+               while ((inp = getc(f)) != '\n' && inp != EOF) {
+                       ;
+               }
+               if (inp == EOF) {
+                       break;
+               }
+       }
+       if (inp != EOF) {
+               (void) fprintf(stderr, "    ");
+               while ((inp = getc(f)) != '\n' && inp != EOF) {
+                       putc(inp, stderr);
+               }
+               putc('\n', stderr);
+       }
+       prev_lineno = lineno;
+       /* Note that we leave the file open, to save time
+        * in case we need to read more from it
+        * due to additional errors from the same file.
+        */
+}
diff --git a/mup/mup/extchar.h b/mup/mup/extchar.h
new file mode 100644 (file)
index 0000000..3d2bdc2
--- /dev/null
@@ -0,0 +1,106 @@
+/* Copyright (c) 1996, 2002, 2004 by Arkkra Enterprises */
+/* All rights reserved. */
+
+#ifdef EXTCHAR
+
+/* Define the extended (non-ASCII) characters */
+/* Mapping between name and number is done via Ext_char_table[] */
+
+#define C_exclamdown   (32)    
+#define C_cent                 (33)    
+#define C_sterling     (34)    
+#define C_yen          (35)    
+#define C_quotedblleft         (36)    
+#define C_guillemotleft        (37)    
+#define C_guillemotright       (38)    
+#define C_guilsinglleft        (39)    
+#define C_guilsinglright       (40)    
+#define C_dagger       (41)    
+#define C_daggerdbl    (42)    
+#define C_bullet       (43)    
+#define C_quotedblbase         (44)    
+#define C_quotedblright        (45)    
+#define C_questiondown         (46)    
+#define C_grave        (47)    
+#define C_acute        (48)    
+#define C_macron       (49)    
+#define C_breve        (50)    
+#define C_dotaccent    (51)    
+#define C_dieresis     (52)    
+#define C_ring                 (53)    
+#define C_cedilla      (54)    
+#define C_hungarumlaut         (55)    
+#define C_ogonek       (56)    
+#define C_caron        (57)    
+#define C_emdash       (58)    
+#define C_AE           (59)    
+#define C_ae           (60)    
+#define C_ordfeminine  (61)    
+#define C_ordmasculine         (62)    
+#define C_Lslash       (63)    
+#define C_lslash       (64)    
+#define C_Oslash       (65)    
+#define C_oslash       (66)    
+#define C_OE           (67)    
+#define C_oe           (68)    
+#define C_dotlessi     (69)    
+#define C_germandbls   (70)    
+#define C_Aacute       (71)    
+#define C_aacute       (72)    
+#define C_Acircumflex  (73)    
+#define C_acircumflex  (74)    
+#define C_Adieresis    (75)    
+#define C_adieresis    (76)    
+#define C_Agrave       (77)    
+#define C_agrave       (78)    
+#define C_Aring        (79)    
+#define C_aring        (80)    
+#define C_Atilde       (81)    
+#define C_atilde       (82)    
+#define C_Ccedilla     (83)    
+#define C_ccedilla     (84)    
+#define C_Eacute       (85)    
+#define C_eacute       (86)    
+#define C_Ecircumflex  (87)    
+#define C_ecircumflex  (88)    
+#define C_Edieresis    (89)    
+#define C_edieresis    (90)    
+#define C_Egrave       (91)    
+#define C_egrave       (92)    
+#define C_Iacute       (93)    
+#define C_iacute       (94)    
+#define C_Icircumflex  (95)    
+#define C_icircumflex  (96)    
+#define C_Idieresis    (97)    
+#define C_idieresis    (98)    
+#define C_Igrave       (99)    
+#define C_igrave       (100)   
+#define C_Ntilde       (101)   
+#define C_ntilde       (102)   
+#define C_Oacute       (103)   
+#define C_oacute       (104)   
+#define C_Ocircumflex  (105)   
+#define C_ocircumflex  (106)   
+#define C_Odieresis    (107)   
+#define C_odieresis    (108)   
+#define C_Ograve       (109)   
+#define C_ograve       (110)   
+#define C_Otilde       (111)   
+#define C_otilde       (112)   
+#define C_Scaron       (113)   
+#define C_scaron       (114)   
+#define C_Uacute       (115)   
+#define C_uacute       (116)   
+#define C_Ucircumflex  (117)   
+#define C_ucircumflex  (118)   
+#define C_Udieresis    (119)   
+#define C_udieresis    (120)   
+#define C_Ugrave       (121)   
+#define C_ugrave       (122)   
+#define C_Ydieresis    (123)   
+#define C_ydieresis    (124)   
+#define C_Zcaron       (125)   
+#define C_zcaron       (126)   
+#define C_space        (127)   
+
+#endif
diff --git a/mup/mup/extchtbl.c b/mup/mup/extchtbl.c
new file mode 100644 (file)
index 0000000..2dfa2fe
--- /dev/null
@@ -0,0 +1,114 @@
+/* Copyright (c) 1996, 2002, 2004 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* Machine-generated mapping of music char names to code numbers */
+
+#include "defines.h"
+#include "structs.h"
+
+#ifdef EXTCHAR
+
+struct SPECCHAR Ext_char_table[CHARS_IN_FONT+1] = {
+       { "AE", C_AE },
+       { "Aacute", C_Aacute },
+       { "Acircumflex", C_Acircumflex },
+       { "Adieresis", C_Adieresis },
+       { "Agrave", C_Agrave },
+       { "Aring", C_Aring },
+       { "Atilde", C_Atilde },
+       { "Ccedilla", C_Ccedilla },
+       { "Eacute", C_Eacute },
+       { "Ecircumflex", C_Ecircumflex },
+       { "Edieresis", C_Edieresis },
+       { "Egrave", C_Egrave },
+       { "Iacute", C_Iacute },
+       { "Icircumflex", C_Icircumflex },
+       { "Idieresis", C_Idieresis },
+       { "Igrave", C_Igrave },
+       { "Lslash", C_Lslash },
+       { "Ntilde", C_Ntilde },
+       { "OE", C_OE },
+       { "Oacute", C_Oacute },
+       { "Ocircumflex", C_Ocircumflex },
+       { "Odieresis", C_Odieresis },
+       { "Ograve", C_Ograve },
+       { "Oslash", C_Oslash },
+       { "Otilde", C_Otilde },
+       { "Scaron", C_Scaron },
+       { "Uacute", C_Uacute },
+       { "Ucircumflex", C_Ucircumflex },
+       { "Udieresis", C_Udieresis },
+       { "Ugrave", C_Ugrave },
+       { "Ydieresis", C_Ydieresis },
+       { "Zcaron", C_Zcaron },
+       { "aacute", C_aacute },
+       { "acircumflex", C_acircumflex },
+       { "acute", C_acute },
+       { "adieresis", C_adieresis },
+       { "ae", C_ae },
+       { "agrave", C_agrave },
+       { "aring", C_aring },
+       { "atilde", C_atilde },
+       { "breve", C_breve },
+       { "bullet", C_bullet },
+       { "caron", C_caron },
+       { "ccedilla", C_ccedilla },
+       { "cedilla", C_cedilla },
+       { "cent", C_cent },
+       { "dagger", C_dagger },
+       { "daggerdbl", C_daggerdbl },
+       { "dieresis", C_dieresis },
+       { "dotaccent", C_dotaccent },
+       { "dotlessi", C_dotlessi },
+       { "eacute", C_eacute },
+       { "ecircumflex", C_ecircumflex },
+       { "edieresis", C_edieresis },
+       { "egrave", C_egrave },
+       { "emdash", C_emdash },
+       { "exclamdown", C_exclamdown },
+       { "germandbls", C_germandbls },
+       { "grave", C_grave },
+       { "guillemotleft", C_guillemotleft },
+       { "guillemotright", C_guillemotright },
+       { "guilsinglleft", C_guilsinglleft },
+       { "guilsinglright", C_guilsinglright },
+       { "hungarumlaut", C_hungarumlaut },
+       { "iacute", C_iacute },
+       { "icircumflex", C_icircumflex },
+       { "idieresis", C_idieresis },
+       { "igrave", C_igrave },
+       { "lslash", C_lslash },
+       { "macron", C_macron },
+       { "ntilde", C_ntilde },
+       { "oacute", C_oacute },
+       { "ocircumflex", C_ocircumflex },
+       { "odieresis", C_odieresis },
+       { "oe", C_oe },
+       { "ogonek", C_ogonek },
+       { "ograve", C_ograve },
+       { "ordfeminine", C_ordfeminine },
+       { "ordmasculine", C_ordmasculine },
+       { "oslash", C_oslash },
+       { "otilde", C_otilde },
+       { "questiondown", C_questiondown },
+       { "quotedblbase", C_quotedblbase },
+       { "quotedblleft", C_quotedblleft },
+       { "quotedblright", C_quotedblright },
+       { "ring", C_ring },
+       { "scaron", C_scaron },
+       { "space", C_space },
+       { "sterling", C_sterling },
+       { "uacute", C_uacute },
+       { "ucircumflex", C_ucircumflex },
+       { "udieresis", C_udieresis },
+       { "ugrave", C_ugrave },
+       { "ydieresis", C_ydieresis },
+       { "yen", C_yen },
+       { "zcaron", C_zcaron },
+       { (char *) 0, 0 }
+
+};
+#else
+/* to avoid 'empty translation unit' warnings */
+static int dummy;
+#endif
diff --git a/mup/mup/font.c b/mup/mup/font.c
new file mode 100644 (file)
index 0000000..c74aec4
--- /dev/null
@@ -0,0 +1,426 @@
+
+/* Copyright (c) 1999, 2000, 2002, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* This file contains functions related to fonts,
+ * both user defined and native PostScript fonts.
+ */
+
+#include <string.h>
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+/* The font size info is machine generated, so refer to it here. */
+/* This gives the initialization for FONTINFO structs for all fonts. */
+extern struct FONTINFO Fontinfo[MAXFONTS];
+
+/* map font names to numbers. */
+static struct FONTMAP {
+       char *fontname;         /* abbreviated (similar to troff-style)
+                                * or full font name */
+       char    findex;         /* font number */
+} Font_table[] = {
+       /*====== this table must be sorted alphabetically to allow
+        *====== binary search!!!!!  */
+       { "AB", FONT_AB },
+       { "AI", FONT_AI },
+       { "AR", FONT_AR },
+       { "AX", FONT_AX },
+       { "BB", FONT_BB },
+       { "BI", FONT_BI },
+       { "BR", FONT_BR },
+       { "BX", FONT_BX },
+       { "CB", FONT_CB },
+       { "CI", FONT_CI },
+       { "CR", FONT_CR },
+       { "CX", FONT_CX },
+       { "HB", FONT_HB },
+       { "HI", FONT_HI },
+       { "HR", FONT_HR },
+       { "HX", FONT_HX },
+       { "NB", FONT_NB },
+       { "NI", FONT_NI },
+       { "NR", FONT_NR },
+       { "NX", FONT_NX },
+       { "PB", FONT_PB },
+       { "PI", FONT_PI },
+       { "PR", FONT_PR },
+       { "PX", FONT_PX },
+       { "TB", FONT_TB },
+       { "TI", FONT_TI },
+       { "TR", FONT_TR },
+       { "TX", FONT_TX },
+       { "avantgarde bold", FONT_AB },
+       { "avantgarde boldital", FONT_AX },
+       { "avantgarde ital", FONT_AI },
+       { "avantgarde rom", FONT_AR },
+       { "bookman bold", FONT_BB },
+       { "bookman boldital", FONT_BX },
+       { "bookman ital", FONT_BI },
+       { "bookman rom", FONT_BR },
+       { "courier bold", FONT_CB },
+       { "courier boldital", FONT_CX },
+       { "courier ital", FONT_CI },
+       { "courier rom", FONT_CR },
+       { "helvetica bold", FONT_HB },
+       { "helvetica boldital", FONT_HX },
+       { "helvetica ital", FONT_HI },
+       { "helvetica rom", FONT_HR },
+       { "newcentury bold", FONT_NB },
+       { "newcentury boldital", FONT_NX },
+       { "newcentury ital", FONT_NI },
+       { "newcentury rom", FONT_NR },
+       { "palatino bold", FONT_PB },
+       { "palatino boldital", FONT_PX },
+       { "palatino ital", FONT_PI },
+       { "palatino rom", FONT_PR },
+       { "times bold", FONT_TB },
+       { "times boldital", FONT_TX },
+       { "times ital", FONT_TI },
+       { "times rom", FONT_TR }
+};
+
+/* Strings to look for in a fontfile */
+char *Mup_name = "Mup font name:";
+char *PostScript_name = "PostScript font name:";
+char *PS_definition = "PostScript:";
+char *Size_data = "Size data:";
+
+/* static functions */
+static int fncmp P((const void *fn1, const void * fn2));
+static char *get_expected P((FILE *fontfile_p, char *filename, char *expected,
+               int *lineno_p));
+static char *get_noncomment P((FILE *fontfile_p, int *lineno_p));
+\f
+
+/* given a font number, return its index into Fontinfo table. FONT_TR
+ * is the first entry in the table.
+ * If the font number given is out of range, pfatal.
+ */
+
+int
+font_index(font)
+
+int font;      /* which font */
+
+{
+       if ((font < 0) || (font >= MAXFONTS)) {
+               pfatal("font %d out of range", font);
+       }
+       /* offset relative to first valid font */
+       font = font - FONT_TR;
+
+       return(font);
+}
+\f
+
+/* given a fontname, return its number, or FONT_UNKNOWN */
+
+int
+lookup_font(fontname)
+
+char *fontname;
+
+{
+       struct FONTMAP *finfo_p;
+
+
+       if ((finfo_p = (struct FONTMAP *) bsearch(fontname, Font_table,
+                       NUMELEM(Font_table), sizeof(struct FONTMAP), fncmp))
+                       != (struct FONTMAP *) 0) {
+               return(finfo_p->findex);
+       }
+       else {
+               return(FONT_UNKNOWN);
+       }
+}
+
+
+
+/* font name comparision function for use by bsearch() */
+
+static int
+fncmp(fn1, fn2)
+
+#ifdef __STDC__
+const void *fn1;       /* font name to check */
+const void *fn2;       /* pointer to FONTMAP to compare with. declare as char *
+                        * since that's what bsearch() thinks it gives us,
+                        * then we cast appropriately */
+#else
+char *fn1;     /* font name to check */
+char *fn2;     /* pointer to FONTMAP to compare with. declare as char *
+                * since that's what bsearch() thinks it gives us, then we
+                * cast appropriately */
+#endif
+
+{
+       return(strcmp(fn1, ((struct FONTMAP *) fn2)->fontname));
+}
+\f
+
+/* Given a font number, return its name. We don't have to do this too often,
+ * it's a simple int compare, and we only need to look through
+ * abbreviated names, so just do linear search. */
+
+char *
+fontnum2name(font)
+
+int font;
+
+{
+       int f;
+       int elements;
+
+       /* divide by 2 because only need to check abbreviations */
+       elements = NUMELEM(Font_table) / 2;
+       for (f = 0; f < elements; f++) {
+               if (Font_table[f].findex == font) {
+                       return(Font_table[f].fontname);
+               }
+       }
+       return("unknown");
+}
+\f
+
+/* This handles a fontfile, reading it in, validating its contents,
+ * and saving the information in the Fontinfo array.
+ */
+
+void
+parse_font_file(filename)
+
+char *filename;
+
+{
+       FILE *fontfile_p;
+       char *name;     /* Mup font name */
+       char *ps_name;  /* PostScript font name */
+       int findex;     /* which font is being defined */
+       int c;          /* character index */
+       int code;       /* "ASCII" code value */
+       int width, height, ascent;
+       char *buffer;   /* line read from file */
+       int lineno;
+       int max_height, max_ascent;
+
+
+       debug(2, "parse_font_file(%s)", filename);
+
+       if ((fontfile_p = find_file(&filename)) == (FILE *) 0) {
+               l_yyerror(Curr_filename, yylineno, "can't open '%s'", filename);
+               return;
+       }
+
+       /* first line of file is expected to contain the Mup font name */
+       lineno = 0;
+       if ((name = get_expected(fontfile_p, filename, Mup_name, &lineno))
+                                                       != (char *) 0) {
+               if ((findex = lookup_font(name)) == FONT_UNKNOWN) {
+                       l_yyerror(filename, lineno,
+                               "'%s' is not a valid Mup font name", name);
+                       return;
+               }
+               findex = font_index(findex);
+
+               if (Fontinfo[findex].fontfile != (FILE *) 0) {
+                       l_yyerror(filename, lineno,
+                               "Font '%s' redefined more than once", name);
+                       return;
+               }
+               /* Save the file pointer, since we'll need to read the rest of
+                * the file to put into the Mup output */
+               Fontinfo[findex].fontfile = fontfile_p;
+       }
+       else {
+               return;
+       }
+
+       /* Next line of file is expected to contain the PostScript font name */
+       if ((ps_name = get_expected(fontfile_p, filename, PostScript_name, &lineno))
+                                                       != (char *) 0) {
+               if (strlen(ps_name) == 0 ) {
+                       l_yyerror(filename, lineno,
+                                       "No PostScript font name value given");
+                       return;
+               }
+               Fontinfo[findex].ps_name = ps_name;
+       }
+       else {
+               return;
+       }
+
+       /* Next line of file is expected to contain the Size data line */
+       if ((ps_name = get_expected(fontfile_p, filename, Size_data, &lineno))
+                                                       == (char *) 0) {
+               return;
+       }
+
+       max_height = max_ascent = 0;
+       for (c = FIRST_CHAR; c < FIRST_CHAR + CHARS_IN_FONT - 1; c++) {
+               buffer = get_noncomment(fontfile_p, &lineno);
+               if ( sscanf(buffer, "%d %d %d %d",
+                                       &code, &width, &height, &ascent) != 4) {
+                       buffer[strlen(buffer) - 1] =  '\0';
+                       l_yyerror(filename, lineno,
+                               "size data line has incorrect format: '%s'",
+                               buffer);
+                       return;
+               }
+               if (c != code) {
+                       l_yyerror(filename, lineno,
+                               "expecting size data for character %d, but got %d instead",
+                               c, code);
+                       return;
+               }
+
+               /* Because of how backspace works (see comment in defines.h)
+                * we need to limit width to 0.5 inch for a DEFAULT_SIZE
+                * character. */
+               if (width > 500) {
+                       l_yyerror(filename, lineno, "width must be less than 500");
+                       return;
+               }
+
+               /* save size in table */
+               code = CHAR_INDEX(code);
+               Fontinfo[findex].ch_height[code] = height;
+               Fontinfo[findex].ch_width[code] = width;
+               Fontinfo[findex].ch_ascent[code] = ascent;
+
+               if (height > max_height) {
+                       max_height = height;
+               }
+               if (ascent > max_ascent) {
+                       max_ascent = ascent;
+               }
+       }
+
+       Maxfontheight[findex] =  (double) max_height / (double) FONTFACTOR;
+       Maxfontascent[findex] =  (double) max_ascent / (double) FONTFACTOR;
+
+       /* Next line of file is expected to contain the PostScript: line */
+       if ((ps_name = get_expected(fontfile_p, filename, PS_definition, &lineno))
+                                                       == (char *) 0) {
+               return;
+       }
+}
+\f
+
+/* Read from given file. If next non-comment line starts as expected,
+ * return a copy of the rest of the line after any white space.
+ * Otherwise print an error and return 0.
+ */
+
+static char *
+get_expected(fontfile_p, filename, expected, lineno_p)
+
+FILE *fontfile_p;
+char *filename;
+char *expected;        /* line read is expected to start with this */
+int *lineno_p; /* line number where line was found is returned here */
+
+{
+       char *buffer;
+       char *newstring;
+       char *p;
+
+       buffer = get_noncomment(fontfile_p, lineno_p);
+       if (strncmp(buffer, expected, strlen(expected)) != 0) {
+               l_yyerror(filename, *lineno_p,
+                       "Expecting '%s' in font_file '%s'", expected, filename);
+               return((char *) 0);
+       }
+
+       /* skip any leading white space */
+       for (buffer += strlen(expected); isspace(*buffer); buffer++) {
+               ;
+       }
+
+       /* trim any white space from the end of the string */
+       for (p = buffer + strlen(buffer) - 1; p >= buffer; p--) {
+               if (isspace(*p)) {
+                       *p = '\0';
+               }
+               else {
+                       break;
+               }
+       }
+
+       /* make a copy and return it */
+       MALLOCA(char, newstring, strlen(buffer) + 1);
+       strcpy(newstring, buffer);
+       return(newstring);
+}
+\f
+
+/* Read lines from given file until a non-comment line is found, and
+ * return that line. A comment is a line that has # in its first column.
+ * Returns a null string on end of file. The line returned is in a static
+ * buffer overwritten on each call, so caller must save if they need a copy.
+ */
+
+static char *
+get_noncomment(file, lineno_p)
+
+FILE *file;
+int *lineno_p; /* line number gets sents in and returned here */
+
+{
+       static char buffer[128];
+
+       while (fgets(buffer, sizeof(buffer), file) != (char *) 0) {
+               (*lineno_p)++;
+               if ( *buffer != '#') {
+                       /* not a comment, so return it */
+                       return(buffer);
+               }
+       }
+       buffer[0] = '\0';
+       return(buffer);
+}
+\f
+
+/* return the height for a font in inches for a given size */
+
+double
+fontheight(font, size)
+
+int font;
+int size;
+
+{
+       return( (double) Maxfontheight[font_index(font)] *
+                       ((double) size / (double) DFLT_SIZE) );
+}
+
+
+
+/* return the ascent for a font in inches for a given size */
+
+double
+fontascent(font, size)
+
+int font;
+int size;
+
+{
+       return( (double) Maxfontascent[font_index(font)] *
+                       ((double) size / (double) DFLT_SIZE) );
+}
+
+
+
+/* return the descent for a font in inches for a given size */
+
+double
+fontdescent(font, size)
+
+int font;
+int size;
+
+{
+       return( fontheight(font, size) - fontascent (font, size) );
+}
diff --git a/mup/mup/fontdata.c b/mup/mup/fontdata.c
new file mode 100644 (file)
index 0000000..343b082
--- /dev/null
@@ -0,0 +1,17883 @@
+/* Copyright (c) 1995, 1996, 1999 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* this file was generated from font information.
+ * It gives the width, height, and ascent for all the
+ * text characters in FONTFACTORs of an inch */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+struct FONTINFO Fontinfo[MAXFONTS] = {
+{
+       /* width table for font TR */
+       {
+       42,     /* ' ' */
+       55,     /* '!' */
+       68,     /* '"' */
+       83,     /* '#' */
+       83,     /* '$' */
+       139,    /* '%' */
+       130,    /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       55,     /* ')' */
+       83,     /* '*' */
+       94,     /* '+' */
+       42,     /* ',' */
+       55,     /* '-' */
+       42,     /* '.' */
+       46,     /* '/' */
+       83,     /* '0' */
+       83,     /* '1' */
+       83,     /* '2' */
+       83,     /* '3' */
+       83,     /* '4' */
+       83,     /* '5' */
+       83,     /* '6' */
+       83,     /* '7' */
+       83,     /* '8' */
+       83,     /* '9' */
+       46,     /* ':' */
+       46,     /* ';' */
+       94,     /* '<' */
+       94,     /* '=' */
+       94,     /* '>' */
+       74,     /* '?' */
+       153,    /* '@' */
+       120,    /* 'A' */
+       111,    /* 'B' */
+       111,    /* 'C' */
+       120,    /* 'D' */
+       102,    /* 'E' */
+       93,     /* 'F' */
+       120,    /* 'G' */
+       120,    /* 'H' */
+       55,     /* 'I' */
+       65,     /* 'J' */
+       120,    /* 'K' */
+       102,    /* 'L' */
+       148,    /* 'M' */
+       120,    /* 'N' */
+       120,    /* 'O' */
+       93,     /* 'P' */
+       120,    /* 'Q' */
+       111,    /* 'R' */
+       93,     /* 'S' */
+       102,    /* 'T' */
+       120,    /* 'U' */
+       120,    /* 'V' */
+       157,    /* 'W' */
+       120,    /* 'X' */
+       120,    /* 'Y' */
+       102,    /* 'Z' */
+       55,     /* '[' */
+       46,     /* '\' */
+       55,     /* ']' */
+       78,     /* '^' */
+       83,     /* '_' */
+       55,     /* '`' */
+       74,     /* 'a' */
+       83,     /* 'b' */
+       74,     /* 'c' */
+       83,     /* 'd' */
+       74,     /* 'e' */
+       55,     /* 'f' */
+       83,     /* 'g' */
+       83,     /* 'h' */
+       46,     /* 'i' */
+       46,     /* 'j' */
+       83,     /* 'k' */
+       46,     /* 'l' */
+       130,    /* 'm' */
+       83,     /* 'n' */
+       83,     /* 'o' */
+       83,     /* 'p' */
+       83,     /* 'q' */
+       55,     /* 'r' */
+       65,     /* 's' */
+       46,     /* 't' */
+       83,     /* 'u' */
+       83,     /* 'v' */
+       120,    /* 'w' */
+       83,     /* 'x' */
+       83,     /* 'y' */
+       74,     /* 'z' */
+       80,     /* '{' */
+       33,     /* '|' */
+       80,     /* '}' */
+       90,     /* '~' */
+       },
+       /* height table for font TR */
+       {
+       153,    /* ' ' */
+       144,    /* '!' */
+       142,    /* '"' */
+       139,    /* '#' */
+       163,    /* '$' */
+       144,    /* '%' */
+       144,    /* '&' */
+       142,    /* ''' */
+       170,    /* '(' */
+       170,    /* ')' */
+       142,    /* '*' */
+       112,    /* '+' */
+       69,     /* ',' */
+       69,     /* '-' */
+       47,     /* '.' */
+       144,    /* '/' */
+       144,    /* '0' */
+       140,    /* '1' */
+       142,    /* '2' */
+       144,    /* '3' */
+       142,    /* '4' */
+       145,    /* '5' */
+       144,    /* '6' */
+       141,    /* '7' */
+       144,    /* '8' */
+       146,    /* '9' */
+       108,    /* ':' */
+       129,    /* ';' */
+       115,    /* '<' */
+       92,     /* '=' */
+       115,    /* '>' */
+       144,    /* '?' */
+       144,    /* '@' */
+       142,    /* 'A' */
+       139,    /* 'B' */
+       144,    /* 'C' */
+       139,    /* 'D' */
+       139,    /* 'E' */
+       139,    /* 'F' */
+       144,    /* 'G' */
+       139,    /* 'H' */
+       139,    /* 'I' */
+       141,    /* 'J' */
+       139,    /* 'K' */
+       139,    /* 'L' */
+       139,    /* 'M' */
+       141,    /* 'N' */
+       144,    /* 'O' */
+       139,    /* 'P' */
+       172,    /* 'Q' */
+       139,    /* 'R' */
+       144,    /* 'S' */
+       139,    /* 'T' */
+       141,    /* 'U' */
+       141,    /* 'V' */
+       141,    /* 'W' */
+       139,    /* 'X' */
+       139,    /* 'Y' */
+       139,    /* 'Z' */
+       164,    /* '[' */
+       144,    /* '\' */
+       164,    /* ']' */
+       139,    /* '^' */
+       38,     /* '_' */
+       140,    /* '`' */
+       108,    /* 'a' */
+       144,    /* 'b' */
+       108,    /* 'c' */
+       144,    /* 'd' */
+       108,    /* 'e' */
+       142,    /* 'f' */
+       141,    /* 'g' */
+       142,    /* 'h' */
+       142,    /* 'i' */
+       178,    /* 'j' */
+       142,    /* 'k' */
+       142,    /* 'l' */
+       106,    /* 'm' */
+       106,    /* 'n' */
+       108,    /* 'o' */
+       141,    /* 'p' */
+       141,    /* 'q' */
+       106,    /* 'r' */
+       108,    /* 's' */
+       126,    /* 't' */
+       104,    /* 'u' */
+       104,    /* 'v' */
+       104,    /* 'w' */
+       102,    /* 'x' */
+       138,    /* 'y' */
+       102,    /* 'z' */
+       172,    /* '{' */
+       144,    /* '|' */
+       172,    /* '}' */
+       82,     /* '~' */
+       },
+       /* ascent table for font TR */
+       {
+       108,    /* ' ' */
+       128,    /* '!' */
+       128,    /* '"' */
+       125,    /* '#' */
+       135,    /* '$' */
+       128,    /* '%' */
+       128,    /* '&' */
+       128,    /* ''' */
+       127,    /* '(' */
+       127,    /* ')' */
+       128,    /* '*' */
+       98,     /* '+' */
+       32,     /* ',' */
+       55,     /* '-' */
+       31,     /* '.' */
+       128,    /* '/' */
+       128,    /* '0' */
+       127,    /* '1' */
+       128,    /* '2' */
+       128,    /* '3' */
+       128,    /* '4' */
+       129,    /* '5' */
+       128,    /* '6' */
+       125,    /* '7' */
+       128,    /* '8' */
+       128,    /* '9' */
+       92,     /* ':' */
+       92,     /* ';' */
+       100,    /* '<' */
+       78,     /* '=' */
+       100,    /* '>' */
+       128,    /* '?' */
+       128,    /* '@' */
+       128,    /* 'A' */
+       125,    /* 'B' */
+       128,    /* 'C' */
+       125,    /* 'D' */
+       125,    /* 'E' */
+       125,    /* 'F' */
+       128,    /* 'G' */
+       125,    /* 'H' */
+       125,    /* 'I' */
+       125,    /* 'J' */
+       125,    /* 'K' */
+       125,    /* 'L' */
+       125,    /* 'M' */
+       125,    /* 'N' */
+       128,    /* 'O' */
+       125,    /* 'P' */
+       128,    /* 'Q' */
+       125,    /* 'R' */
+       128,    /* 'S' */
+       125,    /* 'T' */
+       125,    /* 'U' */
+       125,    /* 'V' */
+       125,    /* 'W' */
+       125,    /* 'X' */
+       125,    /* 'Y' */
+       125,    /* 'Z' */
+       125,    /* '[' */
+       128,    /* '\' */
+       125,    /* ']' */
+       125,    /* '^' */
+       2,      /* '_' */
+       127,    /* '`' */
+       92,     /* 'a' */
+       128,    /* 'b' */
+       92,     /* 'c' */
+       128,    /* 'd' */
+       92,     /* 'e' */
+       128,    /* 'f' */
+       92,     /* 'g' */
+       128,    /* 'h' */
+       128,    /* 'i' */
+       128,    /* 'j' */
+       128,    /* 'k' */
+       128,    /* 'l' */
+       92,     /* 'm' */
+       92,     /* 'n' */
+       92,     /* 'o' */
+       92,     /* 'p' */
+       92,     /* 'q' */
+       92,     /* 'r' */
+       92,     /* 's' */
+       110,    /* 't' */
+       88,     /* 'u' */
+       88,     /* 'v' */
+       88,     /* 'w' */
+       88,     /* 'x' */
+       88,     /* 'y' */
+       88,     /* 'z' */
+       128,    /* '{' */
+       128,    /* '|' */
+       128,    /* '}' */
+       68,     /* '~' */
+       },
+
+       "Times-Roman",
+       0,
+       NO
+       }, {
+       /* width table for font TI */
+       {
+       42,     /* ' ' */
+       55,     /* '!' */
+       70,     /* '"' */
+       83,     /* '#' */
+       83,     /* '$' */
+       139,    /* '%' */
+       130,    /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       55,     /* ')' */
+       83,     /* '*' */
+       112,    /* '+' */
+       42,     /* ',' */
+       55,     /* '-' */
+       42,     /* '.' */
+       46,     /* '/' */
+       83,     /* '0' */
+       83,     /* '1' */
+       83,     /* '2' */
+       83,     /* '3' */
+       83,     /* '4' */
+       83,     /* '5' */
+       83,     /* '6' */
+       83,     /* '7' */
+       83,     /* '8' */
+       83,     /* '9' */
+       55,     /* ':' */
+       55,     /* ';' */
+       112,    /* '<' */
+       112,    /* '=' */
+       112,    /* '>' */
+       83,     /* '?' */
+       153,    /* '@' */
+       102,    /* 'A' */
+       102,    /* 'B' */
+       111,    /* 'C' */
+       120,    /* 'D' */
+       102,    /* 'E' */
+       102,    /* 'F' */
+       120,    /* 'G' */
+       120,    /* 'H' */
+       55,     /* 'I' */
+       74,     /* 'J' */
+       111,    /* 'K' */
+       93,     /* 'L' */
+       139,    /* 'M' */
+       111,    /* 'N' */
+       120,    /* 'O' */
+       102,    /* 'P' */
+       120,    /* 'Q' */
+       102,    /* 'R' */
+       83,     /* 'S' */
+       93,     /* 'T' */
+       120,    /* 'U' */
+       102,    /* 'V' */
+       139,    /* 'W' */
+       102,    /* 'X' */
+       93,     /* 'Y' */
+       93,     /* 'Z' */
+       65,     /* '[' */
+       46,     /* '\' */
+       65,     /* ']' */
+       70,     /* '^' */
+       83,     /* '_' */
+       55,     /* '`' */
+       83,     /* 'a' */
+       83,     /* 'b' */
+       74,     /* 'c' */
+       83,     /* 'd' */
+       74,     /* 'e' */
+       46,     /* 'f' */
+       83,     /* 'g' */
+       83,     /* 'h' */
+       46,     /* 'i' */
+       46,     /* 'j' */
+       74,     /* 'k' */
+       46,     /* 'l' */
+       120,    /* 'm' */
+       83,     /* 'n' */
+       83,     /* 'o' */
+       83,     /* 'p' */
+       83,     /* 'q' */
+       65,     /* 'r' */
+       65,     /* 's' */
+       46,     /* 't' */
+       83,     /* 'u' */
+       74,     /* 'v' */
+       111,    /* 'w' */
+       74,     /* 'x' */
+       74,     /* 'y' */
+       65,     /* 'z' */
+       67,     /* '{' */
+       46,     /* '|' */
+       67,     /* '}' */
+       90,     /* '~' */
+       },
+       /* height table for font TI */
+       {
+       153,    /* ' ' */
+       141,    /* '!' */
+       139,    /* '"' */
+       140,    /* '#' */
+       164,    /* '$' */
+       143,    /* '%' */
+       141,    /* '&' */
+       139,    /* ''' */
+       169,    /* '(' */
+       169,    /* ')' */
+       139,    /* '*' */
+       112,    /* '+' */
+       66,     /* ',' */
+       69,     /* '-' */
+       47,     /* '.' */
+       141,    /* '/' */
+       144,    /* '0' */
+       140,    /* '1' */
+       142,    /* '2' */
+       141,    /* '3' */
+       140,    /* '4' */
+       141,    /* '5' */
+       144,    /* '6' */
+       141,    /* '7' */
+       141,    /* '8' */
+       142,    /* '9' */
+       104,    /* ':' */
+       124,    /* ';' */
+       115,    /* '<' */
+       92,     /* '=' */
+       115,    /* '>' */
+       141,    /* '?' */
+       141,    /* '@' */
+       139,    /* 'A' */
+       136,    /* 'B' */
+       141,    /* 'C' */
+       136,    /* 'D' */
+       136,    /* 'E' */
+       136,    /* 'F' */
+       141,    /* 'G' */
+       136,    /* 'H' */
+       136,    /* 'I' */
+       138,    /* 'J' */
+       136,    /* 'K' */
+       136,    /* 'L' */
+       136,    /* 'M' */
+       138,    /* 'N' */
+       141,    /* 'O' */
+       136,    /* 'P' */
+       168,    /* 'Q' */
+       136,    /* 'R' */
+       141,    /* 'S' */
+       136,    /* 'T' */
+       138,    /* 'U' */
+       138,    /* 'V' */
+       138,    /* 'W' */
+       136,    /* 'X' */
+       136,    /* 'Y' */
+       136,    /* 'Z' */
+       164,    /* '[' */
+       141,    /* '\' */
+       164,    /* ']' */
+       139,    /* '^' */
+       38,     /* '_' */
+       139,    /* '`' */
+       104,    /* 'a' */
+       144,    /* 'b' */
+       104,    /* 'c' */
+       144,    /* 'd' */
+       104,    /* 'e' */
+       178,    /* 'f' */
+       138,    /* 'g' */
+       144,    /* 'h' */
+       138,    /* 'i' */
+       171,    /* 'j' */
+       144,    /* 'k' */
+       144,    /* 'l' */
+       104,    /* 'm' */
+       104,    /* 'n' */
+       104,    /* 'o' */
+       136,    /* 'p' */
+       138,    /* 'q' */
+       102,    /* 'r' */
+       104,    /* 's' */
+       121,    /* 't' */
+       104,    /* 'u' */
+       104,    /* 'v' */
+       104,    /* 'w' */
+       104,    /* 'x' */
+       137,    /* 'y' */
+       111,    /* 'z' */
+       172,    /* '{' */
+       141,    /* '|' */
+       172,    /* '}' */
+       82,     /* '~' */
+       },
+       /* ascent table for font TI */
+       {
+       108,    /* ' ' */
+       125,    /* '!' */
+       125,    /* '"' */
+       127,    /* '#' */
+       136,    /* '$' */
+       127,    /* '%' */
+       125,    /* '&' */
+       125,    /* ''' */
+       125,    /* '(' */
+       125,    /* ')' */
+       125,    /* '*' */
+       98,     /* '+' */
+       31,     /* ',' */
+       55,     /* '-' */
+       31,     /* '.' */
+       125,    /* '/' */
+       128,    /* '0' */
+       126,    /* '1' */
+       128,    /* '2' */
+       125,    /* '3' */
+       127,    /* '4' */
+       125,    /* '5' */
+       128,    /* '6' */
+       125,    /* '7' */
+       125,    /* '8' */
+       125,    /* '9' */
+       88,     /* ':' */
+       88,     /* ';' */
+       100,    /* '<' */
+       78,     /* '=' */
+       100,    /* '>' */
+       125,    /* '?' */
+       125,    /* '@' */
+       125,    /* 'A' */
+       122,    /* 'B' */
+       125,    /* 'C' */
+       122,    /* 'D' */
+       122,    /* 'E' */
+       122,    /* 'F' */
+       125,    /* 'G' */
+       122,    /* 'H' */
+       122,    /* 'I' */
+       122,    /* 'J' */
+       122,    /* 'K' */
+       122,    /* 'L' */
+       122,    /* 'M' */
+       122,    /* 'N' */
+       125,    /* 'O' */
+       122,    /* 'P' */
+       125,    /* 'Q' */
+       122,    /* 'R' */
+       125,    /* 'S' */
+       122,    /* 'T' */
+       122,    /* 'U' */
+       122,    /* 'V' */
+       122,    /* 'W' */
+       122,    /* 'X' */
+       122,    /* 'Y' */
+       122,    /* 'Z' */
+       125,    /* '[' */
+       125,    /* '\' */
+       125,    /* ']' */
+       125,    /* '^' */
+       2,      /* '_' */
+       125,    /* '`' */
+       88,     /* 'a' */
+       128,    /* 'b' */
+       88,     /* 'c' */
+       128,    /* 'd' */
+       88,     /* 'e' */
+       128,    /* 'f' */
+       88,     /* 'g' */
+       128,    /* 'h' */
+       122,    /* 'i' */
+       122,    /* 'j' */
+       128,    /* 'k' */
+       128,    /* 'l' */
+       88,     /* 'm' */
+       88,     /* 'n' */
+       88,     /* 'o' */
+       88,     /* 'p' */
+       88,     /* 'q' */
+       88,     /* 'r' */
+       88,     /* 's' */
+       105,    /* 't' */
+       87,     /* 'u' */
+       88,     /* 'v' */
+       88,     /* 'w' */
+       88,     /* 'x' */
+       88,     /* 'y' */
+       85,     /* 'z' */
+       128,    /* '{' */
+       125,    /* '|' */
+       128,    /* '}' */
+       68,     /* '~' */
+       },
+
+       "Times-Italic",
+       0,
+       YES
+       }, {
+       /* width table for font TB */
+       {
+       42,     /* ' ' */
+       55,     /* '!' */
+       92,     /* '"' */
+       83,     /* '#' */
+       83,     /* '$' */
+       167,    /* '%' */
+       139,    /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       55,     /* ')' */
+       83,     /* '*' */
+       95,     /* '+' */
+       42,     /* ',' */
+       55,     /* '-' */
+       42,     /* '.' */
+       46,     /* '/' */
+       83,     /* '0' */
+       83,     /* '1' */
+       83,     /* '2' */
+       83,     /* '3' */
+       83,     /* '4' */
+       83,     /* '5' */
+       83,     /* '6' */
+       83,     /* '7' */
+       83,     /* '8' */
+       83,     /* '9' */
+       55,     /* ':' */
+       55,     /* ';' */
+       95,     /* '<' */
+       95,     /* '=' */
+       95,     /* '>' */
+       83,     /* '?' */
+       155,    /* '@' */
+       120,    /* 'A' */
+       111,    /* 'B' */
+       120,    /* 'C' */
+       120,    /* 'D' */
+       111,    /* 'E' */
+       102,    /* 'F' */
+       130,    /* 'G' */
+       130,    /* 'H' */
+       65,     /* 'I' */
+       83,     /* 'J' */
+       130,    /* 'K' */
+       111,    /* 'L' */
+       157,    /* 'M' */
+       120,    /* 'N' */
+       130,    /* 'O' */
+       102,    /* 'P' */
+       130,    /* 'Q' */
+       120,    /* 'R' */
+       93,     /* 'S' */
+       111,    /* 'T' */
+       120,    /* 'U' */
+       120,    /* 'V' */
+       167,    /* 'W' */
+       120,    /* 'X' */
+       120,    /* 'Y' */
+       111,    /* 'Z' */
+       55,     /* '[' */
+       46,     /* '\' */
+       55,     /* ']' */
+       97,     /* '^' */
+       83,     /* '_' */
+       55,     /* '`' */
+       83,     /* 'a' */
+       93,     /* 'b' */
+       74,     /* 'c' */
+       93,     /* 'd' */
+       74,     /* 'e' */
+       55,     /* 'f' */
+       83,     /* 'g' */
+       93,     /* 'h' */
+       46,     /* 'i' */
+       55,     /* 'j' */
+       93,     /* 'k' */
+       46,     /* 'l' */
+       139,    /* 'm' */
+       93,     /* 'n' */
+       83,     /* 'o' */
+       93,     /* 'p' */
+       93,     /* 'q' */
+       74,     /* 'r' */
+       65,     /* 's' */
+       55,     /* 't' */
+       93,     /* 'u' */
+       83,     /* 'v' */
+       120,    /* 'w' */
+       83,     /* 'x' */
+       83,     /* 'y' */
+       74,     /* 'z' */
+       66,     /* '{' */
+       37,     /* '|' */
+       66,     /* '}' */
+       87,     /* '~' */
+       },
+       /* height table for font TB */
+       {
+       153,    /* ' ' */
+       144,    /* '!' */
+       142,    /* '"' */
+       144,    /* '#' */
+       169,    /* '$' */
+       144,    /* '%' */
+       144,    /* '&' */
+       142,    /* ''' */
+       171,    /* '(' */
+       171,    /* ')' */
+       142,    /* '*' */
+       112,    /* '+' */
+       86,     /* ',' */
+       76,     /* '-' */
+       56,     /* '.' */
+       144,    /* '/' */
+       144,    /* '0' */
+       142,    /* '1' */
+       142,    /* '2' */
+       144,    /* '3' */
+       142,    /* '4' */
+       141,    /* '5' */
+       145,    /* '6' */
+       139,    /* '7' */
+       144,    /* '8' */
+       144,    /* '9' */
+       111,    /* ':' */
+       139,    /* ';' */
+       116,    /* '<' */
+       92,     /* '=' */
+       116,    /* '>' */
+       144,    /* '?' */
+       144,    /* '@' */
+       142,    /* 'A' */
+       139,    /* 'B' */
+       144,    /* 'C' */
+       139,    /* 'D' */
+       139,    /* 'E' */
+       139,    /* 'F' */
+       144,    /* 'G' */
+       139,    /* 'H' */
+       139,    /* 'I' */
+       154,    /* 'J' */
+       139,    /* 'K' */
+       139,    /* 'L' */
+       139,    /* 'M' */
+       141,    /* 'N' */
+       144,    /* 'O' */
+       139,    /* 'P' */
+       171,    /* 'Q' */
+       139,    /* 'R' */
+       144,    /* 'S' */
+       139,    /* 'T' */
+       141,    /* 'U' */
+       141,    /* 'V' */
+       141,    /* 'W' */
+       139,    /* 'X' */
+       139,    /* 'Y' */
+       139,    /* 'Z' */
+       164,    /* '[' */
+       144,    /* '\' */
+       164,    /* ']' */
+       139,    /* '^' */
+       38,     /* '_' */
+       143,    /* '`' */
+       111,    /* 'a' */
+       141,    /* 'b' */
+       111,    /* 'c' */
+       141,    /* 'd' */
+       111,    /* 'e' */
+       142,    /* 'f' */
+       144,    /* 'g' */
+       139,    /* 'h' */
+       142,    /* 'i' */
+       178,    /* 'j' */
+       139,    /* 'k' */
+       139,    /* 'l' */
+       109,    /* 'm' */
+       109,    /* 'n' */
+       111,    /* 'o' */
+       144,    /* 'p' */
+       144,    /* 'q' */
+       109,    /* 'r' */
+       111,    /* 's' */
+       135,    /* 't' */
+       108,    /* 'u' */
+       108,    /* 'v' */
+       108,    /* 'w' */
+       106,    /* 'x' */
+       141,    /* 'y' */
+       106,    /* 'z' */
+       174,    /* '{' */
+       144,    /* '|' */
+       174,    /* '}' */
+       82,     /* '~' */
+       },
+       /* ascent table for font TB */
+       {
+       108,    /* ' ' */
+       128,    /* '!' */
+       128,    /* '"' */
+       131,    /* '#' */
+       139,    /* '$' */
+       128,    /* '%' */
+       128,    /* '&' */
+       128,    /* ''' */
+       130,    /* '(' */
+       130,    /* ')' */
+       128,    /* '*' */
+       98,     /* '+' */
+       42,     /* ',' */
+       62,     /* '-' */
+       40,     /* '.' */
+       128,    /* '/' */
+       128,    /* '0' */
+       128,    /* '1' */
+       128,    /* '2' */
+       128,    /* '3' */
+       128,    /* '4' */
+       125,    /* '5' */
+       129,    /* '6' */
+       125,    /* '7' */
+       128,    /* '8' */
+       128,    /* '9' */
+       95,     /* ':' */
+       95,     /* ';' */
+       100,    /* '<' */
+       78,     /* '=' */
+       100,    /* '>' */
+       128,    /* '?' */
+       128,    /* '@' */
+       128,    /* 'A' */
+       125,    /* 'B' */
+       128,    /* 'C' */
+       125,    /* 'D' */
+       125,    /* 'E' */
+       125,    /* 'F' */
+       128,    /* 'G' */
+       125,    /* 'H' */
+       125,    /* 'I' */
+       125,    /* 'J' */
+       125,    /* 'K' */
+       125,    /* 'L' */
+       125,    /* 'M' */
+       125,    /* 'N' */
+       128,    /* 'O' */
+       125,    /* 'P' */
+       128,    /* 'Q' */
+       125,    /* 'R' */
+       128,    /* 'S' */
+       125,    /* 'T' */
+       125,    /* 'U' */
+       125,    /* 'V' */
+       125,    /* 'W' */
+       125,    /* 'X' */
+       125,    /* 'Y' */
+       125,    /* 'Z' */
+       125,    /* '[' */
+       128,    /* '\' */
+       125,    /* ']' */
+       125,    /* '^' */
+       2,      /* '_' */
+       129,    /* '`' */
+       95,     /* 'a' */
+       125,    /* 'b' */
+       95,     /* 'c' */
+       125,    /* 'd' */
+       95,     /* 'e' */
+       128,    /* 'f' */
+       95,     /* 'g' */
+       125,    /* 'h' */
+       128,    /* 'i' */
+       128,    /* 'j' */
+       125,    /* 'k' */
+       125,    /* 'l' */
+       95,     /* 'm' */
+       95,     /* 'n' */
+       95,     /* 'o' */
+       95,     /* 'p' */
+       95,     /* 'q' */
+       95,     /* 'r' */
+       95,     /* 's' */
+       119,    /* 't' */
+       92,     /* 'u' */
+       92,     /* 'v' */
+       92,     /* 'w' */
+       92,     /* 'x' */
+       92,     /* 'y' */
+       92,     /* 'z' */
+       132,    /* '{' */
+       128,    /* '|' */
+       132,    /* '}' */
+       68,     /* '~' */
+       },
+
+       "Times-Bold",
+       0,
+       NO
+       }, {
+       /* width table for font TX */
+       {
+       42,     /* ' ' */
+       65,     /* '!' */
+       92,     /* '"' */
+       83,     /* '#' */
+       83,     /* '$' */
+       139,    /* '%' */
+       130,    /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       55,     /* ')' */
+       83,     /* '*' */
+       95,     /* '+' */
+       42,     /* ',' */
+       55,     /* '-' */
+       42,     /* '.' */
+       46,     /* '/' */
+       83,     /* '0' */
+       83,     /* '1' */
+       83,     /* '2' */
+       83,     /* '3' */
+       83,     /* '4' */
+       83,     /* '5' */
+       83,     /* '6' */
+       83,     /* '7' */
+       83,     /* '8' */
+       83,     /* '9' */
+       55,     /* ':' */
+       55,     /* ';' */
+       95,     /* '<' */
+       95,     /* '=' */
+       95,     /* '>' */
+       83,     /* '?' */
+       139,    /* '@' */
+       111,    /* 'A' */
+       111,    /* 'B' */
+       111,    /* 'C' */
+       120,    /* 'D' */
+       111,    /* 'E' */
+       111,    /* 'F' */
+       120,    /* 'G' */
+       130,    /* 'H' */
+       65,     /* 'I' */
+       83,     /* 'J' */
+       111,    /* 'K' */
+       102,    /* 'L' */
+       148,    /* 'M' */
+       120,    /* 'N' */
+       120,    /* 'O' */
+       102,    /* 'P' */
+       120,    /* 'Q' */
+       111,    /* 'R' */
+       93,     /* 'S' */
+       102,    /* 'T' */
+       120,    /* 'U' */
+       111,    /* 'V' */
+       148,    /* 'W' */
+       111,    /* 'X' */
+       102,    /* 'Y' */
+       102,    /* 'Z' */
+       55,     /* '[' */
+       46,     /* '\' */
+       55,     /* ']' */
+       95,     /* '^' */
+       83,     /* '_' */
+       55,     /* '`' */
+       83,     /* 'a' */
+       83,     /* 'b' */
+       74,     /* 'c' */
+       83,     /* 'd' */
+       74,     /* 'e' */
+       55,     /* 'f' */
+       83,     /* 'g' */
+       93,     /* 'h' */
+       46,     /* 'i' */
+       46,     /* 'j' */
+       83,     /* 'k' */
+       46,     /* 'l' */
+       130,    /* 'm' */
+       93,     /* 'n' */
+       83,     /* 'o' */
+       83,     /* 'p' */
+       83,     /* 'q' */
+       65,     /* 'r' */
+       65,     /* 's' */
+       46,     /* 't' */
+       93,     /* 'u' */
+       74,     /* 'v' */
+       111,    /* 'w' */
+       83,     /* 'x' */
+       74,     /* 'y' */
+       65,     /* 'z' */
+       58,     /* '{' */
+       37,     /* '|' */
+       58,     /* '}' */
+       95,     /* '~' */
+       },
+       /* height table for font TX */
+       {
+       153,    /* ' ' */
+       144,    /* '!' */
+       142,    /* '"' */
+       144,    /* '#' */
+       167,    /* '$' */
+       145,    /* '%' */
+       144,    /* '&' */
+       142,    /* ''' */
+       172,    /* '(' */
+       172,    /* ')' */
+       142,    /* '*' */
+       112,    /* '+' */
+       80,     /* ',' */
+       76,     /* '-' */
+       53,     /* '.' */
+       144,    /* '/' */
+       144,    /* '0' */
+       142,    /* '1' */
+       142,    /* '2' */
+       144,    /* '3' */
+       142,    /* '4' */
+       141,    /* '5' */
+       143,    /* '6' */
+       139,    /* '7' */
+       144,    /* '8' */
+       144,    /* '9' */
+       108,    /* ':' */
+       136,    /* ';' */
+       116,    /* '<' */
+       92,     /* '=' */
+       116,    /* '>' */
+       144,    /* '?' */
+       144,    /* '@' */
+       142,    /* 'A' */
+       139,    /* 'B' */
+       144,    /* 'C' */
+       139,    /* 'D' */
+       139,    /* 'E' */
+       139,    /* 'F' */
+       144,    /* 'G' */
+       139,    /* 'H' */
+       139,    /* 'I' */
+       154,    /* 'J' */
+       139,    /* 'K' */
+       139,    /* 'L' */
+       141,    /* 'M' */
+       141,    /* 'N' */
+       144,    /* 'O' */
+       139,    /* 'P' */
+       178,    /* 'Q' */
+       139,    /* 'R' */
+       144,    /* 'S' */
+       139,    /* 'T' */
+       141,    /* 'U' */
+       141,    /* 'V' */
+       141,    /* 'W' */
+       139,    /* 'X' */
+       139,    /* 'Y' */
+       139,    /* 'Z' */
+       164,    /* '[' */
+       144,    /* '\' */
+       164,    /* ']' */
+       139,    /* '^' */
+       38,     /* '_' */
+       142,    /* '`' */
+       108,    /* 'a' */
+       146,    /* 'b' */
+       108,    /* 'c' */
+       146,    /* 'd' */
+       108,    /* 'e' */
+       178,    /* 'f' */
+       141,    /* 'g' */
+       147,    /* 'h' */
+       144,    /* 'i' */
+       178,    /* 'j' */
+       146,    /* 'k' */
+       147,    /* 'l' */
+       108,    /* 'm' */
+       108,    /* 'n' */
+       108,    /* 'o' */
+       138,    /* 'p' */
+       141,    /* 'q' */
+       106,    /* 'r' */
+       108,    /* 's' */
+       129,    /* 't' */
+       107,    /* 'u' */
+       108,    /* 'v' */
+       108,    /* 'w' */
+       108,    /* 'x' */
+       141,    /* 'y' */
+       114,    /* 'z' */
+       173,    /* '{' */
+       144,    /* '|' */
+       173,    /* '}' */
+       82,     /* '~' */
+       },
+       /* ascent table for font TX */
+       {
+       108,    /* ' ' */
+       128,    /* '!' */
+       128,    /* '"' */
+       131,    /* '#' */
+       136,    /* '$' */
+       129,    /* '%' */
+       128,    /* '&' */
+       128,    /* ''' */
+       128,    /* '(' */
+       128,    /* ')' */
+       128,    /* '*' */
+       98,     /* '+' */
+       36,     /* ',' */
+       62,     /* '-' */
+       36,     /* '.' */
+       128,    /* '/' */
+       128,    /* '0' */
+       128,    /* '1' */
+       128,    /* '2' */
+       128,    /* '3' */
+       128,    /* '4' */
+       125,    /* '5' */
+       127,    /* '6' */
+       125,    /* '7' */
+       128,    /* '8' */
+       128,    /* '9' */
+       92,     /* ':' */
+       92,     /* ';' */
+       100,    /* '<' */
+       78,     /* '=' */
+       100,    /* '>' */
+       128,    /* '?' */
+       128,    /* '@' */
+       128,    /* 'A' */
+       125,    /* 'B' */
+       128,    /* 'C' */
+       125,    /* 'D' */
+       125,    /* 'E' */
+       125,    /* 'F' */
+       128,    /* 'G' */
+       125,    /* 'H' */
+       125,    /* 'I' */
+       125,    /* 'J' */
+       125,    /* 'K' */
+       125,    /* 'L' */
+       125,    /* 'M' */
+       125,    /* 'N' */
+       128,    /* 'O' */
+       125,    /* 'P' */
+       128,    /* 'Q' */
+       125,    /* 'R' */
+       128,    /* 'S' */
+       125,    /* 'T' */
+       125,    /* 'U' */
+       125,    /* 'V' */
+       125,    /* 'W' */
+       125,    /* 'X' */
+       125,    /* 'Y' */
+       125,    /* 'Z' */
+       125,    /* '[' */
+       128,    /* '\' */
+       125,    /* ']' */
+       125,    /* '^' */
+       2,      /* '_' */
+       128,    /* '`' */
+       92,     /* 'a' */
+       130,    /* 'b' */
+       92,     /* 'c' */
+       130,    /* 'd' */
+       92,     /* 'e' */
+       128,    /* 'f' */
+       92,     /* 'g' */
+       130,    /* 'h' */
+       128,    /* 'i' */
+       128,    /* 'j' */
+       130,    /* 'k' */
+       130,    /* 'l' */
+       92,     /* 'm' */
+       92,     /* 'n' */
+       92,     /* 'o' */
+       92,     /* 'p' */
+       92,     /* 'q' */
+       92,     /* 'r' */
+       92,     /* 's' */
+       113,    /* 't' */
+       91,     /* 'u' */
+       92,     /* 'v' */
+       92,     /* 'w' */
+       92,     /* 'x' */
+       92,     /* 'y' */
+       88,     /* 'z' */
+       128,    /* '{' */
+       128,    /* '|' */
+       128,    /* '}' */
+       68,     /* '~' */
+       },
+
+       "Times-BoldItalic",
+       0,
+       YES
+       }, {
+       /* width table for font AR */
+       {
+       46,     /* ' ' */
+       49,     /* '!' */
+       51,     /* '"' */
+       92,     /* '#' */
+       92,     /* '$' */
+       129,    /* '%' */
+       126,    /* '&' */
+       58,     /* ''' */
+       61,     /* '(' */
+       61,     /* ')' */
+       71,     /* '*' */
+       101,    /* '+' */
+       46,     /* ',' */
+       55,     /* '-' */
+       46,     /* '.' */
+       73,     /* '/' */
+       92,     /* '0' */
+       92,     /* '1' */
+       92,     /* '2' */
+       92,     /* '3' */
+       92,     /* '4' */
+       92,     /* '5' */
+       92,     /* '6' */
+       92,     /* '7' */
+       92,     /* '8' */
+       92,     /* '9' */
+       46,     /* ':' */
+       46,     /* ';' */
+       101,    /* '<' */
+       101,    /* '=' */
+       101,    /* '>' */
+       98,     /* '?' */
+       144,    /* '@' */
+       123,    /* 'A' */
+       96,     /* 'B' */
+       135,    /* 'C' */
+       124,    /* 'D' */
+       89,     /* 'E' */
+       81,     /* 'F' */
+       145,    /* 'G' */
+       114,    /* 'H' */
+       38,     /* 'I' */
+       80,     /* 'J' */
+       98,     /* 'K' */
+       77,     /* 'L' */
+       153,    /* 'M' */
+       123,    /* 'N' */
+       145,    /* 'O' */
+       99,     /* 'P' */
+       145,    /* 'Q' */
+       101,    /* 'R' */
+       83,     /* 'S' */
+       71,     /* 'T' */
+       109,    /* 'U' */
+       117,    /* 'V' */
+       160,    /* 'W' */
+       101,    /* 'X' */
+       99,     /* 'Y' */
+       80,     /* 'Z' */
+       58,     /* '[' */
+       101,    /* '\' */
+       58,     /* ']' */
+       101,    /* '^' */
+       83,     /* '_' */
+       58,     /* '`' */
+       114,    /* 'a' */
+       114,    /* 'b' */
+       108,    /* 'c' */
+       114,    /* 'd' */
+       108,    /* 'e' */
+       52,     /* 'f' */
+       112,    /* 'g' */
+       102,    /* 'h' */
+       33,     /* 'i' */
+       34,     /* 'j' */
+       84,     /* 'k' */
+       33,     /* 'l' */
+       156,    /* 'm' */
+       102,    /* 'n' */
+       109,    /* 'o' */
+       114,    /* 'p' */
+       114,    /* 'q' */
+       50,     /* 'r' */
+       65,     /* 's' */
+       56,     /* 't' */
+       101,    /* 'u' */
+       92,     /* 'v' */
+       138,    /* 'w' */
+       80,     /* 'x' */
+       89,     /* 'y' */
+       71,     /* 'z' */
+       58,     /* '{' */
+       112,    /* '|' */
+       58,     /* '}' */
+       101,    /* '~' */
+       },
+       /* height table for font AR */
+       {
+       153,    /* ' ' */
+       152,    /* '!' */
+       152,    /* '"' */
+       152,    /* '#' */
+       171,    /* '$' */
+       158,    /* '%' */
+       158,    /* '&' */
+       152,    /* ''' */
+       172,    /* '(' */
+       172,    /* ')' */
+       153,    /* '*' */
+       122,    /* '+' */
+       60,     /* ',' */
+       76,     /* '-' */
+       49,     /* '.' */
+       174,    /* '/' */
+       158,    /* '0' */
+       152,    /* '1' */
+       156,    /* '2' */
+       158,    /* '3' */
+       152,    /* '4' */
+       154,    /* '5' */
+       154,    /* '6' */
+       152,    /* '7' */
+       158,    /* '8' */
+       156,    /* '9' */
+       112,    /* ':' */
+       123,    /* ';' */
+       122,    /* '<' */
+       99,     /* '=' */
+       122,    /* '>' */
+       156,    /* '?' */
+       158,    /* '@' */
+       152,    /* 'A' */
+       152,    /* 'B' */
+       158,    /* 'C' */
+       152,    /* 'D' */
+       152,    /* 'E' */
+       152,    /* 'F' */
+       158,    /* 'G' */
+       152,    /* 'H' */
+       152,    /* 'I' */
+       154,    /* 'J' */
+       152,    /* 'K' */
+       152,    /* 'L' */
+       152,    /* 'M' */
+       152,    /* 'N' */
+       158,    /* 'O' */
+       152,    /* 'P' */
+       158,    /* 'Q' */
+       152,    /* 'R' */
+       158,    /* 'S' */
+       152,    /* 'T' */
+       154,    /* 'U' */
+       152,    /* 'V' */
+       152,    /* 'W' */
+       152,    /* 'X' */
+       152,    /* 'Y' */
+       152,    /* 'Z' */
+       172,    /* '[' */
+       152,    /* '\' */
+       172,    /* ']' */
+       152,    /* '^' */
+       38,     /* '_' */
+       152,    /* '`' */
+       124,    /* 'a' */
+       154,    /* 'b' */
+       124,    /* 'c' */
+       154,    /* 'd' */
+       124,    /* 'e' */
+       152,    /* 'f' */
+       158,    /* 'g' */
+       152,    /* 'h' */
+       152,    /* 'i' */
+       184,    /* 'j' */
+       152,    /* 'k' */
+       152,    /* 'l' */
+       122,    /* 'm' */
+       122,    /* 'n' */
+       124,    /* 'o' */
+       154,    /* 'p' */
+       154,    /* 'q' */
+       122,    /* 'r' */
+       124,    /* 's' */
+       152,    /* 't' */
+       121,    /* 'u' */
+       119,    /* 'v' */
+       119,    /* 'w' */
+       119,    /* 'x' */
+       151,    /* 'y' */
+       119,    /* 'z' */
+       173,    /* '{' */
+       152,    /* '|' */
+       173,    /* '}' */
+       93,     /* '~' */
+       },
+       /* ascent table for font AR */
+       {
+       108,    /* ' ' */
+       138,    /* '!' */
+       138,    /* '"' */
+       138,    /* '#' */
+       148,    /* '$' */
+       142,    /* '%' */
+       142,    /* '&' */
+       138,    /* ''' */
+       137,    /* '(' */
+       137,    /* ')' */
+       139,    /* '*' */
+       108,    /* '+' */
+       35,     /* ',' */
+       62,     /* '-' */
+       35,     /* '.' */
+       138,    /* '/' */
+       142,    /* '0' */
+       138,    /* '1' */
+       142,    /* '2' */
+       142,    /* '3' */
+       138,    /* '4' */
+       138,    /* '5' */
+       138,    /* '6' */
+       138,    /* '7' */
+       142,    /* '8' */
+       142,    /* '9' */
+       98,     /* ':' */
+       98,     /* ';' */
+       108,    /* '<' */
+       85,     /* '=' */
+       108,    /* '>' */
+       142,    /* '?' */
+       142,    /* '@' */
+       138,    /* 'A' */
+       138,    /* 'B' */
+       142,    /* 'C' */
+       138,    /* 'D' */
+       138,    /* 'E' */
+       138,    /* 'F' */
+       142,    /* 'G' */
+       138,    /* 'H' */
+       138,    /* 'I' */
+       138,    /* 'J' */
+       138,    /* 'K' */
+       138,    /* 'L' */
+       138,    /* 'M' */
+       138,    /* 'N' */
+       142,    /* 'O' */
+       138,    /* 'P' */
+       142,    /* 'Q' */
+       138,    /* 'R' */
+       142,    /* 'S' */
+       138,    /* 'T' */
+       138,    /* 'U' */
+       138,    /* 'V' */
+       138,    /* 'W' */
+       138,    /* 'X' */
+       138,    /* 'Y' */
+       138,    /* 'Z' */
+       137,    /* '[' */
+       138,    /* '\' */
+       137,    /* ']' */
+       138,    /* '^' */
+       2,      /* '_' */
+       138,    /* '`' */
+       108,    /* 'a' */
+       138,    /* 'b' */
+       108,    /* 'c' */
+       138,    /* 'd' */
+       108,    /* 'e' */
+       138,    /* 'f' */
+       108,    /* 'g' */
+       138,    /* 'h' */
+       138,    /* 'i' */
+       138,    /* 'j' */
+       138,    /* 'k' */
+       138,    /* 'l' */
+       108,    /* 'm' */
+       108,    /* 'n' */
+       108,    /* 'o' */
+       108,    /* 'p' */
+       108,    /* 'q' */
+       108,    /* 'r' */
+       108,    /* 's' */
+       138,    /* 't' */
+       105,    /* 'u' */
+       105,    /* 'v' */
+       105,    /* 'w' */
+       105,    /* 'x' */
+       105,    /* 'y' */
+       105,    /* 'z' */
+       138,    /* '{' */
+       138,    /* '|' */
+       138,    /* '}' */
+       79,     /* '~' */
+       },
+
+       "AvantGarde-Book",
+       0,
+       NO
+       }, {
+       /* width table for font AI */
+       {
+       46,     /* ' ' */
+       49,     /* '!' */
+       51,     /* '"' */
+       92,     /* '#' */
+       92,     /* '$' */
+       129,    /* '%' */
+       126,    /* '&' */
+       58,     /* ''' */
+       61,     /* '(' */
+       61,     /* ')' */
+       71,     /* '*' */
+       101,    /* '+' */
+       46,     /* ',' */
+       55,     /* '-' */
+       46,     /* '.' */
+       73,     /* '/' */
+       92,     /* '0' */
+       92,     /* '1' */
+       92,     /* '2' */
+       92,     /* '3' */
+       92,     /* '4' */
+       92,     /* '5' */
+       92,     /* '6' */
+       92,     /* '7' */
+       92,     /* '8' */
+       92,     /* '9' */
+       46,     /* ':' */
+       46,     /* ';' */
+       101,    /* '<' */
+       101,    /* '=' */
+       101,    /* '>' */
+       98,     /* '?' */
+       144,    /* '@' */
+       123,    /* 'A' */
+       96,     /* 'B' */
+       135,    /* 'C' */
+       124,    /* 'D' */
+       89,     /* 'E' */
+       81,     /* 'F' */
+       145,    /* 'G' */
+       114,    /* 'H' */
+       38,     /* 'I' */
+       80,     /* 'J' */
+       98,     /* 'K' */
+       77,     /* 'L' */
+       153,    /* 'M' */
+       123,    /* 'N' */
+       145,    /* 'O' */
+       99,     /* 'P' */
+       145,    /* 'Q' */
+       101,    /* 'R' */
+       83,     /* 'S' */
+       71,     /* 'T' */
+       109,    /* 'U' */
+       117,    /* 'V' */
+       160,    /* 'W' */
+       101,    /* 'X' */
+       99,     /* 'Y' */
+       80,     /* 'Z' */
+       58,     /* '[' */
+       101,    /* '\' */
+       58,     /* ']' */
+       101,    /* '^' */
+       83,     /* '_' */
+       58,     /* '`' */
+       114,    /* 'a' */
+       114,    /* 'b' */
+       108,    /* 'c' */
+       114,    /* 'd' */
+       108,    /* 'e' */
+       52,     /* 'f' */
+       112,    /* 'g' */
+       102,    /* 'h' */
+       33,     /* 'i' */
+       34,     /* 'j' */
+       84,     /* 'k' */
+       33,     /* 'l' */
+       156,    /* 'm' */
+       102,    /* 'n' */
+       109,    /* 'o' */
+       114,    /* 'p' */
+       114,    /* 'q' */
+       50,     /* 'r' */
+       65,     /* 's' */
+       56,     /* 't' */
+       101,    /* 'u' */
+       92,     /* 'v' */
+       138,    /* 'w' */
+       80,     /* 'x' */
+       89,     /* 'y' */
+       71,     /* 'z' */
+       58,     /* '{' */
+       112,    /* '|' */
+       58,     /* '}' */
+       101,    /* '~' */
+       },
+       /* height table for font AI */
+       {
+       153,    /* ' ' */
+       152,    /* '!' */
+       152,    /* '"' */
+       152,    /* '#' */
+       171,    /* '$' */
+       158,    /* '%' */
+       158,    /* '&' */
+       152,    /* ''' */
+       172,    /* '(' */
+       172,    /* ')' */
+       153,    /* '*' */
+       119,    /* '+' */
+       60,     /* ',' */
+       76,     /* '-' */
+       49,     /* '.' */
+       174,    /* '/' */
+       158,    /* '0' */
+       152,    /* '1' */
+       156,    /* '2' */
+       158,    /* '3' */
+       152,    /* '4' */
+       154,    /* '5' */
+       154,    /* '6' */
+       152,    /* '7' */
+       158,    /* '8' */
+       156,    /* '9' */
+       112,    /* ':' */
+       123,    /* ';' */
+       122,    /* '<' */
+       99,     /* '=' */
+       122,    /* '>' */
+       156,    /* '?' */
+       158,    /* '@' */
+       152,    /* 'A' */
+       152,    /* 'B' */
+       158,    /* 'C' */
+       152,    /* 'D' */
+       152,    /* 'E' */
+       152,    /* 'F' */
+       158,    /* 'G' */
+       152,    /* 'H' */
+       152,    /* 'I' */
+       154,    /* 'J' */
+       152,    /* 'K' */
+       152,    /* 'L' */
+       152,    /* 'M' */
+       152,    /* 'N' */
+       158,    /* 'O' */
+       152,    /* 'P' */
+       158,    /* 'Q' */
+       152,    /* 'R' */
+       158,    /* 'S' */
+       152,    /* 'T' */
+       154,    /* 'U' */
+       152,    /* 'V' */
+       152,    /* 'W' */
+       152,    /* 'X' */
+       152,    /* 'Y' */
+       152,    /* 'Z' */
+       172,    /* '[' */
+       152,    /* '\' */
+       172,    /* ']' */
+       152,    /* '^' */
+       38,     /* '_' */
+       152,    /* '`' */
+       124,    /* 'a' */
+       154,    /* 'b' */
+       124,    /* 'c' */
+       154,    /* 'd' */
+       124,    /* 'e' */
+       152,    /* 'f' */
+       158,    /* 'g' */
+       152,    /* 'h' */
+       152,    /* 'i' */
+       184,    /* 'j' */
+       152,    /* 'k' */
+       152,    /* 'l' */
+       122,    /* 'm' */
+       122,    /* 'n' */
+       124,    /* 'o' */
+       154,    /* 'p' */
+       154,    /* 'q' */
+       122,    /* 'r' */
+       124,    /* 's' */
+       152,    /* 't' */
+       121,    /* 'u' */
+       119,    /* 'v' */
+       119,    /* 'w' */
+       119,    /* 'x' */
+       151,    /* 'y' */
+       119,    /* 'z' */
+       173,    /* '{' */
+       152,    /* '|' */
+       173,    /* '}' */
+       93,     /* '~' */
+       },
+       /* ascent table for font AI */
+       {
+       108,    /* ' ' */
+       138,    /* '!' */
+       138,    /* '"' */
+       138,    /* '#' */
+       148,    /* '$' */
+       142,    /* '%' */
+       142,    /* '&' */
+       138,    /* ''' */
+       137,    /* '(' */
+       137,    /* ')' */
+       139,    /* '*' */
+       105,    /* '+' */
+       35,     /* ',' */
+       62,     /* '-' */
+       35,     /* '.' */
+       138,    /* '/' */
+       142,    /* '0' */
+       138,    /* '1' */
+       142,    /* '2' */
+       142,    /* '3' */
+       138,    /* '4' */
+       138,    /* '5' */
+       138,    /* '6' */
+       138,    /* '7' */
+       142,    /* '8' */
+       142,    /* '9' */
+       98,     /* ':' */
+       98,     /* ';' */
+       108,    /* '<' */
+       85,     /* '=' */
+       108,    /* '>' */
+       142,    /* '?' */
+       142,    /* '@' */
+       138,    /* 'A' */
+       138,    /* 'B' */
+       142,    /* 'C' */
+       138,    /* 'D' */
+       138,    /* 'E' */
+       138,    /* 'F' */
+       142,    /* 'G' */
+       138,    /* 'H' */
+       138,    /* 'I' */
+       138,    /* 'J' */
+       138,    /* 'K' */
+       138,    /* 'L' */
+       138,    /* 'M' */
+       138,    /* 'N' */
+       142,    /* 'O' */
+       138,    /* 'P' */
+       142,    /* 'Q' */
+       138,    /* 'R' */
+       142,    /* 'S' */
+       138,    /* 'T' */
+       138,    /* 'U' */
+       138,    /* 'V' */
+       138,    /* 'W' */
+       138,    /* 'X' */
+       138,    /* 'Y' */
+       138,    /* 'Z' */
+       137,    /* '[' */
+       138,    /* '\' */
+       137,    /* ']' */
+       138,    /* '^' */
+       2,      /* '_' */
+       138,    /* '`' */
+       108,    /* 'a' */
+       138,    /* 'b' */
+       108,    /* 'c' */
+       138,    /* 'd' */
+       108,    /* 'e' */
+       138,    /* 'f' */
+       108,    /* 'g' */
+       138,    /* 'h' */
+       138,    /* 'i' */
+       138,    /* 'j' */
+       138,    /* 'k' */
+       138,    /* 'l' */
+       108,    /* 'm' */
+       108,    /* 'n' */
+       108,    /* 'o' */
+       108,    /* 'p' */
+       108,    /* 'q' */
+       108,    /* 'r' */
+       108,    /* 's' */
+       138,    /* 't' */
+       105,    /* 'u' */
+       105,    /* 'v' */
+       105,    /* 'w' */
+       105,    /* 'x' */
+       105,    /* 'y' */
+       105,    /* 'z' */
+       138,    /* '{' */
+       138,    /* '|' */
+       138,    /* '}' */
+       79,     /* '~' */
+       },
+
+       "AvantGarde-BookOblique",
+       0,
+       YES
+       }, {
+       /* width table for font AB */
+       {
+       47,     /* ' ' */
+       47,     /* '!' */
+       60,     /* '"' */
+       93,     /* '#' */
+       93,     /* '$' */
+       143,    /* '%' */
+       113,    /* '&' */
+       47,     /* ''' */
+       63,     /* '(' */
+       63,     /* ')' */
+       73,     /* '*' */
+       100,    /* '+' */
+       47,     /* ',' */
+       70,     /* '-' */
+       47,     /* '.' */
+       77,     /* '/' */
+       93,     /* '0' */
+       93,     /* '1' */
+       93,     /* '2' */
+       93,     /* '3' */
+       93,     /* '4' */
+       93,     /* '5' */
+       93,     /* '6' */
+       93,     /* '7' */
+       93,     /* '8' */
+       93,     /* '9' */
+       47,     /* ':' */
+       47,     /* ';' */
+       100,    /* '<' */
+       100,    /* '=' */
+       100,    /* '>' */
+       93,     /* '?' */
+       123,    /* '@' */
+       123,    /* 'A' */
+       97,     /* 'B' */
+       130,    /* 'C' */
+       117,    /* 'D' */
+       87,     /* 'E' */
+       80,     /* 'F' */
+       140,    /* 'G' */
+       113,    /* 'H' */
+       47,     /* 'I' */
+       80,     /* 'J' */
+       103,    /* 'K' */
+       73,     /* 'L' */
+       150,    /* 'M' */
+       123,    /* 'N' */
+       140,    /* 'O' */
+       93,     /* 'P' */
+       140,    /* 'Q' */
+       97,     /* 'R' */
+       87,     /* 'S' */
+       70,     /* 'T' */
+       107,    /* 'U' */
+       117,    /* 'V' */
+       150,    /* 'W' */
+       113,    /* 'X' */
+       103,    /* 'Y' */
+       83,     /* 'Z' */
+       53,     /* '[' */
+       107,    /* '\' */
+       53,     /* ']' */
+       100,    /* '^' */
+       83,     /* '_' */
+       47,     /* '`' */
+       110,    /* 'a' */
+       110,    /* 'b' */
+       107,    /* 'c' */
+       110,    /* 'd' */
+       107,    /* 'e' */
+       47,     /* 'f' */
+       110,    /* 'g' */
+       100,    /* 'h' */
+       40,     /* 'i' */
+       43,     /* 'j' */
+       97,     /* 'k' */
+       40,     /* 'l' */
+       157,    /* 'm' */
+       100,    /* 'n' */
+       107,    /* 'o' */
+       110,    /* 'p' */
+       110,    /* 'q' */
+       53,     /* 'r' */
+       73,     /* 's' */
+       50,     /* 't' */
+       100,    /* 'u' */
+       93,     /* 'v' */
+       133,    /* 'w' */
+       93,     /* 'x' */
+       97,     /* 'y' */
+       77,     /* 'z' */
+       57,     /* '{' */
+       100,    /* '|' */
+       57,     /* '}' */
+       100,    /* '~' */
+       },
+       /* height table for font AB */
+       {
+       153,    /* ' ' */
+       152,    /* '!' */
+       152,    /* '"' */
+       152,    /* '#' */
+       181,    /* '$' */
+       158,    /* '%' */
+       158,    /* '&' */
+       152,    /* ''' */
+       174,    /* '(' */
+       174,    /* ')' */
+       151,    /* '*' */
+       132,    /* '+' */
+       72,     /* ',' */
+       86,     /* '-' */
+       49,     /* '.' */
+       174,    /* '/' */
+       158,    /* '0' */
+       152,    /* '1' */
+       156,    /* '2' */
+       158,    /* '3' */
+       152,    /* '4' */
+       154,    /* '5' */
+       154,    /* '6' */
+       152,    /* '7' */
+       158,    /* '8' */
+       156,    /* '9' */
+       112,    /* ':' */
+       136,    /* ';' */
+       125,    /* '<' */
+       116,    /* '=' */
+       125,    /* '>' */
+       156,    /* '?' */
+       158,    /* '@' */
+       152,    /* 'A' */
+       152,    /* 'B' */
+       158,    /* 'C' */
+       152,    /* 'D' */
+       152,    /* 'E' */
+       152,    /* 'F' */
+       158,    /* 'G' */
+       152,    /* 'H' */
+       152,    /* 'I' */
+       154,    /* 'J' */
+       152,    /* 'K' */
+       152,    /* 'L' */
+       152,    /* 'M' */
+       152,    /* 'N' */
+       158,    /* 'O' */
+       152,    /* 'P' */
+       158,    /* 'Q' */
+       152,    /* 'R' */
+       158,    /* 'S' */
+       152,    /* 'T' */
+       154,    /* 'U' */
+       152,    /* 'V' */
+       152,    /* 'W' */
+       152,    /* 'X' */
+       152,    /* 'Y' */
+       152,    /* 'Z' */
+       174,    /* '[' */
+       152,    /* '\' */
+       174,    /* ']' */
+       152,    /* '^' */
+       44,     /* '_' */
+       152,    /* '`' */
+       124,    /* 'a' */
+       154,    /* 'b' */
+       124,    /* 'c' */
+       154,    /* 'd' */
+       124,    /* 'e' */
+       152,    /* 'f' */
+       158,    /* 'g' */
+       152,    /* 'h' */
+       152,    /* 'i' */
+       184,    /* 'j' */
+       152,    /* 'k' */
+       152,    /* 'l' */
+       122,    /* 'm' */
+       122,    /* 'n' */
+       124,    /* 'o' */
+       154,    /* 'p' */
+       154,    /* 'q' */
+       122,    /* 'r' */
+       124,    /* 's' */
+       152,    /* 't' */
+       121,    /* 'u' */
+       119,    /* 'v' */
+       119,    /* 'w' */
+       119,    /* 'x' */
+       151,    /* 'y' */
+       119,    /* 'z' */
+       174,    /* '{' */
+       152,    /* '|' */
+       174,    /* '}' */
+       98,     /* '~' */
+       },
+       /* ascent table for font AB */
+       {
+       108,    /* ' ' */
+       138,    /* '!' */
+       138,    /* '"' */
+       138,    /* '#' */
+       155,    /* '$' */
+       142,    /* '%' */
+       142,    /* '&' */
+       138,    /* ''' */
+       137,    /* '(' */
+       137,    /* ')' */
+       137,    /* '*' */
+       118,    /* '+' */
+       35,     /* ',' */
+       72,     /* '-' */
+       35,     /* '.' */
+       138,    /* '/' */
+       142,    /* '0' */
+       138,    /* '1' */
+       142,    /* '2' */
+       142,    /* '3' */
+       138,    /* '4' */
+       138,    /* '5' */
+       138,    /* '6' */
+       138,    /* '7' */
+       142,    /* '8' */
+       142,    /* '9' */
+       98,     /* ':' */
+       98,     /* ';' */
+       111,    /* '<' */
+       102,    /* '=' */
+       111,    /* '>' */
+       142,    /* '?' */
+       142,    /* '@' */
+       138,    /* 'A' */
+       138,    /* 'B' */
+       142,    /* 'C' */
+       138,    /* 'D' */
+       138,    /* 'E' */
+       138,    /* 'F' */
+       142,    /* 'G' */
+       138,    /* 'H' */
+       138,    /* 'I' */
+       138,    /* 'J' */
+       138,    /* 'K' */
+       138,    /* 'L' */
+       138,    /* 'M' */
+       138,    /* 'N' */
+       142,    /* 'O' */
+       138,    /* 'P' */
+       142,    /* 'Q' */
+       138,    /* 'R' */
+       142,    /* 'S' */
+       138,    /* 'T' */
+       138,    /* 'U' */
+       138,    /* 'V' */
+       138,    /* 'W' */
+       138,    /* 'X' */
+       138,    /* 'Y' */
+       138,    /* 'Z' */
+       137,    /* '[' */
+       138,    /* '\' */
+       137,    /* ']' */
+       138,    /* '^' */
+       8,      /* '_' */
+       138,    /* '`' */
+       108,    /* 'a' */
+       138,    /* 'b' */
+       108,    /* 'c' */
+       138,    /* 'd' */
+       108,    /* 'e' */
+       138,    /* 'f' */
+       108,    /* 'g' */
+       138,    /* 'h' */
+       138,    /* 'i' */
+       138,    /* 'j' */
+       138,    /* 'k' */
+       138,    /* 'l' */
+       108,    /* 'm' */
+       108,    /* 'n' */
+       108,    /* 'o' */
+       108,    /* 'p' */
+       108,    /* 'q' */
+       108,    /* 'r' */
+       108,    /* 's' */
+       138,    /* 't' */
+       105,    /* 'u' */
+       105,    /* 'v' */
+       105,    /* 'w' */
+       105,    /* 'x' */
+       105,    /* 'y' */
+       105,    /* 'z' */
+       138,    /* '{' */
+       138,    /* '|' */
+       138,    /* '}' */
+       84,     /* '~' */
+       },
+
+       "AvantGarde-Demi",
+       0,
+       NO
+       }, {
+       /* width table for font AX */
+       {
+       47,     /* ' ' */
+       47,     /* '!' */
+       60,     /* '"' */
+       93,     /* '#' */
+       93,     /* '$' */
+       143,    /* '%' */
+       113,    /* '&' */
+       47,     /* ''' */
+       63,     /* '(' */
+       63,     /* ')' */
+       73,     /* '*' */
+       100,    /* '+' */
+       47,     /* ',' */
+       70,     /* '-' */
+       47,     /* '.' */
+       77,     /* '/' */
+       93,     /* '0' */
+       93,     /* '1' */
+       93,     /* '2' */
+       93,     /* '3' */
+       93,     /* '4' */
+       93,     /* '5' */
+       93,     /* '6' */
+       93,     /* '7' */
+       93,     /* '8' */
+       93,     /* '9' */
+       47,     /* ':' */
+       47,     /* ';' */
+       100,    /* '<' */
+       100,    /* '=' */
+       100,    /* '>' */
+       93,     /* '?' */
+       123,    /* '@' */
+       123,    /* 'A' */
+       97,     /* 'B' */
+       130,    /* 'C' */
+       117,    /* 'D' */
+       87,     /* 'E' */
+       80,     /* 'F' */
+       140,    /* 'G' */
+       113,    /* 'H' */
+       47,     /* 'I' */
+       80,     /* 'J' */
+       103,    /* 'K' */
+       73,     /* 'L' */
+       150,    /* 'M' */
+       123,    /* 'N' */
+       140,    /* 'O' */
+       93,     /* 'P' */
+       140,    /* 'Q' */
+       97,     /* 'R' */
+       87,     /* 'S' */
+       70,     /* 'T' */
+       107,    /* 'U' */
+       117,    /* 'V' */
+       150,    /* 'W' */
+       113,    /* 'X' */
+       103,    /* 'Y' */
+       83,     /* 'Z' */
+       53,     /* '[' */
+       107,    /* '\' */
+       53,     /* ']' */
+       100,    /* '^' */
+       83,     /* '_' */
+       47,     /* '`' */
+       110,    /* 'a' */
+       110,    /* 'b' */
+       107,    /* 'c' */
+       110,    /* 'd' */
+       107,    /* 'e' */
+       47,     /* 'f' */
+       110,    /* 'g' */
+       100,    /* 'h' */
+       40,     /* 'i' */
+       43,     /* 'j' */
+       97,     /* 'k' */
+       40,     /* 'l' */
+       157,    /* 'm' */
+       100,    /* 'n' */
+       107,    /* 'o' */
+       110,    /* 'p' */
+       110,    /* 'q' */
+       53,     /* 'r' */
+       73,     /* 's' */
+       50,     /* 't' */
+       100,    /* 'u' */
+       93,     /* 'v' */
+       133,    /* 'w' */
+       93,     /* 'x' */
+       97,     /* 'y' */
+       77,     /* 'z' */
+       57,     /* '{' */
+       100,    /* '|' */
+       57,     /* '}' */
+       100,    /* '~' */
+       },
+       /* height table for font AX */
+       {
+       153,    /* ' ' */
+       152,    /* '!' */
+       152,    /* '"' */
+       152,    /* '#' */
+       181,    /* '$' */
+       158,    /* '%' */
+       158,    /* '&' */
+       152,    /* ''' */
+       174,    /* '(' */
+       174,    /* ')' */
+       151,    /* '*' */
+       129,    /* '+' */
+       72,     /* ',' */
+       86,     /* '-' */
+       49,     /* '.' */
+       174,    /* '/' */
+       158,    /* '0' */
+       152,    /* '1' */
+       156,    /* '2' */
+       158,    /* '3' */
+       152,    /* '4' */
+       154,    /* '5' */
+       154,    /* '6' */
+       152,    /* '7' */
+       158,    /* '8' */
+       156,    /* '9' */
+       112,    /* ':' */
+       136,    /* ';' */
+       125,    /* '<' */
+       116,    /* '=' */
+       125,    /* '>' */
+       156,    /* '?' */
+       158,    /* '@' */
+       152,    /* 'A' */
+       152,    /* 'B' */
+       158,    /* 'C' */
+       152,    /* 'D' */
+       152,    /* 'E' */
+       152,    /* 'F' */
+       158,    /* 'G' */
+       152,    /* 'H' */
+       152,    /* 'I' */
+       154,    /* 'J' */
+       152,    /* 'K' */
+       152,    /* 'L' */
+       152,    /* 'M' */
+       152,    /* 'N' */
+       158,    /* 'O' */
+       152,    /* 'P' */
+       158,    /* 'Q' */
+       152,    /* 'R' */
+       158,    /* 'S' */
+       152,    /* 'T' */
+       154,    /* 'U' */
+       152,    /* 'V' */
+       152,    /* 'W' */
+       152,    /* 'X' */
+       152,    /* 'Y' */
+       152,    /* 'Z' */
+       174,    /* '[' */
+       152,    /* '\' */
+       174,    /* ']' */
+       156,    /* '^' */
+       44,     /* '_' */
+       152,    /* '`' */
+       124,    /* 'a' */
+       154,    /* 'b' */
+       124,    /* 'c' */
+       154,    /* 'd' */
+       124,    /* 'e' */
+       152,    /* 'f' */
+       158,    /* 'g' */
+       152,    /* 'h' */
+       152,    /* 'i' */
+       184,    /* 'j' */
+       152,    /* 'k' */
+       152,    /* 'l' */
+       122,    /* 'm' */
+       122,    /* 'n' */
+       124,    /* 'o' */
+       154,    /* 'p' */
+       154,    /* 'q' */
+       122,    /* 'r' */
+       124,    /* 's' */
+       152,    /* 't' */
+       121,    /* 'u' */
+       119,    /* 'v' */
+       119,    /* 'w' */
+       119,    /* 'x' */
+       151,    /* 'y' */
+       119,    /* 'z' */
+       174,    /* '{' */
+       152,    /* '|' */
+       174,    /* '}' */
+       98,     /* '~' */
+       },
+       /* ascent table for font AX */
+       {
+       108,    /* ' ' */
+       138,    /* '!' */
+       138,    /* '"' */
+       138,    /* '#' */
+       155,    /* '$' */
+       142,    /* '%' */
+       142,    /* '&' */
+       138,    /* ''' */
+       137,    /* '(' */
+       137,    /* ')' */
+       137,    /* '*' */
+       115,    /* '+' */
+       35,     /* ',' */
+       72,     /* '-' */
+       35,     /* '.' */
+       138,    /* '/' */
+       142,    /* '0' */
+       138,    /* '1' */
+       142,    /* '2' */
+       142,    /* '3' */
+       138,    /* '4' */
+       138,    /* '5' */
+       138,    /* '6' */
+       138,    /* '7' */
+       142,    /* '8' */
+       142,    /* '9' */
+       98,     /* ':' */
+       98,     /* ';' */
+       111,    /* '<' */
+       102,    /* '=' */
+       111,    /* '>' */
+       142,    /* '?' */
+       142,    /* '@' */
+       138,    /* 'A' */
+       138,    /* 'B' */
+       142,    /* 'C' */
+       138,    /* 'D' */
+       138,    /* 'E' */
+       138,    /* 'F' */
+       142,    /* 'G' */
+       138,    /* 'H' */
+       138,    /* 'I' */
+       138,    /* 'J' */
+       138,    /* 'K' */
+       138,    /* 'L' */
+       138,    /* 'M' */
+       138,    /* 'N' */
+       142,    /* 'O' */
+       138,    /* 'P' */
+       142,    /* 'Q' */
+       138,    /* 'R' */
+       142,    /* 'S' */
+       138,    /* 'T' */
+       138,    /* 'U' */
+       138,    /* 'V' */
+       138,    /* 'W' */
+       138,    /* 'X' */
+       138,    /* 'Y' */
+       138,    /* 'Z' */
+       137,    /* '[' */
+       138,    /* '\' */
+       137,    /* ']' */
+       142,    /* '^' */
+       8,      /* '_' */
+       138,    /* '`' */
+       108,    /* 'a' */
+       138,    /* 'b' */
+       108,    /* 'c' */
+       138,    /* 'd' */
+       108,    /* 'e' */
+       138,    /* 'f' */
+       108,    /* 'g' */
+       138,    /* 'h' */
+       138,    /* 'i' */
+       138,    /* 'j' */
+       138,    /* 'k' */
+       138,    /* 'l' */
+       108,    /* 'm' */
+       108,    /* 'n' */
+       108,    /* 'o' */
+       108,    /* 'p' */
+       108,    /* 'q' */
+       108,    /* 'r' */
+       108,    /* 's' */
+       138,    /* 't' */
+       105,    /* 'u' */
+       105,    /* 'v' */
+       105,    /* 'w' */
+       105,    /* 'x' */
+       105,    /* 'y' */
+       105,    /* 'z' */
+       138,    /* '{' */
+       138,    /* '|' */
+       138,    /* '}' */
+       84,     /* '~' */
+       },
+
+       "AvantGarde-DemiOblique",
+       0,
+       YES
+       }, {
+       /* width table for font CR */
+       {
+       100,    /* ' ' */
+       100,    /* '!' */
+       100,    /* '"' */
+       100,    /* '#' */
+       100,    /* '$' */
+       100,    /* '%' */
+       100,    /* '&' */
+       100,    /* ''' */
+       100,    /* '(' */
+       100,    /* ')' */
+       100,    /* '*' */
+       100,    /* '+' */
+       100,    /* ',' */
+       100,    /* '-' */
+       100,    /* '.' */
+       100,    /* '/' */
+       100,    /* '0' */
+       100,    /* '1' */
+       100,    /* '2' */
+       100,    /* '3' */
+       100,    /* '4' */
+       100,    /* '5' */
+       100,    /* '6' */
+       100,    /* '7' */
+       100,    /* '8' */
+       100,    /* '9' */
+       100,    /* ':' */
+       100,    /* ';' */
+       100,    /* '<' */
+       100,    /* '=' */
+       100,    /* '>' */
+       100,    /* '?' */
+       100,    /* '@' */
+       100,    /* 'A' */
+       100,    /* 'B' */
+       100,    /* 'C' */
+       100,    /* 'D' */
+       100,    /* 'E' */
+       100,    /* 'F' */
+       100,    /* 'G' */
+       100,    /* 'H' */
+       100,    /* 'I' */
+       100,    /* 'J' */
+       100,    /* 'K' */
+       100,    /* 'L' */
+       100,    /* 'M' */
+       100,    /* 'N' */
+       100,    /* 'O' */
+       100,    /* 'P' */
+       100,    /* 'Q' */
+       100,    /* 'R' */
+       100,    /* 'S' */
+       100,    /* 'T' */
+       100,    /* 'U' */
+       100,    /* 'V' */
+       100,    /* 'W' */
+       100,    /* 'X' */
+       100,    /* 'Y' */
+       100,    /* 'Z' */
+       100,    /* '[' */
+       100,    /* '\' */
+       100,    /* ']' */
+       100,    /* '^' */
+       100,    /* '_' */
+       100,    /* '`' */
+       100,    /* 'a' */
+       100,    /* 'b' */
+       100,    /* 'c' */
+       100,    /* 'd' */
+       100,    /* 'e' */
+       100,    /* 'f' */
+       100,    /* 'g' */
+       100,    /* 'h' */
+       100,    /* 'i' */
+       100,    /* 'j' */
+       100,    /* 'k' */
+       100,    /* 'l' */
+       100,    /* 'm' */
+       100,    /* 'n' */
+       100,    /* 'o' */
+       100,    /* 'p' */
+       100,    /* 'q' */
+       100,    /* 'r' */
+       100,    /* 's' */
+       100,    /* 't' */
+       100,    /* 'u' */
+       100,    /* 'v' */
+       100,    /* 'w' */
+       100,    /* 'x' */
+       100,    /* 'y' */
+       100,    /* 'z' */
+       100,    /* '{' */
+       100,    /* '|' */
+       100,    /* '}' */
+       100,    /* '~' */
+       },
+       /* height table for font CR */
+       {
+       153,    /* ' ' */
+       133,    /* '!' */
+       128,    /* '"' */
+       146,    /* '#' */
+       151,    /* '$' */
+       134,    /* '%' */
+       118,    /* '&' */
+       128,    /* ''' */
+       149,    /* '(' */
+       149,    /* ')' */
+       128,    /* '*' */
+       116,    /* '+' */
+       76,     /* ',' */
+       79,     /* '-' */
+       49,     /* '.' */
+       153,    /* '/' */
+       134,    /* '0' */
+       130,    /* '1' */
+       132,    /* '2' */
+       134,    /* '3' */
+       129,    /* '4' */
+       131,    /* '5' */
+       134,    /* '6' */
+       129,    /* '7' */
+       134,    /* '8' */
+       134,    /* '9' */
+       101,    /* ':' */
+       123,    /* ';' */
+       114,    /* '<' */
+       89,     /* '=' */
+       114,    /* '>' */
+       128,    /* '?' */
+       141,    /* '@' */
+       122,    /* 'A' */
+       122,    /* 'B' */
+       128,    /* 'C' */
+       122,    /* 'D' */
+       122,    /* 'E' */
+       122,    /* 'F' */
+       128,    /* 'G' */
+       122,    /* 'H' */
+       122,    /* 'I' */
+       124,    /* 'J' */
+       122,    /* 'K' */
+       122,    /* 'L' */
+       122,    /* 'M' */
+       122,    /* 'N' */
+       128,    /* 'O' */
+       122,    /* 'P' */
+       145,    /* 'Q' */
+       122,    /* 'R' */
+       128,    /* 'S' */
+       122,    /* 'T' */
+       124,    /* 'U' */
+       122,    /* 'V' */
+       122,    /* 'W' */
+       122,    /* 'X' */
+       122,    /* 'Y' */
+       122,    /* 'Z' */
+       151,    /* '[' */
+       153,    /* '\' */
+       151,    /* ']' */
+       130,    /* '^' */
+       34,     /* '_' */
+       128,    /* '`' */
+       104,    /* 'a' */
+       131,    /* 'b' */
+       104,    /* 'c' */
+       131,    /* 'd' */
+       104,    /* 'e' */
+       129,    /* 'f' */
+       134,    /* 'g' */
+       129,    /* 'h' */
+       132,    /* 'i' */
+       164,    /* 'j' */
+       129,    /* 'k' */
+       129,    /* 'l' */
+       102,    /* 'm' */
+       102,    /* 'n' */
+       104,    /* 'o' */
+       134,    /* 'p' */
+       134,    /* 'q' */
+       102,    /* 'r' */
+       104,    /* 's' */
+       124,    /* 't' */
+       101,    /* 'u' */
+       99,     /* 'v' */
+       99,     /* 'w' */
+       99,     /* 'x' */
+       128,    /* 'y' */
+       99,     /* 'z' */
+       149,    /* '{' */
+       149,    /* '|' */
+       149,    /* '}' */
+       86,     /* '~' */
+       },
+       /* ascent table for font CR */
+       {
+       108,    /* ' ' */
+       117,    /* '!' */
+       115,    /* '"' */
+       122,    /* '#' */
+       122,    /* '$' */
+       118,    /* '%' */
+       102,    /* '&' */
+       115,    /* ''' */
+       115,    /* '(' */
+       115,    /* ')' */
+       115,    /* '*' */
+       102,    /* '+' */
+       38,     /* ',' */
+       65,     /* '-' */
+       33,     /* '.' */
+       125,    /* '/' */
+       118,    /* '0' */
+       116,    /* '1' */
+       118,    /* '2' */
+       118,    /* '3' */
+       115,    /* '4' */
+       115,    /* '5' */
+       118,    /* '6' */
+       115,    /* '7' */
+       118,    /* '8' */
+       118,    /* '9' */
+       85,     /* ':' */
+       85,     /* ';' */
+       100,    /* '<' */
+       75,     /* '=' */
+       100,    /* '>' */
+       112,    /* '?' */
+       118,    /* '@' */
+       108,    /* 'A' */
+       108,    /* 'B' */
+       112,    /* 'C' */
+       108,    /* 'D' */
+       108,    /* 'E' */
+       108,    /* 'F' */
+       112,    /* 'G' */
+       108,    /* 'H' */
+       108,    /* 'I' */
+       108,    /* 'J' */
+       108,    /* 'K' */
+       108,    /* 'L' */
+       108,    /* 'M' */
+       108,    /* 'N' */
+       112,    /* 'O' */
+       108,    /* 'P' */
+       112,    /* 'Q' */
+       108,    /* 'R' */
+       112,    /* 'S' */
+       108,    /* 'T' */
+       108,    /* 'U' */
+       108,    /* 'V' */
+       108,    /* 'W' */
+       108,    /* 'X' */
+       108,    /* 'Y' */
+       108,    /* 'Z' */
+       115,    /* '[' */
+       125,    /* '\' */
+       115,    /* ']' */
+       116,    /* '^' */
+       2,      /* '_' */
+       115,    /* '`' */
+       88,     /* 'a' */
+       115,    /* 'b' */
+       88,     /* 'c' */
+       115,    /* 'd' */
+       88,     /* 'e' */
+       115,    /* 'f' */
+       88,     /* 'g' */
+       115,    /* 'h' */
+       118,    /* 'i' */
+       118,    /* 'j' */
+       115,    /* 'k' */
+       115,    /* 'l' */
+       88,     /* 'm' */
+       88,     /* 'n' */
+       88,     /* 'o' */
+       88,     /* 'p' */
+       88,     /* 'q' */
+       88,     /* 'r' */
+       88,     /* 's' */
+       108,    /* 't' */
+       85,     /* 'u' */
+       85,     /* 'v' */
+       85,     /* 'w' */
+       85,     /* 'x' */
+       85,     /* 'y' */
+       85,     /* 'z' */
+       115,    /* '{' */
+       115,    /* '|' */
+       115,    /* '}' */
+       72,     /* '~' */
+       },
+
+       "Courier",
+       0,
+       NO
+       }, {
+       /* width table for font CI */
+       {
+       100,    /* ' ' */
+       100,    /* '!' */
+       100,    /* '"' */
+       100,    /* '#' */
+       100,    /* '$' */
+       100,    /* '%' */
+       100,    /* '&' */
+       100,    /* ''' */
+       100,    /* '(' */
+       100,    /* ')' */
+       100,    /* '*' */
+       100,    /* '+' */
+       100,    /* ',' */
+       100,    /* '-' */
+       100,    /* '.' */
+       100,    /* '/' */
+       100,    /* '0' */
+       100,    /* '1' */
+       100,    /* '2' */
+       100,    /* '3' */
+       100,    /* '4' */
+       100,    /* '5' */
+       100,    /* '6' */
+       100,    /* '7' */
+       100,    /* '8' */
+       100,    /* '9' */
+       100,    /* ':' */
+       100,    /* ';' */
+       100,    /* '<' */
+       100,    /* '=' */
+       100,    /* '>' */
+       100,    /* '?' */
+       100,    /* '@' */
+       100,    /* 'A' */
+       100,    /* 'B' */
+       100,    /* 'C' */
+       100,    /* 'D' */
+       100,    /* 'E' */
+       100,    /* 'F' */
+       100,    /* 'G' */
+       100,    /* 'H' */
+       100,    /* 'I' */
+       100,    /* 'J' */
+       100,    /* 'K' */
+       100,    /* 'L' */
+       100,    /* 'M' */
+       100,    /* 'N' */
+       100,    /* 'O' */
+       100,    /* 'P' */
+       100,    /* 'Q' */
+       100,    /* 'R' */
+       100,    /* 'S' */
+       100,    /* 'T' */
+       100,    /* 'U' */
+       100,    /* 'V' */
+       100,    /* 'W' */
+       100,    /* 'X' */
+       100,    /* 'Y' */
+       100,    /* 'Z' */
+       100,    /* '[' */
+       100,    /* '\' */
+       100,    /* ']' */
+       100,    /* '^' */
+       100,    /* '_' */
+       100,    /* '`' */
+       100,    /* 'a' */
+       100,    /* 'b' */
+       100,    /* 'c' */
+       100,    /* 'd' */
+       100,    /* 'e' */
+       100,    /* 'f' */
+       100,    /* 'g' */
+       100,    /* 'h' */
+       100,    /* 'i' */
+       100,    /* 'j' */
+       100,    /* 'k' */
+       100,    /* 'l' */
+       100,    /* 'm' */
+       100,    /* 'n' */
+       100,    /* 'o' */
+       100,    /* 'p' */
+       100,    /* 'q' */
+       100,    /* 'r' */
+       100,    /* 's' */
+       100,    /* 't' */
+       100,    /* 'u' */
+       100,    /* 'v' */
+       100,    /* 'w' */
+       100,    /* 'x' */
+       100,    /* 'y' */
+       100,    /* 'z' */
+       100,    /* '{' */
+       100,    /* '|' */
+       100,    /* '}' */
+       100,    /* '~' */
+       },
+       /* height table for font CI */
+       {
+       153,    /* ' ' */
+       133,    /* '!' */
+       128,    /* '"' */
+       146,    /* '#' */
+       154,    /* '$' */
+       134,    /* '%' */
+       118,    /* '&' */
+       128,    /* ''' */
+       149,    /* '(' */
+       149,    /* ')' */
+       128,    /* '*' */
+       116,    /* '+' */
+       76,     /* ',' */
+       79,     /* '-' */
+       49,     /* '.' */
+       153,    /* '/' */
+       134,    /* '0' */
+       130,    /* '1' */
+       132,    /* '2' */
+       134,    /* '3' */
+       129,    /* '4' */
+       131,    /* '5' */
+       134,    /* '6' */
+       129,    /* '7' */
+       134,    /* '8' */
+       134,    /* '9' */
+       101,    /* ':' */
+       123,    /* ';' */
+       114,    /* '<' */
+       89,     /* '=' */
+       114,    /* '>' */
+       128,    /* '?' */
+       141,    /* '@' */
+       122,    /* 'A' */
+       122,    /* 'B' */
+       128,    /* 'C' */
+       122,    /* 'D' */
+       122,    /* 'E' */
+       122,    /* 'F' */
+       128,    /* 'G' */
+       122,    /* 'H' */
+       122,    /* 'I' */
+       124,    /* 'J' */
+       122,    /* 'K' */
+       122,    /* 'L' */
+       122,    /* 'M' */
+       122,    /* 'N' */
+       128,    /* 'O' */
+       122,    /* 'P' */
+       145,    /* 'Q' */
+       122,    /* 'R' */
+       128,    /* 'S' */
+       122,    /* 'T' */
+       124,    /* 'U' */
+       122,    /* 'V' */
+       122,    /* 'W' */
+       122,    /* 'X' */
+       122,    /* 'Y' */
+       122,    /* 'Z' */
+       151,    /* '[' */
+       153,    /* '\' */
+       151,    /* ']' */
+       130,    /* '^' */
+       34,     /* '_' */
+       129,    /* '`' */
+       104,    /* 'a' */
+       131,    /* 'b' */
+       104,    /* 'c' */
+       131,    /* 'd' */
+       104,    /* 'e' */
+       129,    /* 'f' */
+       134,    /* 'g' */
+       129,    /* 'h' */
+       132,    /* 'i' */
+       164,    /* 'j' */
+       129,    /* 'k' */
+       129,    /* 'l' */
+       102,    /* 'm' */
+       102,    /* 'n' */
+       104,    /* 'o' */
+       134,    /* 'p' */
+       134,    /* 'q' */
+       102,    /* 'r' */
+       104,    /* 's' */
+       124,    /* 't' */
+       101,    /* 'u' */
+       99,     /* 'v' */
+       99,     /* 'w' */
+       99,     /* 'x' */
+       128,    /* 'y' */
+       99,     /* 'z' */
+       149,    /* '{' */
+       149,    /* '|' */
+       149,    /* '}' */
+       86,     /* '~' */
+       },
+       /* ascent table for font CI */
+       {
+       108,    /* ' ' */
+       117,    /* '!' */
+       115,    /* '"' */
+       122,    /* '#' */
+       125,    /* '$' */
+       118,    /* '%' */
+       102,    /* '&' */
+       115,    /* ''' */
+       115,    /* '(' */
+       115,    /* ')' */
+       115,    /* '*' */
+       102,    /* '+' */
+       38,     /* ',' */
+       65,     /* '-' */
+       33,     /* '.' */
+       125,    /* '/' */
+       118,    /* '0' */
+       116,    /* '1' */
+       118,    /* '2' */
+       118,    /* '3' */
+       115,    /* '4' */
+       115,    /* '5' */
+       118,    /* '6' */
+       115,    /* '7' */
+       118,    /* '8' */
+       118,    /* '9' */
+       85,     /* ':' */
+       85,     /* ';' */
+       100,    /* '<' */
+       75,     /* '=' */
+       100,    /* '>' */
+       112,    /* '?' */
+       118,    /* '@' */
+       108,    /* 'A' */
+       108,    /* 'B' */
+       112,    /* 'C' */
+       108,    /* 'D' */
+       108,    /* 'E' */
+       108,    /* 'F' */
+       112,    /* 'G' */
+       108,    /* 'H' */
+       108,    /* 'I' */
+       108,    /* 'J' */
+       108,    /* 'K' */
+       108,    /* 'L' */
+       108,    /* 'M' */
+       108,    /* 'N' */
+       112,    /* 'O' */
+       108,    /* 'P' */
+       112,    /* 'Q' */
+       108,    /* 'R' */
+       112,    /* 'S' */
+       108,    /* 'T' */
+       108,    /* 'U' */
+       108,    /* 'V' */
+       108,    /* 'W' */
+       108,    /* 'X' */
+       108,    /* 'Y' */
+       108,    /* 'Z' */
+       115,    /* '[' */
+       125,    /* '\' */
+       115,    /* ']' */
+       116,    /* '^' */
+       2,      /* '_' */
+       115,    /* '`' */
+       88,     /* 'a' */
+       115,    /* 'b' */
+       88,     /* 'c' */
+       115,    /* 'd' */
+       88,     /* 'e' */
+       115,    /* 'f' */
+       88,     /* 'g' */
+       115,    /* 'h' */
+       118,    /* 'i' */
+       118,    /* 'j' */
+       115,    /* 'k' */
+       115,    /* 'l' */
+       88,     /* 'm' */
+       88,     /* 'n' */
+       88,     /* 'o' */
+       88,     /* 'p' */
+       88,     /* 'q' */
+       88,     /* 'r' */
+       88,     /* 's' */
+       108,    /* 't' */
+       85,     /* 'u' */
+       85,     /* 'v' */
+       85,     /* 'w' */
+       85,     /* 'x' */
+       85,     /* 'y' */
+       85,     /* 'z' */
+       115,    /* '{' */
+       115,    /* '|' */
+       115,    /* '}' */
+       72,     /* '~' */
+       },
+
+       "Courier-Italic",
+       0,
+       YES
+       }, {
+       /* width table for font CB */
+       {
+       100,    /* ' ' */
+       100,    /* '!' */
+       100,    /* '"' */
+       100,    /* '#' */
+       100,    /* '$' */
+       100,    /* '%' */
+       100,    /* '&' */
+       100,    /* ''' */
+       100,    /* '(' */
+       100,    /* ')' */
+       100,    /* '*' */
+       100,    /* '+' */
+       100,    /* ',' */
+       100,    /* '-' */
+       100,    /* '.' */
+       100,    /* '/' */
+       100,    /* '0' */
+       100,    /* '1' */
+       100,    /* '2' */
+       100,    /* '3' */
+       100,    /* '4' */
+       100,    /* '5' */
+       100,    /* '6' */
+       100,    /* '7' */
+       100,    /* '8' */
+       100,    /* '9' */
+       100,    /* ':' */
+       100,    /* ';' */
+       100,    /* '<' */
+       100,    /* '=' */
+       100,    /* '>' */
+       100,    /* '?' */
+       100,    /* '@' */
+       100,    /* 'A' */
+       100,    /* 'B' */
+       100,    /* 'C' */
+       100,    /* 'D' */
+       100,    /* 'E' */
+       100,    /* 'F' */
+       100,    /* 'G' */
+       100,    /* 'H' */
+       100,    /* 'I' */
+       100,    /* 'J' */
+       100,    /* 'K' */
+       100,    /* 'L' */
+       100,    /* 'M' */
+       100,    /* 'N' */
+       100,    /* 'O' */
+       100,    /* 'P' */
+       100,    /* 'Q' */
+       100,    /* 'R' */
+       100,    /* 'S' */
+       100,    /* 'T' */
+       100,    /* 'U' */
+       100,    /* 'V' */
+       100,    /* 'W' */
+       100,    /* 'X' */
+       100,    /* 'Y' */
+       100,    /* 'Z' */
+       100,    /* '[' */
+       100,    /* '\' */
+       100,    /* ']' */
+       100,    /* '^' */
+       100,    /* '_' */
+       100,    /* '`' */
+       100,    /* 'a' */
+       100,    /* 'b' */
+       100,    /* 'c' */
+       100,    /* 'd' */
+       100,    /* 'e' */
+       100,    /* 'f' */
+       100,    /* 'g' */
+       100,    /* 'h' */
+       100,    /* 'i' */
+       100,    /* 'j' */
+       100,    /* 'k' */
+       100,    /* 'l' */
+       100,    /* 'm' */
+       100,    /* 'n' */
+       100,    /* 'o' */
+       100,    /* 'p' */
+       100,    /* 'q' */
+       100,    /* 'r' */
+       100,    /* 's' */
+       100,    /* 't' */
+       100,    /* 'u' */
+       100,    /* 'v' */
+       100,    /* 'w' */
+       100,    /* 'x' */
+       100,    /* 'y' */
+       100,    /* 'z' */
+       100,    /* '{' */
+       100,    /* '|' */
+       100,    /* '}' */
+       100,    /* '~' */
+       },
+       /* height table for font CB */
+       {
+       153,    /* ' ' */
+       136,    /* '!' */
+       129,    /* '"' */
+       156,    /* '#' */
+       161,    /* '$' */
+       131,    /* '%' */
+       121,    /* '&' */
+       132,    /* ''' */
+       159,    /* '(' */
+       159,    /* ')' */
+       131,    /* '*' */
+       121,    /* '+' */
+       76,     /* ',' */
+       82,     /* '-' */
+       49,     /* '.' */
+       162,    /* '/' */
+       138,    /* '0' */
+       134,    /* '1' */
+       136,    /* '2' */
+       138,    /* '3' */
+       131,    /* '4' */
+       134,    /* '5' */
+       138,    /* '6' */
+       132,    /* '7' */
+       138,    /* '8' */
+       138,    /* '9' */
+       104,    /* ':' */
+       129,    /* ';' */
+       111,    /* '<' */
+       99,     /* '=' */
+       111,    /* '>' */
+       131,    /* '?' */
+       158,    /* '@' */
+       126,    /* 'A' */
+       126,    /* 'B' */
+       131,    /* 'C' */
+       126,    /* 'D' */
+       126,    /* 'E' */
+       126,    /* 'F' */
+       131,    /* 'G' */
+       126,    /* 'H' */
+       126,    /* 'I' */
+       128,    /* 'J' */
+       126,    /* 'K' */
+       126,    /* 'L' */
+       126,    /* 'M' */
+       126,    /* 'N' */
+       131,    /* 'O' */
+       126,    /* 'P' */
+       154,    /* 'Q' */
+       126,    /* 'R' */
+       131,    /* 'S' */
+       126,    /* 'T' */
+       128,    /* 'U' */
+       126,    /* 'V' */
+       126,    /* 'W' */
+       126,    /* 'X' */
+       126,    /* 'Y' */
+       126,    /* 'Z' */
+       158,    /* '[' */
+       162,    /* '\' */
+       158,    /* ']' */
+       136,    /* '^' */
+       38,     /* '_' */
+       129,    /* '`' */
+       108,    /* 'a' */
+       134,    /* 'b' */
+       108,    /* 'c' */
+       134,    /* 'd' */
+       108,    /* 'e' */
+       132,    /* 'f' */
+       141,    /* 'g' */
+       132,    /* 'h' */
+       132,    /* 'i' */
+       168,    /* 'j' */
+       132,    /* 'k' */
+       132,    /* 'l' */
+       106,    /* 'm' */
+       106,    /* 'n' */
+       108,    /* 'o' */
+       141,    /* 'p' */
+       141,    /* 'q' */
+       106,    /* 'r' */
+       108,    /* 's' */
+       131,    /* 't' */
+       104,    /* 'u' */
+       102,    /* 'v' */
+       102,    /* 'w' */
+       102,    /* 'x' */
+       138,    /* 'y' */
+       102,    /* 'z' */
+       157,    /* '{' */
+       157,    /* '|' */
+       157,    /* '}' */
+       92,     /* '~' */
+       },
+       /* ascent table for font CB */
+       {
+       108,    /* ' ' */
+       120,    /* '!' */
+       115,    /* '"' */
+       126,    /* '#' */
+       128,    /* '$' */
+       115,    /* '%' */
+       105,    /* '&' */
+       118,    /* ''' */
+       119,    /* '(' */
+       119,    /* ')' */
+       118,    /* '*' */
+       107,    /* '+' */
+       36,     /* ',' */
+       68,     /* '-' */
+       33,     /* '.' */
+       130,    /* '/' */
+       122,    /* '0' */
+       120,    /* '1' */
+       122,    /* '2' */
+       122,    /* '3' */
+       118,    /* '4' */
+       118,    /* '5' */
+       122,    /* '6' */
+       118,    /* '7' */
+       122,    /* '8' */
+       122,    /* '9' */
+       88,     /* ':' */
+       88,     /* ';' */
+       97,     /* '<' */
+       85,     /* '=' */
+       97,     /* '>' */
+       115,    /* '?' */
+       118,    /* '@' */
+       112,    /* 'A' */
+       112,    /* 'B' */
+       115,    /* 'C' */
+       112,    /* 'D' */
+       112,    /* 'E' */
+       112,    /* 'F' */
+       115,    /* 'G' */
+       112,    /* 'H' */
+       112,    /* 'I' */
+       112,    /* 'J' */
+       112,    /* 'K' */
+       112,    /* 'L' */
+       112,    /* 'M' */
+       112,    /* 'N' */
+       115,    /* 'O' */
+       112,    /* 'P' */
+       115,    /* 'Q' */
+       112,    /* 'R' */
+       115,    /* 'S' */
+       112,    /* 'T' */
+       112,    /* 'U' */
+       112,    /* 'V' */
+       112,    /* 'W' */
+       112,    /* 'X' */
+       112,    /* 'Y' */
+       112,    /* 'Z' */
+       118,    /* '[' */
+       130,    /* '\' */
+       118,    /* ']' */
+       123,    /* '^' */
+       2,      /* '_' */
+       115,    /* '`' */
+       92,     /* 'a' */
+       118,    /* 'b' */
+       92,     /* 'c' */
+       118,    /* 'd' */
+       92,     /* 'e' */
+       118,    /* 'f' */
+       92,     /* 'g' */
+       118,    /* 'h' */
+       118,    /* 'i' */
+       118,    /* 'j' */
+       118,    /* 'k' */
+       118,    /* 'l' */
+       92,     /* 'm' */
+       92,     /* 'n' */
+       92,     /* 'o' */
+       92,     /* 'p' */
+       92,     /* 'q' */
+       92,     /* 'r' */
+       92,     /* 's' */
+       115,    /* 't' */
+       88,     /* 'u' */
+       88,     /* 'v' */
+       88,     /* 'w' */
+       88,     /* 'x' */
+       88,     /* 'y' */
+       88,     /* 'z' */
+       118,    /* '{' */
+       118,    /* '|' */
+       118,    /* '}' */
+       78,     /* '~' */
+       },
+
+       "Courier-Bold",
+       0,
+       NO
+       }, {
+       /* width table for font CX */
+       {
+       100,    /* ' ' */
+       100,    /* '!' */
+       100,    /* '"' */
+       100,    /* '#' */
+       100,    /* '$' */
+       100,    /* '%' */
+       100,    /* '&' */
+       100,    /* ''' */
+       100,    /* '(' */
+       100,    /* ')' */
+       100,    /* '*' */
+       100,    /* '+' */
+       100,    /* ',' */
+       100,    /* '-' */
+       100,    /* '.' */
+       100,    /* '/' */
+       100,    /* '0' */
+       100,    /* '1' */
+       100,    /* '2' */
+       100,    /* '3' */
+       100,    /* '4' */
+       100,    /* '5' */
+       100,    /* '6' */
+       100,    /* '7' */
+       100,    /* '8' */
+       100,    /* '9' */
+       100,    /* ':' */
+       100,    /* ';' */
+       100,    /* '<' */
+       100,    /* '=' */
+       100,    /* '>' */
+       100,    /* '?' */
+       100,    /* '@' */
+       100,    /* 'A' */
+       100,    /* 'B' */
+       100,    /* 'C' */
+       100,    /* 'D' */
+       100,    /* 'E' */
+       100,    /* 'F' */
+       100,    /* 'G' */
+       100,    /* 'H' */
+       100,    /* 'I' */
+       100,    /* 'J' */
+       100,    /* 'K' */
+       100,    /* 'L' */
+       100,    /* 'M' */
+       100,    /* 'N' */
+       100,    /* 'O' */
+       100,    /* 'P' */
+       100,    /* 'Q' */
+       100,    /* 'R' */
+       100,    /* 'S' */
+       100,    /* 'T' */
+       100,    /* 'U' */
+       100,    /* 'V' */
+       100,    /* 'W' */
+       100,    /* 'X' */
+       100,    /* 'Y' */
+       100,    /* 'Z' */
+       100,    /* '[' */
+       100,    /* '\' */
+       100,    /* ']' */
+       100,    /* '^' */
+       100,    /* '_' */
+       100,    /* '`' */
+       100,    /* 'a' */
+       100,    /* 'b' */
+       100,    /* 'c' */
+       100,    /* 'd' */
+       100,    /* 'e' */
+       100,    /* 'f' */
+       100,    /* 'g' */
+       100,    /* 'h' */
+       100,    /* 'i' */
+       100,    /* 'j' */
+       100,    /* 'k' */
+       100,    /* 'l' */
+       100,    /* 'm' */
+       100,    /* 'n' */
+       100,    /* 'o' */
+       100,    /* 'p' */
+       100,    /* 'q' */
+       100,    /* 'r' */
+       100,    /* 's' */
+       100,    /* 't' */
+       100,    /* 'u' */
+       100,    /* 'v' */
+       100,    /* 'w' */
+       100,    /* 'x' */
+       100,    /* 'y' */
+       100,    /* 'z' */
+       100,    /* '{' */
+       100,    /* '|' */
+       100,    /* '}' */
+       100,    /* '~' */
+       },
+       /* height table for font CX */
+       {
+       153,    /* ' ' */
+       136,    /* '!' */
+       129,    /* '"' */
+       156,    /* '#' */
+       161,    /* '$' */
+       131,    /* '%' */
+       121,    /* '&' */
+       132,    /* ''' */
+       159,    /* '(' */
+       159,    /* ')' */
+       131,    /* '*' */
+       121,    /* '+' */
+       76,     /* ',' */
+       82,     /* '-' */
+       49,     /* '.' */
+       162,    /* '/' */
+       138,    /* '0' */
+       134,    /* '1' */
+       136,    /* '2' */
+       138,    /* '3' */
+       131,    /* '4' */
+       134,    /* '5' */
+       138,    /* '6' */
+       132,    /* '7' */
+       138,    /* '8' */
+       138,    /* '9' */
+       104,    /* ':' */
+       129,    /* ';' */
+       111,    /* '<' */
+       99,     /* '=' */
+       111,    /* '>' */
+       131,    /* '?' */
+       158,    /* '@' */
+       126,    /* 'A' */
+       126,    /* 'B' */
+       131,    /* 'C' */
+       126,    /* 'D' */
+       126,    /* 'E' */
+       126,    /* 'F' */
+       131,    /* 'G' */
+       126,    /* 'H' */
+       126,    /* 'I' */
+       128,    /* 'J' */
+       126,    /* 'K' */
+       126,    /* 'L' */
+       126,    /* 'M' */
+       126,    /* 'N' */
+       131,    /* 'O' */
+       126,    /* 'P' */
+       154,    /* 'Q' */
+       126,    /* 'R' */
+       131,    /* 'S' */
+       126,    /* 'T' */
+       128,    /* 'U' */
+       126,    /* 'V' */
+       126,    /* 'W' */
+       126,    /* 'X' */
+       126,    /* 'Y' */
+       126,    /* 'Z' */
+       158,    /* '[' */
+       162,    /* '\' */
+       158,    /* ']' */
+       136,    /* '^' */
+       38,     /* '_' */
+       129,    /* '`' */
+       108,    /* 'a' */
+       134,    /* 'b' */
+       108,    /* 'c' */
+       134,    /* 'd' */
+       108,    /* 'e' */
+       132,    /* 'f' */
+       141,    /* 'g' */
+       132,    /* 'h' */
+       132,    /* 'i' */
+       168,    /* 'j' */
+       132,    /* 'k' */
+       132,    /* 'l' */
+       106,    /* 'm' */
+       106,    /* 'n' */
+       108,    /* 'o' */
+       141,    /* 'p' */
+       141,    /* 'q' */
+       106,    /* 'r' */
+       108,    /* 's' */
+       131,    /* 't' */
+       104,    /* 'u' */
+       102,    /* 'v' */
+       102,    /* 'w' */
+       102,    /* 'x' */
+       138,    /* 'y' */
+       102,    /* 'z' */
+       157,    /* '{' */
+       157,    /* '|' */
+       157,    /* '}' */
+       92,     /* '~' */
+       },
+       /* ascent table for font CX */
+       {
+       108,    /* ' ' */
+       120,    /* '!' */
+       115,    /* '"' */
+       126,    /* '#' */
+       128,    /* '$' */
+       115,    /* '%' */
+       105,    /* '&' */
+       118,    /* ''' */
+       119,    /* '(' */
+       119,    /* ')' */
+       118,    /* '*' */
+       107,    /* '+' */
+       36,     /* ',' */
+       68,     /* '-' */
+       33,     /* '.' */
+       130,    /* '/' */
+       122,    /* '0' */
+       120,    /* '1' */
+       122,    /* '2' */
+       122,    /* '3' */
+       118,    /* '4' */
+       118,    /* '5' */
+       122,    /* '6' */
+       118,    /* '7' */
+       122,    /* '8' */
+       122,    /* '9' */
+       88,     /* ':' */
+       88,     /* ';' */
+       97,     /* '<' */
+       85,     /* '=' */
+       97,     /* '>' */
+       115,    /* '?' */
+       118,    /* '@' */
+       112,    /* 'A' */
+       112,    /* 'B' */
+       115,    /* 'C' */
+       112,    /* 'D' */
+       112,    /* 'E' */
+       112,    /* 'F' */
+       115,    /* 'G' */
+       112,    /* 'H' */
+       112,    /* 'I' */
+       112,    /* 'J' */
+       112,    /* 'K' */
+       112,    /* 'L' */
+       112,    /* 'M' */
+       112,    /* 'N' */
+       115,    /* 'O' */
+       112,    /* 'P' */
+       115,    /* 'Q' */
+       112,    /* 'R' */
+       115,    /* 'S' */
+       112,    /* 'T' */
+       112,    /* 'U' */
+       112,    /* 'V' */
+       112,    /* 'W' */
+       112,    /* 'X' */
+       112,    /* 'Y' */
+       112,    /* 'Z' */
+       118,    /* '[' */
+       130,    /* '\' */
+       118,    /* ']' */
+       123,    /* '^' */
+       2,      /* '_' */
+       115,    /* '`' */
+       92,     /* 'a' */
+       118,    /* 'b' */
+       92,     /* 'c' */
+       118,    /* 'd' */
+       92,     /* 'e' */
+       118,    /* 'f' */
+       92,     /* 'g' */
+       118,    /* 'h' */
+       118,    /* 'i' */
+       118,    /* 'j' */
+       118,    /* 'k' */
+       118,    /* 'l' */
+       92,     /* 'm' */
+       92,     /* 'n' */
+       92,     /* 'o' */
+       92,     /* 'p' */
+       92,     /* 'q' */
+       92,     /* 'r' */
+       92,     /* 's' */
+       115,    /* 't' */
+       88,     /* 'u' */
+       88,     /* 'v' */
+       88,     /* 'w' */
+       88,     /* 'x' */
+       88,     /* 'y' */
+       88,     /* 'z' */
+       118,    /* '{' */
+       118,    /* '|' */
+       118,    /* '}' */
+       78,     /* '~' */
+       },
+
+       "Courier-BoldItalic",
+       0,
+       YES
+       }, {
+       /* width table for font HR */
+       {
+       46,     /* ' ' */
+       46,     /* '!' */
+       59,     /* '"' */
+       93,     /* '#' */
+       93,     /* '$' */
+       148,    /* '%' */
+       111,    /* '&' */
+       37,     /* ''' */
+       55,     /* '(' */
+       55,     /* ')' */
+       65,     /* '*' */
+       97,     /* '+' */
+       46,     /* ',' */
+       55,     /* '-' */
+       46,     /* '.' */
+       46,     /* '/' */
+       93,     /* '0' */
+       93,     /* '1' */
+       93,     /* '2' */
+       93,     /* '3' */
+       93,     /* '4' */
+       93,     /* '5' */
+       93,     /* '6' */
+       93,     /* '7' */
+       93,     /* '8' */
+       93,     /* '9' */
+       46,     /* ':' */
+       46,     /* ';' */
+       97,     /* '<' */
+       97,     /* '=' */
+       97,     /* '>' */
+       93,     /* '?' */
+       169,    /* '@' */
+       111,    /* 'A' */
+       111,    /* 'B' */
+       120,    /* 'C' */
+       120,    /* 'D' */
+       111,    /* 'E' */
+       102,    /* 'F' */
+       130,    /* 'G' */
+       120,    /* 'H' */
+       46,     /* 'I' */
+       83,     /* 'J' */
+       111,    /* 'K' */
+       93,     /* 'L' */
+       139,    /* 'M' */
+       120,    /* 'N' */
+       130,    /* 'O' */
+       111,    /* 'P' */
+       130,    /* 'Q' */
+       120,    /* 'R' */
+       111,    /* 'S' */
+       102,    /* 'T' */
+       120,    /* 'U' */
+       111,    /* 'V' */
+       157,    /* 'W' */
+       111,    /* 'X' */
+       111,    /* 'Y' */
+       102,    /* 'Z' */
+       46,     /* '[' */
+       46,     /* '\' */
+       46,     /* ']' */
+       78,     /* '^' */
+       93,     /* '_' */
+       37,     /* '`' */
+       93,     /* 'a' */
+       93,     /* 'b' */
+       83,     /* 'c' */
+       93,     /* 'd' */
+       93,     /* 'e' */
+       46,     /* 'f' */
+       93,     /* 'g' */
+       93,     /* 'h' */
+       37,     /* 'i' */
+       37,     /* 'j' */
+       83,     /* 'k' */
+       37,     /* 'l' */
+       139,    /* 'm' */
+       93,     /* 'n' */
+       93,     /* 'o' */
+       93,     /* 'p' */
+       93,     /* 'q' */
+       55,     /* 'r' */
+       83,     /* 's' */
+       46,     /* 't' */
+       93,     /* 'u' */
+       83,     /* 'v' */
+       120,    /* 'w' */
+       83,     /* 'x' */
+       83,     /* 'y' */
+       83,     /* 'z' */
+       56,     /* '{' */
+       43,     /* '|' */
+       56,     /* '}' */
+       97,     /* '~' */
+       },
+       /* height table for font HR */
+       {
+       153,    /* ' ' */
+       149,    /* '!' */
+       146,    /* '"' */
+       146,    /* '#' */
+       177,    /* '$' */
+       148,    /* '%' */
+       149,    /* '&' */
+       149,    /* ''' */
+       184,    /* '(' */
+       184,    /* ')' */
+       149,    /* '*' */
+       109,    /* '+' */
+       70,     /* ',' */
+       79,     /* '-' */
+       46,     /* '.' */
+       151,    /* '/' */
+       149,    /* '0' */
+       146,    /* '1' */
+       146,    /* '2' */
+       149,    /* '3' */
+       146,    /* '4' */
+       149,    /* '5' */
+       149,    /* '6' */
+       146,    /* '7' */
+       149,    /* '8' */
+       149,    /* '9' */
+       116,    /* ':' */
+       140,    /* ';' */
+       108,    /* '<' */
+       89,     /* '=' */
+       108,    /* '>' */
+       152,    /* '?' */
+       178,    /* '@' */
+       149,    /* 'A' */
+       149,    /* 'B' */
+       155,    /* 'C' */
+       149,    /* 'D' */
+       149,    /* 'E' */
+       149,    /* 'F' */
+       155,    /* 'G' */
+       149,    /* 'H' */
+       149,    /* 'I' */
+       152,    /* 'J' */
+       149,    /* 'K' */
+       149,    /* 'L' */
+       149,    /* 'M' */
+       149,    /* 'N' */
+       155,    /* 'O' */
+       149,    /* 'P' */
+       162,    /* 'Q' */
+       149,    /* 'R' */
+       155,    /* 'S' */
+       149,    /* 'T' */
+       152,    /* 'U' */
+       149,    /* 'V' */
+       149,    /* 'W' */
+       149,    /* 'X' */
+       149,    /* 'Y' */
+       149,    /* 'Z' */
+       184,    /* '[' */
+       151,    /* '\' */
+       184,    /* ']' */
+       146,    /* '^' */
+       38,     /* '_' */
+       146,    /* '`' */
+       122,    /* 'a' */
+       152,    /* 'b' */
+       122,    /* 'c' */
+       152,    /* 'd' */
+       122,    /* 'e' */
+       149,    /* 'f' */
+       154,    /* 'g' */
+       149,    /* 'h' */
+       149,    /* 'i' */
+       185,    /* 'j' */
+       149,    /* 'k' */
+       149,    /* 'l' */
+       119,    /* 'm' */
+       119,    /* 'n' */
+       122,    /* 'o' */
+       154,    /* 'p' */
+       154,    /* 'q' */
+       119,    /* 'r' */
+       122,    /* 's' */
+       142,    /* 't' */
+       118,    /* 'u' */
+       116,    /* 'v' */
+       116,    /* 'w' */
+       116,    /* 'x' */
+       151,    /* 'y' */
+       116,    /* 'z' */
+       184,    /* '{' */
+       184,    /* '|' */
+       184,    /* '}' */
+       99,     /* '~' */
+       },
+       /* ascent table for font HR */
+       {
+       108,    /* ' ' */
+       135,    /* '!' */
+       132,    /* '"' */
+       130,    /* '#' */
+       142,    /* '$' */
+       132,    /* '%' */
+       132,    /* '&' */
+       135,    /* ''' */
+       135,    /* '(' */
+       135,    /* ')' */
+       135,    /* '*' */
+       93,     /* '+' */
+       32,     /* ',' */
+       65,     /* '-' */
+       32,     /* '.' */
+       135,    /* '/' */
+       132,    /* '0' */
+       132,    /* '1' */
+       132,    /* '2' */
+       132,    /* '3' */
+       132,    /* '4' */
+       132,    /* '5' */
+       132,    /* '6' */
+       132,    /* '7' */
+       132,    /* '8' */
+       132,    /* '9' */
+       102,    /* ':' */
+       102,    /* ';' */
+       93,     /* '<' */
+       75,     /* '=' */
+       93,     /* '>' */
+       138,    /* '?' */
+       138,    /* '@' */
+       135,    /* 'A' */
+       135,    /* 'B' */
+       138,    /* 'C' */
+       135,    /* 'D' */
+       135,    /* 'E' */
+       135,    /* 'F' */
+       138,    /* 'G' */
+       135,    /* 'H' */
+       135,    /* 'I' */
+       135,    /* 'J' */
+       135,    /* 'K' */
+       135,    /* 'L' */
+       135,    /* 'M' */
+       135,    /* 'N' */
+       138,    /* 'O' */
+       135,    /* 'P' */
+       138,    /* 'Q' */
+       135,    /* 'R' */
+       138,    /* 'S' */
+       135,    /* 'T' */
+       135,    /* 'U' */
+       135,    /* 'V' */
+       135,    /* 'W' */
+       135,    /* 'X' */
+       135,    /* 'Y' */
+       135,    /* 'Z' */
+       135,    /* '[' */
+       135,    /* '\' */
+       135,    /* ']' */
+       132,    /* '^' */
+       -5,     /* '_' */
+       132,    /* '`' */
+       105,    /* 'a' */
+       135,    /* 'b' */
+       105,    /* 'c' */
+       135,    /* 'd' */
+       105,    /* 'e' */
+       135,    /* 'f' */
+       105,    /* 'g' */
+       135,    /* 'h' */
+       135,    /* 'i' */
+       135,    /* 'j' */
+       135,    /* 'k' */
+       135,    /* 'l' */
+       105,    /* 'm' */
+       105,    /* 'n' */
+       105,    /* 'o' */
+       105,    /* 'p' */
+       105,    /* 'q' */
+       105,    /* 'r' */
+       105,    /* 's' */
+       125,    /* 't' */
+       102,    /* 'u' */
+       102,    /* 'v' */
+       102,    /* 'w' */
+       102,    /* 'x' */
+       102,    /* 'y' */
+       102,    /* 'z' */
+       135,    /* '{' */
+       135,    /* '|' */
+       135,    /* '}' */
+       85,     /* '~' */
+       },
+
+       "Helvetica",
+       0,
+       NO
+       }, {
+       /* width table for font HI */
+       {
+       46,     /* ' ' */
+       46,     /* '!' */
+       59,     /* '"' */
+       93,     /* '#' */
+       93,     /* '$' */
+       148,    /* '%' */
+       111,    /* '&' */
+       37,     /* ''' */
+       55,     /* '(' */
+       55,     /* ')' */
+       65,     /* '*' */
+       97,     /* '+' */
+       46,     /* ',' */
+       55,     /* '-' */
+       46,     /* '.' */
+       46,     /* '/' */
+       93,     /* '0' */
+       93,     /* '1' */
+       93,     /* '2' */
+       93,     /* '3' */
+       93,     /* '4' */
+       93,     /* '5' */
+       93,     /* '6' */
+       93,     /* '7' */
+       93,     /* '8' */
+       93,     /* '9' */
+       46,     /* ':' */
+       46,     /* ';' */
+       97,     /* '<' */
+       97,     /* '=' */
+       97,     /* '>' */
+       93,     /* '?' */
+       169,    /* '@' */
+       111,    /* 'A' */
+       111,    /* 'B' */
+       120,    /* 'C' */
+       120,    /* 'D' */
+       111,    /* 'E' */
+       102,    /* 'F' */
+       130,    /* 'G' */
+       120,    /* 'H' */
+       46,     /* 'I' */
+       83,     /* 'J' */
+       111,    /* 'K' */
+       93,     /* 'L' */
+       139,    /* 'M' */
+       120,    /* 'N' */
+       130,    /* 'O' */
+       111,    /* 'P' */
+       130,    /* 'Q' */
+       120,    /* 'R' */
+       111,    /* 'S' */
+       102,    /* 'T' */
+       120,    /* 'U' */
+       111,    /* 'V' */
+       157,    /* 'W' */
+       111,    /* 'X' */
+       111,    /* 'Y' */
+       102,    /* 'Z' */
+       46,     /* '[' */
+       46,     /* '\' */
+       46,     /* ']' */
+       78,     /* '^' */
+       93,     /* '_' */
+       37,     /* '`' */
+       93,     /* 'a' */
+       93,     /* 'b' */
+       83,     /* 'c' */
+       93,     /* 'd' */
+       93,     /* 'e' */
+       46,     /* 'f' */
+       93,     /* 'g' */
+       93,     /* 'h' */
+       37,     /* 'i' */
+       37,     /* 'j' */
+       83,     /* 'k' */
+       37,     /* 'l' */
+       139,    /* 'm' */
+       93,     /* 'n' */
+       93,     /* 'o' */
+       93,     /* 'p' */
+       93,     /* 'q' */
+       55,     /* 'r' */
+       83,     /* 's' */
+       46,     /* 't' */
+       93,     /* 'u' */
+       83,     /* 'v' */
+       120,    /* 'w' */
+       83,     /* 'x' */
+       83,     /* 'y' */
+       83,     /* 'z' */
+       56,     /* '{' */
+       43,     /* '|' */
+       56,     /* '}' */
+       97,     /* '~' */
+       },
+       /* height table for font HI */
+       {
+       153,    /* ' ' */
+       149,    /* '!' */
+       146,    /* '"' */
+       146,    /* '#' */
+       177,    /* '$' */
+       148,    /* '%' */
+       149,    /* '&' */
+       146,    /* ''' */
+       184,    /* '(' */
+       184,    /* ')' */
+       149,    /* '*' */
+       109,    /* '+' */
+       70,     /* ',' */
+       79,     /* '-' */
+       46,     /* '.' */
+       151,    /* '/' */
+       149,    /* '0' */
+       146,    /* '1' */
+       146,    /* '2' */
+       149,    /* '3' */
+       146,    /* '4' */
+       149,    /* '5' */
+       149,    /* '6' */
+       146,    /* '7' */
+       149,    /* '8' */
+       149,    /* '9' */
+       116,    /* ':' */
+       140,    /* ';' */
+       108,    /* '<' */
+       89,     /* '=' */
+       108,    /* '>' */
+       152,    /* '?' */
+       178,    /* '@' */
+       149,    /* 'A' */
+       149,    /* 'B' */
+       155,    /* 'C' */
+       149,    /* 'D' */
+       149,    /* 'E' */
+       149,    /* 'F' */
+       155,    /* 'G' */
+       149,    /* 'H' */
+       149,    /* 'I' */
+       152,    /* 'J' */
+       149,    /* 'K' */
+       149,    /* 'L' */
+       149,    /* 'M' */
+       149,    /* 'N' */
+       155,    /* 'O' */
+       149,    /* 'P' */
+       162,    /* 'Q' */
+       149,    /* 'R' */
+       155,    /* 'S' */
+       149,    /* 'T' */
+       152,    /* 'U' */
+       149,    /* 'V' */
+       149,    /* 'W' */
+       149,    /* 'X' */
+       149,    /* 'Y' */
+       149,    /* 'Z' */
+       184,    /* '[' */
+       151,    /* '\' */
+       184,    /* ']' */
+       146,    /* '^' */
+       38,     /* '_' */
+       146,    /* '`' */
+       122,    /* 'a' */
+       152,    /* 'b' */
+       122,    /* 'c' */
+       152,    /* 'd' */
+       122,    /* 'e' */
+       149,    /* 'f' */
+       154,    /* 'g' */
+       149,    /* 'h' */
+       149,    /* 'i' */
+       185,    /* 'j' */
+       149,    /* 'k' */
+       149,    /* 'l' */
+       119,    /* 'm' */
+       119,    /* 'n' */
+       122,    /* 'o' */
+       154,    /* 'p' */
+       154,    /* 'q' */
+       119,    /* 'r' */
+       122,    /* 's' */
+       142,    /* 't' */
+       118,    /* 'u' */
+       116,    /* 'v' */
+       116,    /* 'w' */
+       116,    /* 'x' */
+       151,    /* 'y' */
+       116,    /* 'z' */
+       184,    /* '{' */
+       184,    /* '|' */
+       184,    /* '}' */
+       99,     /* '~' */
+       },
+       /* ascent table for font HI */
+       {
+       108,    /* ' ' */
+       135,    /* '!' */
+       132,    /* '"' */
+       130,    /* '#' */
+       142,    /* '$' */
+       132,    /* '%' */
+       132,    /* '&' */
+       132,    /* ''' */
+       135,    /* '(' */
+       135,    /* ')' */
+       135,    /* '*' */
+       93,     /* '+' */
+       32,     /* ',' */
+       65,     /* '-' */
+       32,     /* '.' */
+       135,    /* '/' */
+       132,    /* '0' */
+       132,    /* '1' */
+       132,    /* '2' */
+       132,    /* '3' */
+       132,    /* '4' */
+       132,    /* '5' */
+       132,    /* '6' */
+       132,    /* '7' */
+       132,    /* '8' */
+       132,    /* '9' */
+       102,    /* ':' */
+       102,    /* ';' */
+       93,     /* '<' */
+       75,     /* '=' */
+       93,     /* '>' */
+       138,    /* '?' */
+       138,    /* '@' */
+       135,    /* 'A' */
+       135,    /* 'B' */
+       138,    /* 'C' */
+       135,    /* 'D' */
+       135,    /* 'E' */
+       135,    /* 'F' */
+       138,    /* 'G' */
+       135,    /* 'H' */
+       135,    /* 'I' */
+       135,    /* 'J' */
+       135,    /* 'K' */
+       135,    /* 'L' */
+       135,    /* 'M' */
+       135,    /* 'N' */
+       138,    /* 'O' */
+       135,    /* 'P' */
+       138,    /* 'Q' */
+       135,    /* 'R' */
+       138,    /* 'S' */
+       135,    /* 'T' */
+       135,    /* 'U' */
+       135,    /* 'V' */
+       135,    /* 'W' */
+       135,    /* 'X' */
+       135,    /* 'Y' */
+       135,    /* 'Z' */
+       135,    /* '[' */
+       135,    /* '\' */
+       135,    /* ']' */
+       132,    /* '^' */
+       -5,     /* '_' */
+       132,    /* '`' */
+       105,    /* 'a' */
+       135,    /* 'b' */
+       105,    /* 'c' */
+       135,    /* 'd' */
+       105,    /* 'e' */
+       135,    /* 'f' */
+       105,    /* 'g' */
+       135,    /* 'h' */
+       135,    /* 'i' */
+       135,    /* 'j' */
+       135,    /* 'k' */
+       135,    /* 'l' */
+       105,    /* 'm' */
+       105,    /* 'n' */
+       105,    /* 'o' */
+       105,    /* 'p' */
+       105,    /* 'q' */
+       105,    /* 'r' */
+       105,    /* 's' */
+       125,    /* 't' */
+       102,    /* 'u' */
+       102,    /* 'v' */
+       102,    /* 'w' */
+       102,    /* 'x' */
+       102,    /* 'y' */
+       102,    /* 'z' */
+       135,    /* '{' */
+       135,    /* '|' */
+       135,    /* '}' */
+       85,     /* '~' */
+       },
+
+       "Helvetica-Oblique",
+       0,
+       YES
+       }, {
+       /* width table for font HB */
+       {
+       46,     /* ' ' */
+       55,     /* '!' */
+       79,     /* '"' */
+       93,     /* '#' */
+       93,     /* '$' */
+       148,    /* '%' */
+       120,    /* '&' */
+       46,     /* ''' */
+       55,     /* '(' */
+       55,     /* ')' */
+       65,     /* '*' */
+       97,     /* '+' */
+       46,     /* ',' */
+       55,     /* '-' */
+       46,     /* '.' */
+       46,     /* '/' */
+       93,     /* '0' */
+       93,     /* '1' */
+       93,     /* '2' */
+       93,     /* '3' */
+       93,     /* '4' */
+       93,     /* '5' */
+       93,     /* '6' */
+       93,     /* '7' */
+       93,     /* '8' */
+       93,     /* '9' */
+       55,     /* ':' */
+       55,     /* ';' */
+       97,     /* '<' */
+       97,     /* '=' */
+       97,     /* '>' */
+       102,    /* '?' */
+       162,    /* '@' */
+       120,    /* 'A' */
+       120,    /* 'B' */
+       120,    /* 'C' */
+       120,    /* 'D' */
+       111,    /* 'E' */
+       102,    /* 'F' */
+       130,    /* 'G' */
+       120,    /* 'H' */
+       46,     /* 'I' */
+       93,     /* 'J' */
+       120,    /* 'K' */
+       102,    /* 'L' */
+       139,    /* 'M' */
+       120,    /* 'N' */
+       130,    /* 'O' */
+       111,    /* 'P' */
+       130,    /* 'Q' */
+       120,    /* 'R' */
+       111,    /* 'S' */
+       102,    /* 'T' */
+       120,    /* 'U' */
+       111,    /* 'V' */
+       157,    /* 'W' */
+       111,    /* 'X' */
+       111,    /* 'Y' */
+       102,    /* 'Z' */
+       55,     /* '[' */
+       46,     /* '\' */
+       55,     /* ']' */
+       97,     /* '^' */
+       93,     /* '_' */
+       46,     /* '`' */
+       93,     /* 'a' */
+       102,    /* 'b' */
+       93,     /* 'c' */
+       102,    /* 'd' */
+       93,     /* 'e' */
+       55,     /* 'f' */
+       102,    /* 'g' */
+       102,    /* 'h' */
+       46,     /* 'i' */
+       46,     /* 'j' */
+       93,     /* 'k' */
+       46,     /* 'l' */
+       148,    /* 'm' */
+       102,    /* 'n' */
+       102,    /* 'o' */
+       102,    /* 'p' */
+       102,    /* 'q' */
+       65,     /* 'r' */
+       93,     /* 's' */
+       55,     /* 't' */
+       102,    /* 'u' */
+       93,     /* 'v' */
+       130,    /* 'w' */
+       93,     /* 'x' */
+       93,     /* 'y' */
+       83,     /* 'z' */
+       65,     /* '{' */
+       47,     /* '|' */
+       65,     /* '}' */
+       97,     /* '~' */
+       },
+       /* height table for font HB */
+       {
+       153,    /* ' ' */
+       149,    /* '!' */
+       149,    /* '"' */
+       149,    /* '#' */
+       176,    /* '$' */
+       148,    /* '%' */
+       152,    /* '&' */
+       149,    /* ''' */
+       182,    /* '(' */
+       182,    /* ')' */
+       149,    /* '*' */
+       109,    /* '+' */
+       81,     /* ',' */
+       82,     /* '-' */
+       52,     /* '.' */
+       149,    /* '/' */
+       152,    /* '0' */
+       146,    /* '1' */
+       149,    /* '2' */
+       152,    /* '3' */
+       146,    /* '4' */
+       152,    /* '5' */
+       152,    /* '6' */
+       149,    /* '7' */
+       152,    /* '8' */
+       155,    /* '9' */
+       116,    /* ':' */
+       145,    /* ';' */
+       108,    /* '<' */
+       96,     /* '=' */
+       108,    /* '>' */
+       152,    /* '?' */
+       174,    /* '@' */
+       149,    /* 'A' */
+       149,    /* 'B' */
+       155,    /* 'C' */
+       149,    /* 'D' */
+       149,    /* 'E' */
+       149,    /* 'F' */
+       155,    /* 'G' */
+       149,    /* 'H' */
+       149,    /* 'I' */
+       152,    /* 'J' */
+       149,    /* 'K' */
+       149,    /* 'L' */
+       149,    /* 'M' */
+       149,    /* 'N' */
+       155,    /* 'O' */
+       149,    /* 'P' */
+       161,    /* 'Q' */
+       149,    /* 'R' */
+       155,    /* 'S' */
+       149,    /* 'T' */
+       152,    /* 'U' */
+       149,    /* 'V' */
+       149,    /* 'W' */
+       149,    /* 'X' */
+       149,    /* 'Y' */
+       149,    /* 'Z' */
+       181,    /* '[' */
+       149,    /* '\' */
+       181,    /* ']' */
+       144,    /* '^' */
+       38,     /* '_' */
+       149,    /* '`' */
+       125,    /* 'a' */
+       152,    /* 'b' */
+       125,    /* 'c' */
+       152,    /* 'd' */
+       125,    /* 'e' */
+       149,    /* 'f' */
+       158,    /* 'g' */
+       149,    /* 'h' */
+       149,    /* 'i' */
+       185,    /* 'j' */
+       149,    /* 'k' */
+       149,    /* 'l' */
+       122,    /* 'm' */
+       122,    /* 'n' */
+       125,    /* 'o' */
+       158,    /* 'p' */
+       158,    /* 'q' */
+       122,    /* 'r' */
+       125,    /* 's' */
+       143,    /* 't' */
+       122,    /* 'u' */
+       119,    /* 'v' */
+       119,    /* 'w' */
+       119,    /* 'x' */
+       155,    /* 'y' */
+       119,    /* 'z' */
+       181,    /* '{' */
+       182,    /* '|' */
+       181,    /* '}' */
+       79,     /* '~' */
+       },
+       /* ascent table for font HB */
+       {
+       108,    /* ' ' */
+       135,    /* '!' */
+       135,    /* '"' */
+       130,    /* '#' */
+       141,    /* '$' */
+       132,    /* '%' */
+       135,    /* '&' */
+       135,    /* ''' */
+       135,    /* '(' */
+       135,    /* ')' */
+       135,    /* '*' */
+       93,     /* '+' */
+       38,     /* ',' */
+       68,     /* '-' */
+       38,     /* '.' */
+       133,    /* '/' */
+       136,    /* '0' */
+       132,    /* '1' */
+       136,    /* '2' */
+       135,    /* '3' */
+       132,    /* '4' */
+       135,    /* '5' */
+       136,    /* '6' */
+       135,    /* '7' */
+       136,    /* '8' */
+       136,    /* '9' */
+       102,    /* ':' */
+       102,    /* ';' */
+       93,     /* '<' */
+       82,     /* '=' */
+       93,     /* '>' */
+       138,    /* '?' */
+       138,    /* '@' */
+       135,    /* 'A' */
+       135,    /* 'B' */
+       138,    /* 'C' */
+       135,    /* 'D' */
+       135,    /* 'E' */
+       135,    /* 'F' */
+       138,    /* 'G' */
+       135,    /* 'H' */
+       135,    /* 'I' */
+       135,    /* 'J' */
+       135,    /* 'K' */
+       135,    /* 'L' */
+       135,    /* 'M' */
+       135,    /* 'N' */
+       138,    /* 'O' */
+       135,    /* 'P' */
+       138,    /* 'Q' */
+       135,    /* 'R' */
+       138,    /* 'S' */
+       135,    /* 'T' */
+       135,    /* 'U' */
+       135,    /* 'V' */
+       135,    /* 'W' */
+       135,    /* 'X' */
+       135,    /* 'Y' */
+       135,    /* 'Z' */
+       135,    /* '[' */
+       133,    /* '\' */
+       135,    /* ']' */
+       130,    /* '^' */
+       -8,     /* '_' */
+       135,    /* '`' */
+       108,    /* 'a' */
+       135,    /* 'b' */
+       108,    /* 'c' */
+       135,    /* 'd' */
+       108,    /* 'e' */
+       135,    /* 'f' */
+       108,    /* 'g' */
+       135,    /* 'h' */
+       135,    /* 'i' */
+       135,    /* 'j' */
+       135,    /* 'k' */
+       135,    /* 'l' */
+       108,    /* 'm' */
+       108,    /* 'n' */
+       108,    /* 'o' */
+       108,    /* 'p' */
+       108,    /* 'q' */
+       108,    /* 'r' */
+       108,    /* 's' */
+       126,    /* 't' */
+       105,    /* 'u' */
+       105,    /* 'v' */
+       105,    /* 'w' */
+       105,    /* 'x' */
+       105,    /* 'y' */
+       105,    /* 'z' */
+       135,    /* '{' */
+       135,    /* '|' */
+       135,    /* '}' */
+       65,     /* '~' */
+       },
+
+       "Helvetica-Bold",
+       0,
+       NO
+       }, {
+       /* width table for font HX */
+       {
+       46,     /* ' ' */
+       55,     /* '!' */
+       79,     /* '"' */
+       93,     /* '#' */
+       93,     /* '$' */
+       148,    /* '%' */
+       120,    /* '&' */
+       46,     /* ''' */
+       55,     /* '(' */
+       55,     /* ')' */
+       65,     /* '*' */
+       97,     /* '+' */
+       46,     /* ',' */
+       55,     /* '-' */
+       46,     /* '.' */
+       46,     /* '/' */
+       93,     /* '0' */
+       93,     /* '1' */
+       93,     /* '2' */
+       93,     /* '3' */
+       93,     /* '4' */
+       93,     /* '5' */
+       93,     /* '6' */
+       93,     /* '7' */
+       93,     /* '8' */
+       93,     /* '9' */
+       55,     /* ':' */
+       55,     /* ';' */
+       97,     /* '<' */
+       97,     /* '=' */
+       97,     /* '>' */
+       102,    /* '?' */
+       162,    /* '@' */
+       120,    /* 'A' */
+       120,    /* 'B' */
+       120,    /* 'C' */
+       120,    /* 'D' */
+       111,    /* 'E' */
+       102,    /* 'F' */
+       130,    /* 'G' */
+       120,    /* 'H' */
+       46,     /* 'I' */
+       93,     /* 'J' */
+       120,    /* 'K' */
+       102,    /* 'L' */
+       139,    /* 'M' */
+       120,    /* 'N' */
+       130,    /* 'O' */
+       111,    /* 'P' */
+       130,    /* 'Q' */
+       120,    /* 'R' */
+       111,    /* 'S' */
+       102,    /* 'T' */
+       120,    /* 'U' */
+       111,    /* 'V' */
+       157,    /* 'W' */
+       111,    /* 'X' */
+       111,    /* 'Y' */
+       102,    /* 'Z' */
+       55,     /* '[' */
+       46,     /* '\' */
+       55,     /* ']' */
+       97,     /* '^' */
+       93,     /* '_' */
+       46,     /* '`' */
+       93,     /* 'a' */
+       102,    /* 'b' */
+       93,     /* 'c' */
+       102,    /* 'd' */
+       93,     /* 'e' */
+       55,     /* 'f' */
+       102,    /* 'g' */
+       102,    /* 'h' */
+       46,     /* 'i' */
+       46,     /* 'j' */
+       93,     /* 'k' */
+       46,     /* 'l' */
+       148,    /* 'm' */
+       102,    /* 'n' */
+       102,    /* 'o' */
+       102,    /* 'p' */
+       102,    /* 'q' */
+       65,     /* 'r' */
+       93,     /* 's' */
+       55,     /* 't' */
+       102,    /* 'u' */
+       93,     /* 'v' */
+       130,    /* 'w' */
+       93,     /* 'x' */
+       93,     /* 'y' */
+       83,     /* 'z' */
+       65,     /* '{' */
+       47,     /* '|' */
+       65,     /* '}' */
+       97,     /* '~' */
+       },
+       /* height table for font HX */
+       {
+       153,    /* ' ' */
+       149,    /* '!' */
+       149,    /* '"' */
+       149,    /* '#' */
+       176,    /* '$' */
+       149,    /* '%' */
+       152,    /* '&' */
+       149,    /* ''' */
+       182,    /* '(' */
+       182,    /* ')' */
+       149,    /* '*' */
+       109,    /* '+' */
+       81,     /* ',' */
+       82,     /* '-' */
+       52,     /* '.' */
+       149,    /* '/' */
+       152,    /* '0' */
+       146,    /* '1' */
+       149,    /* '2' */
+       152,    /* '3' */
+       146,    /* '4' */
+       152,    /* '5' */
+       152,    /* '6' */
+       149,    /* '7' */
+       152,    /* '8' */
+       152,    /* '9' */
+       116,    /* ':' */
+       145,    /* ';' */
+       108,    /* '<' */
+       96,     /* '=' */
+       108,    /* '>' */
+       152,    /* '?' */
+       174,    /* '@' */
+       149,    /* 'A' */
+       149,    /* 'B' */
+       155,    /* 'C' */
+       149,    /* 'D' */
+       149,    /* 'E' */
+       149,    /* 'F' */
+       155,    /* 'G' */
+       149,    /* 'H' */
+       149,    /* 'I' */
+       152,    /* 'J' */
+       149,    /* 'K' */
+       149,    /* 'L' */
+       149,    /* 'M' */
+       149,    /* 'N' */
+       155,    /* 'O' */
+       149,    /* 'P' */
+       161,    /* 'Q' */
+       149,    /* 'R' */
+       155,    /* 'S' */
+       149,    /* 'T' */
+       152,    /* 'U' */
+       149,    /* 'V' */
+       149,    /* 'W' */
+       149,    /* 'X' */
+       149,    /* 'Y' */
+       149,    /* 'Z' */
+       181,    /* '[' */
+       150,    /* '\' */
+       181,    /* ']' */
+       144,    /* '^' */
+       38,     /* '_' */
+       149,    /* '`' */
+       125,    /* 'a' */
+       152,    /* 'b' */
+       125,    /* 'c' */
+       152,    /* 'd' */
+       125,    /* 'e' */
+       149,    /* 'f' */
+       158,    /* 'g' */
+       149,    /* 'h' */
+       149,    /* 'i' */
+       185,    /* 'j' */
+       149,    /* 'k' */
+       149,    /* 'l' */
+       122,    /* 'm' */
+       122,    /* 'n' */
+       125,    /* 'o' */
+       158,    /* 'p' */
+       158,    /* 'q' */
+       122,    /* 'r' */
+       125,    /* 's' */
+       143,    /* 't' */
+       122,    /* 'u' */
+       119,    /* 'v' */
+       119,    /* 'w' */
+       119,    /* 'x' */
+       158,    /* 'y' */
+       119,    /* 'z' */
+       181,    /* '{' */
+       182,    /* '|' */
+       181,    /* '}' */
+       79,     /* '~' */
+       },
+       /* ascent table for font HX */
+       {
+       108,    /* ' ' */
+       135,    /* '!' */
+       135,    /* '"' */
+       130,    /* '#' */
+       141,    /* '$' */
+       132,    /* '%' */
+       135,    /* '&' */
+       135,    /* ''' */
+       135,    /* '(' */
+       135,    /* ')' */
+       135,    /* '*' */
+       93,     /* '+' */
+       38,     /* ',' */
+       68,     /* '-' */
+       38,     /* '.' */
+       133,    /* '/' */
+       136,    /* '0' */
+       132,    /* '1' */
+       136,    /* '2' */
+       136,    /* '3' */
+       132,    /* '4' */
+       135,    /* '5' */
+       135,    /* '6' */
+       135,    /* '7' */
+       136,    /* '8' */
+       136,    /* '9' */
+       102,    /* ':' */
+       102,    /* ';' */
+       93,     /* '<' */
+       82,     /* '=' */
+       93,     /* '>' */
+       138,    /* '?' */
+       138,    /* '@' */
+       135,    /* 'A' */
+       135,    /* 'B' */
+       138,    /* 'C' */
+       135,    /* 'D' */
+       135,    /* 'E' */
+       135,    /* 'F' */
+       138,    /* 'G' */
+       135,    /* 'H' */
+       135,    /* 'I' */
+       135,    /* 'J' */
+       135,    /* 'K' */
+       135,    /* 'L' */
+       135,    /* 'M' */
+       135,    /* 'N' */
+       138,    /* 'O' */
+       135,    /* 'P' */
+       138,    /* 'Q' */
+       135,    /* 'R' */
+       138,    /* 'S' */
+       135,    /* 'T' */
+       135,    /* 'U' */
+       135,    /* 'V' */
+       135,    /* 'W' */
+       135,    /* 'X' */
+       135,    /* 'Y' */
+       135,    /* 'Z' */
+       135,    /* '[' */
+       132,    /* '\' */
+       135,    /* ']' */
+       130,    /* '^' */
+       2,      /* '_' */
+       135,    /* '`' */
+       108,    /* 'a' */
+       135,    /* 'b' */
+       108,    /* 'c' */
+       135,    /* 'd' */
+       108,    /* 'e' */
+       135,    /* 'f' */
+       108,    /* 'g' */
+       135,    /* 'h' */
+       135,    /* 'i' */
+       135,    /* 'j' */
+       135,    /* 'k' */
+       135,    /* 'l' */
+       108,    /* 'm' */
+       108,    /* 'n' */
+       108,    /* 'o' */
+       108,    /* 'p' */
+       108,    /* 'q' */
+       108,    /* 'r' */
+       108,    /* 's' */
+       126,    /* 't' */
+       105,    /* 'u' */
+       105,    /* 'v' */
+       105,    /* 'w' */
+       105,    /* 'x' */
+       105,    /* 'y' */
+       105,    /* 'z' */
+       135,    /* '{' */
+       135,    /* '|' */
+       135,    /* '}' */
+       65,     /* '~' */
+       },
+
+       "Helvetica-BoldOblique",
+       0,
+       YES
+       }, {
+       /* width table for font BR */
+       {
+       53,     /* ' ' */
+       50,     /* '!' */
+       63,     /* '"' */
+       103,    /* '#' */
+       103,    /* '$' */
+       150,    /* '%' */
+       133,    /* '&' */
+       37,     /* ''' */
+       50,     /* '(' */
+       50,     /* ')' */
+       73,     /* '*' */
+       100,    /* '+' */
+       53,     /* ',' */
+       67,     /* '-' */
+       53,     /* '.' */
+       100,    /* '/' */
+       103,    /* '0' */
+       103,    /* '1' */
+       103,    /* '2' */
+       103,    /* '3' */
+       103,    /* '4' */
+       103,    /* '5' */
+       103,    /* '6' */
+       103,    /* '7' */
+       103,    /* '8' */
+       103,    /* '9' */
+       53,     /* ':' */
+       53,     /* ';' */
+       100,    /* '<' */
+       100,    /* '=' */
+       100,    /* '>' */
+       90,     /* '?' */
+       137,    /* '@' */
+       113,    /* 'A' */
+       123,    /* 'B' */
+       123,    /* 'C' */
+       133,    /* 'D' */
+       120,    /* 'E' */
+       107,    /* 'F' */
+       133,    /* 'G' */
+       133,    /* 'H' */
+       57,     /* 'I' */
+       100,    /* 'J' */
+       120,    /* 'K' */
+       100,    /* 'L' */
+       153,    /* 'M' */
+       123,    /* 'N' */
+       133,    /* 'O' */
+       103,    /* 'P' */
+       137,    /* 'Q' */
+       120,    /* 'R' */
+       110,    /* 'S' */
+       103,    /* 'T' */
+       130,    /* 'U' */
+       117,    /* 'V' */
+       160,    /* 'W' */
+       120,    /* 'X' */
+       107,    /* 'Y' */
+       107,    /* 'Z' */
+       50,     /* '[' */
+       100,    /* '\' */
+       50,     /* ']' */
+       100,    /* '^' */
+       83,     /* '_' */
+       37,     /* '`' */
+       97,     /* 'a' */
+       103,    /* 'b' */
+       87,     /* 'c' */
+       103,    /* 'd' */
+       87,     /* 'e' */
+       53,     /* 'f' */
+       90,     /* 'g' */
+       110,    /* 'h' */
+       50,     /* 'i' */
+       50,     /* 'j' */
+       103,    /* 'k' */
+       50,     /* 'l' */
+       157,    /* 'm' */
+       110,    /* 'n' */
+       93,     /* 'o' */
+       103,    /* 'p' */
+       97,     /* 'q' */
+       73,     /* 'r' */
+       87,     /* 's' */
+       63,     /* 't' */
+       113,    /* 'u' */
+       87,     /* 'v' */
+       130,    /* 'w' */
+       93,     /* 'x' */
+       90,     /* 'y' */
+       80,     /* 'z' */
+       47,     /* '{' */
+       100,    /* '|' */
+       47,     /* '}' */
+       100,    /* '~' */
+       },
+       /* height table for font BR */
+       {
+       153,    /* ' ' */
+       148,    /* '!' */
+       146,    /* '"' */
+       139,    /* '#' */
+       178,    /* '$' */
+       148,    /* '%' */
+       148,    /* '&' */
+       146,    /* ''' */
+       172,    /* '(' */
+       172,    /* ')' */
+       146,    /* '*' */
+       127,    /* '+' */
+       66,     /* ',' */
+       76,     /* '-' */
+       49,     /* '.' */
+       171,    /* '/' */
+       148,    /* '0' */
+       142,    /* '1' */
+       146,    /* '2' */
+       148,    /* '3' */
+       142,    /* '4' */
+       150,    /* '5' */
+       148,    /* '6' */
+       142,    /* '7' */
+       148,    /* '8' */
+       148,    /* '9' */
+       114,    /* ':' */
+       131,    /* ';' */
+       128,    /* '<' */
+       109,    /* '=' */
+       128,    /* '>' */
+       148,    /* '?' */
+       148,    /* '@' */
+       142,    /* 'A' */
+       142,    /* 'B' */
+       148,    /* 'C' */
+       142,    /* 'D' */
+       142,    /* 'E' */
+       142,    /* 'F' */
+       148,    /* 'G' */
+       142,    /* 'H' */
+       142,    /* 'I' */
+       144,    /* 'J' */
+       142,    /* 'K' */
+       142,    /* 'L' */
+       142,    /* 'M' */
+       142,    /* 'N' */
+       148,    /* 'O' */
+       142,    /* 'P' */
+       178,    /* 'Q' */
+       142,    /* 'R' */
+       148,    /* 'S' */
+       142,    /* 'T' */
+       144,    /* 'U' */
+       142,    /* 'V' */
+       142,    /* 'W' */
+       142,    /* 'X' */
+       142,    /* 'Y' */
+       142,    /* 'Z' */
+       168,    /* '[' */
+       147,    /* '\' */
+       169,    /* ']' */
+       148,    /* '^' */
+       38,     /* '_' */
+       143,    /* '`' */
+       114,    /* 'a' */
+       149,    /* 'b' */
+       114,    /* 'c' */
+       149,    /* 'd' */
+       114,    /* 'e' */
+       149,    /* 'f' */
+       161,    /* 'g' */
+       147,    /* 'h' */
+       136,    /* 'i' */
+       174,    /* 'j' */
+       147,    /* 'k' */
+       147,    /* 'l' */
+       112,    /* 'm' */
+       112,    /* 'n' */
+       114,    /* 'o' */
+       151,    /* 'p' */
+       151,    /* 'q' */
+       112,    /* 'r' */
+       114,    /* 's' */
+       141,    /* 't' */
+       111,    /* 'u' */
+       109,    /* 'v' */
+       109,    /* 'w' */
+       109,    /* 'x' */
+       148,    /* 'y' */
+       109,    /* 'z' */
+       171,    /* '{' */
+       148,    /* '|' */
+       171,    /* '}' */
+       83,     /* '~' */
+       },
+       /* ascent table for font BR */
+       {
+       108,    /* ' ' */
+       132,    /* '!' */
+       132,    /* '"' */
+       125,    /* '#' */
+       146,    /* '$' */
+       132,    /* '%' */
+       132,    /* '&' */
+       132,    /* ''' */
+       133,    /* '(' */
+       133,    /* ')' */
+       132,    /* '*' */
+       113,    /* '+' */
+       33,     /* ',' */
+       62,     /* '-' */
+       33,     /* '.' */
+       133,    /* '/' */
+       132,    /* '0' */
+       128,    /* '1' */
+       132,    /* '2' */
+       132,    /* '3' */
+       128,    /* '4' */
+       133,    /* '5' */
+       132,    /* '6' */
+       128,    /* '7' */
+       132,    /* '8' */
+       132,    /* '9' */
+       98,     /* ':' */
+       98,     /* ';' */
+       114,    /* '<' */
+       95,     /* '=' */
+       114,    /* '>' */
+       132,    /* '?' */
+       132,    /* '@' */
+       128,    /* 'A' */
+       128,    /* 'B' */
+       132,    /* 'C' */
+       128,    /* 'D' */
+       128,    /* 'E' */
+       128,    /* 'F' */
+       132,    /* 'G' */
+       128,    /* 'H' */
+       128,    /* 'I' */
+       128,    /* 'J' */
+       128,    /* 'K' */
+       128,    /* 'L' */
+       128,    /* 'M' */
+       128,    /* 'N' */
+       132,    /* 'O' */
+       128,    /* 'P' */
+       132,    /* 'Q' */
+       128,    /* 'R' */
+       132,    /* 'S' */
+       128,    /* 'T' */
+       128,    /* 'U' */
+       128,    /* 'V' */
+       128,    /* 'W' */
+       128,    /* 'X' */
+       128,    /* 'Y' */
+       128,    /* 'Z' */
+       132,    /* '[' */
+       133,    /* '\' */
+       132,    /* ']' */
+       134,    /* '^' */
+       -2,     /* '_' */
+       130,    /* '`' */
+       98,     /* 'a' */
+       133,    /* 'b' */
+       98,     /* 'c' */
+       133,    /* 'd' */
+       98,     /* 'e' */
+       135,    /* 'f' */
+       108,    /* 'g' */
+       133,    /* 'h' */
+       122,    /* 'i' */
+       122,    /* 'j' */
+       133,    /* 'k' */
+       133,    /* 'l' */
+       98,     /* 'm' */
+       98,     /* 'n' */
+       98,     /* 'o' */
+       98,     /* 'p' */
+       98,     /* 'q' */
+       98,     /* 'r' */
+       98,     /* 's' */
+       125,    /* 't' */
+       95,     /* 'u' */
+       95,     /* 'v' */
+       95,     /* 'w' */
+       95,     /* 'x' */
+       95,     /* 'y' */
+       95,     /* 'z' */
+       137,    /* '{' */
+       134,    /* '|' */
+       137,    /* '}' */
+       69,     /* '~' */
+       },
+
+       "Bookman-Light",
+       0,
+       NO
+       }, {
+       /* width table for font BI */
+       {
+       50,     /* ' ' */
+       53,     /* '!' */
+       60,     /* '"' */
+       103,    /* '#' */
+       103,    /* '$' */
+       133,    /* '%' */
+       137,    /* '&' */
+       47,     /* ''' */
+       47,     /* '(' */
+       47,     /* ')' */
+       73,     /* '*' */
+       100,    /* '+' */
+       50,     /* ',' */
+       53,     /* '-' */
+       50,     /* '.' */
+       100,    /* '/' */
+       103,    /* '0' */
+       103,    /* '1' */
+       103,    /* '2' */
+       103,    /* '3' */
+       103,    /* '4' */
+       103,    /* '5' */
+       103,    /* '6' */
+       103,    /* '7' */
+       103,    /* '8' */
+       103,    /* '9' */
+       50,     /* ':' */
+       50,     /* ';' */
+       100,    /* '<' */
+       100,    /* '=' */
+       100,    /* '>' */
+       90,     /* '?' */
+       130,    /* '@' */
+       117,    /* 'A' */
+       120,    /* 'B' */
+       120,    /* 'C' */
+       123,    /* 'D' */
+       113,    /* 'E' */
+       103,    /* 'F' */
+       127,    /* 'G' */
+       133,    /* 'H' */
+       53,     /* 'I' */
+       93,     /* 'J' */
+       120,    /* 'K' */
+       97,     /* 'L' */
+       143,    /* 'M' */
+       120,    /* 'N' */
+       127,    /* 'O' */
+       100,    /* 'P' */
+       130,    /* 'Q' */
+       117,    /* 'R' */
+       107,    /* 'S' */
+       100,    /* 'T' */
+       120,    /* 'U' */
+       113,    /* 'V' */
+       160,    /* 'W' */
+       117,    /* 'X' */
+       110,    /* 'Y' */
+       97,     /* 'Z' */
+       43,     /* '[' */
+       100,    /* '\' */
+       43,     /* ']' */
+       100,    /* '^' */
+       83,     /* '_' */
+       47,     /* '`' */
+       103,    /* 'a' */
+       100,    /* 'b' */
+       80,     /* 'c' */
+       107,    /* 'd' */
+       90,     /* 'e' */
+       57,     /* 'f' */
+       93,     /* 'g' */
+       103,    /* 'h' */
+       47,     /* 'i' */
+       47,     /* 'j' */
+       100,    /* 'k' */
+       47,     /* 'l' */
+       147,    /* 'm' */
+       103,    /* 'n' */
+       90,     /* 'o' */
+       100,    /* 'p' */
+       93,     /* 'q' */
+       67,     /* 'r' */
+       90,     /* 's' */
+       57,     /* 't' */
+       103,    /* 'u' */
+       90,     /* 'v' */
+       147,    /* 'w' */
+       90,     /* 'x' */
+       100,    /* 'y' */
+       87,     /* 'z' */
+       60,     /* '{' */
+       100,    /* '|' */
+       63,     /* '}' */
+       100,    /* '~' */
+       },
+       /* height table for font BI */
+       {
+       153,    /* ' ' */
+       148,    /* '!' */
+       146,    /* '"' */
+       139,    /* '#' */
+       169,    /* '$' */
+       148,    /* '%' */
+       148,    /* '&' */
+       146,    /* ''' */
+       167,    /* '(' */
+       167,    /* ')' */
+       146,    /* '*' */
+       127,    /* '+' */
+       66,     /* ',' */
+       76,     /* '-' */
+       50,     /* '.' */
+       167,    /* '/' */
+       148,    /* '0' */
+       142,    /* '1' */
+       146,    /* '2' */
+       148,    /* '3' */
+       142,    /* '4' */
+       144,    /* '5' */
+       148,    /* '6' */
+       142,    /* '7' */
+       148,    /* '8' */
+       148,    /* '9' */
+       114,    /* ':' */
+       131,    /* ';' */
+       128,    /* '<' */
+       109,    /* '=' */
+       128,    /* '>' */
+       148,    /* '?' */
+       148,    /* '@' */
+       142,    /* 'A' */
+       142,    /* 'B' */
+       148,    /* 'C' */
+       142,    /* 'D' */
+       142,    /* 'E' */
+       142,    /* 'F' */
+       148,    /* 'G' */
+       142,    /* 'H' */
+       142,    /* 'I' */
+       144,    /* 'J' */
+       142,    /* 'K' */
+       142,    /* 'L' */
+       142,    /* 'M' */
+       142,    /* 'N' */
+       148,    /* 'O' */
+       142,    /* 'P' */
+       178,    /* 'Q' */
+       142,    /* 'R' */
+       148,    /* 'S' */
+       142,    /* 'T' */
+       144,    /* 'U' */
+       142,    /* 'V' */
+       142,    /* 'W' */
+       142,    /* 'X' */
+       142,    /* 'Y' */
+       142,    /* 'Z' */
+       171,    /* '[' */
+       147,    /* '\' */
+       169,    /* ']' */
+       148,    /* '^' */
+       38,     /* '_' */
+       143,    /* '`' */
+       114,    /* 'a' */
+       149,    /* 'b' */
+       114,    /* 'c' */
+       149,    /* 'd' */
+       114,    /* 'e' */
+       184,    /* 'f' */
+       148,    /* 'g' */
+       149,    /* 'h' */
+       141,    /* 'i' */
+       174,    /* 'j' */
+       149,    /* 'k' */
+       149,    /* 'l' */
+       114,    /* 'm' */
+       114,    /* 'n' */
+       114,    /* 'o' */
+       148,    /* 'p' */
+       148,    /* 'q' */
+       112,    /* 'r' */
+       114,    /* 's' */
+       141,    /* 't' */
+       111,    /* 'u' */
+       114,    /* 'v' */
+       114,    /* 'w' */
+       114,    /* 'x' */
+       144,    /* 'y' */
+       114,    /* 'z' */
+       179,    /* '{' */
+       148,    /* '|' */
+       179,    /* '}' */
+       83,     /* '~' */
+       },
+       /* ascent table for font BI */
+       {
+       108,    /* ' ' */
+       132,    /* '!' */
+       132,    /* '"' */
+       125,    /* '#' */
+       141,    /* '$' */
+       132,    /* '%' */
+       132,    /* '&' */
+       132,    /* ''' */
+       133,    /* '(' */
+       133,    /* ')' */
+       132,    /* '*' */
+       113,    /* '+' */
+       33,     /* ',' */
+       62,     /* '-' */
+       34,     /* '.' */
+       133,    /* '/' */
+       132,    /* '0' */
+       128,    /* '1' */
+       132,    /* '2' */
+       132,    /* '3' */
+       128,    /* '4' */
+       128,    /* '5' */
+       132,    /* '6' */
+       128,    /* '7' */
+       132,    /* '8' */
+       132,    /* '9' */
+       98,     /* ':' */
+       98,     /* ';' */
+       114,    /* '<' */
+       95,     /* '=' */
+       114,    /* '>' */
+       132,    /* '?' */
+       132,    /* '@' */
+       128,    /* 'A' */
+       128,    /* 'B' */
+       132,    /* 'C' */
+       128,    /* 'D' */
+       128,    /* 'E' */
+       128,    /* 'F' */
+       132,    /* 'G' */
+       128,    /* 'H' */
+       128,    /* 'I' */
+       128,    /* 'J' */
+       128,    /* 'K' */
+       128,    /* 'L' */
+       128,    /* 'M' */
+       128,    /* 'N' */
+       132,    /* 'O' */
+       128,    /* 'P' */
+       132,    /* 'Q' */
+       128,    /* 'R' */
+       132,    /* 'S' */
+       128,    /* 'T' */
+       128,    /* 'U' */
+       128,    /* 'V' */
+       128,    /* 'W' */
+       128,    /* 'X' */
+       128,    /* 'Y' */
+       128,    /* 'Z' */
+       135,    /* '[' */
+       133,    /* '\' */
+       133,    /* ']' */
+       134,    /* '^' */
+       -2,     /* '_' */
+       130,    /* '`' */
+       98,     /* 'a' */
+       133,    /* 'b' */
+       98,     /* 'c' */
+       133,    /* 'd' */
+       98,     /* 'e' */
+       135,    /* 'f' */
+       98,     /* 'g' */
+       133,    /* 'h' */
+       125,    /* 'i' */
+       125,    /* 'j' */
+       133,    /* 'k' */
+       133,    /* 'l' */
+       98,     /* 'm' */
+       98,     /* 'n' */
+       98,     /* 'o' */
+       98,     /* 'p' */
+       98,     /* 'q' */
+       98,     /* 'r' */
+       98,     /* 's' */
+       125,    /* 't' */
+       95,     /* 'u' */
+       98,     /* 'v' */
+       98,     /* 'w' */
+       98,     /* 'x' */
+       95,     /* 'y' */
+       98,     /* 'z' */
+       139,    /* '{' */
+       134,    /* '|' */
+       139,    /* '}' */
+       69,     /* '~' */
+       },
+
+       "Bookman-LightItalic",
+       0,
+       YES
+       }, {
+       /* width table for font BB */
+       {
+       57,     /* ' ' */
+       60,     /* '!' */
+       70,     /* '"' */
+       110,    /* '#' */
+       110,    /* '$' */
+       157,    /* '%' */
+       133,    /* '&' */
+       53,     /* ''' */
+       53,     /* '(' */
+       53,     /* ')' */
+       77,     /* '*' */
+       100,    /* '+' */
+       57,     /* ',' */
+       60,     /* '-' */
+       57,     /* '.' */
+       100,    /* '/' */
+       110,    /* '0' */
+       110,    /* '1' */
+       110,    /* '2' */
+       110,    /* '3' */
+       110,    /* '4' */
+       110,    /* '5' */
+       110,    /* '6' */
+       110,    /* '7' */
+       110,    /* '8' */
+       110,    /* '9' */
+       57,     /* ':' */
+       57,     /* ';' */
+       100,    /* '<' */
+       100,    /* '=' */
+       100,    /* '>' */
+       110,    /* '?' */
+       137,    /* '@' */
+       120,    /* 'A' */
+       120,    /* 'B' */
+       123,    /* 'C' */
+       130,    /* 'D' */
+       120,    /* 'E' */
+       113,    /* 'F' */
+       130,    /* 'G' */
+       137,    /* 'H' */
+       67,     /* 'I' */
+       107,    /* 'J' */
+       133,    /* 'K' */
+       107,    /* 'L' */
+       157,    /* 'M' */
+       123,    /* 'N' */
+       133,    /* 'O' */
+       110,    /* 'P' */
+       133,    /* 'Q' */
+       130,    /* 'R' */
+       110,    /* 'S' */
+       117,    /* 'T' */
+       123,    /* 'U' */
+       120,    /* 'V' */
+       157,    /* 'W' */
+       130,    /* 'X' */
+       117,    /* 'Y' */
+       107,    /* 'Z' */
+       50,     /* '[' */
+       100,    /* '\' */
+       50,     /* ']' */
+       100,    /* '^' */
+       83,     /* '_' */
+       53,     /* '`' */
+       97,     /* 'a' */
+       100,    /* 'b' */
+       97,     /* 'c' */
+       107,    /* 'd' */
+       97,     /* 'e' */
+       63,     /* 'f' */
+       97,     /* 'g' */
+       113,    /* 'h' */
+       60,     /* 'i' */
+       57,     /* 'j' */
+       110,    /* 'k' */
+       57,     /* 'l' */
+       167,    /* 'm' */
+       113,    /* 'n' */
+       103,    /* 'o' */
+       107,    /* 'p' */
+       103,    /* 'q' */
+       77,     /* 'r' */
+       87,     /* 's' */
+       77,     /* 't' */
+       110,    /* 'u' */
+       100,    /* 'v' */
+       133,    /* 'w' */
+       100,    /* 'x' */
+       103,    /* 'y' */
+       93,     /* 'z' */
+       53,     /* '{' */
+       100,    /* '|' */
+       53,     /* '}' */
+       100,    /* '~' */
+       },
+       /* height table for font BB */
+       {
+       153,    /* ' ' */
+       148,    /* '!' */
+       146,    /* '"' */
+       142,    /* '#' */
+       181,    /* '$' */
+       148,    /* '%' */
+       148,    /* '&' */
+       146,    /* ''' */
+       176,    /* '(' */
+       176,    /* ')' */
+       146,    /* '*' */
+       127,    /* '+' */
+       76,     /* ',' */
+       79,     /* '-' */
+       58,     /* '.' */
+       171,    /* '/' */
+       148,    /* '0' */
+       142,    /* '1' */
+       146,    /* '2' */
+       148,    /* '3' */
+       142,    /* '4' */
+       151,    /* '5' */
+       148,    /* '6' */
+       142,    /* '7' */
+       148,    /* '8' */
+       148,    /* '9' */
+       118,    /* ':' */
+       136,    /* ';' */
+       135,    /* '<' */
+       112,    /* '=' */
+       135,    /* '>' */
+       148,    /* '?' */
+       148,    /* '@' */
+       142,    /* 'A' */
+       142,    /* 'B' */
+       148,    /* 'C' */
+       142,    /* 'D' */
+       142,    /* 'E' */
+       142,    /* 'F' */
+       148,    /* 'G' */
+       142,    /* 'H' */
+       142,    /* 'I' */
+       144,    /* 'J' */
+       142,    /* 'K' */
+       142,    /* 'L' */
+       142,    /* 'M' */
+       142,    /* 'N' */
+       148,    /* 'O' */
+       142,    /* 'P' */
+       181,    /* 'Q' */
+       142,    /* 'R' */
+       148,    /* 'S' */
+       142,    /* 'T' */
+       144,    /* 'U' */
+       142,    /* 'V' */
+       142,    /* 'W' */
+       142,    /* 'X' */
+       142,    /* 'Y' */
+       142,    /* 'Z' */
+       171,    /* '[' */
+       149,    /* '\' */
+       171,    /* ']' */
+       148,    /* '^' */
+       38,     /* '_' */
+       143,    /* '`' */
+       118,    /* 'a' */
+       151,    /* 'b' */
+       118,    /* 'c' */
+       151,    /* 'd' */
+       118,    /* 'e' */
+       149,    /* 'f' */
+       168,    /* 'g' */
+       148,    /* 'h' */
+       149,    /* 'i' */
+       188,    /* 'j' */
+       148,    /* 'k' */
+       148,    /* 'l' */
+       116,    /* 'm' */
+       116,    /* 'n' */
+       118,    /* 'o' */
+       151,    /* 'p' */
+       151,    /* 'q' */
+       116,    /* 'r' */
+       118,    /* 's' */
+       140,    /* 't' */
+       114,    /* 'u' */
+       112,    /* 'v' */
+       112,    /* 'w' */
+       112,    /* 'x' */
+       151,    /* 'y' */
+       112,    /* 'z' */
+       171,    /* '{' */
+       148,    /* '|' */
+       171,    /* '}' */
+       102,    /* '~' */
+       },
+       /* ascent table for font BB */
+       {
+       108,    /* ' ' */
+       132,    /* '!' */
+       132,    /* '"' */
+       128,    /* '#' */
+       148,    /* '$' */
+       132,    /* '%' */
+       132,    /* '&' */
+       132,    /* ''' */
+       137,    /* '(' */
+       137,    /* ')' */
+       132,    /* '*' */
+       113,    /* '+' */
+       42,     /* ',' */
+       65,     /* '-' */
+       42,     /* '.' */
+       134,    /* '/' */
+       132,    /* '0' */
+       128,    /* '1' */
+       132,    /* '2' */
+       132,    /* '3' */
+       128,    /* '4' */
+       135,    /* '5' */
+       132,    /* '6' */
+       128,    /* '7' */
+       132,    /* '8' */
+       132,    /* '9' */
+       102,    /* ':' */
+       102,    /* ';' */
+       121,    /* '<' */
+       98,     /* '=' */
+       121,    /* '>' */
+       132,    /* '?' */
+       132,    /* '@' */
+       128,    /* 'A' */
+       128,    /* 'B' */
+       132,    /* 'C' */
+       128,    /* 'D' */
+       128,    /* 'E' */
+       128,    /* 'F' */
+       132,    /* 'G' */
+       128,    /* 'H' */
+       128,    /* 'I' */
+       128,    /* 'J' */
+       128,    /* 'K' */
+       128,    /* 'L' */
+       128,    /* 'M' */
+       128,    /* 'N' */
+       132,    /* 'O' */
+       128,    /* 'P' */
+       132,    /* 'Q' */
+       128,    /* 'R' */
+       132,    /* 'S' */
+       128,    /* 'T' */
+       128,    /* 'U' */
+       128,    /* 'V' */
+       128,    /* 'W' */
+       128,    /* 'X' */
+       128,    /* 'Y' */
+       128,    /* 'Z' */
+       135,    /* '[' */
+       135,    /* '\' */
+       135,    /* ']' */
+       134,    /* '^' */
+       -2,     /* '_' */
+       130,    /* '`' */
+       102,    /* 'a' */
+       135,    /* 'b' */
+       102,    /* 'c' */
+       135,    /* 'd' */
+       102,    /* 'e' */
+       135,    /* 'f' */
+       112,    /* 'g' */
+       135,    /* 'h' */
+       135,    /* 'i' */
+       136,    /* 'j' */
+       135,    /* 'k' */
+       135,    /* 'l' */
+       102,    /* 'm' */
+       102,    /* 'n' */
+       102,    /* 'o' */
+       102,    /* 'p' */
+       102,    /* 'q' */
+       102,    /* 'r' */
+       102,    /* 's' */
+       124,    /* 't' */
+       98,     /* 'u' */
+       98,     /* 'v' */
+       98,     /* 'w' */
+       98,     /* 'x' */
+       98,     /* 'y' */
+       98,     /* 'z' */
+       134,    /* '{' */
+       134,    /* '|' */
+       134,    /* '}' */
+       88,     /* '~' */
+       },
+
+       "Bookman-Demi",
+       0,
+       NO
+       }, {
+       /* width table for font BX */
+       {
+       57,     /* ' ' */
+       53,     /* '!' */
+       63,     /* '"' */
+       113,    /* '#' */
+       113,    /* '$' */
+       147,    /* '%' */
+       163,    /* '&' */
+       53,     /* ''' */
+       43,     /* '(' */
+       43,     /* ')' */
+       77,     /* '*' */
+       100,    /* '+' */
+       57,     /* ',' */
+       47,     /* '-' */
+       57,     /* '.' */
+       60,     /* '/' */
+       113,    /* '0' */
+       113,    /* '1' */
+       113,    /* '2' */
+       113,    /* '3' */
+       113,    /* '4' */
+       113,    /* '5' */
+       113,    /* '6' */
+       113,    /* '7' */
+       113,    /* '8' */
+       113,    /* '9' */
+       57,     /* ':' */
+       57,     /* ';' */
+       103,    /* '<' */
+       100,    /* '=' */
+       103,    /* '>' */
+       103,    /* '?' */
+       130,    /* '@' */
+       120,    /* 'A' */
+       120,    /* 'B' */
+       117,    /* 'C' */
+       127,    /* 'D' */
+       120,    /* 'E' */
+       110,    /* 'F' */
+       127,    /* 'G' */
+       133,    /* 'H' */
+       63,     /* 'I' */
+       103,    /* 'J' */
+       130,    /* 'K' */
+       107,    /* 'L' */
+       143,    /* 'M' */
+       123,    /* 'N' */
+       127,    /* 'O' */
+       107,    /* 'P' */
+       127,    /* 'Q' */
+       123,    /* 'R' */
+       117,    /* 'S' */
+       117,    /* 'T' */
+       123,    /* 'U' */
+       110,    /* 'V' */
+       167,    /* 'W' */
+       123,    /* 'X' */
+       110,    /* 'Y' */
+       113,    /* 'Z' */
+       43,     /* '[' */
+       97,     /* '\' */
+       43,     /* ']' */
+       103,    /* '^' */
+       83,     /* '_' */
+       53,     /* '`' */
+       113,    /* 'a' */
+       100,    /* 'b' */
+       93,     /* 'c' */
+       113,    /* 'd' */
+       93,     /* 'e' */
+       70,     /* 'f' */
+       103,    /* 'g' */
+       117,    /* 'h' */
+       63,     /* 'i' */
+       53,     /* 'j' */
+       117,    /* 'k' */
+       63,     /* 'l' */
+       160,    /* 'm' */
+       113,    /* 'n' */
+       100,    /* 'o' */
+       110,    /* 'p' */
+       103,    /* 'q' */
+       83,     /* 'r' */
+       90,     /* 's' */
+       73,     /* 't' */
+       113,    /* 'u' */
+       90,     /* 'v' */
+       143,    /* 'w' */
+       103,    /* 'x' */
+       100,    /* 'y' */
+       93,     /* 'z' */
+       50,     /* '{' */
+       103,    /* '|' */
+       50,     /* '}' */
+       103,    /* '~' */
+       },
+       /* height table for font BX */
+       {
+       153,    /* ' ' */
+       148,    /* '!' */
+       142,    /* '"' */
+       142,    /* '#' */
+       186,    /* '$' */
+       148,    /* '%' */
+       148,    /* '&' */
+       146,    /* ''' */
+       170,    /* '(' */
+       170,    /* ')' */
+       146,    /* '*' */
+       127,    /* '+' */
+       79,     /* ',' */
+       79,     /* '-' */
+       59,     /* '.' */
+       170,    /* '/' */
+       148,    /* '0' */
+       142,    /* '1' */
+       146,    /* '2' */
+       148,    /* '3' */
+       142,    /* '4' */
+       144,    /* '5' */
+       148,    /* '6' */
+       142,    /* '7' */
+       148,    /* '8' */
+       148,    /* '9' */
+       118,    /* ':' */
+       137,    /* ';' */
+       135,    /* '<' */
+       112,    /* '=' */
+       135,    /* '>' */
+       148,    /* '?' */
+       148,    /* '@' */
+       142,    /* 'A' */
+       142,    /* 'B' */
+       148,    /* 'C' */
+       142,    /* 'D' */
+       142,    /* 'E' */
+       142,    /* 'F' */
+       148,    /* 'G' */
+       142,    /* 'H' */
+       142,    /* 'I' */
+       144,    /* 'J' */
+       142,    /* 'K' */
+       142,    /* 'L' */
+       142,    /* 'M' */
+       142,    /* 'N' */
+       148,    /* 'O' */
+       142,    /* 'P' */
+       181,    /* 'Q' */
+       142,    /* 'R' */
+       148,    /* 'S' */
+       142,    /* 'T' */
+       144,    /* 'U' */
+       142,    /* 'V' */
+       142,    /* 'W' */
+       142,    /* 'X' */
+       142,    /* 'Y' */
+       142,    /* 'Z' */
+       171,    /* '[' */
+       151,    /* '\' */
+       171,    /* ']' */
+       148,    /* '^' */
+       38,     /* '_' */
+       143,    /* '`' */
+       118,    /* 'a' */
+       152,    /* 'b' */
+       118,    /* 'c' */
+       152,    /* 'd' */
+       118,    /* 'e' */
+       188,    /* 'f' */
+       148,    /* 'g' */
+       152,    /* 'h' */
+       157,    /* 'i' */
+       190,    /* 'j' */
+       152,    /* 'k' */
+       152,    /* 'l' */
+       118,    /* 'm' */
+       118,    /* 'n' */
+       118,    /* 'o' */
+       151,    /* 'p' */
+       151,    /* 'q' */
+       116,    /* 'r' */
+       118,    /* 's' */
+       140,    /* 't' */
+       114,    /* 'u' */
+       118,    /* 'v' */
+       118,    /* 'w' */
+       118,    /* 'x' */
+       144,    /* 'y' */
+       118,    /* 'z' */
+       170,    /* '{' */
+       148,    /* '|' */
+       170,    /* '}' */
+       102,    /* '~' */
+       },
+       /* ascent table for font BX */
+       {
+       108,    /* ' ' */
+       132,    /* '!' */
+       128,    /* '"' */
+       128,    /* '#' */
+       145,    /* '$' */
+       132,    /* '%' */
+       132,    /* '&' */
+       132,    /* ''' */
+       132,    /* '(' */
+       132,    /* ')' */
+       132,    /* '*' */
+       113,    /* '+' */
+       44,     /* ',' */
+       65,     /* '-' */
+       43,     /* '.' */
+       132,    /* '/' */
+       132,    /* '0' */
+       128,    /* '1' */
+       132,    /* '2' */
+       132,    /* '3' */
+       128,    /* '4' */
+       128,    /* '5' */
+       132,    /* '6' */
+       128,    /* '7' */
+       132,    /* '8' */
+       132,    /* '9' */
+       102,    /* ':' */
+       102,    /* ';' */
+       121,    /* '<' */
+       98,     /* '=' */
+       121,    /* '>' */
+       132,    /* '?' */
+       132,    /* '@' */
+       128,    /* 'A' */
+       128,    /* 'B' */
+       132,    /* 'C' */
+       128,    /* 'D' */
+       128,    /* 'E' */
+       128,    /* 'F' */
+       132,    /* 'G' */
+       128,    /* 'H' */
+       128,    /* 'I' */
+       128,    /* 'J' */
+       128,    /* 'K' */
+       128,    /* 'L' */
+       128,    /* 'M' */
+       128,    /* 'N' */
+       132,    /* 'O' */
+       128,    /* 'P' */
+       132,    /* 'Q' */
+       128,    /* 'R' */
+       132,    /* 'S' */
+       128,    /* 'T' */
+       128,    /* 'U' */
+       128,    /* 'V' */
+       128,    /* 'W' */
+       128,    /* 'X' */
+       128,    /* 'Y' */
+       128,    /* 'Z' */
+       132,    /* '[' */
+       137,    /* '\' */
+       132,    /* ']' */
+       134,    /* '^' */
+       -2,     /* '_' */
+       130,    /* '`' */
+       102,    /* 'a' */
+       136,    /* 'b' */
+       102,    /* 'c' */
+       136,    /* 'd' */
+       102,    /* 'e' */
+       138,    /* 'f' */
+       102,    /* 'g' */
+       136,    /* 'h' */
+       141,    /* 'i' */
+       141,    /* 'j' */
+       136,    /* 'k' */
+       136,    /* 'l' */
+       102,    /* 'm' */
+       102,    /* 'n' */
+       102,    /* 'o' */
+       102,    /* 'p' */
+       102,    /* 'q' */
+       102,    /* 'r' */
+       102,    /* 's' */
+       124,    /* 't' */
+       98,     /* 'u' */
+       102,    /* 'v' */
+       102,    /* 'w' */
+       102,    /* 'x' */
+       98,     /* 'y' */
+       102,    /* 'z' */
+       132,    /* '{' */
+       134,    /* '|' */
+       132,    /* '}' */
+       88,     /* '~' */
+       },
+
+       "Bookman-DemiItalic",
+       0,
+       YES
+       }, {
+       /* width table for font NR */
+       {
+       46,     /* ' ' */
+       49,     /* '!' */
+       65,     /* '"' */
+       93,     /* '#' */
+       93,     /* '$' */
+       139,    /* '%' */
+       136,    /* '&' */
+       34,     /* ''' */
+       55,     /* '(' */
+       55,     /* ')' */
+       83,     /* '*' */
+       101,    /* '+' */
+       46,     /* ',' */
+       55,     /* '-' */
+       46,     /* '.' */
+       46,     /* '/' */
+       93,     /* '0' */
+       93,     /* '1' */
+       93,     /* '2' */
+       93,     /* '3' */
+       93,     /* '4' */
+       93,     /* '5' */
+       93,     /* '6' */
+       93,     /* '7' */
+       93,     /* '8' */
+       93,     /* '9' */
+       46,     /* ':' */
+       46,     /* ';' */
+       101,    /* '<' */
+       101,    /* '=' */
+       101,    /* '>' */
+       74,     /* '?' */
+       123,    /* '@' */
+       120,    /* 'A' */
+       120,    /* 'B' */
+       120,    /* 'C' */
+       130,    /* 'D' */
+       120,    /* 'E' */
+       111,    /* 'F' */
+       130,    /* 'G' */
+       139,    /* 'H' */
+       68,     /* 'I' */
+       93,     /* 'J' */
+       130,    /* 'K' */
+       111,    /* 'L' */
+       157,    /* 'M' */
+       136,    /* 'N' */
+       130,    /* 'O' */
+       111,    /* 'P' */
+       130,    /* 'Q' */
+       120,    /* 'R' */
+       105,    /* 'S' */
+       111,    /* 'T' */
+       136,    /* 'U' */
+       120,    /* 'V' */
+       163,    /* 'W' */
+       117,    /* 'X' */
+       117,    /* 'Y' */
+       102,    /* 'Z' */
+       55,     /* '[' */
+       101,    /* '\' */
+       55,     /* ']' */
+       101,    /* '^' */
+       83,     /* '_' */
+       34,     /* '`' */
+       93,     /* 'a' */
+       93,     /* 'b' */
+       74,     /* 'c' */
+       96,     /* 'd' */
+       83,     /* 'e' */
+       55,     /* 'f' */
+       89,     /* 'g' */
+       102,    /* 'h' */
+       52,     /* 'i' */
+       49,     /* 'j' */
+       99,     /* 'k' */
+       52,     /* 'l' */
+       148,    /* 'm' */
+       102,    /* 'n' */
+       83,     /* 'o' */
+       96,     /* 'p' */
+       93,     /* 'q' */
+       74,     /* 'r' */
+       77,     /* 's' */
+       65,     /* 't' */
+       102,    /* 'u' */
+       89,     /* 'v' */
+       130,    /* 'w' */
+       89,     /* 'x' */
+       89,     /* 'y' */
+       80,     /* 'z' */
+       55,     /* '{' */
+       101,    /* '|' */
+       55,     /* '}' */
+       101,    /* '~' */
+       },
+       /* height table for font NR */
+       {
+       153,    /* ' ' */
+       154,    /* '!' */
+       152,    /* '"' */
+       142,    /* '#' */
+       183,    /* '$' */
+       149,    /* '%' */
+       154,    /* '&' */
+       152,    /* ''' */
+       171,    /* '(' */
+       171,    /* ')' */
+       152,    /* '*' */
+       112,    /* '+' */
+       76,     /* ',' */
+       72,     /* '-' */
+       48,     /* '.' */
+       154,    /* '/' */
+       148,    /* '0' */
+       145,    /* '1' */
+       146,    /* '2' */
+       148,    /* '3' */
+       145,    /* '4' */
+       147,    /* '5' */
+       148,    /* '6' */
+       147,    /* '7' */
+       148,    /* '8' */
+       148,    /* '9' */
+       111,    /* ':' */
+       136,    /* ';' */
+       118,    /* '<' */
+       92,     /* '=' */
+       118,    /* '>' */
+       154,    /* '?' */
+       154,    /* '@' */
+       152,    /* 'A' */
+       149,    /* 'B' */
+       154,    /* 'C' */
+       149,    /* 'D' */
+       149,    /* 'E' */
+       149,    /* 'F' */
+       154,    /* 'G' */
+       149,    /* 'H' */
+       149,    /* 'I' */
+       151,    /* 'J' */
+       149,    /* 'K' */
+       149,    /* 'L' */
+       149,    /* 'M' */
+       151,    /* 'N' */
+       154,    /* 'O' */
+       149,    /* 'P' */
+       184,    /* 'Q' */
+       151,    /* 'R' */
+       154,    /* 'S' */
+       149,    /* 'T' */
+       151,    /* 'U' */
+       151,    /* 'V' */
+       151,    /* 'W' */
+       149,    /* 'X' */
+       149,    /* 'Y' */
+       149,    /* 'Z' */
+       168,    /* '[' */
+       152,    /* '\' */
+       168,    /* ']' */
+       149,    /* '^' */
+       38,     /* '_' */
+       150,    /* '`' */
+       111,    /* 'a' */
+       153,    /* 'b' */
+       111,    /* 'c' */
+       153,    /* 'd' */
+       111,    /* 'e' */
+       152,    /* 'f' */
+       144,    /* 'g' */
+       151,    /* 'h' */
+       149,    /* 'i' */
+       181,    /* 'j' */
+       151,    /* 'k' */
+       151,    /* 'l' */
+       109,    /* 'm' */
+       109,    /* 'n' */
+       111,    /* 'o' */
+       144,    /* 'p' */
+       144,    /* 'q' */
+       109,    /* 'r' */
+       111,    /* 's' */
+       141,    /* 't' */
+       108,    /* 'u' */
+       108,    /* 'v' */
+       108,    /* 'w' */
+       106,    /* 'x' */
+       138,    /* 'y' */
+       106,    /* 'z' */
+       167,    /* '{' */
+       149,    /* '|' */
+       167,    /* '}' */
+       82,     /* '~' */
+       },
+       /* ascent table for font NR */
+       {
+       108,    /* ' ' */
+       138,    /* '!' */
+       138,    /* '"' */
+       128,    /* '#' */
+       147,    /* '$' */
+       135,    /* '%' */
+       138,    /* '&' */
+       138,    /* ''' */
+       137,    /* '(' */
+       137,    /* ')' */
+       138,    /* '*' */
+       98,     /* '+' */
+       32,     /* ',' */
+       58,     /* '-' */
+       32,     /* '.' */
+       138,    /* '/' */
+       132,    /* '0' */
+       131,    /* '1' */
+       132,    /* '2' */
+       132,    /* '3' */
+       131,    /* '4' */
+       131,    /* '5' */
+       132,    /* '6' */
+       131,    /* '7' */
+       132,    /* '8' */
+       132,    /* '9' */
+       95,     /* ':' */
+       92,     /* ';' */
+       101,    /* '<' */
+       78,     /* '=' */
+       101,    /* '>' */
+       138,    /* '?' */
+       138,    /* '@' */
+       138,    /* 'A' */
+       135,    /* 'B' */
+       138,    /* 'C' */
+       135,    /* 'D' */
+       135,    /* 'E' */
+       135,    /* 'F' */
+       138,    /* 'G' */
+       135,    /* 'H' */
+       135,    /* 'I' */
+       135,    /* 'J' */
+       135,    /* 'K' */
+       135,    /* 'L' */
+       135,    /* 'M' */
+       135,    /* 'N' */
+       138,    /* 'O' */
+       135,    /* 'P' */
+       138,    /* 'Q' */
+       135,    /* 'R' */
+       138,    /* 'S' */
+       135,    /* 'T' */
+       135,    /* 'U' */
+       135,    /* 'V' */
+       135,    /* 'W' */
+       135,    /* 'X' */
+       135,    /* 'Y' */
+       135,    /* 'Z' */
+       135,    /* '[' */
+       138,    /* '\' */
+       135,    /* ']' */
+       135,    /* '^' */
+       2,      /* '_' */
+       137,    /* '`' */
+       95,     /* 'a' */
+       137,    /* 'b' */
+       95,     /* 'c' */
+       137,    /* 'd' */
+       95,     /* 'e' */
+       138,    /* 'f' */
+       98,     /* 'g' */
+       137,    /* 'h' */
+       135,    /* 'i' */
+       135,    /* 'j' */
+       137,    /* 'k' */
+       137,    /* 'l' */
+       95,     /* 'm' */
+       95,     /* 'n' */
+       95,     /* 'o' */
+       95,     /* 'p' */
+       95,     /* 'q' */
+       95,     /* 'r' */
+       95,     /* 's' */
+       125,    /* 't' */
+       92,     /* 'u' */
+       92,     /* 'v' */
+       92,     /* 'w' */
+       92,     /* 'x' */
+       92,     /* 'y' */
+       92,     /* 'z' */
+       135,    /* '{' */
+       135,    /* '|' */
+       135,    /* '}' */
+       68,     /* '~' */
+       },
+
+       "NewCenturySchlbk-Roman",
+       0,
+       NO
+       }, {
+       /* width table for font NI */
+       {
+       46,     /* ' ' */
+       55,     /* '!' */
+       67,     /* '"' */
+       93,     /* '#' */
+       93,     /* '$' */
+       139,    /* '%' */
+       142,    /* '&' */
+       34,     /* ''' */
+       55,     /* '(' */
+       55,     /* ')' */
+       83,     /* '*' */
+       101,    /* '+' */
+       46,     /* ',' */
+       55,     /* '-' */
+       46,     /* '.' */
+       101,    /* '/' */
+       93,     /* '0' */
+       93,     /* '1' */
+       93,     /* '2' */
+       93,     /* '3' */
+       93,     /* '4' */
+       93,     /* '5' */
+       93,     /* '6' */
+       93,     /* '7' */
+       93,     /* '8' */
+       93,     /* '9' */
+       46,     /* ':' */
+       46,     /* ';' */
+       101,    /* '<' */
+       101,    /* '=' */
+       101,    /* '>' */
+       74,     /* '?' */
+       124,    /* '@' */
+       117,    /* 'A' */
+       120,    /* 'B' */
+       120,    /* 'C' */
+       130,    /* 'D' */
+       120,    /* 'E' */
+       111,    /* 'F' */
+       130,    /* 'G' */
+       139,    /* 'H' */
+       68,     /* 'I' */
+       102,    /* 'J' */
+       123,    /* 'K' */
+       111,    /* 'L' */
+       157,    /* 'M' */
+       136,    /* 'N' */
+       130,    /* 'O' */
+       111,    /* 'P' */
+       130,    /* 'Q' */
+       123,    /* 'R' */
+       111,    /* 'S' */
+       114,    /* 'T' */
+       136,    /* 'U' */
+       117,    /* 'V' */
+       154,    /* 'W' */
+       117,    /* 'X' */
+       114,    /* 'Y' */
+       111,    /* 'Z' */
+       55,     /* '[' */
+       101,    /* '\' */
+       55,     /* ']' */
+       101,    /* '^' */
+       83,     /* '_' */
+       34,     /* '`' */
+       96,     /* 'a' */
+       93,     /* 'b' */
+       74,     /* 'c' */
+       102,    /* 'd' */
+       74,     /* 'e' */
+       55,     /* 'f' */
+       89,     /* 'g' */
+       102,    /* 'h' */
+       55,     /* 'i' */
+       52,     /* 'j' */
+       93,     /* 'k' */
+       55,     /* 'l' */
+       148,    /* 'm' */
+       102,    /* 'n' */
+       83,     /* 'o' */
+       96,     /* 'p' */
+       93,     /* 'q' */
+       74,     /* 'r' */
+       74,     /* 's' */
+       59,     /* 't' */
+       102,    /* 'u' */
+       86,     /* 'v' */
+       130,    /* 'w' */
+       83,     /* 'x' */
+       83,     /* 'y' */
+       77,     /* 'z' */
+       55,     /* '{' */
+       101,    /* '|' */
+       55,     /* '}' */
+       101,    /* '~' */
+       },
+       /* height table for font NI */
+       {
+       153,    /* ' ' */
+       154,    /* '!' */
+       152,    /* '"' */
+       142,    /* '#' */
+       182,    /* '$' */
+       149,    /* '%' */
+       154,    /* '&' */
+       146,    /* ''' */
+       171,    /* '(' */
+       171,    /* ')' */
+       145,    /* '*' */
+       112,    /* '+' */
+       74,     /* ',' */
+       72,     /* '-' */
+       48,     /* '.' */
+       167,    /* '/' */
+       148,    /* '0' */
+       146,    /* '1' */
+       146,    /* '2' */
+       148,    /* '3' */
+       146,    /* '4' */
+       147,    /* '5' */
+       148,    /* '6' */
+       147,    /* '7' */
+       148,    /* '8' */
+       148,    /* '9' */
+       108,    /* ':' */
+       133,    /* ';' */
+       118,    /* '<' */
+       92,     /* '=' */
+       118,    /* '>' */
+       154,    /* '?' */
+       154,    /* '@' */
+       152,    /* 'A' */
+       149,    /* 'B' */
+       154,    /* 'C' */
+       149,    /* 'D' */
+       149,    /* 'E' */
+       149,    /* 'F' */
+       154,    /* 'G' */
+       149,    /* 'H' */
+       149,    /* 'I' */
+       151,    /* 'J' */
+       149,    /* 'K' */
+       149,    /* 'L' */
+       149,    /* 'M' */
+       151,    /* 'N' */
+       154,    /* 'O' */
+       149,    /* 'P' */
+       184,    /* 'Q' */
+       151,    /* 'R' */
+       154,    /* 'S' */
+       149,    /* 'T' */
+       151,    /* 'U' */
+       151,    /* 'V' */
+       151,    /* 'W' */
+       149,    /* 'X' */
+       149,    /* 'Y' */
+       149,    /* 'Z' */
+       168,    /* '[' */
+       146,    /* '\' */
+       168,    /* ']' */
+       149,    /* '^' */
+       34,     /* '_' */
+       151,    /* '`' */
+       108,    /* 'a' */
+       153,    /* 'b' */
+       108,    /* 'c' */
+       153,    /* 'd' */
+       108,    /* 'e' */
+       186,    /* 'f' */
+       144,    /* 'g' */
+       153,    /* 'h' */
+       148,    /* 'i' */
+       181,    /* 'j' */
+       153,    /* 'k' */
+       153,    /* 'l' */
+       108,    /* 'm' */
+       108,    /* 'n' */
+       108,    /* 'o' */
+       138,    /* 'p' */
+       138,    /* 'q' */
+       106,    /* 'r' */
+       107,    /* 's' */
+       134,    /* 't' */
+       108,    /* 'u' */
+       108,    /* 'v' */
+       108,    /* 'w' */
+       108,    /* 'x' */
+       138,    /* 'y' */
+       108,    /* 'z' */
+       167,    /* '{' */
+       149,    /* '|' */
+       167,    /* '}' */
+       82,     /* '~' */
+       },
+       /* ascent table for font NI */
+       {
+       108,    /* ' ' */
+       138,    /* '!' */
+       138,    /* '"' */
+       128,    /* '#' */
+       146,    /* '$' */
+       135,    /* '%' */
+       138,    /* '&' */
+       132,    /* ''' */
+       137,    /* '(' */
+       137,    /* ')' */
+       131,    /* '*' */
+       98,     /* '+' */
+       32,     /* ',' */
+       58,     /* '-' */
+       32,     /* '.' */
+       135,    /* '/' */
+       132,    /* '0' */
+       132,    /* '1' */
+       132,    /* '2' */
+       132,    /* '3' */
+       132,    /* '4' */
+       131,    /* '5' */
+       132,    /* '6' */
+       131,    /* '7' */
+       132,    /* '8' */
+       132,    /* '9' */
+       92,     /* ':' */
+       92,     /* ';' */
+       101,    /* '<' */
+       78,     /* '=' */
+       101,    /* '>' */
+       138,    /* '?' */
+       138,    /* '@' */
+       138,    /* 'A' */
+       135,    /* 'B' */
+       138,    /* 'C' */
+       135,    /* 'D' */
+       135,    /* 'E' */
+       135,    /* 'F' */
+       138,    /* 'G' */
+       135,    /* 'H' */
+       135,    /* 'I' */
+       135,    /* 'J' */
+       135,    /* 'K' */
+       135,    /* 'L' */
+       135,    /* 'M' */
+       135,    /* 'N' */
+       138,    /* 'O' */
+       135,    /* 'P' */
+       138,    /* 'Q' */
+       135,    /* 'R' */
+       138,    /* 'S' */
+       135,    /* 'T' */
+       135,    /* 'U' */
+       135,    /* 'V' */
+       135,    /* 'W' */
+       135,    /* 'X' */
+       135,    /* 'Y' */
+       135,    /* 'Z' */
+       135,    /* '[' */
+       132,    /* '\' */
+       135,    /* ']' */
+       135,    /* '^' */
+       2,      /* '_' */
+       137,    /* '`' */
+       92,     /* 'a' */
+       137,    /* 'b' */
+       92,     /* 'c' */
+       137,    /* 'd' */
+       92,     /* 'e' */
+       138,    /* 'f' */
+       98,     /* 'g' */
+       137,    /* 'h' */
+       132,    /* 'i' */
+       132,    /* 'j' */
+       137,    /* 'k' */
+       137,    /* 'l' */
+       92,     /* 'm' */
+       92,     /* 'n' */
+       92,     /* 'o' */
+       92,     /* 'p' */
+       92,     /* 'q' */
+       92,     /* 'r' */
+       91,     /* 's' */
+       117,    /* 't' */
+       92,     /* 'u' */
+       92,     /* 'v' */
+       92,     /* 'w' */
+       92,     /* 'x' */
+       92,     /* 'y' */
+       92,     /* 'z' */
+       135,    /* '{' */
+       135,    /* '|' */
+       135,    /* '}' */
+       68,     /* '~' */
+       },
+
+       "NewCenturySchlbk-Italic",
+       0,
+       YES
+       }, {
+       /* width table for font NB */
+       {
+       48,     /* ' ' */
+       49,     /* '!' */
+       55,     /* '"' */
+       96,     /* '#' */
+       96,     /* '$' */
+       139,    /* '%' */
+       142,    /* '&' */
+       40,     /* ''' */
+       65,     /* '(' */
+       65,     /* ')' */
+       83,     /* '*' */
+       101,    /* '+' */
+       46,     /* ',' */
+       55,     /* '-' */
+       46,     /* '.' */
+       46,     /* '/' */
+       96,     /* '0' */
+       96,     /* '1' */
+       96,     /* '2' */
+       96,     /* '3' */
+       96,     /* '4' */
+       96,     /* '5' */
+       96,     /* '6' */
+       96,     /* '7' */
+       96,     /* '8' */
+       96,     /* '9' */
+       46,     /* ':' */
+       46,     /* ';' */
+       101,    /* '<' */
+       101,    /* '=' */
+       101,    /* '>' */
+       83,     /* '?' */
+       124,    /* '@' */
+       126,    /* 'A' */
+       130,    /* 'B' */
+       130,    /* 'C' */
+       139,    /* 'D' */
+       126,    /* 'E' */
+       120,    /* 'F' */
+       139,    /* 'G' */
+       145,    /* 'H' */
+       74,     /* 'I' */
+       108,    /* 'J' */
+       136,    /* 'K' */
+       120,    /* 'L' */
+       163,    /* 'M' */
+       139,    /* 'N' */
+       139,    /* 'O' */
+       126,    /* 'P' */
+       139,    /* 'Q' */
+       136,    /* 'R' */
+       111,    /* 'S' */
+       120,    /* 'T' */
+       139,    /* 'U' */
+       126,    /* 'V' */
+       163,    /* 'W' */
+       120,    /* 'X' */
+       120,    /* 'Y' */
+       111,    /* 'Z' */
+       65,     /* '[' */
+       101,    /* '\' */
+       65,     /* ']' */
+       101,    /* '^' */
+       83,     /* '_' */
+       40,     /* '`' */
+       102,    /* 'a' */
+       108,    /* 'b' */
+       93,     /* 'c' */
+       111,    /* 'd' */
+       96,     /* 'e' */
+       65,     /* 'f' */
+       102,    /* 'g' */
+       114,    /* 'h' */
+       62,     /* 'i' */
+       59,     /* 'j' */
+       111,    /* 'k' */
+       59,     /* 'l' */
+       160,    /* 'm' */
+       114,    /* 'n' */
+       102,    /* 'o' */
+       111,    /* 'p' */
+       108,    /* 'q' */
+       86,     /* 'r' */
+       83,     /* 's' */
+       71,     /* 't' */
+       114,    /* 'u' */
+       102,    /* 'v' */
+       148,    /* 'w' */
+       102,    /* 'x' */
+       102,    /* 'y' */
+       89,     /* 'z' */
+       65,     /* '{' */
+       101,    /* '|' */
+       65,     /* '}' */
+       101,    /* '~' */
+       },
+       /* height table for font NB */
+       {
+       153,    /* ' ' */
+       154,    /* '!' */
+       152,    /* '"' */
+       144,    /* '#' */
+       184,    /* '$' */
+       149,    /* '%' */
+       154,    /* '&' */
+       152,    /* ''' */
+       170,    /* '(' */
+       170,    /* ')' */
+       152,    /* '*' */
+       112,    /* '+' */
+       87,     /* ',' */
+       79,     /* '-' */
+       59,     /* '.' */
+       154,    /* '/' */
+       148,    /* '0' */
+       146,    /* '1' */
+       146,    /* '2' */
+       148,    /* '3' */
+       146,    /* '4' */
+       148,    /* '5' */
+       148,    /* '6' */
+       148,    /* '7' */
+       148,    /* '8' */
+       148,    /* '9' */
+       111,    /* ':' */
+       140,    /* ';' */
+       120,    /* '<' */
+       96,     /* '=' */
+       120,    /* '>' */
+       154,    /* '?' */
+       154,    /* '@' */
+       152,    /* 'A' */
+       149,    /* 'B' */
+       154,    /* 'C' */
+       149,    /* 'D' */
+       149,    /* 'E' */
+       149,    /* 'F' */
+       154,    /* 'G' */
+       149,    /* 'H' */
+       149,    /* 'I' */
+       151,    /* 'J' */
+       149,    /* 'K' */
+       149,    /* 'L' */
+       149,    /* 'M' */
+       151,    /* 'N' */
+       154,    /* 'O' */
+       149,    /* 'P' */
+       184,    /* 'Q' */
+       151,    /* 'R' */
+       154,    /* 'S' */
+       149,    /* 'T' */
+       151,    /* 'U' */
+       151,    /* 'V' */
+       151,    /* 'W' */
+       149,    /* 'X' */
+       149,    /* 'Y' */
+       149,    /* 'Z' */
+       168,    /* '[' */
+       152,    /* '\' */
+       168,    /* ']' */
+       149,    /* '^' */
+       44,     /* '_' */
+       152,    /* '`' */
+       111,    /* 'a' */
+       153,    /* 'b' */
+       111,    /* 'c' */
+       153,    /* 'd' */
+       111,    /* 'e' */
+       152,    /* 'f' */
+       154,    /* 'g' */
+       151,    /* 'h' */
+       152,    /* 'i' */
+       188,    /* 'j' */
+       151,    /* 'k' */
+       151,    /* 'l' */
+       109,    /* 'm' */
+       109,    /* 'n' */
+       111,    /* 'o' */
+       144,    /* 'p' */
+       144,    /* 'q' */
+       109,    /* 'r' */
+       111,    /* 's' */
+       142,    /* 't' */
+       109,    /* 'u' */
+       108,    /* 'v' */
+       108,    /* 'w' */
+       106,    /* 'x' */
+       138,    /* 'y' */
+       106,    /* 'z' */
+       167,    /* '{' */
+       149,    /* '|' */
+       167,    /* '}' */
+       86,     /* '~' */
+       },
+       /* ascent table for font NB */
+       {
+       108,    /* ' ' */
+       138,    /* '!' */
+       138,    /* '"' */
+       131,    /* '#' */
+       147,    /* '$' */
+       135,    /* '%' */
+       138,    /* '&' */
+       138,    /* ''' */
+       137,    /* '(' */
+       137,    /* ')' */
+       138,    /* '*' */
+       98,     /* '+' */
+       42,     /* ',' */
+       65,     /* '-' */
+       43,     /* '.' */
+       138,    /* '/' */
+       132,    /* '0' */
+       132,    /* '1' */
+       132,    /* '2' */
+       132,    /* '3' */
+       132,    /* '4' */
+       132,    /* '5' */
+       132,    /* '6' */
+       132,    /* '7' */
+       132,    /* '8' */
+       132,    /* '9' */
+       95,     /* ':' */
+       95,     /* ';' */
+       102,    /* '<' */
+       82,     /* '=' */
+       102,    /* '>' */
+       138,    /* '?' */
+       138,    /* '@' */
+       138,    /* 'A' */
+       135,    /* 'B' */
+       138,    /* 'C' */
+       135,    /* 'D' */
+       135,    /* 'E' */
+       135,    /* 'F' */
+       138,    /* 'G' */
+       135,    /* 'H' */
+       135,    /* 'I' */
+       135,    /* 'J' */
+       135,    /* 'K' */
+       135,    /* 'L' */
+       135,    /* 'M' */
+       135,    /* 'N' */
+       138,    /* 'O' */
+       135,    /* 'P' */
+       138,    /* 'Q' */
+       135,    /* 'R' */
+       138,    /* 'S' */
+       135,    /* 'T' */
+       135,    /* 'U' */
+       135,    /* 'V' */
+       135,    /* 'W' */
+       135,    /* 'X' */
+       135,    /* 'Y' */
+       135,    /* 'Z' */
+       135,    /* '[' */
+       138,    /* '\' */
+       135,    /* ']' */
+       135,    /* '^' */
+       5,      /* '_' */
+       138,    /* '`' */
+       95,     /* 'a' */
+       137,    /* 'b' */
+       95,     /* 'c' */
+       137,    /* 'd' */
+       95,     /* 'e' */
+       138,    /* 'f' */
+       105,    /* 'g' */
+       137,    /* 'h' */
+       138,    /* 'i' */
+       138,    /* 'j' */
+       137,    /* 'k' */
+       137,    /* 'l' */
+       95,     /* 'm' */
+       95,     /* 'n' */
+       95,     /* 'o' */
+       95,     /* 'p' */
+       95,     /* 'q' */
+       95,     /* 'r' */
+       95,     /* 's' */
+       126,    /* 't' */
+       93,     /* 'u' */
+       92,     /* 'v' */
+       92,     /* 'w' */
+       92,     /* 'x' */
+       92,     /* 'y' */
+       92,     /* 'z' */
+       135,    /* '{' */
+       135,    /* '|' */
+       135,    /* '}' */
+       72,     /* '~' */
+       },
+
+       "NewCenturySchlbk-Bold",
+       0,
+       NO
+       }, {
+       /* width table for font NX */
+       {
+       48,     /* ' ' */
+       55,     /* '!' */
+       67,     /* '"' */
+       96,     /* '#' */
+       96,     /* '$' */
+       148,    /* '%' */
+       148,    /* '&' */
+       43,     /* ''' */
+       68,     /* '(' */
+       68,     /* ')' */
+       83,     /* '*' */
+       101,    /* '+' */
+       48,     /* ',' */
+       55,     /* '-' */
+       48,     /* '.' */
+       46,     /* '/' */
+       96,     /* '0' */
+       96,     /* '1' */
+       96,     /* '2' */
+       96,     /* '3' */
+       96,     /* '4' */
+       96,     /* '5' */
+       96,     /* '6' */
+       96,     /* '7' */
+       96,     /* '8' */
+       96,     /* '9' */
+       48,     /* ':' */
+       48,     /* ';' */
+       101,    /* '<' */
+       101,    /* '=' */
+       101,    /* '>' */
+       80,     /* '?' */
+       124,    /* '@' */
+       123,    /* 'A' */
+       126,    /* 'B' */
+       126,    /* 'C' */
+       139,    /* 'D' */
+       123,    /* 'E' */
+       117,    /* 'F' */
+       136,    /* 'G' */
+       145,    /* 'H' */
+       74,     /* 'I' */
+       111,    /* 'J' */
+       130,    /* 'K' */
+       117,    /* 'L' */
+       157,    /* 'M' */
+       142,    /* 'N' */
+       139,    /* 'O' */
+       123,    /* 'P' */
+       139,    /* 'Q' */
+       133,    /* 'R' */
+       114,    /* 'S' */
+       120,    /* 'T' */
+       139,    /* 'U' */
+       123,    /* 'V' */
+       157,    /* 'W' */
+       123,    /* 'X' */
+       117,    /* 'Y' */
+       117,    /* 'Z' */
+       68,     /* '[' */
+       101,    /* '\' */
+       68,     /* ']' */
+       101,    /* '^' */
+       83,     /* '_' */
+       43,     /* '`' */
+       111,    /* 'a' */
+       102,    /* 'b' */
+       89,     /* 'c' */
+       111,    /* 'd' */
+       86,     /* 'e' */
+       65,     /* 'f' */
+       102,    /* 'g' */
+       114,    /* 'h' */
+       65,     /* 'i' */
+       62,     /* 'j' */
+       108,    /* 'k' */
+       65,     /* 'l' */
+       157,    /* 'm' */
+       114,    /* 'n' */
+       96,     /* 'o' */
+       108,    /* 'p' */
+       105,    /* 'q' */
+       86,     /* 'r' */
+       80,     /* 's' */
+       68,     /* 't' */
+       114,    /* 'u' */
+       93,     /* 'v' */
+       139,    /* 'w' */
+       96,     /* 'x' */
+       86,     /* 'y' */
+       86,     /* 'z' */
+       68,     /* '{' */
+       101,    /* '|' */
+       68,     /* '}' */
+       101,    /* '~' */
+       },
+       /* height table for font NX */
+       {
+       153,    /* ' ' */
+       154,    /* '!' */
+       152,    /* '"' */
+       144,    /* '#' */
+       184,    /* '$' */
+       149,    /* '%' */
+       154,    /* '&' */
+       149,    /* ''' */
+       170,    /* '(' */
+       170,    /* ')' */
+       152,    /* '*' */
+       112,    /* '+' */
+       85,     /* ',' */
+       79,     /* '-' */
+       56,     /* '.' */
+       154,    /* '/' */
+       148,    /* '0' */
+       146,    /* '1' */
+       146,    /* '2' */
+       148,    /* '3' */
+       146,    /* '4' */
+       148,    /* '5' */
+       148,    /* '6' */
+       147,    /* '7' */
+       148,    /* '8' */
+       148,    /* '9' */
+       111,    /* ':' */
+       140,    /* ';' */
+       120,    /* '<' */
+       96,     /* '=' */
+       120,    /* '>' */
+       154,    /* '?' */
+       154,    /* '@' */
+       152,    /* 'A' */
+       149,    /* 'B' */
+       154,    /* 'C' */
+       149,    /* 'D' */
+       149,    /* 'E' */
+       149,    /* 'F' */
+       154,    /* 'G' */
+       149,    /* 'H' */
+       149,    /* 'I' */
+       151,    /* 'J' */
+       149,    /* 'K' */
+       149,    /* 'L' */
+       149,    /* 'M' */
+       151,    /* 'N' */
+       154,    /* 'O' */
+       149,    /* 'P' */
+       184,    /* 'Q' */
+       151,    /* 'R' */
+       154,    /* 'S' */
+       149,    /* 'T' */
+       151,    /* 'U' */
+       151,    /* 'V' */
+       151,    /* 'W' */
+       149,    /* 'X' */
+       149,    /* 'Y' */
+       149,    /* 'Z' */
+       168,    /* '[' */
+       149,    /* '\' */
+       168,    /* ']' */
+       149,    /* '^' */
+       38,     /* '_' */
+       151,    /* '`' */
+       111,    /* 'a' */
+       154,    /* 'b' */
+       111,    /* 'c' */
+       154,    /* 'd' */
+       111,    /* 'e' */
+       186,    /* 'f' */
+       149,    /* 'g' */
+       154,    /* 'h' */
+       154,    /* 'i' */
+       184,    /* 'j' */
+       154,    /* 'k' */
+       154,    /* 'l' */
+       111,    /* 'm' */
+       111,    /* 'n' */
+       111,    /* 'o' */
+       141,    /* 'p' */
+       141,    /* 'q' */
+       109,    /* 'r' */
+       111,    /* 's' */
+       138,    /* 't' */
+       111,    /* 'u' */
+       111,    /* 'v' */
+       111,    /* 'w' */
+       111,    /* 'x' */
+       144,    /* 'y' */
+       111,    /* 'z' */
+       167,    /* '{' */
+       149,    /* '|' */
+       167,    /* '}' */
+       86,     /* '~' */
+       },
+       /* ascent table for font NX */
+       {
+       108,    /* ' ' */
+       138,    /* '!' */
+       138,    /* '"' */
+       131,    /* '#' */
+       146,    /* '$' */
+       135,    /* '%' */
+       138,    /* '&' */
+       135,    /* ''' */
+       137,    /* '(' */
+       137,    /* ')' */
+       138,    /* '*' */
+       98,     /* '+' */
+       40,     /* ',' */
+       65,     /* '-' */
+       40,     /* '.' */
+       138,    /* '/' */
+       132,    /* '0' */
+       132,    /* '1' */
+       132,    /* '2' */
+       132,    /* '3' */
+       132,    /* '4' */
+       132,    /* '5' */
+       132,    /* '6' */
+       131,    /* '7' */
+       132,    /* '8' */
+       132,    /* '9' */
+       95,     /* ':' */
+       95,     /* ';' */
+       102,    /* '<' */
+       82,     /* '=' */
+       102,    /* '>' */
+       138,    /* '?' */
+       138,    /* '@' */
+       138,    /* 'A' */
+       135,    /* 'B' */
+       138,    /* 'C' */
+       135,    /* 'D' */
+       135,    /* 'E' */
+       135,    /* 'F' */
+       138,    /* 'G' */
+       135,    /* 'H' */
+       135,    /* 'I' */
+       135,    /* 'J' */
+       135,    /* 'K' */
+       135,    /* 'L' */
+       135,    /* 'M' */
+       135,    /* 'N' */
+       138,    /* 'O' */
+       135,    /* 'P' */
+       138,    /* 'Q' */
+       135,    /* 'R' */
+       138,    /* 'S' */
+       135,    /* 'T' */
+       135,    /* 'U' */
+       135,    /* 'V' */
+       135,    /* 'W' */
+       135,    /* 'X' */
+       135,    /* 'Y' */
+       135,    /* 'Z' */
+       135,    /* '[' */
+       135,    /* '\' */
+       135,    /* ']' */
+       135,    /* '^' */
+       2,      /* '_' */
+       137,    /* '`' */
+       95,     /* 'a' */
+       138,    /* 'b' */
+       95,     /* 'c' */
+       138,    /* 'd' */
+       95,     /* 'e' */
+       138,    /* 'f' */
+       103,    /* 'g' */
+       138,    /* 'h' */
+       138,    /* 'i' */
+       138,    /* 'j' */
+       138,    /* 'k' */
+       138,    /* 'l' */
+       95,     /* 'm' */
+       95,     /* 'n' */
+       95,     /* 'o' */
+       95,     /* 'p' */
+       95,     /* 'q' */
+       95,     /* 'r' */
+       95,     /* 's' */
+       122,    /* 't' */
+       95,     /* 'u' */
+       95,     /* 'v' */
+       95,     /* 'w' */
+       95,     /* 'x' */
+       95,     /* 'y' */
+       95,     /* 'z' */
+       135,    /* '{' */
+       135,    /* '|' */
+       135,    /* '}' */
+       72,     /* '~' */
+       },
+
+       "NewCenturySchlbk-BoldItalic",
+       0,
+       YES
+       }, {
+       /* width table for font PR */
+       {
+       42,     /* ' ' */
+       46,     /* '!' */
+       62,     /* '"' */
+       83,     /* '#' */
+       83,     /* '$' */
+       140,    /* '%' */
+       130,    /* '&' */
+       46,     /* ''' */
+       55,     /* '(' */
+       55,     /* ')' */
+       65,     /* '*' */
+       101,    /* '+' */
+       42,     /* ',' */
+       55,     /* '-' */
+       42,     /* '.' */
+       101,    /* '/' */
+       83,     /* '0' */
+       83,     /* '1' */
+       83,     /* '2' */
+       83,     /* '3' */
+       83,     /* '4' */
+       83,     /* '5' */
+       83,     /* '6' */
+       83,     /* '7' */
+       83,     /* '8' */
+       83,     /* '9' */
+       42,     /* ':' */
+       42,     /* ';' */
+       101,    /* '<' */
+       101,    /* '=' */
+       101,    /* '>' */
+       74,     /* '?' */
+       124,    /* '@' */
+       130,    /* 'A' */
+       102,    /* 'B' */
+       118,    /* 'C' */
+       129,    /* 'D' */
+       102,    /* 'E' */
+       93,     /* 'F' */
+       127,    /* 'G' */
+       139,    /* 'H' */
+       56,     /* 'I' */
+       55,     /* 'J' */
+       121,    /* 'K' */
+       102,    /* 'L' */
+       158,    /* 'M' */
+       138,    /* 'N' */
+       131,    /* 'O' */
+       101,    /* 'P' */
+       131,    /* 'Q' */
+       111,    /* 'R' */
+       87,     /* 'S' */
+       102,    /* 'T' */
+       130,    /* 'U' */
+       120,    /* 'V' */
+       167,    /* 'W' */
+       111,    /* 'X' */
+       111,    /* 'Y' */
+       111,    /* 'Z' */
+       55,     /* '[' */
+       101,    /* '\' */
+       55,     /* ']' */
+       101,    /* '^' */
+       83,     /* '_' */
+       46,     /* '`' */
+       83,     /* 'a' */
+       92,     /* 'b' */
+       74,     /* 'c' */
+       102,    /* 'd' */
+       80,     /* 'e' */
+       55,     /* 'f' */
+       93,     /* 'g' */
+       97,     /* 'h' */
+       48,     /* 'i' */
+       39,     /* 'j' */
+       93,     /* 'k' */
+       48,     /* 'l' */
+       147,    /* 'm' */
+       97,     /* 'n' */
+       91,     /* 'o' */
+       100,    /* 'p' */
+       93,     /* 'q' */
+       66,     /* 'r' */
+       71,     /* 's' */
+       54,     /* 't' */
+       100,    /* 'u' */
+       94,     /* 'v' */
+       139,    /* 'w' */
+       86,     /* 'x' */
+       93,     /* 'y' */
+       83,     /* 'z' */
+       55,     /* '{' */
+       101,    /* '|' */
+       55,     /* '}' */
+       101,    /* '~' */
+       },
+       /* height table for font PR */
+       {
+       153,    /* ' ' */
+       142,    /* '!' */
+       146,    /* '"' */
+       142,    /* '#' */
+       169,    /* '$' */
+       149,    /* '%' */
+       145,    /* '&' */
+       146,    /* ''' */
+       185,    /* '(' */
+       185,    /* ')' */
+       143,    /* '*' */
+       113,    /* '+' */
+       74,     /* ',' */
+       76,     /* '-' */
+       46,     /* '.' */
+       169,    /* '/' */
+       144,    /* '0' */
+       144,    /* '1' */
+       143,    /* '2' */
+       144,    /* '3' */
+       144,    /* '4' */
+       145,    /* '5' */
+       145,    /* '6' */
+       143,    /* '7' */
+       144,    /* '8' */
+       146,    /* '9' */
+       106,    /* ':' */
+       131,    /* ';' */
+       115,    /* '<' */
+       92,     /* '=' */
+       115,    /* '>' */
+       142,    /* '?' */
+       144,    /* '@' */
+       146,    /* 'A' */
+       143,    /* 'B' */
+       148,    /* 'C' */
+       143,    /* 'D' */
+       143,    /* 'E' */
+       143,    /* 'F' */
+       148,    /* 'G' */
+       143,    /* 'H' */
+       143,    /* 'I' */
+       175,    /* 'J' */
+       143,    /* 'K' */
+       143,    /* 'L' */
+       145,    /* 'M' */
+       146,    /* 'N' */
+       148,    /* 'O' */
+       143,    /* 'P' */
+       175,    /* 'Q' */
+       143,    /* 'R' */
+       148,    /* 'S' */
+       143,    /* 'T' */
+       145,    /* 'U' */
+       145,    /* 'V' */
+       148,    /* 'W' */
+       145,    /* 'X' */
+       146,    /* 'Y' */
+       144,    /* 'Z' */
+       180,    /* '[' */
+       149,    /* '\' */
+       180,    /* ']' */
+       143,    /* '^' */
+       34,     /* '_' */
+       146,    /* '`' */
+       108,    /* 'a' */
+       151,    /* 'b' */
+       108,    /* 'c' */
+       151,    /* 'd' */
+       108,    /* 'e' */
+       149,    /* 'f' */
+       154,    /* 'g' */
+       149,    /* 'h' */
+       143,    /* 'i' */
+       189,    /* 'j' */
+       151,    /* 'k' */
+       149,    /* 'l' */
+       106,    /* 'm' */
+       106,    /* 'n' */
+       108,    /* 'o' */
+       155,    /* 'p' */
+       154,    /* 'q' */
+       106,    /* 'r' */
+       108,    /* 's' */
+       133,    /* 't' */
+       108,    /* 'u' */
+       106,    /* 'v' */
+       108,    /* 'w' */
+       106,    /* 'x' */
+       150,    /* 'y' */
+       106,    /* 'z' */
+       178,    /* '{' */
+       149,    /* '|' */
+       178,    /* '}' */
+       85,     /* '~' */
+       },
+       /* ascent table for font PR */
+       {
+       108,    /* ' ' */
+       128,    /* '!' */
+       132,    /* '"' */
+       128,    /* '#' */
+       136,    /* '$' */
+       132,    /* '%' */
+       128,    /* '&' */
+       132,    /* ''' */
+       135,    /* '(' */
+       135,    /* ')' */
+       129,    /* '*' */
+       99,     /* '+' */
+       34,     /* ',' */
+       62,     /* '-' */
+       32,     /* '.' */
+       135,    /* '/' */
+       128,    /* '0' */
+       130,    /* '1' */
+       128,    /* '2' */
+       128,    /* '3' */
+       130,    /* '4' */
+       129,    /* '5' */
+       129,    /* '6' */
+       129,    /* '7' */
+       128,    /* '8' */
+       128,    /* '9' */
+       92,     /* ':' */
+       92,     /* ';' */
+       101,    /* '<' */
+       78,     /* '=' */
+       101,    /* '>' */
+       128,    /* '?' */
+       128,    /* '@' */
+       132,    /* 'A' */
+       128,    /* 'B' */
+       132,    /* 'C' */
+       128,    /* 'D' */
+       128,    /* 'E' */
+       128,    /* 'F' */
+       132,    /* 'G' */
+       128,    /* 'H' */
+       128,    /* 'I' */
+       128,    /* 'J' */
+       128,    /* 'K' */
+       128,    /* 'L' */
+       128,    /* 'M' */
+       128,    /* 'N' */
+       132,    /* 'O' */
+       128,    /* 'P' */
+       132,    /* 'Q' */
+       128,    /* 'R' */
+       132,    /* 'S' */
+       129,    /* 'T' */
+       128,    /* 'U' */
+       129,    /* 'V' */
+       132,    /* 'W' */
+       131,    /* 'X' */
+       131,    /* 'Y' */
+       129,    /* 'Z' */
+       135,    /* '[' */
+       135,    /* '\' */
+       135,    /* ']' */
+       129,    /* '^' */
+       2,      /* '_' */
+       132,    /* '`' */
+       92,     /* 'a' */
+       135,    /* 'b' */
+       92,     /* 'c' */
+       135,    /* 'd' */
+       92,     /* 'e' */
+       135,    /* 'f' */
+       92,     /* 'g' */
+       135,    /* 'h' */
+       128,    /* 'i' */
+       128,    /* 'j' */
+       135,    /* 'k' */
+       135,    /* 'l' */
+       92,     /* 'm' */
+       92,     /* 'n' */
+       92,     /* 'o' */
+       92,     /* 'p' */
+       92,     /* 'q' */
+       92,     /* 'r' */
+       92,     /* 's' */
+       117,    /* 't' */
+       92,     /* 'u' */
+       90,     /* 'v' */
+       92,     /* 'w' */
+       92,     /* 'x' */
+       90,     /* 'y' */
+       92,     /* 'z' */
+       135,    /* '{' */
+       135,    /* '|' */
+       135,    /* '}' */
+       71,     /* '~' */
+       },
+
+       "Palatino-Roman",
+       0,
+       NO
+       }, {
+       /* width table for font PI */
+       {
+       42,     /* ' ' */
+       55,     /* '!' */
+       83,     /* '"' */
+       83,     /* '#' */
+       83,     /* '$' */
+       148,    /* '%' */
+       130,    /* '&' */
+       46,     /* ''' */
+       55,     /* '(' */
+       55,     /* ')' */
+       65,     /* '*' */
+       101,    /* '+' */
+       42,     /* ',' */
+       55,     /* '-' */
+       42,     /* '.' */
+       49,     /* '/' */
+       83,     /* '0' */
+       83,     /* '1' */
+       83,     /* '2' */
+       83,     /* '3' */
+       83,     /* '4' */
+       83,     /* '5' */
+       83,     /* '6' */
+       83,     /* '7' */
+       83,     /* '8' */
+       83,     /* '9' */
+       42,     /* ':' */
+       42,     /* ';' */
+       101,    /* '<' */
+       101,    /* '=' */
+       101,    /* '>' */
+       83,     /* '?' */
+       124,    /* '@' */
+       120,    /* 'A' */
+       102,    /* 'B' */
+       111,    /* 'C' */
+       130,    /* 'D' */
+       102,    /* 'E' */
+       93,     /* 'F' */
+       120,    /* 'G' */
+       130,    /* 'H' */
+       55,     /* 'I' */
+       55,     /* 'J' */
+       111,    /* 'K' */
+       93,     /* 'L' */
+       157,    /* 'M' */
+       130,    /* 'N' */
+       130,    /* 'O' */
+       102,    /* 'P' */
+       130,    /* 'Q' */
+       111,    /* 'R' */
+       93,     /* 'S' */
+       102,    /* 'T' */
+       130,    /* 'U' */
+       120,    /* 'V' */
+       157,    /* 'W' */
+       120,    /* 'X' */
+       111,    /* 'Y' */
+       111,    /* 'Z' */
+       55,     /* '[' */
+       101,    /* '\' */
+       55,     /* ']' */
+       101,    /* '^' */
+       83,     /* '_' */
+       46,     /* '`' */
+       74,     /* 'a' */
+       77,     /* 'b' */
+       68,     /* 'c' */
+       83,     /* 'd' */
+       65,     /* 'e' */
+       46,     /* 'f' */
+       83,     /* 'g' */
+       83,     /* 'h' */
+       46,     /* 'i' */
+       46,     /* 'j' */
+       74,     /* 'k' */
+       46,     /* 'l' */
+       130,    /* 'm' */
+       93,     /* 'n' */
+       74,     /* 'o' */
+       83,     /* 'p' */
+       77,     /* 'q' */
+       65,     /* 'r' */
+       65,     /* 's' */
+       55,     /* 't' */
+       93,     /* 'u' */
+       83,     /* 'v' */
+       120,    /* 'w' */
+       83,     /* 'x' */
+       83,     /* 'y' */
+       74,     /* 'z' */
+       55,     /* '{' */
+       101,    /* '|' */
+       55,     /* '}' */
+       101,    /* '~' */
+       },
+       /* height table for font PI */
+       {
+       153,    /* ' ' */
+       152,    /* '!' */
+       150,    /* '"' */
+       142,    /* '#' */
+       169,    /* '$' */
+       148,    /* '%' */
+       144,    /* '&' */
+       150,    /* ''' */
+       168,    /* '(' */
+       168,    /* ')' */
+       145,    /* '*' */
+       112,    /* '+' */
+       72,     /* ',' */
+       76,     /* '-' */
+       46,     /* '.' */
+       170,    /* '/' */
+       148,    /* '0' */
+       145,    /* '1' */
+       146,    /* '2' */
+       148,    /* '3' */
+       145,    /* '4' */
+       145,    /* '5' */
+       148,    /* '6' */
+       143,    /* '7' */
+       148,    /* '8' */
+       148,    /* '9' */
+       104,    /* ':' */
+       128,    /* ';' */
+       115,    /* '<' */
+       92,     /* '=' */
+       115,    /* '>' */
+       148,    /* '?' */
+       148,    /* '@' */
+       146,    /* 'A' */
+       143,    /* 'B' */
+       148,    /* 'C' */
+       142,    /* 'D' */
+       143,    /* 'E' */
+       143,    /* 'F' */
+       148,    /* 'G' */
+       142,    /* 'H' */
+       142,    /* 'I' */
+       178,    /* 'J' */
+       143,    /* 'K' */
+       142,    /* 'L' */
+       144,    /* 'M' */
+       145,    /* 'N' */
+       148,    /* 'O' */
+       143,    /* 'P' */
+       178,    /* 'Q' */
+       144,    /* 'R' */
+       148,    /* 'S' */
+       142,    /* 'T' */
+       144,    /* 'U' */
+       144,    /* 'V' */
+       148,    /* 'W' */
+       143,    /* 'X' */
+       146,    /* 'Y' */
+       144,    /* 'Z' */
+       167,    /* '[' */
+       150,    /* '\' */
+       167,    /* ']' */
+       143,    /* '^' */
+       34,     /* '_' */
+       150,    /* '`' */
+       111,    /* 'a' */
+       152,    /* 'b' */
+       111,    /* 'c' */
+       152,    /* 'd' */
+       111,    /* 'e' */
+       195,    /* 'f' */
+       154,    /* 'g' */
+       152,    /* 'h' */
+       148,    /* 'i' */
+       191,    /* 'j' */
+       152,    /* 'k' */
+       152,    /* 'l' */
+       111,    /* 'm' */
+       111,    /* 'n' */
+       111,    /* 'o' */
+       155,    /* 'p' */
+       155,    /* 'q' */
+       110,    /* 'r' */
+       111,    /* 's' */
+       138,    /* 't' */
+       111,    /* 'u' */
+       111,    /* 'v' */
+       111,    /* 'w' */
+       111,    /* 'x' */
+       154,    /* 'y' */
+       111,    /* 'z' */
+       167,    /* '{' */
+       150,    /* '|' */
+       167,    /* '}' */
+       82,     /* '~' */
+       },
+       /* ascent table for font PI */
+       {
+       108,    /* ' ' */
+       136,    /* '!' */
+       136,    /* '"' */
+       128,    /* '#' */
+       136,    /* '$' */
+       132,    /* '%' */
+       128,    /* '&' */
+       136,    /* ''' */
+       136,    /* '(' */
+       136,    /* ')' */
+       132,    /* '*' */
+       98,     /* '+' */
+       34,     /* ',' */
+       62,     /* '-' */
+       33,     /* '.' */
+       136,    /* '/' */
+       132,    /* '0' */
+       130,    /* '1' */
+       132,    /* '2' */
+       132,    /* '3' */
+       130,    /* '4' */
+       129,    /* '5' */
+       132,    /* '6' */
+       129,    /* '7' */
+       132,    /* '8' */
+       132,    /* '9' */
+       90,     /* ':' */
+       90,     /* ';' */
+       101,    /* '<' */
+       78,     /* '=' */
+       101,    /* '>' */
+       132,    /* '?' */
+       132,    /* '@' */
+       132,    /* 'A' */
+       128,    /* 'B' */
+       132,    /* 'C' */
+       128,    /* 'D' */
+       129,    /* 'E' */
+       129,    /* 'F' */
+       132,    /* 'G' */
+       128,    /* 'H' */
+       128,    /* 'I' */
+       128,    /* 'J' */
+       128,    /* 'K' */
+       128,    /* 'L' */
+       128,    /* 'M' */
+       129,    /* 'N' */
+       132,    /* 'O' */
+       129,    /* 'P' */
+       132,    /* 'Q' */
+       129,    /* 'R' */
+       132,    /* 'S' */
+       128,    /* 'T' */
+       128,    /* 'U' */
+       128,    /* 'V' */
+       132,    /* 'W' */
+       128,    /* 'X' */
+       132,    /* 'Y' */
+       129,    /* 'Z' */
+       136,    /* '[' */
+       136,    /* '\' */
+       136,    /* ']' */
+       129,    /* '^' */
+       2,      /* '_' */
+       136,    /* '`' */
+       95,     /* 'a' */
+       136,    /* 'b' */
+       95,     /* 'c' */
+       136,    /* 'd' */
+       95,     /* 'e' */
+       136,    /* 'f' */
+       95,     /* 'g' */
+       136,    /* 'h' */
+       132,    /* 'i' */
+       132,    /* 'j' */
+       136,    /* 'k' */
+       136,    /* 'l' */
+       95,     /* 'm' */
+       95,     /* 'n' */
+       95,     /* 'o' */
+       95,     /* 'p' */
+       95,     /* 'q' */
+       95,     /* 'r' */
+       95,     /* 's' */
+       122,    /* 't' */
+       95,     /* 'u' */
+       95,     /* 'v' */
+       95,     /* 'w' */
+       95,     /* 'x' */
+       95,     /* 'y' */
+       95,     /* 'z' */
+       136,    /* '{' */
+       136,    /* '|' */
+       136,    /* '}' */
+       69,     /* '~' */
+       },
+
+       "Palatino-Italic",
+       0,
+       YES
+       }, {
+       /* width table for font PB */
+       {
+       42,     /* ' ' */
+       46,     /* '!' */
+       67,     /* '"' */
+       83,     /* '#' */
+       83,     /* '$' */
+       148,    /* '%' */
+       139,    /* '&' */
+       46,     /* ''' */
+       55,     /* '(' */
+       55,     /* ')' */
+       74,     /* '*' */
+       101,    /* '+' */
+       42,     /* ',' */
+       55,     /* '-' */
+       42,     /* '.' */
+       49,     /* '/' */
+       83,     /* '0' */
+       83,     /* '1' */
+       83,     /* '2' */
+       83,     /* '3' */
+       83,     /* '4' */
+       83,     /* '5' */
+       83,     /* '6' */
+       83,     /* '7' */
+       83,     /* '8' */
+       83,     /* '9' */
+       42,     /* ':' */
+       42,     /* ';' */
+       101,    /* '<' */
+       101,    /* '=' */
+       101,    /* '>' */
+       74,     /* '?' */
+       124,    /* '@' */
+       130,    /* 'A' */
+       111,    /* 'B' */
+       120,    /* 'C' */
+       139,    /* 'D' */
+       102,    /* 'E' */
+       93,     /* 'F' */
+       139,    /* 'G' */
+       139,    /* 'H' */
+       65,     /* 'I' */
+       65,     /* 'J' */
+       130,    /* 'K' */
+       102,    /* 'L' */
+       167,    /* 'M' */
+       139,    /* 'N' */
+       139,    /* 'O' */
+       102,    /* 'P' */
+       139,    /* 'Q' */
+       120,    /* 'R' */
+       102,    /* 'S' */
+       111,    /* 'T' */
+       130,    /* 'U' */
+       130,    /* 'V' */
+       167,    /* 'W' */
+       111,    /* 'X' */
+       111,    /* 'Y' */
+       111,    /* 'Z' */
+       55,     /* '[' */
+       101,    /* '\' */
+       55,     /* ']' */
+       101,    /* '^' */
+       83,     /* '_' */
+       46,     /* '`' */
+       83,     /* 'a' */
+       102,    /* 'b' */
+       74,     /* 'c' */
+       102,    /* 'd' */
+       83,     /* 'e' */
+       65,     /* 'f' */
+       93,     /* 'g' */
+       102,    /* 'h' */
+       55,     /* 'i' */
+       55,     /* 'j' */
+       102,    /* 'k' */
+       55,     /* 'l' */
+       148,    /* 'm' */
+       102,    /* 'n' */
+       93,     /* 'o' */
+       102,    /* 'p' */
+       102,    /* 'q' */
+       65,     /* 'r' */
+       74,     /* 's' */
+       55,     /* 't' */
+       102,    /* 'u' */
+       93,     /* 'v' */
+       139,    /* 'w' */
+       83,     /* 'x' */
+       93,     /* 'y' */
+       83,     /* 'z' */
+       52,     /* '{' */
+       101,    /* '|' */
+       52,     /* '}' */
+       101,    /* '~' */
+       },
+       /* height table for font PB */
+       {
+       153,    /* ' ' */
+       148,    /* '!' */
+       146,    /* '"' */
+       140,    /* '#' */
+       167,    /* '$' */
+       149,    /* '%' */
+       144,    /* '&' */
+       144,    /* ''' */
+       166,    /* '(' */
+       166,    /* ')' */
+       144,    /* '*' */
+       112,    /* '+' */
+       79,     /* ',' */
+       79,     /* '-' */
+       54,     /* '.' */
+       150,    /* '/' */
+       141,    /* '0' */
+       139,    /* '1' */
+       139,    /* '2' */
+       141,    /* '3' */
+       140,    /* '4' */
+       139,    /* '5' */
+       140,    /* '6' */
+       139,    /* '7' */
+       141,    /* '8' */
+       141,    /* '9' */
+       104,    /* ':' */
+       130,    /* ';' */
+       118,    /* '<' */
+       92,     /* '=' */
+       118,    /* '>' */
+       144,    /* '?' */
+       144,    /* '@' */
+       143,    /* 'A' */
+       143,    /* 'B' */
+       148,    /* 'C' */
+       143,    /* 'D' */
+       143,    /* 'E' */
+       143,    /* 'F' */
+       148,    /* 'G' */
+       143,    /* 'H' */
+       143,    /* 'I' */
+       178,    /* 'J' */
+       143,    /* 'K' */
+       143,    /* 'L' */
+       144,    /* 'M' */
+       145,    /* 'N' */
+       148,    /* 'O' */
+       143,    /* 'P' */
+       176,    /* 'Q' */
+       143,    /* 'R' */
+       148,    /* 'S' */
+       143,    /* 'T' */
+       144,    /* 'U' */
+       142,    /* 'V' */
+       142,    /* 'W' */
+       144,    /* 'X' */
+       144,    /* 'Y' */
+       143,    /* 'Z' */
+       166,    /* '[' */
+       148,    /* '\' */
+       166,    /* ']' */
+       141,    /* '^' */
+       34,     /* '_' */
+       144,    /* '`' */
+       108,    /* 'a' */
+       150,    /* 'b' */
+       108,    /* 'c' */
+       150,    /* 'd' */
+       108,    /* 'e' */
+       148,    /* 'f' */
+       148,    /* 'g' */
+       148,    /* 'h' */
+       146,    /* 'i' */
+       191,    /* 'j' */
+       148,    /* 'k' */
+       148,    /* 'l' */
+       107,    /* 'm' */
+       107,    /* 'n' */
+       108,    /* 'o' */
+       149,    /* 'p' */
+       148,    /* 'q' */
+       106,    /* 'r' */
+       108,    /* 's' */
+       135,    /* 't' */
+       108,    /* 'u' */
+       104,    /* 'v' */
+       106,    /* 'w' */
+       107,    /* 'x' */
+       150,    /* 'y' */
+       105,    /* 'z' */
+       168,    /* '{' */
+       148,    /* '|' */
+       168,    /* '}' */
+       82,     /* '~' */
+       },
+       /* ascent table for font PB */
+       {
+       108,    /* ' ' */
+       132,    /* '!' */
+       132,    /* '"' */
+       126,    /* '#' */
+       134,    /* '$' */
+       133,    /* '%' */
+       128,    /* '&' */
+       130,    /* ''' */
+       134,    /* '(' */
+       134,    /* ')' */
+       130,    /* '*' */
+       98,     /* '+' */
+       37,     /* ',' */
+       65,     /* '-' */
+       38,     /* '.' */
+       134,    /* '/' */
+       125,    /* '0' */
+       126,    /* '1' */
+       125,    /* '2' */
+       125,    /* '3' */
+       126,    /* '4' */
+       123,    /* '5' */
+       124,    /* '6' */
+       125,    /* '7' */
+       125,    /* '8' */
+       125,    /* '9' */
+       88,     /* ':' */
+       88,     /* ';' */
+       101,    /* '<' */
+       78,     /* '=' */
+       101,    /* '>' */
+       128,    /* '?' */
+       128,    /* '@' */
+       128,    /* 'A' */
+       128,    /* 'B' */
+       132,    /* 'C' */
+       128,    /* 'D' */
+       128,    /* 'E' */
+       128,    /* 'F' */
+       132,    /* 'G' */
+       128,    /* 'H' */
+       128,    /* 'I' */
+       128,    /* 'J' */
+       128,    /* 'K' */
+       128,    /* 'L' */
+       128,    /* 'M' */
+       128,    /* 'N' */
+       132,    /* 'O' */
+       128,    /* 'P' */
+       132,    /* 'Q' */
+       128,    /* 'R' */
+       132,    /* 'S' */
+       128,    /* 'T' */
+       128,    /* 'U' */
+       128,    /* 'V' */
+       128,    /* 'W' */
+       130,    /* 'X' */
+       130,    /* 'Y' */
+       128,    /* 'Z' */
+       135,    /* '[' */
+       134,    /* '\' */
+       135,    /* ']' */
+       127,    /* '^' */
+       2,      /* '_' */
+       130,    /* '`' */
+       92,     /* 'a' */
+       134,    /* 'b' */
+       92,     /* 'c' */
+       134,    /* 'd' */
+       92,     /* 'e' */
+       134,    /* 'f' */
+       92,     /* 'g' */
+       134,    /* 'h' */
+       132,    /* 'i' */
+       132,    /* 'j' */
+       134,    /* 'k' */
+       134,    /* 'l' */
+       92,     /* 'm' */
+       92,     /* 'n' */
+       92,     /* 'o' */
+       92,     /* 'p' */
+       92,     /* 'q' */
+       92,     /* 'r' */
+       92,     /* 's' */
+       119,    /* 't' */
+       92,     /* 'u' */
+       90,     /* 'v' */
+       92,     /* 'w' */
+       92,     /* 'x' */
+       90,     /* 'y' */
+       90,     /* 'z' */
+       135,    /* '{' */
+       134,    /* '|' */
+       135,    /* '}' */
+       68,     /* '~' */
+       },
+
+       "Palatino-Bold",
+       0,
+       NO
+       }, {
+       /* width table for font PX */
+       {
+       42,     /* ' ' */
+       55,     /* '!' */
+       83,     /* '"' */
+       83,     /* '#' */
+       83,     /* '$' */
+       148,    /* '%' */
+       139,    /* '&' */
+       46,     /* ''' */
+       55,     /* '(' */
+       55,     /* ')' */
+       74,     /* '*' */
+       101,    /* '+' */
+       42,     /* ',' */
+       65,     /* '-' */
+       42,     /* '.' */
+       52,     /* '/' */
+       83,     /* '0' */
+       83,     /* '1' */
+       83,     /* '2' */
+       83,     /* '3' */
+       83,     /* '4' */
+       83,     /* '5' */
+       83,     /* '6' */
+       83,     /* '7' */
+       83,     /* '8' */
+       83,     /* '9' */
+       42,     /* ':' */
+       42,     /* ';' */
+       101,    /* '<' */
+       101,    /* '=' */
+       101,    /* '>' */
+       74,     /* '?' */
+       139,    /* '@' */
+       120,    /* 'A' */
+       111,    /* 'B' */
+       114,    /* 'C' */
+       130,    /* 'D' */
+       102,    /* 'E' */
+       93,     /* 'F' */
+       130,    /* 'G' */
+       130,    /* 'H' */
+       65,     /* 'I' */
+       65,     /* 'J' */
+       120,    /* 'K' */
+       102,    /* 'L' */
+       157,    /* 'M' */
+       130,    /* 'N' */
+       139,    /* 'O' */
+       111,    /* 'P' */
+       139,    /* 'Q' */
+       120,    /* 'R' */
+       93,     /* 'S' */
+       102,    /* 'T' */
+       130,    /* 'U' */
+       111,    /* 'V' */
+       167,    /* 'W' */
+       120,    /* 'X' */
+       102,    /* 'Y' */
+       111,    /* 'Z' */
+       55,     /* '[' */
+       101,    /* '\' */
+       55,     /* ']' */
+       101,    /* '^' */
+       83,     /* '_' */
+       46,     /* '`' */
+       93,     /* 'a' */
+       89,     /* 'b' */
+       74,     /* 'c' */
+       93,     /* 'd' */
+       74,     /* 'e' */
+       55,     /* 'f' */
+       83,     /* 'g' */
+       93,     /* 'h' */
+       55,     /* 'i' */
+       55,     /* 'j' */
+       93,     /* 'k' */
+       55,     /* 'l' */
+       139,    /* 'm' */
+       93,     /* 'n' */
+       93,     /* 'o' */
+       93,     /* 'p' */
+       89,     /* 'q' */
+       65,     /* 'r' */
+       74,     /* 's' */
+       65,     /* 't' */
+       93,     /* 'u' */
+       93,     /* 'v' */
+       139,    /* 'w' */
+       83,     /* 'x' */
+       93,     /* 'y' */
+       83,     /* 'z' */
+       55,     /* '{' */
+       101,    /* '|' */
+       55,     /* '}' */
+       101,    /* '~' */
+       },
+       /* height table for font PX */
+       {
+       153,    /* ' ' */
+       146,    /* '!' */
+       148,    /* '"' */
+       140,    /* '#' */
+       169,    /* '$' */
+       148,    /* '%' */
+       148,    /* '&' */
+       148,    /* ''' */
+       170,    /* '(' */
+       170,    /* ')' */
+       144,    /* '*' */
+       111,    /* '+' */
+       80,     /* ',' */
+       79,     /* '-' */
+       52,     /* '.' */
+       150,    /* '/' */
+       144,    /* '0' */
+       141,    /* '1' */
+       143,    /* '2' */
+       144,    /* '3' */
+       142,    /* '4' */
+       143,    /* '5' */
+       144,    /* '6' */
+       140,    /* '7' */
+       144,    /* '8' */
+       144,    /* '9' */
+       104,    /* ':' */
+       130,    /* ';' */
+       118,    /* '<' */
+       92,     /* '=' */
+       118,    /* '>' */
+       148,    /* '?' */
+       144,    /* '@' */
+       143,    /* 'A' */
+       143,    /* 'B' */
+       148,    /* 'C' */
+       143,    /* 'D' */
+       143,    /* 'E' */
+       143,    /* 'F' */
+       148,    /* 'G' */
+       143,    /* 'H' */
+       143,    /* 'I' */
+       178,    /* 'J' */
+       143,    /* 'K' */
+       143,    /* 'L' */
+       144,    /* 'M' */
+       143,    /* 'N' */
+       148,    /* 'O' */
+       143,    /* 'P' */
+       181,    /* 'Q' */
+       143,    /* 'R' */
+       148,    /* 'S' */
+       143,    /* 'T' */
+       144,    /* 'U' */
+       142,    /* 'V' */
+       146,    /* 'W' */
+       143,    /* 'X' */
+       146,    /* 'Y' */
+       142,    /* 'Z' */
+       165,    /* '[' */
+       148,    /* '\' */
+       165,    /* ']' */
+       141,    /* '^' */
+       34,     /* '_' */
+       148,    /* '`' */
+       108,    /* 'a' */
+       151,    /* 'b' */
+       108,    /* 'c' */
+       151,    /* 'd' */
+       108,    /* 'e' */
+       194,    /* 'f' */
+       151,    /* 'g' */
+       151,    /* 'h' */
+       148,    /* 'i' */
+       191,    /* 'j' */
+       151,    /* 'k' */
+       151,    /* 'l' */
+       108,    /* 'm' */
+       108,    /* 'n' */
+       108,    /* 'o' */
+       151,    /* 'p' */
+       151,    /* 'q' */
+       108,    /* 'r' */
+       108,    /* 's' */
+       136,    /* 't' */
+       108,    /* 'u' */
+       108,    /* 'v' */
+       108,    /* 'w' */
+       108,    /* 'x' */
+       151,    /* 'y' */
+       108,    /* 'z' */
+       165,    /* '{' */
+       148,    /* '|' */
+       165,    /* '}' */
+       82,     /* '~' */
+       },
+       /* ascent table for font PX */
+       {
+       108,    /* ' ' */
+       130,    /* '!' */
+       134,    /* '"' */
+       126,    /* '#' */
+       137,    /* '$' */
+       132,    /* '%' */
+       132,    /* '&' */
+       134,    /* ''' */
+       134,    /* '(' */
+       134,    /* ')' */
+       130,    /* '*' */
+       97,     /* '+' */
+       38,     /* ',' */
+       65,     /* '-' */
+       36,     /* '.' */
+       134,    /* '/' */
+       128,    /* '0' */
+       127,    /* '1' */
+       128,    /* '2' */
+       128,    /* '3' */
+       128,    /* '4' */
+       126,    /* '5' */
+       128,    /* '6' */
+       126,    /* '7' */
+       128,    /* '8' */
+       128,    /* '9' */
+       88,     /* ':' */
+       88,     /* ';' */
+       101,    /* '<' */
+       78,     /* '=' */
+       101,    /* '>' */
+       132,    /* '?' */
+       128,    /* '@' */
+       128,    /* 'A' */
+       128,    /* 'B' */
+       132,    /* 'C' */
+       128,    /* 'D' */
+       128,    /* 'E' */
+       128,    /* 'F' */
+       132,    /* 'G' */
+       128,    /* 'H' */
+       128,    /* 'I' */
+       128,    /* 'J' */
+       128,    /* 'K' */
+       128,    /* 'L' */
+       128,    /* 'M' */
+       128,    /* 'N' */
+       132,    /* 'O' */
+       128,    /* 'P' */
+       132,    /* 'Q' */
+       128,    /* 'R' */
+       132,    /* 'S' */
+       128,    /* 'T' */
+       128,    /* 'U' */
+       128,    /* 'V' */
+       132,    /* 'W' */
+       128,    /* 'X' */
+       132,    /* 'Y' */
+       128,    /* 'Z' */
+       134,    /* '[' */
+       134,    /* '\' */
+       134,    /* ']' */
+       127,    /* '^' */
+       2,      /* '_' */
+       134,    /* '`' */
+       92,     /* 'a' */
+       135,    /* 'b' */
+       92,     /* 'c' */
+       135,    /* 'd' */
+       92,     /* 'e' */
+       135,    /* 'f' */
+       92,     /* 'g' */
+       135,    /* 'h' */
+       132,    /* 'i' */
+       132,    /* 'j' */
+       135,    /* 'k' */
+       135,    /* 'l' */
+       92,     /* 'm' */
+       92,     /* 'n' */
+       92,     /* 'o' */
+       92,     /* 'p' */
+       92,     /* 'q' */
+       92,     /* 'r' */
+       92,     /* 's' */
+       120,    /* 't' */
+       92,     /* 'u' */
+       92,     /* 'v' */
+       92,     /* 'w' */
+       92,     /* 'x' */
+       92,     /* 'y' */
+       92,     /* 'z' */
+       134,    /* '{' */
+       134,    /* '|' */
+       134,    /* '}' */
+       68,     /* '~' */
+       },
+
+       "Palatino-BoldItalic",
+       0,
+       YES
+       }, {
+#ifdef EXTCHAR
+       /* width table for font XTR */
+       {
+       55,     /* ' ' */
+       83,     /* '!' */
+       83,     /* '"' */
+       83,     /* '#' */
+       74,     /* '$' */
+       83,     /* '%' */
+       83,     /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       83,     /* ')' */
+       83,     /* '*' */
+       58,     /* '+' */
+       74,     /* ',' */
+       74,     /* '-' */
+       74,     /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       148,    /* ';' */
+       111,    /* '<' */
+       46,     /* '=' */
+       52,     /* '>' */
+       102,    /* '?' */
+       46,     /* '@' */
+       120,    /* 'A' */
+       83,     /* 'B' */
+       148,    /* 'C' */
+       120,    /* 'D' */
+       46,     /* 'E' */
+       83,     /* 'F' */
+       120,    /* 'G' */
+       74,     /* 'H' */
+       120,    /* 'I' */
+       74,     /* 'J' */
+       120,    /* 'K' */
+       74,     /* 'L' */
+       120,    /* 'M' */
+       74,     /* 'N' */
+       120,    /* 'O' */
+       74,     /* 'P' */
+       120,    /* 'Q' */
+       74,     /* 'R' */
+       111,    /* 'S' */
+       74,     /* 'T' */
+       102,    /* 'U' */
+       74,     /* 'V' */
+       102,    /* 'W' */
+       74,     /* 'X' */
+       102,    /* 'Y' */
+       74,     /* 'Z' */
+       102,    /* '[' */
+       74,     /* '\' */
+       55,     /* ']' */
+       46,     /* '^' */
+       55,     /* '_' */
+       46,     /* '`' */
+       55,     /* 'a' */
+       46,     /* 'b' */
+       55,     /* 'c' */
+       46,     /* 'd' */
+       120,    /* 'e' */
+       83,     /* 'f' */
+       120,    /* 'g' */
+       83,     /* 'h' */
+       120,    /* 'i' */
+       83,     /* 'j' */
+       120,    /* 'k' */
+       83,     /* 'l' */
+       120,    /* 'm' */
+       83,     /* 'n' */
+       120,    /* 'o' */
+       83,     /* 'p' */
+       93,     /* 'q' */
+       65,     /* 'r' */
+       120,    /* 's' */
+       83,     /* 't' */
+       120,    /* 'u' */
+       83,     /* 'v' */
+       120,    /* 'w' */
+       83,     /* 'x' */
+       120,    /* 'y' */
+       83,     /* 'z' */
+       120,    /* '{' */
+       83,     /* '|' */
+       102,    /* '}' */
+       74,     /* '~' */
+       42,     /* ' ' */
+       },
+       /* height table for font XTR */
+       {
+       266,    /* ' ' */
+       147,    /* '!' */
+       144,    /* '"' */
+       139,    /* '#' */
+       140,    /* '$' */
+       97,     /* '%' */
+       97,     /* '&' */
+       97,     /* ''' */
+       97,     /* '(' */
+       167,    /* ')' */
+       168,    /* '*' */
+       106,    /* '+' */
+       69,     /* ',' */
+       142,    /* '-' */
+       141,    /* '.' */
+       142,    /* '/' */
+       142,    /* '0' */
+       129,    /* '1' */
+       139,    /* '2' */
+       131,    /* '3' */
+       131,    /* '4' */
+       146,    /* '5' */
+       63,     /* '6' */
+       142,    /* '7' */
+       57,     /* '8' */
+       142,    /* '9' */
+       69,     /* ':' */
+       139,    /* ';' */
+       108,    /* '<' */
+       142,    /* '=' */
+       142,    /* '>' */
+       139,    /* '?' */
+       142,    /* '@' */
+       163,    /* 'A' */
+       138,    /* 'B' */
+       139,    /* 'C' */
+       108,    /* 'D' */
+       104,    /* 'E' */
+       144,    /* 'F' */
+       176,    /* 'G' */
+       144,    /* 'H' */
+       175,    /* 'I' */
+       144,    /* 'J' */
+       167,    /* 'K' */
+       134,    /* 'L' */
+       176,    /* 'M' */
+       144,    /* 'N' */
+       181,    /* 'O' */
+       150,    /* 'P' */
+       169,    /* 'Q' */
+       136,    /* 'R' */
+       178,    /* 'S' */
+       141,    /* 'T' */
+       176,    /* 'U' */
+       144,    /* 'V' */
+       175,    /* 'W' */
+       144,    /* 'X' */
+       167,    /* 'Y' */
+       134,    /* 'Z' */
+       176,    /* '[' */
+       144,    /* '\' */
+       176,    /* ']' */
+       142,    /* '^' */
+       175,    /* '_' */
+       142,    /* '`' */
+       167,    /* 'a' */
+       132,    /* 'b' */
+       176,    /* 'c' */
+       142,    /* 'd' */
+       172,    /* 'e' */
+       134,    /* 'f' */
+       178,    /* 'g' */
+       144,    /* 'h' */
+       178,    /* 'i' */
+       144,    /* 'j' */
+       169,    /* 'k' */
+       134,    /* 'l' */
+       178,    /* 'm' */
+       144,    /* 'n' */
+       172,    /* 'o' */
+       136,    /* 'p' */
+       178,    /* 'q' */
+       144,    /* 'r' */
+       178,    /* 's' */
+       144,    /* 't' */
+       178,    /* 'u' */
+       144,    /* 'v' */
+       169,    /* 'w' */
+       134,    /* 'x' */
+       178,    /* 'y' */
+       144,    /* 'z' */
+       167,    /* '{' */
+       167,    /* '|' */
+       175,    /* '}' */
+       142,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XTR */
+       {
+       186,    /* ' ' */
+       110,    /* '!' */
+       128,    /* '"' */
+       125,    /* '#' */
+       127,    /* '$' */
+       83,     /* '%' */
+       83,     /* '&' */
+       83,     /* ''' */
+       83,     /* '(' */
+       128,    /* ')' */
+       128,    /* '*' */
+       92,     /* '+' */
+       32,     /* ',' */
+       128,    /* '-' */
+       92,     /* '.' */
+       128,    /* '/' */
+       128,    /* '0' */
+       115,    /* '1' */
+       125,    /* '2' */
+       118,    /* '3' */
+       118,    /* '4' */
+       132,    /* '5' */
+       14,     /* '6' */
+       128,    /* '7' */
+       14,     /* '8' */
+       128,    /* '9' */
+       55,     /* ':' */
+       125,    /* ';' */
+       92,     /* '<' */
+       128,    /* '=' */
+       128,    /* '>' */
+       125,    /* '?' */
+       128,    /* '@' */
+       136,    /* 'A' */
+       106,    /* 'B' */
+       125,    /* 'C' */
+       92,     /* 'D' */
+       91,     /* 'E' */
+       128,    /* 'F' */
+       162,    /* 'G' */
+       128,    /* 'H' */
+       162,    /* 'I' */
+       128,    /* 'J' */
+       153,    /* 'K' */
+       118,    /* 'L' */
+       162,    /* 'M' */
+       128,    /* 'N' */
+       167,    /* 'O' */
+       134,    /* 'P' */
+       156,    /* 'Q' */
+       120,    /* 'R' */
+       128,    /* 'S' */
+       92,     /* 'T' */
+       162,    /* 'U' */
+       128,    /* 'V' */
+       162,    /* 'W' */
+       128,    /* 'X' */
+       153,    /* 'Y' */
+       118,    /* 'Z' */
+       162,    /* '[' */
+       128,    /* '\' */
+       162,    /* ']' */
+       128,    /* '^' */
+       162,    /* '_' */
+       128,    /* '`' */
+       153,    /* 'a' */
+       118,    /* 'b' */
+       162,    /* 'c' */
+       128,    /* 'd' */
+       156,    /* 'e' */
+       120,    /* 'f' */
+       162,    /* 'g' */
+       128,    /* 'h' */
+       162,    /* 'i' */
+       128,    /* 'j' */
+       153,    /* 'k' */
+       118,    /* 'l' */
+       162,    /* 'm' */
+       128,    /* 'n' */
+       156,    /* 'o' */
+       120,    /* 'p' */
+       162,    /* 'q' */
+       128,    /* 'r' */
+       162,    /* 's' */
+       128,    /* 't' */
+       162,    /* 'u' */
+       128,    /* 'v' */
+       153,    /* 'w' */
+       118,    /* 'x' */
+       162,    /* 'y' */
+       128,    /* 'z' */
+       153,    /* '{' */
+       118,    /* '|' */
+       162,    /* '}' */
+       128,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Times-Roman",
+       0,
+       NO
+       }, {
+       /* width table for font XTI */
+       {
+       65,     /* ' ' */
+       83,     /* '!' */
+       83,     /* '"' */
+       83,     /* '#' */
+       93,     /* '$' */
+       83,     /* '%' */
+       83,     /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       83,     /* ')' */
+       83,     /* '*' */
+       58,     /* '+' */
+       93,     /* ',' */
+       93,     /* '-' */
+       83,     /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       148,    /* ':' */
+       148,    /* ';' */
+       111,    /* '<' */
+       46,     /* '=' */
+       52,     /* '>' */
+       93,     /* '?' */
+       46,     /* '@' */
+       120,    /* 'A' */
+       83,     /* 'B' */
+       157,    /* 'C' */
+       111,    /* 'D' */
+       46,     /* 'E' */
+       83,     /* 'F' */
+       102,    /* 'G' */
+       83,     /* 'H' */
+       102,    /* 'I' */
+       83,     /* 'J' */
+       102,    /* 'K' */
+       83,     /* 'L' */
+       102,    /* 'M' */
+       83,     /* 'N' */
+       102,    /* 'O' */
+       83,     /* 'P' */
+       102,    /* 'Q' */
+       83,     /* 'R' */
+       111,    /* 'S' */
+       74,     /* 'T' */
+       102,    /* 'U' */
+       74,     /* 'V' */
+       102,    /* 'W' */
+       74,     /* 'X' */
+       102,    /* 'Y' */
+       74,     /* 'Z' */
+       102,    /* '[' */
+       74,     /* '\' */
+       55,     /* ']' */
+       46,     /* '^' */
+       55,     /* '_' */
+       46,     /* '`' */
+       55,     /* 'a' */
+       46,     /* 'b' */
+       55,     /* 'c' */
+       46,     /* 'd' */
+       111,    /* 'e' */
+       83,     /* 'f' */
+       120,    /* 'g' */
+       83,     /* 'h' */
+       120,    /* 'i' */
+       83,     /* 'j' */
+       120,    /* 'k' */
+       83,     /* 'l' */
+       120,    /* 'm' */
+       83,     /* 'n' */
+       120,    /* 'o' */
+       83,     /* 'p' */
+       83,     /* 'q' */
+       65,     /* 'r' */
+       120,    /* 's' */
+       83,     /* 't' */
+       120,    /* 'u' */
+       83,     /* 'v' */
+       120,    /* 'w' */
+       83,     /* 'x' */
+       120,    /* 'y' */
+       83,     /* 'z' */
+       93,     /* '{' */
+       74,     /* '|' */
+       93,     /* '}' */
+       65,     /* '~' */
+       42,     /* ' ' */
+       },
+       /* height table for font XTI */
+       {
+       265,    /* ' ' */
+       145,    /* '!' */
+       139,    /* '"' */
+       136,    /* '#' */
+       139,    /* '$' */
+       95,     /* '%' */
+       95,     /* '&' */
+       95,     /* ''' */
+       95,     /* '(' */
+       165,    /* ')' */
+       163,    /* '*' */
+       105,    /* '+' */
+       66,     /* ',' */
+       139,    /* '-' */
+       141,    /* '.' */
+       139,    /* '/' */
+       139,    /* '0' */
+       126,    /* '1' */
+       136,    /* '2' */
+       129,    /* '3' */
+       129,    /* '4' */
+       146,    /* '5' */
+       63,     /* '6' */
+       139,    /* '7' */
+       63,     /* '8' */
+       139,    /* '9' */
+       69,     /* ':' */
+       136,    /* ';' */
+       104,    /* '<' */
+       140,    /* '=' */
+       139,    /* '>' */
+       136,    /* '?' */
+       144,    /* '@' */
+       166,    /* 'A' */
+       143,    /* 'B' */
+       141,    /* 'C' */
+       104,    /* 'D' */
+       103,    /* 'E' */
+       178,    /* 'F' */
+       174,    /* 'G' */
+       141,    /* 'H' */
+       173,    /* 'I' */
+       141,    /* 'J' */
+       164,    /* 'K' */
+       131,    /* 'L' */
+       174,    /* 'M' */
+       141,    /* 'N' */
+       180,    /* 'O' */
+       148,    /* 'P' */
+       167,    /* 'Q' */
+       134,    /* 'R' */
+       174,    /* 'S' */
+       138,    /* 'T' */
+       174,    /* 'U' */
+       141,    /* 'V' */
+       173,    /* 'W' */
+       141,    /* 'X' */
+       164,    /* 'Y' */
+       131,    /* 'Z' */
+       174,    /* '[' */
+       141,    /* '\' */
+       174,    /* ']' */
+       141,    /* '^' */
+       173,    /* '_' */
+       141,    /* '`' */
+       166,    /* 'a' */
+       131,    /* 'b' */
+       174,    /* 'c' */
+       141,    /* 'd' */
+       169,    /* 'e' */
+       134,    /* 'f' */
+       176,    /* 'g' */
+       141,    /* 'h' */
+       176,    /* 'i' */
+       141,    /* 'j' */
+       166,    /* 'k' */
+       131,    /* 'l' */
+       176,    /* 'm' */
+       141,    /* 'n' */
+       169,    /* 'o' */
+       134,    /* 'p' */
+       175,    /* 'q' */
+       141,    /* 'r' */
+       176,    /* 's' */
+       141,    /* 't' */
+       176,    /* 'u' */
+       141,    /* 'v' */
+       166,    /* 'w' */
+       131,    /* 'x' */
+       176,    /* 'y' */
+       141,    /* 'z' */
+       164,    /* '{' */
+       163,    /* '|' */
+       173,    /* '}' */
+       151,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XTI */
+       {
+       186,    /* ' ' */
+       107,    /* '!' */
+       125,    /* '"' */
+       122,    /* '#' */
+       125,    /* '$' */
+       81,     /* '%' */
+       81,     /* '&' */
+       81,     /* ''' */
+       81,     /* '(' */
+       125,    /* ')' */
+       125,    /* '*' */
+       91,     /* '+' */
+       31,     /* ',' */
+       125,    /* '-' */
+       92,     /* '.' */
+       125,    /* '/' */
+       125,    /* '0' */
+       112,    /* '1' */
+       122,    /* '2' */
+       115,    /* '3' */
+       115,    /* '4' */
+       132,    /* '5' */
+       14,     /* '6' */
+       125,    /* '7' */
+       21,     /* '8' */
+       125,    /* '9' */
+       55,     /* ':' */
+       122,    /* ';' */
+       88,     /* '<' */
+       126,    /* '=' */
+       125,    /* '>' */
+       122,    /* '?' */
+       128,    /* '@' */
+       134,    /* 'A' */
+       106,    /* 'B' */
+       125,    /* 'C' */
+       88,     /* 'D' */
+       87,     /* 'E' */
+       128,    /* 'F' */
+       160,    /* 'G' */
+       125,    /* 'H' */
+       159,    /* 'I' */
+       125,    /* 'J' */
+       150,    /* 'K' */
+       115,    /* 'L' */
+       160,    /* 'M' */
+       125,    /* 'N' */
+       166,    /* 'O' */
+       132,    /* 'P' */
+       153,    /* 'Q' */
+       118,    /* 'R' */
+       125,    /* 'S' */
+       88,     /* 'T' */
+       160,    /* 'U' */
+       125,    /* 'V' */
+       159,    /* 'W' */
+       125,    /* 'X' */
+       150,    /* 'Y' */
+       115,    /* 'Z' */
+       160,    /* '[' */
+       125,    /* '\' */
+       160,    /* ']' */
+       125,    /* '^' */
+       159,    /* '_' */
+       125,    /* '`' */
+       152,    /* 'a' */
+       115,    /* 'b' */
+       160,    /* 'c' */
+       125,    /* 'd' */
+       153,    /* 'e' */
+       118,    /* 'f' */
+       160,    /* 'g' */
+       125,    /* 'h' */
+       159,    /* 'i' */
+       125,    /* 'j' */
+       150,    /* 'k' */
+       115,    /* 'l' */
+       160,    /* 'm' */
+       125,    /* 'n' */
+       153,    /* 'o' */
+       118,    /* 'p' */
+       159,    /* 'q' */
+       125,    /* 'r' */
+       160,    /* 's' */
+       125,    /* 't' */
+       159,    /* 'u' */
+       125,    /* 'v' */
+       150,    /* 'w' */
+       115,    /* 'x' */
+       160,    /* 'y' */
+       125,    /* 'z' */
+       150,    /* '{' */
+       115,    /* '|' */
+       159,    /* '}' */
+       125,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Times-Italic",
+       0,
+       YES
+       }, {
+       /* width table for font XTB */
+       {
+       55,     /* ' ' */
+       83,     /* '!' */
+       83,     /* '"' */
+       83,     /* '#' */
+       83,     /* '$' */
+       83,     /* '%' */
+       83,     /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       83,     /* ')' */
+       83,     /* '*' */
+       58,     /* '+' */
+       83,     /* ',' */
+       83,     /* '-' */
+       83,     /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       167,    /* ';' */
+       120,    /* '<' */
+       50,     /* '=' */
+       55,     /* '>' */
+       111,    /* '?' */
+       46,     /* '@' */
+       130,    /* 'A' */
+       83,     /* 'B' */
+       167,    /* 'C' */
+       120,    /* 'D' */
+       46,     /* 'E' */
+       93,     /* 'F' */
+       120,    /* 'G' */
+       83,     /* 'H' */
+       120,    /* 'I' */
+       83,     /* 'J' */
+       120,    /* 'K' */
+       83,     /* 'L' */
+       120,    /* 'M' */
+       83,     /* 'N' */
+       120,    /* 'O' */
+       83,     /* 'P' */
+       120,    /* 'Q' */
+       83,     /* 'R' */
+       120,    /* 'S' */
+       74,     /* 'T' */
+       111,    /* 'U' */
+       74,     /* 'V' */
+       111,    /* 'W' */
+       74,     /* 'X' */
+       111,    /* 'Y' */
+       74,     /* 'Z' */
+       111,    /* '[' */
+       74,     /* '\' */
+       65,     /* ']' */
+       46,     /* '^' */
+       65,     /* '_' */
+       46,     /* '`' */
+       65,     /* 'a' */
+       46,     /* 'b' */
+       65,     /* 'c' */
+       46,     /* 'd' */
+       120,    /* 'e' */
+       93,     /* 'f' */
+       130,    /* 'g' */
+       83,     /* 'h' */
+       130,    /* 'i' */
+       83,     /* 'j' */
+       130,    /* 'k' */
+       83,     /* 'l' */
+       130,    /* 'm' */
+       83,     /* 'n' */
+       130,    /* 'o' */
+       83,     /* 'p' */
+       93,     /* 'q' */
+       65,     /* 'r' */
+       120,    /* 's' */
+       93,     /* 't' */
+       120,    /* 'u' */
+       93,     /* 'v' */
+       120,    /* 'w' */
+       93,     /* 'x' */
+       120,    /* 'y' */
+       93,     /* 'z' */
+       120,    /* '{' */
+       83,     /* '|' */
+       111,    /* '}' */
+       74,     /* '~' */
+       42,     /* ' ' */
+       },
+       /* height table for font XTB */
+       {
+       268,    /* ' ' */
+       149,    /* '!' */
+       144,    /* '"' */
+       139,    /* '#' */
+       143,    /* '$' */
+       97,     /* '%' */
+       97,     /* '&' */
+       97,     /* ''' */
+       97,     /* '(' */
+       165,    /* ')' */
+       164,    /* '*' */
+       109,    /* '+' */
+       86,     /* ',' */
+       142,    /* '-' */
+       141,    /* '.' */
+       147,    /* '/' */
+       147,    /* '0' */
+       132,    /* '1' */
+       142,    /* '2' */
+       139,    /* '3' */
+       139,    /* '4' */
+       152,    /* '5' */
+       63,     /* '6' */
+       147,    /* '7' */
+       64,     /* '8' */
+       145,    /* '9' */
+       72,     /* ':' */
+       139,    /* ';' */
+       111,    /* '<' */
+       142,    /* '=' */
+       142,    /* '>' */
+       139,    /* '?' */
+       139,    /* '@' */
+       163,    /* 'A' */
+       135,    /* 'B' */
+       143,    /* 'C' */
+       111,    /* 'D' */
+       106,    /* 'E' */
+       144,    /* 'F' */
+       182,    /* 'G' */
+       149,    /* 'H' */
+       180,    /* 'I' */
+       147,    /* 'J' */
+       174,    /* 'K' */
+       141,    /* 'L' */
+       182,    /* 'M' */
+       149,    /* 'N' */
+       184,    /* 'O' */
+       154,    /* 'P' */
+       176,    /* 'Q' */
+       142,    /* 'R' */
+       178,    /* 'S' */
+       144,    /* 'T' */
+       182,    /* 'U' */
+       149,    /* 'V' */
+       180,    /* 'W' */
+       147,    /* 'X' */
+       174,    /* 'Y' */
+       141,    /* 'Z' */
+       182,    /* '[' */
+       149,    /* '\' */
+       182,    /* ']' */
+       147,    /* '^' */
+       180,    /* '_' */
+       145,    /* '`' */
+       172,    /* 'a' */
+       139,    /* 'b' */
+       182,    /* 'c' */
+       147,    /* 'd' */
+       178,    /* 'e' */
+       140,    /* 'f' */
+       184,    /* 'g' */
+       149,    /* 'h' */
+       182,    /* 'i' */
+       147,    /* 'j' */
+       176,    /* 'k' */
+       141,    /* 'l' */
+       184,    /* 'm' */
+       149,    /* 'n' */
+       178,    /* 'o' */
+       142,    /* 'p' */
+       182,    /* 'q' */
+       147,    /* 'r' */
+       184,    /* 's' */
+       149,    /* 't' */
+       182,    /* 'u' */
+       147,    /* 'v' */
+       176,    /* 'w' */
+       141,    /* 'x' */
+       184,    /* 'y' */
+       149,    /* 'z' */
+       174,    /* '{' */
+       174,    /* '|' */
+       180,    /* '}' */
+       145,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XTB */
+       {
+       189,    /* ' ' */
+       112,    /* '!' */
+       128,    /* '"' */
+       125,    /* '#' */
+       129,    /* '$' */
+       83,     /* '%' */
+       83,     /* '&' */
+       83,     /* ''' */
+       83,     /* '(' */
+       128,    /* ')' */
+       128,    /* '*' */
+       95,     /* '+' */
+       42,     /* ',' */
+       128,    /* '-' */
+       95,     /* '.' */
+       133,    /* '/' */
+       133,    /* '0' */
+       118,    /* '1' */
+       128,    /* '2' */
+       125,    /* '3' */
+       125,    /* '4' */
+       138,    /* '5' */
+       14,     /* '6' */
+       133,    /* '7' */
+       21,     /* '8' */
+       131,    /* '9' */
+       58,     /* ':' */
+       125,    /* ';' */
+       95,     /* '<' */
+       128,    /* '=' */
+       128,    /* '>' */
+       125,    /* '?' */
+       125,    /* '@' */
+       137,    /* 'A' */
+       105,    /* 'B' */
+       128,    /* 'C' */
+       95,     /* 'D' */
+       92,     /* 'E' */
+       128,    /* 'F' */
+       168,    /* 'G' */
+       133,    /* 'H' */
+       166,    /* 'I' */
+       131,    /* 'J' */
+       160,    /* 'K' */
+       125,    /* 'L' */
+       168,    /* 'M' */
+       133,    /* 'N' */
+       170,    /* 'O' */
+       138,    /* 'P' */
+       162,    /* 'Q' */
+       126,    /* 'R' */
+       128,    /* 'S' */
+       95,     /* 'T' */
+       168,    /* 'U' */
+       133,    /* 'V' */
+       166,    /* 'W' */
+       131,    /* 'X' */
+       160,    /* 'Y' */
+       125,    /* 'Z' */
+       168,    /* '[' */
+       133,    /* '\' */
+       168,    /* ']' */
+       133,    /* '^' */
+       166,    /* '_' */
+       131,    /* '`' */
+       158,    /* 'a' */
+       125,    /* 'b' */
+       168,    /* 'c' */
+       133,    /* 'd' */
+       162,    /* 'e' */
+       126,    /* 'f' */
+       168,    /* 'g' */
+       133,    /* 'h' */
+       166,    /* 'i' */
+       131,    /* 'j' */
+       160,    /* 'k' */
+       125,    /* 'l' */
+       168,    /* 'm' */
+       133,    /* 'n' */
+       162,    /* 'o' */
+       126,    /* 'p' */
+       166,    /* 'q' */
+       131,    /* 'r' */
+       168,    /* 's' */
+       133,    /* 't' */
+       166,    /* 'u' */
+       131,    /* 'v' */
+       160,    /* 'w' */
+       125,    /* 'x' */
+       168,    /* 'y' */
+       133,    /* 'z' */
+       160,    /* '{' */
+       125,    /* '|' */
+       166,    /* '}' */
+       131,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Times-Bold",
+       0,
+       NO
+       }, {
+       /* width table for font XTX */
+       {
+       65,     /* ' ' */
+       83,     /* '!' */
+       83,     /* '"' */
+       83,     /* '#' */
+       83,     /* '$' */
+       83,     /* '%' */
+       83,     /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       83,     /* ')' */
+       83,     /* '*' */
+       58,     /* '+' */
+       83,     /* ',' */
+       83,     /* '-' */
+       83,     /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       157,    /* ';' */
+       120,    /* '<' */
+       44,     /* '=' */
+       50,     /* '>' */
+       102,    /* '?' */
+       46,     /* '@' */
+       120,    /* 'A' */
+       83,     /* 'B' */
+       157,    /* 'C' */
+       120,    /* 'D' */
+       46,     /* 'E' */
+       83,     /* 'F' */
+       111,    /* 'G' */
+       83,     /* 'H' */
+       111,    /* 'I' */
+       83,     /* 'J' */
+       111,    /* 'K' */
+       83,     /* 'L' */
+       111,    /* 'M' */
+       83,     /* 'N' */
+       111,    /* 'O' */
+       83,     /* 'P' */
+       111,    /* 'Q' */
+       83,     /* 'R' */
+       111,    /* 'S' */
+       74,     /* 'T' */
+       111,    /* 'U' */
+       74,     /* 'V' */
+       111,    /* 'W' */
+       74,     /* 'X' */
+       111,    /* 'Y' */
+       74,     /* 'Z' */
+       111,    /* '[' */
+       74,     /* '\' */
+       65,     /* ']' */
+       46,     /* '^' */
+       65,     /* '_' */
+       46,     /* '`' */
+       65,     /* 'a' */
+       46,     /* 'b' */
+       65,     /* 'c' */
+       46,     /* 'd' */
+       120,    /* 'e' */
+       93,     /* 'f' */
+       120,    /* 'g' */
+       83,     /* 'h' */
+       120,    /* 'i' */
+       83,     /* 'j' */
+       120,    /* 'k' */
+       83,     /* 'l' */
+       120,    /* 'm' */
+       83,     /* 'n' */
+       120,    /* 'o' */
+       83,     /* 'p' */
+       93,     /* 'q' */
+       65,     /* 'r' */
+       120,    /* 's' */
+       93,     /* 't' */
+       120,    /* 'u' */
+       93,     /* 'v' */
+       120,    /* 'w' */
+       93,     /* 'x' */
+       120,    /* 'y' */
+       93,     /* 'z' */
+       102,    /* '{' */
+       74,     /* '|' */
+       102,    /* '}' */
+       65,     /* '~' */
+       42,     /* ' ' */
+       },
+       /* height table for font XTX */
+       {
+       269,    /* ' ' */
+       148,    /* '!' */
+       144,    /* '"' */
+       139,    /* '#' */
+       142,    /* '$' */
+       97,     /* '%' */
+       97,     /* '&' */
+       97,     /* ''' */
+       97,     /* '(' */
+       166,    /* ')' */
+       165,    /* '*' */
+       115,    /* '+' */
+       80,     /* ',' */
+       142,    /* '-' */
+       144,    /* '.' */
+       144,    /* '/' */
+       144,    /* '0' */
+       132,    /* '1' */
+       142,    /* '2' */
+       137,    /* '3' */
+       137,    /* '4' */
+       152,    /* '5' */
+       64,     /* '6' */
+       144,    /* '7' */
+       64,     /* '8' */
+       143,    /* '9' */
+       72,     /* ':' */
+       139,    /* ';' */
+       108,    /* '<' */
+       142,    /* '=' */
+       142,    /* '>' */
+       139,    /* '?' */
+       147,    /* '@' */
+       176,    /* 'A' */
+       141,    /* 'B' */
+       144,    /* 'C' */
+       108,    /* 'D' */
+       107,    /* 'E' */
+       181,    /* 'F' */
+       178,    /* 'G' */
+       146,    /* 'H' */
+       177,    /* 'I' */
+       145,    /* 'J' */
+       171,    /* 'K' */
+       139,    /* 'L' */
+       178,    /* 'M' */
+       146,    /* 'N' */
+       187,    /* 'O' */
+       154,    /* 'P' */
+       172,    /* 'Q' */
+       141,    /* 'R' */
+       178,    /* 'S' */
+       141,    /* 'T' */
+       178,    /* 'U' */
+       146,    /* 'V' */
+       177,    /* 'W' */
+       145,    /* 'X' */
+       171,    /* 'Y' */
+       139,    /* 'Z' */
+       178,    /* '[' */
+       146,    /* '\' */
+       179,    /* ']' */
+       146,    /* '^' */
+       177,    /* '_' */
+       145,    /* '`' */
+       172,    /* 'a' */
+       141,    /* 'b' */
+       178,    /* 'c' */
+       146,    /* 'd' */
+       174,    /* 'e' */
+       141,    /* 'f' */
+       181,    /* 'g' */
+       146,    /* 'h' */
+       180,    /* 'i' */
+       145,    /* 'j' */
+       174,    /* 'k' */
+       139,    /* 'l' */
+       181,    /* 'm' */
+       146,    /* 'n' */
+       174,    /* 'o' */
+       141,    /* 'p' */
+       180,    /* 'q' */
+       145,    /* 'r' */
+       181,    /* 's' */
+       146,    /* 't' */
+       179,    /* 'u' */
+       145,    /* 'v' */
+       174,    /* 'w' */
+       139,    /* 'x' */
+       181,    /* 'y' */
+       146,    /* 'z' */
+       171,    /* '{' */
+       173,    /* '|' */
+       177,    /* '}' */
+       155,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XTX */
+       {
+       189,    /* ' ' */
+       110,    /* '!' */
+       128,    /* '"' */
+       125,    /* '#' */
+       128,    /* '$' */
+       83,     /* '%' */
+       83,     /* '&' */
+       83,     /* ''' */
+       83,     /* '(' */
+       128,    /* ')' */
+       128,    /* '*' */
+       101,    /* '+' */
+       36,     /* ',' */
+       128,    /* '-' */
+       95,     /* '.' */
+       130,    /* '/' */
+       130,    /* '0' */
+       118,    /* '1' */
+       128,    /* '2' */
+       123,    /* '3' */
+       123,    /* '4' */
+       138,    /* '5' */
+       15,     /* '6' */
+       130,    /* '7' */
+       21,     /* '8' */
+       129,    /* '9' */
+       58,     /* ':' */
+       125,    /* ';' */
+       92,     /* '<' */
+       128,    /* '=' */
+       128,    /* '>' */
+       125,    /* '?' */
+       130,    /* '@' */
+       141,    /* 'A' */
+       107,    /* 'B' */
+       128,    /* 'C' */
+       92,     /* 'D' */
+       91,     /* 'E' */
+       132,    /* 'F' */
+       165,    /* 'G' */
+       130,    /* 'H' */
+       163,    /* 'I' */
+       129,    /* 'J' */
+       158,    /* 'K' */
+       123,    /* 'L' */
+       165,    /* 'M' */
+       130,    /* 'N' */
+       173,    /* 'O' */
+       138,    /* 'P' */
+       158,    /* 'Q' */
+       125,    /* 'R' */
+       128,    /* 'S' */
+       92,     /* 'T' */
+       165,    /* 'U' */
+       130,    /* 'V' */
+       163,    /* 'W' */
+       129,    /* 'X' */
+       158,    /* 'Y' */
+       123,    /* 'Z' */
+       165,    /* '[' */
+       130,    /* '\' */
+       165,    /* ']' */
+       130,    /* '^' */
+       163,    /* '_' */
+       129,    /* '`' */
+       158,    /* 'a' */
+       125,    /* 'b' */
+       165,    /* 'c' */
+       130,    /* 'd' */
+       158,    /* 'e' */
+       125,    /* 'f' */
+       165,    /* 'g' */
+       130,    /* 'h' */
+       163,    /* 'i' */
+       129,    /* 'j' */
+       158,    /* 'k' */
+       123,    /* 'l' */
+       165,    /* 'm' */
+       130,    /* 'n' */
+       158,    /* 'o' */
+       125,    /* 'p' */
+       163,    /* 'q' */
+       129,    /* 'r' */
+       165,    /* 's' */
+       130,    /* 't' */
+       163,    /* 'u' */
+       129,    /* 'v' */
+       158,    /* 'w' */
+       123,    /* 'x' */
+       165,    /* 'y' */
+       130,    /* 'z' */
+       158,    /* '{' */
+       123,    /* '|' */
+       163,    /* '}' */
+       129,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Times-BoldItalic",
+       0,
+       YES
+       }, {
+       /* width table for font XAR */
+       {
+       49,     /* ' ' */
+       92,     /* '!' */
+       92,     /* '"' */
+       92,     /* '#' */
+       84,     /* '$' */
+       71,     /* '%' */
+       71,     /* '&' */
+       42,     /* ''' */
+       42,     /* '(' */
+       92,     /* ')' */
+       92,     /* '*' */
+       101,    /* '+' */
+       84,     /* ',' */
+       81,     /* '-' */
+       98,     /* '.' */
+       63,     /* '/' */
+       62,     /* '0' */
+       81,     /* '1' */
+       75,     /* '2' */
+       37,     /* '3' */
+       61,     /* '4' */
+       55,     /* '5' */
+       54,     /* '6' */
+       92,     /* '7' */
+       50,     /* '8' */
+       84,     /* '9' */
+       167,    /* ':' */
+       165,    /* ';' */
+       193,    /* '<' */
+       61,     /* '=' */
+       61,     /* '>' */
+       86,     /* '?' */
+       50,     /* '@' */
+       145,    /* 'A' */
+       109,    /* 'B' */
+       199,    /* 'C' */
+       189,    /* 'D' */
+       33,     /* 'E' */
+       92,     /* 'F' */
+       123,    /* 'G' */
+       114,    /* 'H' */
+       123,    /* 'I' */
+       114,    /* 'J' */
+       123,    /* 'K' */
+       114,    /* 'L' */
+       123,    /* 'M' */
+       114,    /* 'N' */
+       123,    /* 'O' */
+       114,    /* 'P' */
+       123,    /* 'Q' */
+       114,    /* 'R' */
+       135,    /* 'S' */
+       108,    /* 'T' */
+       89,     /* 'U' */
+       108,    /* 'V' */
+       89,     /* 'W' */
+       108,    /* 'X' */
+       89,     /* 'Y' */
+       108,    /* 'Z' */
+       89,     /* '[' */
+       108,    /* '\' */
+       38,     /* ']' */
+       33,     /* '^' */
+       38,     /* '_' */
+       33,     /* '`' */
+       38,     /* 'a' */
+       33,     /* 'b' */
+       38,     /* 'c' */
+       33,     /* 'd' */
+       123,    /* 'e' */
+       102,    /* 'f' */
+       145,    /* 'g' */
+       109,    /* 'h' */
+       145,    /* 'i' */
+       109,    /* 'j' */
+       145,    /* 'k' */
+       109,    /* 'l' */
+       145,    /* 'm' */
+       109,    /* 'n' */
+       145,    /* 'o' */
+       109,    /* 'p' */
+       83,     /* 'q' */
+       65,     /* 'r' */
+       109,    /* 's' */
+       101,    /* 't' */
+       109,    /* 'u' */
+       101,    /* 'v' */
+       109,    /* 'w' */
+       101,    /* 'x' */
+       109,    /* 'y' */
+       101,    /* 'z' */
+       99,     /* '{' */
+       89,     /* '|' */
+       80,     /* '}' */
+       71,     /* '~' */
+       46,     /* ' ' */
+       },
+       /* height table for font XAR */
+       {
+       276,    /* ' ' */
+       146,    /* '!' */
+       156,    /* '"' */
+       152,    /* '#' */
+       152,    /* '$' */
+       111,    /* '%' */
+       111,    /* '&' */
+       111,    /* ''' */
+       111,    /* '(' */
+       174,    /* ')' */
+       174,    /* '*' */
+       109,    /* '+' */
+       60,     /* ',' */
+       152,    /* '-' */
+       151,    /* '.' */
+       157,    /* '/' */
+       158,    /* '0' */
+       146,    /* '1' */
+       152,    /* '2' */
+       156,    /* '3' */
+       156,    /* '4' */
+       159,    /* '5' */
+       63,     /* '6' */
+       158,    /* '7' */
+       60,     /* '8' */
+       156,    /* '9' */
+       76,     /* ':' */
+       152,    /* ';' */
+       124,    /* '<' */
+       152,    /* '=' */
+       152,    /* '>' */
+       152,    /* '?' */
+       152,    /* '@' */
+       178,    /* 'A' */
+       133,    /* 'B' */
+       158,    /* 'C' */
+       124,    /* 'D' */
+       119,    /* 'E' */
+       158,    /* 'F' */
+       188,    /* 'G' */
+       160,    /* 'H' */
+       183,    /* 'I' */
+       158,    /* 'J' */
+       182,    /* 'K' */
+       158,    /* 'L' */
+       187,    /* 'M' */
+       159,    /* 'N' */
+       189,    /* 'O' */
+       161,    /* 'P' */
+       179,    /* 'Q' */
+       151,    /* 'R' */
+       194,    /* 'S' */
+       158,    /* 'T' */
+       188,    /* 'U' */
+       160,    /* 'V' */
+       183,    /* 'W' */
+       158,    /* 'X' */
+       182,    /* 'Y' */
+       158,    /* 'Z' */
+       187,    /* '[' */
+       159,    /* '\' */
+       188,    /* ']' */
+       158,    /* '^' */
+       183,    /* '_' */
+       156,    /* '`' */
+       182,    /* 'a' */
+       156,    /* 'b' */
+       187,    /* 'c' */
+       157,    /* 'd' */
+       179,    /* 'e' */
+       149,    /* 'f' */
+       191,    /* 'g' */
+       160,    /* 'h' */
+       185,    /* 'i' */
+       158,    /* 'j' */
+       184,    /* 'k' */
+       158,    /* 'l' */
+       190,    /* 'm' */
+       159,    /* 'n' */
+       182,    /* 'o' */
+       151,    /* 'p' */
+       185,    /* 'q' */
+       158,    /* 'r' */
+       191,    /* 's' */
+       160,    /* 't' */
+       185,    /* 'u' */
+       158,    /* 'v' */
+       184,    /* 'w' */
+       158,    /* 'x' */
+       190,    /* 'y' */
+       159,    /* 'z' */
+       182,    /* '{' */
+       188,    /* '|' */
+       183,    /* '}' */
+       156,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XAR */
+       {
+       199,    /* ' ' */
+       132,    /* '!' */
+       142,    /* '"' */
+       138,    /* '#' */
+       138,    /* '$' */
+       97,     /* '%' */
+       97,     /* '&' */
+       97,     /* ''' */
+       97,     /* '(' */
+       138,    /* ')' */
+       138,    /* '*' */
+       95,     /* '+' */
+       35,     /* ',' */
+       138,    /* '-' */
+       105,    /* '.' */
+       143,    /* '/' */
+       144,    /* '0' */
+       132,    /* '1' */
+       138,    /* '2' */
+       142,    /* '3' */
+       142,    /* '4' */
+       145,    /* '5' */
+       14,     /* '6' */
+       144,    /* '7' */
+       14,     /* '8' */
+       142,    /* '9' */
+       62,     /* ':' */
+       138,    /* ';' */
+       108,    /* '<' */
+       138,    /* '=' */
+       138,    /* '>' */
+       138,    /* '?' */
+       138,    /* '@' */
+       151,    /* 'A' */
+       113,    /* 'B' */
+       142,    /* 'C' */
+       108,    /* 'D' */
+       105,    /* 'E' */
+       142,    /* 'F' */
+       175,    /* 'G' */
+       144,    /* 'H' */
+       169,    /* 'I' */
+       142,    /* 'J' */
+       168,    /* 'K' */
+       142,    /* 'L' */
+       174,    /* 'M' */
+       143,    /* 'N' */
+       175,    /* 'O' */
+       145,    /* 'P' */
+       166,    /* 'Q' */
+       135,    /* 'R' */
+       142,    /* 'S' */
+       108,    /* 'T' */
+       175,    /* 'U' */
+       144,    /* 'V' */
+       169,    /* 'W' */
+       142,    /* 'X' */
+       168,    /* 'Y' */
+       142,    /* 'Z' */
+       174,    /* '[' */
+       143,    /* '\' */
+       175,    /* ']' */
+       144,    /* '^' */
+       169,    /* '_' */
+       142,    /* '`' */
+       168,    /* 'a' */
+       142,    /* 'b' */
+       174,    /* 'c' */
+       143,    /* 'd' */
+       166,    /* 'e' */
+       135,    /* 'f' */
+       175,    /* 'g' */
+       144,    /* 'h' */
+       169,    /* 'i' */
+       142,    /* 'j' */
+       168,    /* 'k' */
+       142,    /* 'l' */
+       174,    /* 'm' */
+       143,    /* 'n' */
+       166,    /* 'o' */
+       135,    /* 'p' */
+       169,    /* 'q' */
+       142,    /* 'r' */
+       175,    /* 's' */
+       144,    /* 't' */
+       169,    /* 'u' */
+       142,    /* 'v' */
+       168,    /* 'w' */
+       142,    /* 'x' */
+       174,    /* 'y' */
+       143,    /* 'z' */
+       168,    /* '{' */
+       142,    /* '|' */
+       169,    /* '}' */
+       142,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-AvantGarde-Book",
+       0,
+       NO
+       }, {
+       /* width table for font XAI */
+       {
+       49,     /* ' ' */
+       92,     /* '!' */
+       92,     /* '"' */
+       92,     /* '#' */
+       84,     /* '$' */
+       71,     /* '%' */
+       71,     /* '&' */
+       42,     /* ''' */
+       42,     /* '(' */
+       92,     /* ')' */
+       92,     /* '*' */
+       101,    /* '+' */
+       84,     /* ',' */
+       81,     /* '-' */
+       98,     /* '.' */
+       63,     /* '/' */
+       62,     /* '0' */
+       81,     /* '1' */
+       75,     /* '2' */
+       37,     /* '3' */
+       61,     /* '4' */
+       55,     /* '5' */
+       54,     /* '6' */
+       92,     /* '7' */
+       50,     /* '8' */
+       84,     /* '9' */
+       167,    /* ':' */
+       165,    /* ';' */
+       193,    /* '<' */
+       61,     /* '=' */
+       61,     /* '>' */
+       86,     /* '?' */
+       50,     /* '@' */
+       145,    /* 'A' */
+       109,    /* 'B' */
+       199,    /* 'C' */
+       189,    /* 'D' */
+       33,     /* 'E' */
+       92,     /* 'F' */
+       123,    /* 'G' */
+       114,    /* 'H' */
+       123,    /* 'I' */
+       114,    /* 'J' */
+       123,    /* 'K' */
+       114,    /* 'L' */
+       123,    /* 'M' */
+       114,    /* 'N' */
+       123,    /* 'O' */
+       114,    /* 'P' */
+       123,    /* 'Q' */
+       114,    /* 'R' */
+       135,    /* 'S' */
+       108,    /* 'T' */
+       89,     /* 'U' */
+       108,    /* 'V' */
+       89,     /* 'W' */
+       108,    /* 'X' */
+       89,     /* 'Y' */
+       108,    /* 'Z' */
+       89,     /* '[' */
+       108,    /* '\' */
+       38,     /* ']' */
+       33,     /* '^' */
+       38,     /* '_' */
+       33,     /* '`' */
+       38,     /* 'a' */
+       33,     /* 'b' */
+       38,     /* 'c' */
+       33,     /* 'd' */
+       123,    /* 'e' */
+       102,    /* 'f' */
+       145,    /* 'g' */
+       109,    /* 'h' */
+       145,    /* 'i' */
+       109,    /* 'j' */
+       145,    /* 'k' */
+       109,    /* 'l' */
+       145,    /* 'm' */
+       109,    /* 'n' */
+       145,    /* 'o' */
+       109,    /* 'p' */
+       83,     /* 'q' */
+       65,     /* 'r' */
+       109,    /* 's' */
+       101,    /* 't' */
+       109,    /* 'u' */
+       101,    /* 'v' */
+       109,    /* 'w' */
+       101,    /* 'x' */
+       109,    /* 'y' */
+       101,    /* 'z' */
+       99,     /* '{' */
+       89,     /* '|' */
+       80,     /* '}' */
+       71,     /* '~' */
+       46,     /* ' ' */
+       },
+       /* height table for font XAI */
+       {
+       276,    /* ' ' */
+       146,    /* '!' */
+       156,    /* '"' */
+       152,    /* '#' */
+       152,    /* '$' */
+       111,    /* '%' */
+       111,    /* '&' */
+       111,    /* ''' */
+       111,    /* '(' */
+       174,    /* ')' */
+       174,    /* '*' */
+       109,    /* '+' */
+       60,     /* ',' */
+       152,    /* '-' */
+       151,    /* '.' */
+       157,    /* '/' */
+       158,    /* '0' */
+       146,    /* '1' */
+       152,    /* '2' */
+       156,    /* '3' */
+       156,    /* '4' */
+       159,    /* '5' */
+       67,     /* '6' */
+       158,    /* '7' */
+       60,     /* '8' */
+       156,    /* '9' */
+       76,     /* ':' */
+       152,    /* ';' */
+       124,    /* '<' */
+       152,    /* '=' */
+       152,    /* '>' */
+       152,    /* '?' */
+       152,    /* '@' */
+       178,    /* 'A' */
+       133,    /* 'B' */
+       158,    /* 'C' */
+       124,    /* 'D' */
+       119,    /* 'E' */
+       158,    /* 'F' */
+       188,    /* 'G' */
+       160,    /* 'H' */
+       183,    /* 'I' */
+       158,    /* 'J' */
+       182,    /* 'K' */
+       158,    /* 'L' */
+       188,    /* 'M' */
+       160,    /* 'N' */
+       189,    /* 'O' */
+       161,    /* 'P' */
+       180,    /* 'Q' */
+       152,    /* 'R' */
+       194,    /* 'S' */
+       161,    /* 'T' */
+       188,    /* 'U' */
+       160,    /* 'V' */
+       183,    /* 'W' */
+       158,    /* 'X' */
+       182,    /* 'Y' */
+       158,    /* 'Z' */
+       188,    /* '[' */
+       160,    /* '\' */
+       188,    /* ']' */
+       158,    /* '^' */
+       183,    /* '_' */
+       156,    /* '`' */
+       182,    /* 'a' */
+       156,    /* 'b' */
+       188,    /* 'c' */
+       157,    /* 'd' */
+       180,    /* 'e' */
+       150,    /* 'f' */
+       191,    /* 'g' */
+       160,    /* 'h' */
+       185,    /* 'i' */
+       158,    /* 'j' */
+       184,    /* 'k' */
+       158,    /* 'l' */
+       190,    /* 'm' */
+       160,    /* 'n' */
+       183,    /* 'o' */
+       152,    /* 'p' */
+       185,    /* 'q' */
+       158,    /* 'r' */
+       191,    /* 's' */
+       160,    /* 't' */
+       185,    /* 'u' */
+       158,    /* 'v' */
+       184,    /* 'w' */
+       158,    /* 'x' */
+       190,    /* 'y' */
+       160,    /* 'z' */
+       182,    /* '{' */
+       188,    /* '|' */
+       183,    /* '}' */
+       156,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XAI */
+       {
+       199,    /* ' ' */
+       132,    /* '!' */
+       142,    /* '"' */
+       138,    /* '#' */
+       138,    /* '$' */
+       97,     /* '%' */
+       97,     /* '&' */
+       97,     /* ''' */
+       97,     /* '(' */
+       138,    /* ')' */
+       138,    /* '*' */
+       95,     /* '+' */
+       35,     /* ',' */
+       138,    /* '-' */
+       105,    /* '.' */
+       144,    /* '/' */
+       144,    /* '0' */
+       132,    /* '1' */
+       138,    /* '2' */
+       142,    /* '3' */
+       142,    /* '4' */
+       145,    /* '5' */
+       14,     /* '6' */
+       144,    /* '7' */
+       14,     /* '8' */
+       142,    /* '9' */
+       62,     /* ':' */
+       138,    /* ';' */
+       108,    /* '<' */
+       138,    /* '=' */
+       138,    /* '>' */
+       138,    /* '?' */
+       138,    /* '@' */
+       151,    /* 'A' */
+       113,    /* 'B' */
+       142,    /* 'C' */
+       108,    /* 'D' */
+       105,    /* 'E' */
+       142,    /* 'F' */
+       175,    /* 'G' */
+       144,    /* 'H' */
+       169,    /* 'I' */
+       142,    /* 'J' */
+       168,    /* 'K' */
+       142,    /* 'L' */
+       174,    /* 'M' */
+       144,    /* 'N' */
+       175,    /* 'O' */
+       145,    /* 'P' */
+       167,    /* 'Q' */
+       136,    /* 'R' */
+       142,    /* 'S' */
+       108,    /* 'T' */
+       175,    /* 'U' */
+       144,    /* 'V' */
+       169,    /* 'W' */
+       142,    /* 'X' */
+       168,    /* 'Y' */
+       142,    /* 'Z' */
+       174,    /* '[' */
+       144,    /* '\' */
+       175,    /* ']' */
+       144,    /* '^' */
+       169,    /* '_' */
+       142,    /* '`' */
+       168,    /* 'a' */
+       142,    /* 'b' */
+       174,    /* 'c' */
+       144,    /* 'd' */
+       167,    /* 'e' */
+       136,    /* 'f' */
+       175,    /* 'g' */
+       144,    /* 'h' */
+       169,    /* 'i' */
+       142,    /* 'j' */
+       168,    /* 'k' */
+       142,    /* 'l' */
+       174,    /* 'm' */
+       144,    /* 'n' */
+       167,    /* 'o' */
+       136,    /* 'p' */
+       169,    /* 'q' */
+       142,    /* 'r' */
+       175,    /* 's' */
+       144,    /* 't' */
+       169,    /* 'u' */
+       142,    /* 'v' */
+       168,    /* 'w' */
+       142,    /* 'x' */
+       174,    /* 'y' */
+       144,    /* 'z' */
+       168,    /* '{' */
+       142,    /* '|' */
+       169,    /* '}' */
+       142,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-AvantGarde-BookOblique",
+       0,
+       YES
+       }, {
+       /* width table for font XAB */
+       {
+       47,     /* ' ' */
+       93,     /* '!' */
+       93,     /* '"' */
+       93,     /* '#' */
+       80,     /* '$' */
+       77,     /* '%' */
+       77,     /* '&' */
+       40,     /* ''' */
+       40,     /* '(' */
+       93,     /* ')' */
+       93,     /* '*' */
+       100,    /* '+' */
+       80,     /* ',' */
+       80,     /* '-' */
+       93,     /* '.' */
+       70,     /* '/' */
+       70,     /* '0' */
+       70,     /* '1' */
+       80,     /* '2' */
+       47,     /* '3' */
+       83,     /* '4' */
+       60,     /* '5' */
+       57,     /* '6' */
+       117,    /* '7' */
+       57,     /* '8' */
+       90,     /* '9' */
+       167,    /* ':' */
+       150,    /* ';' */
+       180,    /* '<' */
+       60,     /* '=' */
+       60,     /* '>' */
+       80,     /* '?' */
+       53,     /* '@' */
+       140,    /* 'A' */
+       110,    /* 'B' */
+       177,    /* 'C' */
+       180,    /* 'D' */
+       40,     /* 'E' */
+       100,    /* 'F' */
+       123,    /* 'G' */
+       110,    /* 'H' */
+       123,    /* 'I' */
+       110,    /* 'J' */
+       123,    /* 'K' */
+       110,    /* 'L' */
+       123,    /* 'M' */
+       110,    /* 'N' */
+       123,    /* 'O' */
+       110,    /* 'P' */
+       123,    /* 'Q' */
+       110,    /* 'R' */
+       130,    /* 'S' */
+       107,    /* 'T' */
+       87,     /* 'U' */
+       107,    /* 'V' */
+       87,     /* 'W' */
+       107,    /* 'X' */
+       87,     /* 'Y' */
+       107,    /* 'Z' */
+       87,     /* '[' */
+       107,    /* '\' */
+       47,     /* ']' */
+       40,     /* '^' */
+       47,     /* '_' */
+       40,     /* '`' */
+       47,     /* 'a' */
+       40,     /* 'b' */
+       47,     /* 'c' */
+       40,     /* 'd' */
+       123,    /* 'e' */
+       100,    /* 'f' */
+       140,    /* 'g' */
+       107,    /* 'h' */
+       140,    /* 'i' */
+       107,    /* 'j' */
+       140,    /* 'k' */
+       107,    /* 'l' */
+       140,    /* 'm' */
+       107,    /* 'n' */
+       140,    /* 'o' */
+       107,    /* 'p' */
+       87,     /* 'q' */
+       73,     /* 'r' */
+       107,    /* 's' */
+       100,    /* 't' */
+       107,    /* 'u' */
+       100,    /* 'v' */
+       107,    /* 'w' */
+       100,    /* 'x' */
+       107,    /* 'y' */
+       100,    /* 'z' */
+       103,    /* '{' */
+       97,     /* '|' */
+       83,     /* '}' */
+       77,     /* '~' */
+       47,     /* ' ' */
+       },
+       /* height table for font XAB */
+       {
+       276,    /* ' ' */
+       146,    /* '!' */
+       156,    /* '"' */
+       152,    /* '#' */
+       152,    /* '$' */
+       106,    /* '%' */
+       106,    /* '&' */
+       106,    /* ''' */
+       106,    /* '(' */
+       174,    /* ')' */
+       174,    /* '*' */
+       108,    /* '+' */
+       72,     /* ',' */
+       152,    /* '-' */
+       151,    /* '.' */
+       165,    /* '/' */
+       165,    /* '0' */
+       156,    /* '1' */
+       156,    /* '2' */
+       156,    /* '3' */
+       156,    /* '4' */
+       162,    /* '5' */
+       70,     /* '6' */
+       165,    /* '7' */
+       63,     /* '8' */
+       156,    /* '9' */
+       86,     /* ':' */
+       152,    /* ';' */
+       124,    /* '<' */
+       156,    /* '=' */
+       156,    /* '>' */
+       152,    /* '?' */
+       152,    /* '@' */
+       173,    /* 'A' */
+       143,    /* 'B' */
+       158,    /* 'C' */
+       124,    /* 'D' */
+       119,    /* 'E' */
+       158,    /* 'F' */
+       194,    /* 'G' */
+       168,    /* 'H' */
+       185,    /* 'I' */
+       158,    /* 'J' */
+       186,    /* 'K' */
+       158,    /* 'L' */
+       194,    /* 'M' */
+       168,    /* 'N' */
+       192,    /* 'O' */
+       164,    /* 'P' */
+       186,    /* 'Q' */
+       159,    /* 'R' */
+       198,    /* 'S' */
+       164,    /* 'T' */
+       194,    /* 'U' */
+       168,    /* 'V' */
+       185,    /* 'W' */
+       158,    /* 'X' */
+       186,    /* 'Y' */
+       158,    /* 'Z' */
+       194,    /* '[' */
+       168,    /* '\' */
+       194,    /* ']' */
+       165,    /* '^' */
+       185,    /* '_' */
+       156,    /* '`' */
+       186,    /* 'a' */
+       156,    /* 'b' */
+       194,    /* 'c' */
+       165,    /* 'd' */
+       186,    /* 'e' */
+       156,    /* 'f' */
+       197,    /* 'g' */
+       167,    /* 'h' */
+       187,    /* 'i' */
+       158,    /* 'j' */
+       188,    /* 'k' */
+       158,    /* 'l' */
+       197,    /* 'm' */
+       167,    /* 'n' */
+       188,    /* 'o' */
+       159,    /* 'p' */
+       187,    /* 'q' */
+       158,    /* 'r' */
+       197,    /* 's' */
+       168,    /* 't' */
+       187,    /* 'u' */
+       158,    /* 'v' */
+       188,    /* 'w' */
+       158,    /* 'x' */
+       197,    /* 'y' */
+       167,    /* 'z' */
+       186,    /* '{' */
+       188,    /* '|' */
+       185,    /* '}' */
+       156,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XAB */
+       {
+       199,    /* ' ' */
+       132,    /* '!' */
+       142,    /* '"' */
+       138,    /* '#' */
+       138,    /* '$' */
+       92,     /* '%' */
+       92,     /* '&' */
+       92,     /* ''' */
+       92,     /* '(' */
+       138,    /* ')' */
+       138,    /* '*' */
+       95,     /* '+' */
+       35,     /* ',' */
+       138,    /* '-' */
+       105,    /* '.' */
+       151,    /* '/' */
+       151,    /* '0' */
+       142,    /* '1' */
+       142,    /* '2' */
+       142,    /* '3' */
+       142,    /* '4' */
+       148,    /* '5' */
+       14,     /* '6' */
+       151,    /* '7' */
+       14,     /* '8' */
+       142,    /* '9' */
+       72,     /* ':' */
+       138,    /* ';' */
+       108,    /* '<' */
+       142,    /* '=' */
+       142,    /* '>' */
+       138,    /* '?' */
+       138,    /* '@' */
+       149,    /* 'A' */
+       118,    /* 'B' */
+       142,    /* 'C' */
+       108,    /* 'D' */
+       105,    /* 'E' */
+       142,    /* 'F' */
+       181,    /* 'G' */
+       151,    /* 'H' */
+       171,    /* 'I' */
+       142,    /* 'J' */
+       172,    /* 'K' */
+       142,    /* 'L' */
+       181,    /* 'M' */
+       151,    /* 'N' */
+       178,    /* 'O' */
+       148,    /* 'P' */
+       172,    /* 'Q' */
+       143,    /* 'R' */
+       142,    /* 'S' */
+       108,    /* 'T' */
+       181,    /* 'U' */
+       151,    /* 'V' */
+       171,    /* 'W' */
+       142,    /* 'X' */
+       172,    /* 'Y' */
+       142,    /* 'Z' */
+       181,    /* '[' */
+       151,    /* '\' */
+       181,    /* ']' */
+       151,    /* '^' */
+       171,    /* '_' */
+       142,    /* '`' */
+       172,    /* 'a' */
+       142,    /* 'b' */
+       181,    /* 'c' */
+       151,    /* 'd' */
+       172,    /* 'e' */
+       143,    /* 'f' */
+       181,    /* 'g' */
+       151,    /* 'h' */
+       171,    /* 'i' */
+       142,    /* 'j' */
+       172,    /* 'k' */
+       142,    /* 'l' */
+       181,    /* 'm' */
+       151,    /* 'n' */
+       172,    /* 'o' */
+       143,    /* 'p' */
+       171,    /* 'q' */
+       142,    /* 'r' */
+       181,    /* 's' */
+       151,    /* 't' */
+       171,    /* 'u' */
+       142,    /* 'v' */
+       172,    /* 'w' */
+       142,    /* 'x' */
+       181,    /* 'y' */
+       151,    /* 'z' */
+       172,    /* '{' */
+       142,    /* '|' */
+       171,    /* '}' */
+       142,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-AvantGarde-Demi",
+       0,
+       NO
+       }, {
+       /* width table for font XAX */
+       {
+       47,     /* ' ' */
+       93,     /* '!' */
+       93,     /* '"' */
+       93,     /* '#' */
+       80,     /* '$' */
+       77,     /* '%' */
+       77,     /* '&' */
+       40,     /* ''' */
+       40,     /* '(' */
+       93,     /* ')' */
+       93,     /* '*' */
+       100,    /* '+' */
+       80,     /* ',' */
+       80,     /* '-' */
+       93,     /* '.' */
+       70,     /* '/' */
+       70,     /* '0' */
+       70,     /* '1' */
+       80,     /* '2' */
+       47,     /* '3' */
+       83,     /* '4' */
+       60,     /* '5' */
+       57,     /* '6' */
+       117,    /* '7' */
+       57,     /* '8' */
+       90,     /* '9' */
+       167,    /* ':' */
+       150,    /* ';' */
+       180,    /* '<' */
+       60,     /* '=' */
+       60,     /* '>' */
+       80,     /* '?' */
+       53,     /* '@' */
+       140,    /* 'A' */
+       110,    /* 'B' */
+       177,    /* 'C' */
+       180,    /* 'D' */
+       40,     /* 'E' */
+       100,    /* 'F' */
+       123,    /* 'G' */
+       110,    /* 'H' */
+       123,    /* 'I' */
+       110,    /* 'J' */
+       123,    /* 'K' */
+       110,    /* 'L' */
+       123,    /* 'M' */
+       110,    /* 'N' */
+       123,    /* 'O' */
+       110,    /* 'P' */
+       123,    /* 'Q' */
+       110,    /* 'R' */
+       130,    /* 'S' */
+       107,    /* 'T' */
+       87,     /* 'U' */
+       107,    /* 'V' */
+       87,     /* 'W' */
+       107,    /* 'X' */
+       87,     /* 'Y' */
+       107,    /* 'Z' */
+       87,     /* '[' */
+       107,    /* '\' */
+       47,     /* ']' */
+       40,     /* '^' */
+       47,     /* '_' */
+       40,     /* '`' */
+       47,     /* 'a' */
+       40,     /* 'b' */
+       47,     /* 'c' */
+       40,     /* 'd' */
+       123,    /* 'e' */
+       100,    /* 'f' */
+       140,    /* 'g' */
+       107,    /* 'h' */
+       140,    /* 'i' */
+       107,    /* 'j' */
+       140,    /* 'k' */
+       107,    /* 'l' */
+       140,    /* 'm' */
+       107,    /* 'n' */
+       140,    /* 'o' */
+       107,    /* 'p' */
+       87,     /* 'q' */
+       73,     /* 'r' */
+       107,    /* 's' */
+       100,    /* 't' */
+       107,    /* 'u' */
+       100,    /* 'v' */
+       107,    /* 'w' */
+       100,    /* 'x' */
+       107,    /* 'y' */
+       100,    /* 'z' */
+       103,    /* '{' */
+       97,     /* '|' */
+       83,     /* '}' */
+       77,     /* '~' */
+       47,     /* ' ' */
+       },
+       /* height table for font XAX */
+       {
+       276,    /* ' ' */
+       146,    /* '!' */
+       156,    /* '"' */
+       152,    /* '#' */
+       152,    /* '$' */
+       106,    /* '%' */
+       106,    /* '&' */
+       106,    /* ''' */
+       106,    /* '(' */
+       174,    /* ')' */
+       174,    /* '*' */
+       109,    /* '+' */
+       73,     /* ',' */
+       152,    /* '-' */
+       151,    /* '.' */
+       166,    /* '/' */
+       166,    /* '0' */
+       156,    /* '1' */
+       155,    /* '2' */
+       156,    /* '3' */
+       156,    /* '4' */
+       166,    /* '5' */
+       70,     /* '6' */
+       167,    /* '7' */
+       63,     /* '8' */
+       156,    /* '9' */
+       86,     /* ':' */
+       152,    /* ';' */
+       124,    /* '<' */
+       156,    /* '=' */
+       156,    /* '>' */
+       152,    /* '?' */
+       152,    /* '@' */
+       179,    /* 'A' */
+       142,    /* 'B' */
+       158,    /* 'C' */
+       124,    /* 'D' */
+       119,    /* 'E' */
+       158,    /* 'F' */
+       196,    /* 'G' */
+       169,    /* 'H' */
+       186,    /* 'I' */
+       158,    /* 'J' */
+       186,    /* 'K' */
+       158,    /* 'L' */
+       196,    /* 'M' */
+       169,    /* 'N' */
+       192,    /* 'O' */
+       168,    /* 'P' */
+       185,    /* 'Q' */
+       158,    /* 'R' */
+       198,    /* 'S' */
+       164,    /* 'T' */
+       196,    /* 'U' */
+       169,    /* 'V' */
+       186,    /* 'W' */
+       158,    /* 'X' */
+       186,    /* 'Y' */
+       158,    /* 'Z' */
+       196,    /* '[' */
+       169,    /* '\' */
+       196,    /* ']' */
+       166,    /* '^' */
+       186,    /* '_' */
+       156,    /* '`' */
+       186,    /* 'a' */
+       156,    /* 'b' */
+       196,    /* 'c' */
+       166,    /* 'd' */
+       185,    /* 'e' */
+       156,    /* 'f' */
+       198,    /* 'g' */
+       169,    /* 'h' */
+       188,    /* 'i' */
+       158,    /* 'j' */
+       188,    /* 'k' */
+       158,    /* 'l' */
+       198,    /* 'm' */
+       169,    /* 'n' */
+       188,    /* 'o' */
+       158,    /* 'p' */
+       188,    /* 'q' */
+       158,    /* 'r' */
+       198,    /* 's' */
+       169,    /* 't' */
+       188,    /* 'u' */
+       158,    /* 'v' */
+       188,    /* 'w' */
+       158,    /* 'x' */
+       198,    /* 'y' */
+       169,    /* 'z' */
+       186,    /* '{' */
+       188,    /* '|' */
+       186,    /* '}' */
+       156,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XAX */
+       {
+       199,    /* ' ' */
+       132,    /* '!' */
+       142,    /* '"' */
+       138,    /* '#' */
+       138,    /* '$' */
+       92,     /* '%' */
+       92,     /* '&' */
+       92,     /* ''' */
+       92,     /* '(' */
+       138,    /* ')' */
+       138,    /* '*' */
+       95,     /* '+' */
+       35,     /* ',' */
+       138,    /* '-' */
+       105,    /* '.' */
+       153,    /* '/' */
+       153,    /* '0' */
+       142,    /* '1' */
+       142,    /* '2' */
+       142,    /* '3' */
+       142,    /* '4' */
+       152,    /* '5' */
+       14,     /* '6' */
+       154,    /* '7' */
+       14,     /* '8' */
+       142,    /* '9' */
+       72,     /* ':' */
+       138,    /* ';' */
+       108,    /* '<' */
+       142,    /* '=' */
+       142,    /* '>' */
+       138,    /* '?' */
+       138,    /* '@' */
+       152,    /* 'A' */
+       117,    /* 'B' */
+       142,    /* 'C' */
+       108,    /* 'D' */
+       105,    /* 'E' */
+       142,    /* 'F' */
+       182,    /* 'G' */
+       153,    /* 'H' */
+       172,    /* 'I' */
+       142,    /* 'J' */
+       172,    /* 'K' */
+       142,    /* 'L' */
+       182,    /* 'M' */
+       153,    /* 'N' */
+       178,    /* 'O' */
+       152,    /* 'P' */
+       172,    /* 'Q' */
+       142,    /* 'R' */
+       142,    /* 'S' */
+       108,    /* 'T' */
+       182,    /* 'U' */
+       153,    /* 'V' */
+       172,    /* 'W' */
+       142,    /* 'X' */
+       172,    /* 'Y' */
+       142,    /* 'Z' */
+       182,    /* '[' */
+       153,    /* '\' */
+       182,    /* ']' */
+       153,    /* '^' */
+       172,    /* '_' */
+       142,    /* '`' */
+       172,    /* 'a' */
+       142,    /* 'b' */
+       182,    /* 'c' */
+       153,    /* 'd' */
+       172,    /* 'e' */
+       142,    /* 'f' */
+       182,    /* 'g' */
+       153,    /* 'h' */
+       172,    /* 'i' */
+       142,    /* 'j' */
+       172,    /* 'k' */
+       142,    /* 'l' */
+       182,    /* 'm' */
+       153,    /* 'n' */
+       171,    /* 'o' */
+       142,    /* 'p' */
+       172,    /* 'q' */
+       142,    /* 'r' */
+       182,    /* 's' */
+       153,    /* 't' */
+       172,    /* 'u' */
+       142,    /* 'v' */
+       172,    /* 'w' */
+       142,    /* 'x' */
+       182,    /* 'y' */
+       153,    /* 'z' */
+       172,    /* '{' */
+       142,    /* '|' */
+       172,    /* '}' */
+       142,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-AvantGarde-DemiOblique",
+       0,
+       YES
+       }, {
+       /* width table for font XCR */
+       {
+       100,    /* ' ' */
+       100,    /* '!' */
+       100,    /* '"' */
+       100,    /* '#' */
+       100,    /* '$' */
+       100,    /* '%' */
+       100,    /* '&' */
+       100,    /* ''' */
+       100,    /* '(' */
+       100,    /* ')' */
+       100,    /* '*' */
+       100,    /* '+' */
+       100,    /* ',' */
+       100,    /* '-' */
+       100,    /* '.' */
+       100,    /* '/' */
+       100,    /* '0' */
+       100,    /* '1' */
+       100,    /* '2' */
+       100,    /* '3' */
+       100,    /* '4' */
+       100,    /* '5' */
+       100,    /* '6' */
+       100,    /* '7' */
+       100,    /* '8' */
+       100,    /* '9' */
+       100,    /* ':' */
+       100,    /* ';' */
+       100,    /* '<' */
+       100,    /* '=' */
+       100,    /* '>' */
+       100,    /* '?' */
+       100,    /* '@' */
+       100,    /* 'A' */
+       100,    /* 'B' */
+       100,    /* 'C' */
+       100,    /* 'D' */
+       100,    /* 'E' */
+       100,    /* 'F' */
+       100,    /* 'G' */
+       100,    /* 'H' */
+       100,    /* 'I' */
+       100,    /* 'J' */
+       100,    /* 'K' */
+       100,    /* 'L' */
+       100,    /* 'M' */
+       100,    /* 'N' */
+       100,    /* 'O' */
+       100,    /* 'P' */
+       100,    /* 'Q' */
+       100,    /* 'R' */
+       100,    /* 'S' */
+       100,    /* 'T' */
+       100,    /* 'U' */
+       100,    /* 'V' */
+       100,    /* 'W' */
+       100,    /* 'X' */
+       100,    /* 'Y' */
+       100,    /* 'Z' */
+       100,    /* '[' */
+       100,    /* '\' */
+       100,    /* ']' */
+       100,    /* '^' */
+       100,    /* '_' */
+       100,    /* '`' */
+       100,    /* 'a' */
+       100,    /* 'b' */
+       100,    /* 'c' */
+       100,    /* 'd' */
+       100,    /* 'e' */
+       100,    /* 'f' */
+       100,    /* 'g' */
+       100,    /* 'h' */
+       100,    /* 'i' */
+       100,    /* 'j' */
+       100,    /* 'k' */
+       100,    /* 'l' */
+       100,    /* 'm' */
+       100,    /* 'n' */
+       100,    /* 'o' */
+       100,    /* 'p' */
+       100,    /* 'q' */
+       100,    /* 'r' */
+       100,    /* 's' */
+       100,    /* 't' */
+       100,    /* 'u' */
+       100,    /* 'v' */
+       100,    /* 'w' */
+       100,    /* 'x' */
+       100,    /* 'y' */
+       100,    /* 'z' */
+       100,    /* '{' */
+       100,    /* '|' */
+       100,    /* '}' */
+       100,    /* '~' */
+       100,    /* ' ' */
+       },
+       /* height table for font XCR */
+       {
+       260,    /* ' ' */
+       134,    /* '!' */
+       126,    /* '"' */
+       122,    /* '#' */
+       128,    /* '$' */
+       99,     /* '%' */
+       99,     /* '&' */
+       99,     /* ''' */
+       99,     /* '(' */
+       139,    /* ')' */
+       139,    /* '*' */
+       84,     /* '+' */
+       71,     /* ',' */
+       128,    /* '-' */
+       128,    /* '.' */
+       134,    /* '/' */
+       134,    /* '0' */
+       126,    /* '1' */
+       131,    /* '2' */
+       130,    /* '3' */
+       130,    /* '4' */
+       139,    /* '5' */
+       58,     /* '6' */
+       133,    /* '7' */
+       53,     /* '8' */
+       134,    /* '9' */
+       79,     /* ':' */
+       122,    /* ';' */
+       104,    /* '<' */
+       126,    /* '=' */
+       126,    /* '>' */
+       122,    /* '?' */
+       129,    /* '@' */
+       136,    /* 'A' */
+       111,    /* 'B' */
+       122,    /* 'C' */
+       104,    /* 'D' */
+       99,     /* 'E' */
+       131,    /* 'F' */
+       159,    /* 'G' */
+       137,    /* 'H' */
+       159,    /* 'I' */
+       137,    /* 'J' */
+       155,    /* 'K' */
+       132,    /* 'L' */
+       159,    /* 'M' */
+       136,    /* 'N' */
+       162,    /* 'O' */
+       141,    /* 'P' */
+       152,    /* 'Q' */
+       131,    /* 'R' */
+       154,    /* 'S' */
+       131,    /* 'T' */
+       159,    /* 'U' */
+       136,    /* 'V' */
+       159,    /* 'W' */
+       136,    /* 'X' */
+       155,    /* 'Y' */
+       132,    /* 'Z' */
+       159,    /* '[' */
+       136,    /* '\' */
+       159,    /* ']' */
+       134,    /* '^' */
+       159,    /* '_' */
+       134,    /* '`' */
+       156,    /* 'a' */
+       132,    /* 'b' */
+       159,    /* 'c' */
+       134,    /* 'd' */
+       152,    /* 'e' */
+       129,    /* 'f' */
+       161,    /* 'g' */
+       137,    /* 'h' */
+       161,    /* 'i' */
+       137,    /* 'j' */
+       157,    /* 'k' */
+       132,    /* 'l' */
+       161,    /* 'm' */
+       137,    /* 'n' */
+       154,    /* 'o' */
+       131,    /* 'p' */
+       161,    /* 'q' */
+       136,    /* 'r' */
+       161,    /* 's' */
+       136,    /* 't' */
+       161,    /* 'u' */
+       136,    /* 'v' */
+       157,    /* 'w' */
+       132,    /* 'x' */
+       161,    /* 'y' */
+       136,    /* 'z' */
+       155,    /* '{' */
+       159,    /* '|' */
+       159,    /* '}' */
+       134,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XCR */
+       {
+       179,    /* ' ' */
+       118,    /* '!' */
+       112,    /* '"' */
+       108,    /* '#' */
+       115,    /* '$' */
+       85,     /* '%' */
+       85,     /* '&' */
+       85,     /* ''' */
+       85,     /* '(' */
+       115,    /* ')' */
+       115,    /* '*' */
+       70,     /* '+' */
+       38,     /* ',' */
+       115,    /* '-' */
+       85,     /* '.' */
+       120,    /* '/' */
+       120,    /* '0' */
+       112,    /* '1' */
+       117,    /* '2' */
+       116,    /* '3' */
+       116,    /* '4' */
+       125,    /* '5' */
+       15,     /* '6' */
+       119,    /* '7' */
+       14,     /* '8' */
+       120,    /* '9' */
+       65,     /* ':' */
+       108,    /* ';' */
+       88,     /* '<' */
+       112,    /* '=' */
+       112,    /* '>' */
+       108,    /* '?' */
+       115,    /* '@' */
+       115,    /* 'A' */
+       90,     /* 'B' */
+       108,    /* 'C' */
+       88,     /* 'D' */
+       85,     /* 'E' */
+       115,    /* 'F' */
+       145,    /* 'G' */
+       120,    /* 'H' */
+       145,    /* 'I' */
+       120,    /* 'J' */
+       141,    /* 'K' */
+       116,    /* 'L' */
+       145,    /* 'M' */
+       120,    /* 'N' */
+       148,    /* 'O' */
+       125,    /* 'P' */
+       138,    /* 'Q' */
+       115,    /* 'R' */
+       112,    /* 'S' */
+       88,     /* 'T' */
+       145,    /* 'U' */
+       120,    /* 'V' */
+       145,    /* 'W' */
+       120,    /* 'X' */
+       141,    /* 'Y' */
+       116,    /* 'Z' */
+       145,    /* '[' */
+       120,    /* '\' */
+       145,    /* ']' */
+       120,    /* '^' */
+       145,    /* '_' */
+       120,    /* '`' */
+       142,    /* 'a' */
+       118,    /* 'b' */
+       145,    /* 'c' */
+       120,    /* 'd' */
+       138,    /* 'e' */
+       115,    /* 'f' */
+       145,    /* 'g' */
+       120,    /* 'h' */
+       145,    /* 'i' */
+       120,    /* 'j' */
+       141,    /* 'k' */
+       116,    /* 'l' */
+       145,    /* 'm' */
+       120,    /* 'n' */
+       138,    /* 'o' */
+       115,    /* 'p' */
+       145,    /* 'q' */
+       120,    /* 'r' */
+       145,    /* 's' */
+       120,    /* 't' */
+       145,    /* 'u' */
+       120,    /* 'v' */
+       141,    /* 'w' */
+       116,    /* 'x' */
+       145,    /* 'y' */
+       120,    /* 'z' */
+       141,    /* '{' */
+       116,    /* '|' */
+       145,    /* '}' */
+       120,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Courier",
+       0,
+       NO
+       }, {
+       /* width table for font XCI */
+       {
+       100,    /* ' ' */
+       100,    /* '!' */
+       100,    /* '"' */
+       100,    /* '#' */
+       100,    /* '$' */
+       100,    /* '%' */
+       100,    /* '&' */
+       100,    /* ''' */
+       100,    /* '(' */
+       100,    /* ')' */
+       100,    /* '*' */
+       100,    /* '+' */
+       100,    /* ',' */
+       100,    /* '-' */
+       100,    /* '.' */
+       100,    /* '/' */
+       100,    /* '0' */
+       100,    /* '1' */
+       100,    /* '2' */
+       100,    /* '3' */
+       100,    /* '4' */
+       100,    /* '5' */
+       100,    /* '6' */
+       100,    /* '7' */
+       100,    /* '8' */
+       100,    /* '9' */
+       100,    /* ':' */
+       100,    /* ';' */
+       100,    /* '<' */
+       100,    /* '=' */
+       100,    /* '>' */
+       100,    /* '?' */
+       100,    /* '@' */
+       100,    /* 'A' */
+       100,    /* 'B' */
+       100,    /* 'C' */
+       100,    /* 'D' */
+       100,    /* 'E' */
+       100,    /* 'F' */
+       100,    /* 'G' */
+       100,    /* 'H' */
+       100,    /* 'I' */
+       100,    /* 'J' */
+       100,    /* 'K' */
+       100,    /* 'L' */
+       100,    /* 'M' */
+       100,    /* 'N' */
+       100,    /* 'O' */
+       100,    /* 'P' */
+       100,    /* 'Q' */
+       100,    /* 'R' */
+       100,    /* 'S' */
+       100,    /* 'T' */
+       100,    /* 'U' */
+       100,    /* 'V' */
+       100,    /* 'W' */
+       100,    /* 'X' */
+       100,    /* 'Y' */
+       100,    /* 'Z' */
+       100,    /* '[' */
+       100,    /* '\' */
+       100,    /* ']' */
+       100,    /* '^' */
+       100,    /* '_' */
+       100,    /* '`' */
+       100,    /* 'a' */
+       100,    /* 'b' */
+       100,    /* 'c' */
+       100,    /* 'd' */
+       100,    /* 'e' */
+       100,    /* 'f' */
+       100,    /* 'g' */
+       100,    /* 'h' */
+       100,    /* 'i' */
+       100,    /* 'j' */
+       100,    /* 'k' */
+       100,    /* 'l' */
+       100,    /* 'm' */
+       100,    /* 'n' */
+       100,    /* 'o' */
+       100,    /* 'p' */
+       100,    /* 'q' */
+       100,    /* 'r' */
+       100,    /* 's' */
+       100,    /* 't' */
+       100,    /* 'u' */
+       100,    /* 'v' */
+       100,    /* 'w' */
+       100,    /* 'x' */
+       100,    /* 'y' */
+       100,    /* 'z' */
+       100,    /* '{' */
+       100,    /* '|' */
+       100,    /* '}' */
+       100,    /* '~' */
+       100,    /* ' ' */
+       },
+       /* height table for font XCI */
+       {
+       260,    /* ' ' */
+       134,    /* '!' */
+       126,    /* '"' */
+       122,    /* '#' */
+       129,    /* '$' */
+       99,     /* '%' */
+       99,     /* '&' */
+       99,     /* ''' */
+       99,     /* '(' */
+       139,    /* ')' */
+       139,    /* '*' */
+       84,     /* '+' */
+       71,     /* ',' */
+       128,    /* '-' */
+       128,    /* '.' */
+       134,    /* '/' */
+       134,    /* '0' */
+       126,    /* '1' */
+       131,    /* '2' */
+       130,    /* '3' */
+       130,    /* '4' */
+       139,    /* '5' */
+       57,     /* '6' */
+       133,    /* '7' */
+       53,     /* '8' */
+       134,    /* '9' */
+       79,     /* ':' */
+       122,    /* ';' */
+       104,    /* '<' */
+       126,    /* '=' */
+       126,    /* '>' */
+       122,    /* '?' */
+       129,    /* '@' */
+       136,    /* 'A' */
+       111,    /* 'B' */
+       122,    /* 'C' */
+       104,    /* 'D' */
+       99,     /* 'E' */
+       131,    /* 'F' */
+       159,    /* 'G' */
+       137,    /* 'H' */
+       159,    /* 'I' */
+       137,    /* 'J' */
+       155,    /* 'K' */
+       132,    /* 'L' */
+       159,    /* 'M' */
+       137,    /* 'N' */
+       162,    /* 'O' */
+       141,    /* 'P' */
+       152,    /* 'Q' */
+       131,    /* 'R' */
+       154,    /* 'S' */
+       131,    /* 'T' */
+       159,    /* 'U' */
+       136,    /* 'V' */
+       159,    /* 'W' */
+       136,    /* 'X' */
+       155,    /* 'Y' */
+       132,    /* 'Z' */
+       159,    /* '[' */
+       136,    /* '\' */
+       159,    /* ']' */
+       134,    /* '^' */
+       159,    /* '_' */
+       134,    /* '`' */
+       155,    /* 'a' */
+       130,    /* 'b' */
+       159,    /* 'c' */
+       134,    /* 'd' */
+       152,    /* 'e' */
+       129,    /* 'f' */
+       161,    /* 'g' */
+       136,    /* 'h' */
+       161,    /* 'i' */
+       136,    /* 'j' */
+       157,    /* 'k' */
+       132,    /* 'l' */
+       161,    /* 'm' */
+       136,    /* 'n' */
+       154,    /* 'o' */
+       131,    /* 'p' */
+       162,    /* 'q' */
+       136,    /* 'r' */
+       161,    /* 's' */
+       136,    /* 't' */
+       161,    /* 'u' */
+       136,    /* 'v' */
+       157,    /* 'w' */
+       132,    /* 'x' */
+       161,    /* 'y' */
+       137,    /* 'z' */
+       155,    /* '{' */
+       159,    /* '|' */
+       159,    /* '}' */
+       134,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XCI */
+       {
+       179,    /* ' ' */
+       118,    /* '!' */
+       112,    /* '"' */
+       108,    /* '#' */
+       115,    /* '$' */
+       85,     /* '%' */
+       85,     /* '&' */
+       85,     /* ''' */
+       85,     /* '(' */
+       115,    /* ')' */
+       115,    /* '*' */
+       70,     /* '+' */
+       38,     /* ',' */
+       115,    /* '-' */
+       85,     /* '.' */
+       120,    /* '/' */
+       120,    /* '0' */
+       112,    /* '1' */
+       117,    /* '2' */
+       116,    /* '3' */
+       116,    /* '4' */
+       125,    /* '5' */
+       14,     /* '6' */
+       119,    /* '7' */
+       14,     /* '8' */
+       120,    /* '9' */
+       65,     /* ':' */
+       108,    /* ';' */
+       88,     /* '<' */
+       112,    /* '=' */
+       112,    /* '>' */
+       108,    /* '?' */
+       115,    /* '@' */
+       115,    /* 'A' */
+       90,     /* 'B' */
+       108,    /* 'C' */
+       88,     /* 'D' */
+       85,     /* 'E' */
+       115,    /* 'F' */
+       145,    /* 'G' */
+       120,    /* 'H' */
+       145,    /* 'I' */
+       120,    /* 'J' */
+       141,    /* 'K' */
+       116,    /* 'L' */
+       145,    /* 'M' */
+       120,    /* 'N' */
+       148,    /* 'O' */
+       125,    /* 'P' */
+       138,    /* 'Q' */
+       115,    /* 'R' */
+       112,    /* 'S' */
+       88,     /* 'T' */
+       145,    /* 'U' */
+       120,    /* 'V' */
+       145,    /* 'W' */
+       120,    /* 'X' */
+       141,    /* 'Y' */
+       116,    /* 'Z' */
+       145,    /* '[' */
+       120,    /* '\' */
+       145,    /* ']' */
+       120,    /* '^' */
+       145,    /* '_' */
+       120,    /* '`' */
+       141,    /* 'a' */
+       116,    /* 'b' */
+       145,    /* 'c' */
+       120,    /* 'd' */
+       138,    /* 'e' */
+       115,    /* 'f' */
+       145,    /* 'g' */
+       120,    /* 'h' */
+       145,    /* 'i' */
+       120,    /* 'j' */
+       141,    /* 'k' */
+       116,    /* 'l' */
+       145,    /* 'm' */
+       120,    /* 'n' */
+       138,    /* 'o' */
+       115,    /* 'p' */
+       145,    /* 'q' */
+       120,    /* 'r' */
+       145,    /* 's' */
+       120,    /* 't' */
+       145,    /* 'u' */
+       120,    /* 'v' */
+       141,    /* 'w' */
+       116,    /* 'x' */
+       145,    /* 'y' */
+       120,    /* 'z' */
+       141,    /* '{' */
+       116,    /* '|' */
+       145,    /* '}' */
+       120,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Courier-Italic",
+       0,
+       YES
+       }, {
+       /* width table for font XCB */
+       {
+       100,    /* ' ' */
+       100,    /* '!' */
+       100,    /* '"' */
+       100,    /* '#' */
+       100,    /* '$' */
+       100,    /* '%' */
+       100,    /* '&' */
+       100,    /* ''' */
+       100,    /* '(' */
+       100,    /* ')' */
+       100,    /* '*' */
+       100,    /* '+' */
+       100,    /* ',' */
+       100,    /* '-' */
+       100,    /* '.' */
+       100,    /* '/' */
+       100,    /* '0' */
+       100,    /* '1' */
+       100,    /* '2' */
+       100,    /* '3' */
+       100,    /* '4' */
+       100,    /* '5' */
+       100,    /* '6' */
+       100,    /* '7' */
+       100,    /* '8' */
+       100,    /* '9' */
+       100,    /* ':' */
+       100,    /* ';' */
+       100,    /* '<' */
+       100,    /* '=' */
+       100,    /* '>' */
+       100,    /* '?' */
+       100,    /* '@' */
+       100,    /* 'A' */
+       100,    /* 'B' */
+       100,    /* 'C' */
+       100,    /* 'D' */
+       100,    /* 'E' */
+       100,    /* 'F' */
+       100,    /* 'G' */
+       100,    /* 'H' */
+       100,    /* 'I' */
+       100,    /* 'J' */
+       100,    /* 'K' */
+       100,    /* 'L' */
+       100,    /* 'M' */
+       100,    /* 'N' */
+       100,    /* 'O' */
+       100,    /* 'P' */
+       100,    /* 'Q' */
+       100,    /* 'R' */
+       100,    /* 'S' */
+       100,    /* 'T' */
+       100,    /* 'U' */
+       100,    /* 'V' */
+       100,    /* 'W' */
+       100,    /* 'X' */
+       100,    /* 'Y' */
+       100,    /* 'Z' */
+       100,    /* '[' */
+       100,    /* '\' */
+       100,    /* ']' */
+       100,    /* '^' */
+       100,    /* '_' */
+       100,    /* '`' */
+       100,    /* 'a' */
+       100,    /* 'b' */
+       100,    /* 'c' */
+       100,    /* 'd' */
+       100,    /* 'e' */
+       100,    /* 'f' */
+       100,    /* 'g' */
+       100,    /* 'h' */
+       100,    /* 'i' */
+       100,    /* 'j' */
+       100,    /* 'k' */
+       100,    /* 'l' */
+       100,    /* 'm' */
+       100,    /* 'n' */
+       100,    /* 'o' */
+       100,    /* 'p' */
+       100,    /* 'q' */
+       100,    /* 'r' */
+       100,    /* 's' */
+       100,    /* 't' */
+       100,    /* 'u' */
+       100,    /* 'v' */
+       100,    /* 'w' */
+       100,    /* 'x' */
+       100,    /* 'y' */
+       100,    /* 'z' */
+       100,    /* '{' */
+       100,    /* '|' */
+       100,    /* '}' */
+       100,    /* '~' */
+       100,    /* ' ' */
+       },
+       /* height table for font XCB */
+       {
+       263,    /* ' ' */
+       148,    /* '!' */
+       129,    /* '"' */
+       124,    /* '#' */
+       129,    /* '$' */
+       97,     /* '%' */
+       97,     /* '&' */
+       97,     /* ''' */
+       97,     /* '(' */
+       147,    /* ')' */
+       147,    /* '*' */
+       106,    /* '+' */
+       70,     /* ',' */
+       129,    /* '-' */
+       131,    /* '.' */
+       144,    /* '/' */
+       144,    /* '0' */
+       132,    /* '1' */
+       142,    /* '2' */
+       137,    /* '3' */
+       137,    /* '4' */
+       149,    /* '5' */
+       68,     /* '6' */
+       143,    /* '7' */
+       63,     /* '8' */
+       144,    /* '9' */
+       82,     /* ':' */
+       126,    /* ';' */
+       108,    /* '<' */
+       129,    /* '=' */
+       129,    /* '>' */
+       126,    /* '?' */
+       132,    /* '@' */
+       146,    /* 'A' */
+       122,    /* 'B' */
+       126,    /* 'C' */
+       108,    /* 'D' */
+       102,    /* 'E' */
+       134,    /* 'F' */
+       168,    /* 'G' */
+       146,    /* 'H' */
+       168,    /* 'I' */
+       146,    /* 'J' */
+       161,    /* 'K' */
+       139,    /* 'L' */
+       168,    /* 'M' */
+       146,    /* 'N' */
+       172,    /* 'O' */
+       151,    /* 'P' */
+       161,    /* 'Q' */
+       139,    /* 'R' */
+       168,    /* 'S' */
+       144,    /* 'T' */
+       168,    /* 'U' */
+       146,    /* 'V' */
+       168,    /* 'W' */
+       146,    /* 'X' */
+       161,    /* 'Y' */
+       139,    /* 'Z' */
+       168,    /* '[' */
+       146,    /* '\' */
+       168,    /* ']' */
+       144,    /* '^' */
+       168,    /* '_' */
+       144,    /* '`' */
+       162,    /* 'a' */
+       136,    /* 'b' */
+       168,    /* 'c' */
+       144,    /* 'd' */
+       161,    /* 'e' */
+       137,    /* 'f' */
+       170,    /* 'g' */
+       146,    /* 'h' */
+       170,    /* 'i' */
+       146,    /* 'j' */
+       163,    /* 'k' */
+       139,    /* 'l' */
+       170,    /* 'm' */
+       146,    /* 'n' */
+       163,    /* 'o' */
+       139,    /* 'p' */
+       170,    /* 'q' */
+       146,    /* 'r' */
+       170,    /* 's' */
+       146,    /* 't' */
+       170,    /* 'u' */
+       146,    /* 'v' */
+       163,    /* 'w' */
+       139,    /* 'x' */
+       170,    /* 'y' */
+       146,    /* 'z' */
+       161,    /* '{' */
+       172,    /* '|' */
+       168,    /* '}' */
+       144,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XCB */
+       {
+       179,    /* ' ' */
+       125,    /* '!' */
+       115,    /* '"' */
+       111,    /* '#' */
+       115,    /* '$' */
+       83,     /* '%' */
+       83,     /* '&' */
+       83,     /* ''' */
+       83,     /* '(' */
+       118,    /* ')' */
+       118,    /* '*' */
+       92,     /* '+' */
+       36,     /* ',' */
+       115,    /* '-' */
+       78,     /* '.' */
+       130,    /* '/' */
+       130,    /* '0' */
+       118,    /* '1' */
+       128,    /* '2' */
+       123,    /* '3' */
+       123,    /* '4' */
+       135,    /* '5' */
+       15,     /* '6' */
+       130,    /* '7' */
+       14,     /* '8' */
+       130,    /* '9' */
+       68,     /* ':' */
+       112,    /* ';' */
+       92,     /* '<' */
+       115,    /* '=' */
+       115,    /* '>' */
+       112,    /* '?' */
+       118,    /* '@' */
+       120,    /* 'A' */
+       96,     /* 'B' */
+       112,    /* 'C' */
+       92,     /* 'D' */
+       88,     /* 'E' */
+       118,    /* 'F' */
+       154,    /* 'G' */
+       130,    /* 'H' */
+       154,    /* 'I' */
+       130,    /* 'J' */
+       147,    /* 'K' */
+       123,    /* 'L' */
+       154,    /* 'M' */
+       130,    /* 'N' */
+       158,    /* 'O' */
+       135,    /* 'P' */
+       147,    /* 'Q' */
+       123,    /* 'R' */
+       115,    /* 'S' */
+       92,     /* 'T' */
+       154,    /* 'U' */
+       130,    /* 'V' */
+       154,    /* 'W' */
+       130,    /* 'X' */
+       147,    /* 'Y' */
+       123,    /* 'Z' */
+       154,    /* '[' */
+       130,    /* '\' */
+       154,    /* ']' */
+       130,    /* '^' */
+       154,    /* '_' */
+       130,    /* '`' */
+       148,    /* 'a' */
+       122,    /* 'b' */
+       154,    /* 'c' */
+       130,    /* 'd' */
+       147,    /* 'e' */
+       123,    /* 'f' */
+       154,    /* 'g' */
+       130,    /* 'h' */
+       154,    /* 'i' */
+       130,    /* 'j' */
+       147,    /* 'k' */
+       123,    /* 'l' */
+       154,    /* 'm' */
+       130,    /* 'n' */
+       147,    /* 'o' */
+       123,    /* 'p' */
+       154,    /* 'q' */
+       130,    /* 'r' */
+       154,    /* 's' */
+       130,    /* 't' */
+       154,    /* 'u' */
+       130,    /* 'v' */
+       147,    /* 'w' */
+       123,    /* 'x' */
+       154,    /* 'y' */
+       130,    /* 'z' */
+       147,    /* '{' */
+       123,    /* '|' */
+       154,    /* '}' */
+       130,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Courier-Bold",
+       0,
+       NO
+       }, {
+       /* width table for font XCX */
+       {
+       100,    /* ' ' */
+       100,    /* '!' */
+       100,    /* '"' */
+       100,    /* '#' */
+       100,    /* '$' */
+       100,    /* '%' */
+       100,    /* '&' */
+       100,    /* ''' */
+       100,    /* '(' */
+       100,    /* ')' */
+       100,    /* '*' */
+       100,    /* '+' */
+       100,    /* ',' */
+       100,    /* '-' */
+       100,    /* '.' */
+       100,    /* '/' */
+       100,    /* '0' */
+       100,    /* '1' */
+       100,    /* '2' */
+       100,    /* '3' */
+       100,    /* '4' */
+       100,    /* '5' */
+       100,    /* '6' */
+       100,    /* '7' */
+       100,    /* '8' */
+       100,    /* '9' */
+       100,    /* ':' */
+       100,    /* ';' */
+       100,    /* '<' */
+       100,    /* '=' */
+       100,    /* '>' */
+       100,    /* '?' */
+       100,    /* '@' */
+       100,    /* 'A' */
+       100,    /* 'B' */
+       100,    /* 'C' */
+       100,    /* 'D' */
+       100,    /* 'E' */
+       100,    /* 'F' */
+       100,    /* 'G' */
+       100,    /* 'H' */
+       100,    /* 'I' */
+       100,    /* 'J' */
+       100,    /* 'K' */
+       100,    /* 'L' */
+       100,    /* 'M' */
+       100,    /* 'N' */
+       100,    /* 'O' */
+       100,    /* 'P' */
+       100,    /* 'Q' */
+       100,    /* 'R' */
+       100,    /* 'S' */
+       100,    /* 'T' */
+       100,    /* 'U' */
+       100,    /* 'V' */
+       100,    /* 'W' */
+       100,    /* 'X' */
+       100,    /* 'Y' */
+       100,    /* 'Z' */
+       100,    /* '[' */
+       100,    /* '\' */
+       100,    /* ']' */
+       100,    /* '^' */
+       100,    /* '_' */
+       100,    /* '`' */
+       100,    /* 'a' */
+       100,    /* 'b' */
+       100,    /* 'c' */
+       100,    /* 'd' */
+       100,    /* 'e' */
+       100,    /* 'f' */
+       100,    /* 'g' */
+       100,    /* 'h' */
+       100,    /* 'i' */
+       100,    /* 'j' */
+       100,    /* 'k' */
+       100,    /* 'l' */
+       100,    /* 'm' */
+       100,    /* 'n' */
+       100,    /* 'o' */
+       100,    /* 'p' */
+       100,    /* 'q' */
+       100,    /* 'r' */
+       100,    /* 's' */
+       100,    /* 't' */
+       100,    /* 'u' */
+       100,    /* 'v' */
+       100,    /* 'w' */
+       100,    /* 'x' */
+       100,    /* 'y' */
+       100,    /* 'z' */
+       100,    /* '{' */
+       100,    /* '|' */
+       100,    /* '}' */
+       100,    /* '~' */
+       100,    /* ' ' */
+       },
+       /* height table for font XCX */
+       {
+       263,    /* ' ' */
+       148,    /* '!' */
+       129,    /* '"' */
+       126,    /* '#' */
+       129,    /* '$' */
+       97,     /* '%' */
+       97,     /* '&' */
+       97,     /* ''' */
+       97,     /* '(' */
+       147,    /* ')' */
+       147,    /* '*' */
+       106,    /* '+' */
+       70,     /* ',' */
+       129,    /* '-' */
+       131,    /* '.' */
+       144,    /* '/' */
+       144,    /* '0' */
+       132,    /* '1' */
+       142,    /* '2' */
+       137,    /* '3' */
+       137,    /* '4' */
+       149,    /* '5' */
+       68,     /* '6' */
+       143,    /* '7' */
+       63,     /* '8' */
+       144,    /* '9' */
+       82,     /* ':' */
+       126,    /* ';' */
+       108,    /* '<' */
+       129,    /* '=' */
+       129,    /* '>' */
+       126,    /* '?' */
+       132,    /* '@' */
+       146,    /* 'A' */
+       122,    /* 'B' */
+       126,    /* 'C' */
+       108,    /* 'D' */
+       102,    /* 'E' */
+       134,    /* 'F' */
+       168,    /* 'G' */
+       146,    /* 'H' */
+       168,    /* 'I' */
+       146,    /* 'J' */
+       161,    /* 'K' */
+       139,    /* 'L' */
+       168,    /* 'M' */
+       146,    /* 'N' */
+       172,    /* 'O' */
+       151,    /* 'P' */
+       161,    /* 'Q' */
+       139,    /* 'R' */
+       168,    /* 'S' */
+       144,    /* 'T' */
+       168,    /* 'U' */
+       146,    /* 'V' */
+       168,    /* 'W' */
+       146,    /* 'X' */
+       161,    /* 'Y' */
+       139,    /* 'Z' */
+       168,    /* '[' */
+       146,    /* '\' */
+       168,    /* ']' */
+       144,    /* '^' */
+       168,    /* '_' */
+       144,    /* '`' */
+       161,    /* 'a' */
+       137,    /* 'b' */
+       168,    /* 'c' */
+       144,    /* 'd' */
+       161,    /* 'e' */
+       137,    /* 'f' */
+       170,    /* 'g' */
+       146,    /* 'h' */
+       170,    /* 'i' */
+       146,    /* 'j' */
+       163,    /* 'k' */
+       139,    /* 'l' */
+       170,    /* 'm' */
+       146,    /* 'n' */
+       163,    /* 'o' */
+       139,    /* 'p' */
+       170,    /* 'q' */
+       146,    /* 'r' */
+       170,    /* 's' */
+       146,    /* 't' */
+       170,    /* 'u' */
+       146,    /* 'v' */
+       163,    /* 'w' */
+       139,    /* 'x' */
+       170,    /* 'y' */
+       146,    /* 'z' */
+       161,    /* '{' */
+       172,    /* '|' */
+       168,    /* '}' */
+       144,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XCX */
+       {
+       179,    /* ' ' */
+       125,    /* '!' */
+       115,    /* '"' */
+       112,    /* '#' */
+       115,    /* '$' */
+       83,     /* '%' */
+       83,     /* '&' */
+       83,     /* ''' */
+       83,     /* '(' */
+       118,    /* ')' */
+       118,    /* '*' */
+       92,     /* '+' */
+       36,     /* ',' */
+       115,    /* '-' */
+       78,     /* '.' */
+       130,    /* '/' */
+       130,    /* '0' */
+       118,    /* '1' */
+       128,    /* '2' */
+       123,    /* '3' */
+       123,    /* '4' */
+       135,    /* '5' */
+       15,     /* '6' */
+       130,    /* '7' */
+       14,     /* '8' */
+       130,    /* '9' */
+       68,     /* ':' */
+       112,    /* ';' */
+       92,     /* '<' */
+       115,    /* '=' */
+       115,    /* '>' */
+       112,    /* '?' */
+       118,    /* '@' */
+       120,    /* 'A' */
+       96,     /* 'B' */
+       112,    /* 'C' */
+       92,     /* 'D' */
+       88,     /* 'E' */
+       118,    /* 'F' */
+       154,    /* 'G' */
+       130,    /* 'H' */
+       154,    /* 'I' */
+       130,    /* 'J' */
+       147,    /* 'K' */
+       123,    /* 'L' */
+       154,    /* 'M' */
+       130,    /* 'N' */
+       158,    /* 'O' */
+       135,    /* 'P' */
+       147,    /* 'Q' */
+       123,    /* 'R' */
+       115,    /* 'S' */
+       92,     /* 'T' */
+       154,    /* 'U' */
+       130,    /* 'V' */
+       154,    /* 'W' */
+       130,    /* 'X' */
+       147,    /* 'Y' */
+       123,    /* 'Z' */
+       154,    /* '[' */
+       130,    /* '\' */
+       154,    /* ']' */
+       130,    /* '^' */
+       154,    /* '_' */
+       130,    /* '`' */
+       147,    /* 'a' */
+       123,    /* 'b' */
+       154,    /* 'c' */
+       130,    /* 'd' */
+       147,    /* 'e' */
+       123,    /* 'f' */
+       154,    /* 'g' */
+       130,    /* 'h' */
+       154,    /* 'i' */
+       130,    /* 'j' */
+       147,    /* 'k' */
+       123,    /* 'l' */
+       154,    /* 'm' */
+       130,    /* 'n' */
+       147,    /* 'o' */
+       123,    /* 'p' */
+       154,    /* 'q' */
+       130,    /* 'r' */
+       154,    /* 's' */
+       130,    /* 't' */
+       154,    /* 'u' */
+       130,    /* 'v' */
+       147,    /* 'w' */
+       123,    /* 'x' */
+       154,    /* 'y' */
+       130,    /* 'z' */
+       147,    /* '{' */
+       123,    /* '|' */
+       154,    /* '}' */
+       130,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Courier-BoldItalic",
+       0,
+       YES
+       }, {
+       /* width table for font XHR */
+       {
+       55,     /* ' ' */
+       93,     /* '!' */
+       93,     /* '"' */
+       93,     /* '#' */
+       55,     /* '$' */
+       93,     /* '%' */
+       93,     /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       93,     /* ')' */
+       93,     /* '*' */
+       58,     /* '+' */
+       55,     /* ',' */
+       55,     /* '-' */
+       102,    /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       167,    /* ';' */
+       148,    /* '<' */
+       62,     /* '=' */
+       61,     /* '>' */
+       93,     /* '?' */
+       37,     /* '@' */
+       130,    /* 'A' */
+       102,    /* 'B' */
+       167,    /* 'C' */
+       157,    /* 'D' */
+       46,     /* 'E' */
+       102,    /* 'F' */
+       111,    /* 'G' */
+       93,     /* 'H' */
+       111,    /* 'I' */
+       93,     /* 'J' */
+       111,    /* 'K' */
+       93,     /* 'L' */
+       111,    /* 'M' */
+       93,     /* 'N' */
+       111,    /* 'O' */
+       93,     /* 'P' */
+       111,    /* 'Q' */
+       93,     /* 'R' */
+       120,    /* 'S' */
+       83,     /* 'T' */
+       111,    /* 'U' */
+       93,     /* 'V' */
+       111,    /* 'W' */
+       93,     /* 'X' */
+       111,    /* 'Y' */
+       93,     /* 'Z' */
+       111,    /* '[' */
+       93,     /* '\' */
+       46,     /* ']' */
+       46,     /* '^' */
+       46,     /* '_' */
+       46,     /* '`' */
+       46,     /* 'a' */
+       46,     /* 'b' */
+       46,     /* 'c' */
+       46,     /* 'd' */
+       120,    /* 'e' */
+       93,     /* 'f' */
+       130,    /* 'g' */
+       93,     /* 'h' */
+       130,    /* 'i' */
+       93,     /* 'j' */
+       130,    /* 'k' */
+       93,     /* 'l' */
+       130,    /* 'm' */
+       93,     /* 'n' */
+       130,    /* 'o' */
+       93,     /* 'p' */
+       111,    /* 'q' */
+       83,     /* 'r' */
+       120,    /* 's' */
+       93,     /* 't' */
+       120,    /* 'u' */
+       93,     /* 'v' */
+       120,    /* 'w' */
+       93,     /* 'x' */
+       120,    /* 'y' */
+       93,     /* 'z' */
+       111,    /* '{' */
+       83,     /* '|' */
+       102,    /* '}' */
+       83,     /* '~' */
+       46,     /* ' ' */
+       },
+       /* height table for font XHR */
+       {
+       275,    /* ' ' */
+       152,    /* '!' */
+       152,    /* '"' */
+       146,    /* '#' */
+       146,    /* '$' */
+       101,    /* '%' */
+       101,    /* '&' */
+       101,    /* ''' */
+       101,    /* '(' */
+       175,    /* ')' */
+       175,    /* '*' */
+       106,    /* '+' */
+       67,     /* ',' */
+       146,    /* '-' */
+       151,    /* '.' */
+       152,    /* '/' */
+       152,    /* '0' */
+       146,    /* '1' */
+       149,    /* '2' */
+       146,    /* '3' */
+       146,    /* '4' */
+       152,    /* '5' */
+       61,     /* '6' */
+       152,    /* '7' */
+       60,     /* '8' */
+       152,    /* '9' */
+       79,     /* ':' */
+       149,    /* ';' */
+       122,    /* '<' */
+       152,    /* '=' */
+       152,    /* '>' */
+       149,    /* '?' */
+       149,    /* '@' */
+       156,    /* 'A' */
+       124,    /* 'B' */
+       154,    /* 'C' */
+       122,    /* 'D' */
+       116,    /* 'E' */
+       152,    /* 'F' */
+       184,    /* 'G' */
+       155,    /* 'H' */
+       184,    /* 'I' */
+       155,    /* 'J' */
+       179,    /* 'K' */
+       148,    /* 'L' */
+       184,    /* 'M' */
+       155,    /* 'N' */
+       186,    /* 'O' */
+       155,    /* 'P' */
+       180,    /* 'Q' */
+       150,    /* 'R' */
+       188,    /* 'S' */
+       154,    /* 'T' */
+       184,    /* 'U' */
+       155,    /* 'V' */
+       184,    /* 'W' */
+       155,    /* 'X' */
+       179,    /* 'Y' */
+       148,    /* 'Z' */
+       184,    /* '[' */
+       155,    /* '\' */
+       184,    /* ']' */
+       152,    /* '^' */
+       184,    /* '_' */
+       152,    /* '`' */
+       179,    /* 'a' */
+       146,    /* 'b' */
+       184,    /* 'c' */
+       152,    /* 'd' */
+       180,    /* 'e' */
+       147,    /* 'f' */
+       187,    /* 'g' */
+       155,    /* 'h' */
+       187,    /* 'i' */
+       155,    /* 'j' */
+       182,    /* 'k' */
+       148,    /* 'l' */
+       187,    /* 'm' */
+       155,    /* 'n' */
+       183,    /* 'o' */
+       150,    /* 'p' */
+       187,    /* 'q' */
+       155,    /* 'r' */
+       187,    /* 's' */
+       155,    /* 't' */
+       187,    /* 'u' */
+       155,    /* 'v' */
+       182,    /* 'w' */
+       148,    /* 'x' */
+       187,    /* 'y' */
+       155,    /* 'z' */
+       179,    /* '{' */
+       181,    /* '|' */
+       184,    /* '}' */
+       152,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XHR */
+       {
+       196,    /* ' ' */
+       119,    /* '!' */
+       135,    /* '"' */
+       132,    /* '#' */
+       132,    /* '$' */
+       87,     /* '%' */
+       87,     /* '&' */
+       87,     /* ''' */
+       87,     /* '(' */
+       132,    /* ')' */
+       132,    /* '*' */
+       92,     /* '+' */
+       32,     /* ',' */
+       132,    /* '-' */
+       102,    /* '.' */
+       138,    /* '/' */
+       138,    /* '0' */
+       132,    /* '1' */
+       135,    /* '2' */
+       132,    /* '3' */
+       132,    /* '4' */
+       138,    /* '5' */
+       12,     /* '6' */
+       138,    /* '7' */
+       14,     /* '8' */
+       138,    /* '9' */
+       65,     /* ':' */
+       135,    /* ';' */
+       105,    /* '<' */
+       138,    /* '=' */
+       138,    /* '>' */
+       135,    /* '?' */
+       135,    /* '@' */
+       140,    /* 'A' */
+       105,    /* 'B' */
+       138,    /* 'C' */
+       105,    /* 'D' */
+       102,    /* 'E' */
+       135,    /* 'F' */
+       170,    /* 'G' */
+       138,    /* 'H' */
+       171,    /* 'I' */
+       138,    /* 'J' */
+       165,    /* 'K' */
+       132,    /* 'L' */
+       170,    /* 'M' */
+       138,    /* 'N' */
+       172,    /* 'O' */
+       138,    /* 'P' */
+       167,    /* 'Q' */
+       133,    /* 'R' */
+       138,    /* 'S' */
+       105,    /* 'T' */
+       170,    /* 'U' */
+       138,    /* 'V' */
+       171,    /* 'W' */
+       138,    /* 'X' */
+       165,    /* 'Y' */
+       132,    /* 'Z' */
+       170,    /* '[' */
+       138,    /* '\' */
+       170,    /* ']' */
+       138,    /* '^' */
+       171,    /* '_' */
+       138,    /* '`' */
+       165,    /* 'a' */
+       132,    /* 'b' */
+       170,    /* 'c' */
+       138,    /* 'd' */
+       167,    /* 'e' */
+       133,    /* 'f' */
+       170,    /* 'g' */
+       138,    /* 'h' */
+       171,    /* 'i' */
+       138,    /* 'j' */
+       165,    /* 'k' */
+       132,    /* 'l' */
+       170,    /* 'm' */
+       138,    /* 'n' */
+       167,    /* 'o' */
+       133,    /* 'p' */
+       171,    /* 'q' */
+       138,    /* 'r' */
+       170,    /* 's' */
+       138,    /* 't' */
+       171,    /* 'u' */
+       138,    /* 'v' */
+       165,    /* 'w' */
+       132,    /* 'x' */
+       170,    /* 'y' */
+       138,    /* 'z' */
+       165,    /* '{' */
+       132,    /* '|' */
+       171,    /* '}' */
+       138,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Helvetica",
+       0,
+       NO
+       }, {
+       /* width table for font XHI */
+       {
+       55,     /* ' ' */
+       93,     /* '!' */
+       93,     /* '"' */
+       93,     /* '#' */
+       55,     /* '$' */
+       93,     /* '%' */
+       93,     /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       93,     /* ')' */
+       93,     /* '*' */
+       58,     /* '+' */
+       55,     /* ',' */
+       55,     /* '-' */
+       102,    /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       167,    /* ';' */
+       148,    /* '<' */
+       62,     /* '=' */
+       61,     /* '>' */
+       93,     /* '?' */
+       37,     /* '@' */
+       130,    /* 'A' */
+       102,    /* 'B' */
+       167,    /* 'C' */
+       157,    /* 'D' */
+       46,     /* 'E' */
+       102,    /* 'F' */
+       111,    /* 'G' */
+       93,     /* 'H' */
+       111,    /* 'I' */
+       93,     /* 'J' */
+       111,    /* 'K' */
+       93,     /* 'L' */
+       111,    /* 'M' */
+       93,     /* 'N' */
+       111,    /* 'O' */
+       93,     /* 'P' */
+       111,    /* 'Q' */
+       93,     /* 'R' */
+       120,    /* 'S' */
+       83,     /* 'T' */
+       111,    /* 'U' */
+       93,     /* 'V' */
+       111,    /* 'W' */
+       93,     /* 'X' */
+       111,    /* 'Y' */
+       93,     /* 'Z' */
+       111,    /* '[' */
+       93,     /* '\' */
+       46,     /* ']' */
+       46,     /* '^' */
+       46,     /* '_' */
+       46,     /* '`' */
+       46,     /* 'a' */
+       46,     /* 'b' */
+       46,     /* 'c' */
+       46,     /* 'd' */
+       120,    /* 'e' */
+       93,     /* 'f' */
+       130,    /* 'g' */
+       93,     /* 'h' */
+       130,    /* 'i' */
+       93,     /* 'j' */
+       130,    /* 'k' */
+       93,     /* 'l' */
+       130,    /* 'm' */
+       93,     /* 'n' */
+       130,    /* 'o' */
+       93,     /* 'p' */
+       111,    /* 'q' */
+       83,     /* 'r' */
+       120,    /* 's' */
+       93,     /* 't' */
+       120,    /* 'u' */
+       93,     /* 'v' */
+       120,    /* 'w' */
+       93,     /* 'x' */
+       120,    /* 'y' */
+       93,     /* 'z' */
+       111,    /* '{' */
+       83,     /* '|' */
+       102,    /* '}' */
+       83,     /* '~' */
+       46,     /* ' ' */
+       },
+       /* height table for font XHI */
+       {
+       275,    /* ' ' */
+       152,    /* '!' */
+       152,    /* '"' */
+       146,    /* '#' */
+       146,    /* '$' */
+       101,    /* '%' */
+       101,    /* '&' */
+       101,    /* ''' */
+       101,    /* '(' */
+       175,    /* ')' */
+       175,    /* '*' */
+       106,    /* '+' */
+       67,     /* ',' */
+       146,    /* '-' */
+       151,    /* '.' */
+       152,    /* '/' */
+       152,    /* '0' */
+       146,    /* '1' */
+       149,    /* '2' */
+       146,    /* '3' */
+       146,    /* '4' */
+       152,    /* '5' */
+       63,     /* '6' */
+       152,    /* '7' */
+       60,     /* '8' */
+       152,    /* '9' */
+       79,     /* ':' */
+       149,    /* ';' */
+       122,    /* '<' */
+       152,    /* '=' */
+       152,    /* '>' */
+       149,    /* '?' */
+       149,    /* '@' */
+       156,    /* 'A' */
+       124,    /* 'B' */
+       155,    /* 'C' */
+       122,    /* 'D' */
+       116,    /* 'E' */
+       152,    /* 'F' */
+       184,    /* 'G' */
+       155,    /* 'H' */
+       184,    /* 'I' */
+       155,    /* 'J' */
+       179,    /* 'K' */
+       149,    /* 'L' */
+       184,    /* 'M' */
+       155,    /* 'N' */
+       186,    /* 'O' */
+       155,    /* 'P' */
+       182,    /* 'Q' */
+       152,    /* 'R' */
+       188,    /* 'S' */
+       154,    /* 'T' */
+       184,    /* 'U' */
+       155,    /* 'V' */
+       184,    /* 'W' */
+       155,    /* 'X' */
+       179,    /* 'Y' */
+       148,    /* 'Z' */
+       184,    /* '[' */
+       155,    /* '\' */
+       184,    /* ']' */
+       152,    /* '^' */
+       184,    /* '_' */
+       152,    /* '`' */
+       178,    /* 'a' */
+       144,    /* 'b' */
+       184,    /* 'c' */
+       152,    /* 'd' */
+       182,    /* 'e' */
+       149,    /* 'f' */
+       187,    /* 'g' */
+       155,    /* 'h' */
+       187,    /* 'i' */
+       155,    /* 'j' */
+       182,    /* 'k' */
+       148,    /* 'l' */
+       187,    /* 'm' */
+       155,    /* 'n' */
+       185,    /* 'o' */
+       152,    /* 'p' */
+       187,    /* 'q' */
+       155,    /* 'r' */
+       187,    /* 's' */
+       155,    /* 't' */
+       187,    /* 'u' */
+       155,    /* 'v' */
+       182,    /* 'w' */
+       148,    /* 'x' */
+       187,    /* 'y' */
+       155,    /* 'z' */
+       179,    /* '{' */
+       181,    /* '|' */
+       184,    /* '}' */
+       152,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XHI */
+       {
+       196,    /* ' ' */
+       119,    /* '!' */
+       135,    /* '"' */
+       132,    /* '#' */
+       132,    /* '$' */
+       87,     /* '%' */
+       87,     /* '&' */
+       87,     /* ''' */
+       87,     /* '(' */
+       132,    /* ')' */
+       132,    /* '*' */
+       92,     /* '+' */
+       32,     /* ',' */
+       132,    /* '-' */
+       102,    /* '.' */
+       138,    /* '/' */
+       138,    /* '0' */
+       132,    /* '1' */
+       135,    /* '2' */
+       132,    /* '3' */
+       132,    /* '4' */
+       138,    /* '5' */
+       14,     /* '6' */
+       138,    /* '7' */
+       14,     /* '8' */
+       138,    /* '9' */
+       65,     /* ':' */
+       135,    /* ';' */
+       105,    /* '<' */
+       138,    /* '=' */
+       138,    /* '>' */
+       135,    /* '?' */
+       135,    /* '@' */
+       138,    /* 'A' */
+       105,    /* 'B' */
+       138,    /* 'C' */
+       105,    /* 'D' */
+       102,    /* 'E' */
+       135,    /* 'F' */
+       170,    /* 'G' */
+       138,    /* 'H' */
+       171,    /* 'I' */
+       138,    /* 'J' */
+       165,    /* 'K' */
+       132,    /* 'L' */
+       170,    /* 'M' */
+       138,    /* 'N' */
+       172,    /* 'O' */
+       138,    /* 'P' */
+       168,    /* 'Q' */
+       135,    /* 'R' */
+       138,    /* 'S' */
+       105,    /* 'T' */
+       170,    /* 'U' */
+       138,    /* 'V' */
+       171,    /* 'W' */
+       138,    /* 'X' */
+       165,    /* 'Y' */
+       132,    /* 'Z' */
+       170,    /* '[' */
+       138,    /* '\' */
+       170,    /* ']' */
+       138,    /* '^' */
+       171,    /* '_' */
+       138,    /* '`' */
+       164,    /* 'a' */
+       131,    /* 'b' */
+       170,    /* 'c' */
+       138,    /* 'd' */
+       168,    /* 'e' */
+       135,    /* 'f' */
+       170,    /* 'g' */
+       138,    /* 'h' */
+       171,    /* 'i' */
+       138,    /* 'j' */
+       165,    /* 'k' */
+       132,    /* 'l' */
+       170,    /* 'm' */
+       138,    /* 'n' */
+       168,    /* 'o' */
+       135,    /* 'p' */
+       170,    /* 'q' */
+       138,    /* 'r' */
+       170,    /* 's' */
+       138,    /* 't' */
+       171,    /* 'u' */
+       138,    /* 'v' */
+       165,    /* 'w' */
+       132,    /* 'x' */
+       170,    /* 'y' */
+       138,    /* 'z' */
+       165,    /* '{' */
+       132,    /* '|' */
+       170,    /* '}' */
+       138,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Helvetica-Oblique",
+       0,
+       YES
+       }, {
+       /* width table for font XHB */
+       {
+       55,     /* ' ' */
+       93,     /* '!' */
+       93,     /* '"' */
+       93,     /* '#' */
+       83,     /* '$' */
+       93,     /* '%' */
+       93,     /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       93,     /* ')' */
+       93,     /* '*' */
+       58,     /* '+' */
+       83,     /* ',' */
+       83,     /* '-' */
+       102,    /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       167,    /* ';' */
+       148,    /* '<' */
+       62,     /* '=' */
+       61,     /* '>' */
+       102,    /* '?' */
+       46,     /* '@' */
+       130,    /* 'A' */
+       102,    /* 'B' */
+       167,    /* 'C' */
+       157,    /* 'D' */
+       46,     /* 'E' */
+       102,    /* 'F' */
+       120,    /* 'G' */
+       93,     /* 'H' */
+       120,    /* 'I' */
+       93,     /* 'J' */
+       120,    /* 'K' */
+       93,     /* 'L' */
+       120,    /* 'M' */
+       93,     /* 'N' */
+       120,    /* 'O' */
+       93,     /* 'P' */
+       120,    /* 'Q' */
+       93,     /* 'R' */
+       120,    /* 'S' */
+       93,     /* 'T' */
+       111,    /* 'U' */
+       93,     /* 'V' */
+       111,    /* 'W' */
+       93,     /* 'X' */
+       111,    /* 'Y' */
+       93,     /* 'Z' */
+       111,    /* '[' */
+       93,     /* '\' */
+       46,     /* ']' */
+       46,     /* '^' */
+       46,     /* '_' */
+       46,     /* '`' */
+       46,     /* 'a' */
+       46,     /* 'b' */
+       46,     /* 'c' */
+       46,     /* 'd' */
+       120,    /* 'e' */
+       102,    /* 'f' */
+       130,    /* 'g' */
+       102,    /* 'h' */
+       130,    /* 'i' */
+       102,    /* 'j' */
+       130,    /* 'k' */
+       102,    /* 'l' */
+       130,    /* 'm' */
+       102,    /* 'n' */
+       130,    /* 'o' */
+       102,    /* 'p' */
+       111,    /* 'q' */
+       93,     /* 'r' */
+       120,    /* 's' */
+       102,    /* 't' */
+       120,    /* 'u' */
+       102,    /* 'v' */
+       120,    /* 'w' */
+       102,    /* 'x' */
+       120,    /* 'y' */
+       102,    /* 'z' */
+       111,    /* '{' */
+       93,     /* '|' */
+       102,    /* '}' */
+       83,     /* '~' */
+       46,     /* ' ' */
+       },
+       /* height table for font XHB */
+       {
+       275,    /* ' ' */
+       154,    /* '!' */
+       152,    /* '"' */
+       145,    /* '#' */
+       149,    /* '$' */
+       108,    /* '%' */
+       108,    /* '&' */
+       108,    /* ''' */
+       108,    /* '(' */
+       178,    /* ')' */
+       178,    /* '*' */
+       99,     /* '+' */
+       71,     /* ',' */
+       149,    /* '-' */
+       154,    /* '.' */
+       154,    /* '/' */
+       154,    /* '0' */
+       149,    /* '1' */
+       152,    /* '2' */
+       152,    /* '3' */
+       152,    /* '4' */
+       156,    /* '5' */
+       67,     /* '6' */
+       154,    /* '7' */
+       67,     /* '8' */
+       154,    /* '9' */
+       79,     /* ':' */
+       149,    /* ';' */
+       128,    /* '<' */
+       149,    /* '=' */
+       149,    /* '>' */
+       149,    /* '?' */
+       149,    /* '@' */
+       159,    /* 'A' */
+       129,    /* 'B' */
+       155,    /* 'C' */
+       125,    /* 'D' */
+       119,    /* 'E' */
+       151,    /* 'F' */
+       184,    /* 'G' */
+       157,    /* 'H' */
+       184,    /* 'I' */
+       157,    /* 'J' */
+       182,    /* 'K' */
+       155,    /* 'L' */
+       184,    /* 'M' */
+       157,    /* 'N' */
+       186,    /* 'O' */
+       158,    /* 'P' */
+       182,    /* 'Q' */
+       155,    /* 'R' */
+       191,    /* 'S' */
+       161,    /* 'T' */
+       184,    /* 'U' */
+       157,    /* 'V' */
+       184,    /* 'W' */
+       157,    /* 'X' */
+       182,    /* 'Y' */
+       155,    /* 'Z' */
+       184,    /* '[' */
+       157,    /* '\' */
+       184,    /* ']' */
+       154,    /* '^' */
+       184,    /* '_' */
+       154,    /* '`' */
+       182,    /* 'a' */
+       152,    /* 'b' */
+       184,    /* 'c' */
+       154,    /* 'd' */
+       182,    /* 'e' */
+       152,    /* 'f' */
+       186,    /* 'g' */
+       157,    /* 'h' */
+       186,    /* 'i' */
+       157,    /* 'j' */
+       185,    /* 'k' */
+       155,    /* 'l' */
+       186,    /* 'm' */
+       157,    /* 'n' */
+       185,    /* 'o' */
+       155,    /* 'p' */
+       186,    /* 'q' */
+       157,    /* 'r' */
+       186,    /* 's' */
+       157,    /* 't' */
+       186,    /* 'u' */
+       157,    /* 'v' */
+       185,    /* 'w' */
+       155,    /* 'x' */
+       186,    /* 'y' */
+       157,    /* 'z' */
+       182,    /* '{' */
+       188,    /* '|' */
+       184,    /* '}' */
+       154,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XHB */
+       {
+       199,    /* ' ' */
+       120,    /* '!' */
+       135,    /* '"' */
+       131,    /* '#' */
+       135,    /* '$' */
+       94,     /* '%' */
+       94,     /* '&' */
+       94,     /* ''' */
+       94,     /* '(' */
+       132,    /* ')' */
+       132,    /* '*' */
+       85,     /* '+' */
+       35,     /* ',' */
+       135,    /* '-' */
+       105,    /* '.' */
+       140,    /* '/' */
+       140,    /* '0' */
+       135,    /* '1' */
+       138,    /* '2' */
+       138,    /* '3' */
+       138,    /* '4' */
+       142,    /* '5' */
+       14,     /* '6' */
+       140,    /* '7' */
+       14,     /* '8' */
+       140,    /* '9' */
+       65,     /* ':' */
+       135,    /* ';' */
+       108,    /* '<' */
+       135,    /* '=' */
+       135,    /* '>' */
+       135,    /* '?' */
+       135,    /* '@' */
+       139,    /* 'A' */
+       108,    /* 'B' */
+       138,    /* 'C' */
+       108,    /* 'D' */
+       105,    /* 'E' */
+       135,    /* 'F' */
+       170,    /* 'G' */
+       140,    /* 'H' */
+       170,    /* 'I' */
+       140,    /* 'J' */
+       168,    /* 'K' */
+       138,    /* 'L' */
+       170,    /* 'M' */
+       140,    /* 'N' */
+       172,    /* 'O' */
+       142,    /* 'P' */
+       169,    /* 'Q' */
+       138,    /* 'R' */
+       138,    /* 'S' */
+       108,    /* 'T' */
+       170,    /* 'U' */
+       140,    /* 'V' */
+       170,    /* 'W' */
+       140,    /* 'X' */
+       168,    /* 'Y' */
+       138,    /* 'Z' */
+       170,    /* '[' */
+       140,    /* '\' */
+       170,    /* ']' */
+       140,    /* '^' */
+       170,    /* '_' */
+       140,    /* '`' */
+       168,    /* 'a' */
+       138,    /* 'b' */
+       170,    /* 'c' */
+       140,    /* 'd' */
+       169,    /* 'e' */
+       138,    /* 'f' */
+       170,    /* 'g' */
+       140,    /* 'h' */
+       170,    /* 'i' */
+       140,    /* 'j' */
+       168,    /* 'k' */
+       138,    /* 'l' */
+       170,    /* 'm' */
+       140,    /* 'n' */
+       169,    /* 'o' */
+       138,    /* 'p' */
+       170,    /* 'q' */
+       140,    /* 'r' */
+       170,    /* 's' */
+       140,    /* 't' */
+       170,    /* 'u' */
+       140,    /* 'v' */
+       168,    /* 'w' */
+       138,    /* 'x' */
+       170,    /* 'y' */
+       140,    /* 'z' */
+       168,    /* '{' */
+       138,    /* '|' */
+       170,    /* '}' */
+       140,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Helvetica-Bold",
+       0,
+       NO
+       }, {
+       /* width table for font XHX */
+       {
+       55,     /* ' ' */
+       93,     /* '!' */
+       93,     /* '"' */
+       93,     /* '#' */
+       83,     /* '$' */
+       93,     /* '%' */
+       93,     /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       93,     /* ')' */
+       93,     /* '*' */
+       58,     /* '+' */
+       83,     /* ',' */
+       83,     /* '-' */
+       102,    /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       167,    /* ';' */
+       148,    /* '<' */
+       62,     /* '=' */
+       61,     /* '>' */
+       102,    /* '?' */
+       46,     /* '@' */
+       130,    /* 'A' */
+       102,    /* 'B' */
+       167,    /* 'C' */
+       157,    /* 'D' */
+       46,     /* 'E' */
+       102,    /* 'F' */
+       120,    /* 'G' */
+       93,     /* 'H' */
+       120,    /* 'I' */
+       93,     /* 'J' */
+       120,    /* 'K' */
+       93,     /* 'L' */
+       120,    /* 'M' */
+       93,     /* 'N' */
+       120,    /* 'O' */
+       93,     /* 'P' */
+       120,    /* 'Q' */
+       93,     /* 'R' */
+       120,    /* 'S' */
+       93,     /* 'T' */
+       111,    /* 'U' */
+       93,     /* 'V' */
+       111,    /* 'W' */
+       93,     /* 'X' */
+       111,    /* 'Y' */
+       93,     /* 'Z' */
+       111,    /* '[' */
+       93,     /* '\' */
+       46,     /* ']' */
+       46,     /* '^' */
+       46,     /* '_' */
+       46,     /* '`' */
+       46,     /* 'a' */
+       46,     /* 'b' */
+       46,     /* 'c' */
+       46,     /* 'd' */
+       120,    /* 'e' */
+       102,    /* 'f' */
+       130,    /* 'g' */
+       102,    /* 'h' */
+       130,    /* 'i' */
+       102,    /* 'j' */
+       130,    /* 'k' */
+       102,    /* 'l' */
+       130,    /* 'm' */
+       102,    /* 'n' */
+       130,    /* 'o' */
+       102,    /* 'p' */
+       111,    /* 'q' */
+       93,     /* 'r' */
+       120,    /* 's' */
+       102,    /* 't' */
+       120,    /* 'u' */
+       102,    /* 'v' */
+       120,    /* 'w' */
+       102,    /* 'x' */
+       120,    /* 'y' */
+       102,    /* 'z' */
+       111,    /* '{' */
+       93,     /* '|' */
+       102,    /* '}' */
+       83,     /* '~' */
+       46,     /* ' ' */
+       },
+       /* height table for font XHX */
+       {
+       275,    /* ' ' */
+       154,    /* '!' */
+       152,    /* '"' */
+       145,    /* '#' */
+       149,    /* '$' */
+       108,    /* '%' */
+       108,    /* '&' */
+       108,    /* ''' */
+       108,    /* '(' */
+       178,    /* ')' */
+       178,    /* '*' */
+       99,     /* '+' */
+       71,     /* ',' */
+       149,    /* '-' */
+       151,    /* '.' */
+       156,    /* '/' */
+       154,    /* '0' */
+       149,    /* '1' */
+       153,    /* '2' */
+       152,    /* '3' */
+       152,    /* '4' */
+       159,    /* '5' */
+       67,     /* '6' */
+       154,    /* '7' */
+       67,     /* '8' */
+       154,    /* '9' */
+       82,     /* ':' */
+       149,    /* ';' */
+       125,    /* '<' */
+       149,    /* '=' */
+       149,    /* '>' */
+       149,    /* '?' */
+       149,    /* '@' */
+       159,    /* 'A' */
+       129,    /* 'B' */
+       155,    /* 'C' */
+       125,    /* 'D' */
+       119,    /* 'E' */
+       152,    /* 'F' */
+       184,    /* 'G' */
+       157,    /* 'H' */
+       184,    /* 'I' */
+       157,    /* 'J' */
+       182,    /* 'K' */
+       155,    /* 'L' */
+       186,    /* 'M' */
+       158,    /* 'N' */
+       189,    /* 'O' */
+       162,    /* 'P' */
+       182,    /* 'Q' */
+       155,    /* 'R' */
+       191,    /* 'S' */
+       161,    /* 'T' */
+       184,    /* 'U' */
+       157,    /* 'V' */
+       184,    /* 'W' */
+       157,    /* 'X' */
+       182,    /* 'Y' */
+       155,    /* 'Z' */
+       186,    /* '[' */
+       158,    /* '\' */
+       184,    /* ']' */
+       154,    /* '^' */
+       184,    /* '_' */
+       154,    /* '`' */
+       182,    /* 'a' */
+       152,    /* 'b' */
+       186,    /* 'c' */
+       156,    /* 'd' */
+       182,    /* 'e' */
+       152,    /* 'f' */
+       186,    /* 'g' */
+       157,    /* 'h' */
+       186,    /* 'i' */
+       157,    /* 'j' */
+       185,    /* 'k' */
+       155,    /* 'l' */
+       188,    /* 'm' */
+       158,    /* 'n' */
+       184,    /* 'o' */
+       155,    /* 'p' */
+       187,    /* 'q' */
+       157,    /* 'r' */
+       186,    /* 's' */
+       157,    /* 't' */
+       186,    /* 'u' */
+       157,    /* 'v' */
+       185,    /* 'w' */
+       155,    /* 'x' */
+       188,    /* 'y' */
+       158,    /* 'z' */
+       182,    /* '{' */
+       191,    /* '|' */
+       184,    /* '}' */
+       154,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XHX */
+       {
+       199,    /* ' ' */
+       120,    /* '!' */
+       135,    /* '"' */
+       131,    /* '#' */
+       135,    /* '$' */
+       94,     /* '%' */
+       94,     /* '&' */
+       94,     /* ''' */
+       94,     /* '(' */
+       132,    /* ')' */
+       132,    /* '*' */
+       85,     /* '+' */
+       35,     /* ',' */
+       135,    /* '-' */
+       105,    /* '.' */
+       142,    /* '/' */
+       140,    /* '0' */
+       135,    /* '1' */
+       140,    /* '2' */
+       138,    /* '3' */
+       138,    /* '4' */
+       145,    /* '5' */
+       14,     /* '6' */
+       140,    /* '7' */
+       14,     /* '8' */
+       140,    /* '9' */
+       68,     /* ':' */
+       135,    /* ';' */
+       108,    /* '<' */
+       135,    /* '=' */
+       135,    /* '>' */
+       135,    /* '?' */
+       135,    /* '@' */
+       139,    /* 'A' */
+       108,    /* 'B' */
+       138,    /* 'C' */
+       108,    /* 'D' */
+       105,    /* 'E' */
+       135,    /* 'F' */
+       170,    /* 'G' */
+       140,    /* 'H' */
+       170,    /* 'I' */
+       140,    /* 'J' */
+       168,    /* 'K' */
+       138,    /* 'L' */
+       172,    /* 'M' */
+       142,    /* 'N' */
+       175,    /* 'O' */
+       145,    /* 'P' */
+       168,    /* 'Q' */
+       138,    /* 'R' */
+       138,    /* 'S' */
+       108,    /* 'T' */
+       170,    /* 'U' */
+       140,    /* 'V' */
+       170,    /* 'W' */
+       140,    /* 'X' */
+       168,    /* 'Y' */
+       138,    /* 'Z' */
+       172,    /* '[' */
+       142,    /* '\' */
+       170,    /* ']' */
+       140,    /* '^' */
+       170,    /* '_' */
+       140,    /* '`' */
+       168,    /* 'a' */
+       138,    /* 'b' */
+       172,    /* 'c' */
+       142,    /* 'd' */
+       168,    /* 'e' */
+       138,    /* 'f' */
+       170,    /* 'g' */
+       140,    /* 'h' */
+       170,    /* 'i' */
+       140,    /* 'j' */
+       168,    /* 'k' */
+       138,    /* 'l' */
+       172,    /* 'm' */
+       142,    /* 'n' */
+       168,    /* 'o' */
+       138,    /* 'p' */
+       170,    /* 'q' */
+       140,    /* 'r' */
+       170,    /* 's' */
+       140,    /* 't' */
+       170,    /* 'u' */
+       140,    /* 'v' */
+       168,    /* 'w' */
+       138,    /* 'x' */
+       172,    /* 'y' */
+       142,    /* 'z' */
+       168,    /* '{' */
+       138,    /* '|' */
+       170,    /* '}' */
+       140,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Helvetica-BoldOblique",
+       0,
+       YES
+       }, {
+       /* width table for font XBR */
+       {
+       50,     /* ' ' */
+       103,    /* '!' */
+       103,    /* '"' */
+       103,    /* '#' */
+       67,     /* '$' */
+       60,     /* '%' */
+       60,     /* '&' */
+       40,     /* ''' */
+       40,     /* '(' */
+       90,     /* ')' */
+       90,     /* '*' */
+       77,     /* '+' */
+       67,     /* ',' */
+       67,     /* '-' */
+       90,     /* '.' */
+       57,     /* '/' */
+       57,     /* '0' */
+       73,     /* '1' */
+       77,     /* '2' */
+       43,     /* '3' */
+       70,     /* '4' */
+       53,     /* '5' */
+       53,     /* '6' */
+       63,     /* '7' */
+       53,     /* '8' */
+       70,     /* '9' */
+       167,    /* ':' */
+       210,    /* ';' */
+       143,    /* '<' */
+       70,     /* '=' */
+       70,     /* '>' */
+       100,    /* '?' */
+       53,     /* '@' */
+       133,    /* 'A' */
+       93,     /* 'B' */
+       207,    /* 'C' */
+       150,    /* 'D' */
+       50,     /* 'E' */
+       110,    /* 'F' */
+       113,    /* 'G' */
+       97,     /* 'H' */
+       113,    /* 'I' */
+       97,     /* 'J' */
+       113,    /* 'K' */
+       97,     /* 'L' */
+       113,    /* 'M' */
+       97,     /* 'N' */
+       113,    /* 'O' */
+       97,     /* 'P' */
+       113,    /* 'Q' */
+       97,     /* 'R' */
+       123,    /* 'S' */
+       87,     /* 'T' */
+       120,    /* 'U' */
+       87,     /* 'V' */
+       120,    /* 'W' */
+       87,     /* 'X' */
+       120,    /* 'Y' */
+       87,     /* 'Z' */
+       120,    /* '[' */
+       87,     /* '\' */
+       57,     /* ']' */
+       50,     /* '^' */
+       57,     /* '_' */
+       50,     /* '`' */
+       57,     /* 'a' */
+       50,     /* 'b' */
+       57,     /* 'c' */
+       50,     /* 'd' */
+       123,    /* 'e' */
+       110,    /* 'f' */
+       133,    /* 'g' */
+       93,     /* 'h' */
+       133,    /* 'i' */
+       93,     /* 'j' */
+       133,    /* 'k' */
+       93,     /* 'l' */
+       133,    /* 'm' */
+       93,     /* 'n' */
+       133,    /* 'o' */
+       93,     /* 'p' */
+       110,    /* 'q' */
+       87,     /* 'r' */
+       130,    /* 's' */
+       113,    /* 't' */
+       130,    /* 'u' */
+       113,    /* 'v' */
+       130,    /* 'w' */
+       113,    /* 'x' */
+       130,    /* 'y' */
+       113,    /* 'z' */
+       107,    /* '{' */
+       90,     /* '|' */
+       107,    /* '}' */
+       80,     /* '~' */
+       53,     /* ' ' */
+       },
+       /* height table for font XBR */
+       {
+       273,    /* ' ' */
+       136,    /* '!' */
+       148,    /* '"' */
+       142,    /* '#' */
+       143,    /* '$' */
+       101,    /* '%' */
+       101,    /* '&' */
+       101,    /* ''' */
+       101,    /* '(' */
+       172,    /* ')' */
+       172,    /* '*' */
+       121,    /* '+' */
+       64,     /* ',' */
+       146,    /* '-' */
+       148,    /* '.' */
+       141,    /* '/' */
+       141,    /* '0' */
+       132,    /* '1' */
+       141,    /* '2' */
+       142,    /* '3' */
+       142,    /* '4' */
+       149,    /* '5' */
+       60,     /* '6' */
+       146,    /* '7' */
+       53,     /* '8' */
+       141,    /* '9' */
+       76,     /* ':' */
+       142,    /* ';' */
+       114,    /* '<' */
+       142,    /* '=' */
+       142,    /* '>' */
+       142,    /* '?' */
+       147,    /* '@' */
+       159,    /* 'A' */
+       125,    /* 'B' */
+       148,    /* 'C' */
+       114,    /* 'D' */
+       109,    /* 'E' */
+       164,    /* 'F' */
+       173,    /* 'G' */
+       143,    /* 'H' */
+       173,    /* 'I' */
+       143,    /* 'J' */
+       173,    /* 'K' */
+       144,    /* 'L' */
+       173,    /* 'M' */
+       143,    /* 'N' */
+       181,    /* 'O' */
+       151,    /* 'P' */
+       170,    /* 'Q' */
+       141,    /* 'R' */
+       178,    /* 'S' */
+       144,    /* 'T' */
+       173,    /* 'U' */
+       143,    /* 'V' */
+       173,    /* 'W' */
+       143,    /* 'X' */
+       173,    /* 'Y' */
+       144,    /* 'Z' */
+       173,    /* '[' */
+       143,    /* '\' */
+       173,    /* ']' */
+       141,    /* '^' */
+       173,    /* '_' */
+       141,    /* '`' */
+       172,    /* 'a' */
+       142,    /* 'b' */
+       173,    /* 'c' */
+       141,    /* 'd' */
+       170,    /* 'e' */
+       139,    /* 'f' */
+       175,    /* 'g' */
+       143,    /* 'h' */
+       175,    /* 'i' */
+       143,    /* 'j' */
+       175,    /* 'k' */
+       144,    /* 'l' */
+       175,    /* 'm' */
+       143,    /* 'n' */
+       172,    /* 'o' */
+       141,    /* 'p' */
+       175,    /* 'q' */
+       143,    /* 'r' */
+       175,    /* 's' */
+       143,    /* 't' */
+       175,    /* 'u' */
+       143,    /* 'v' */
+       175,    /* 'w' */
+       144,    /* 'x' */
+       175,    /* 'y' */
+       143,    /* 'z' */
+       173,    /* '{' */
+       181,    /* '|' */
+       173,    /* '}' */
+       141,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XBR */
+       {
+       193,    /* ' ' */
+       123,    /* '!' */
+       132,    /* '"' */
+       128,    /* '#' */
+       130,    /* '$' */
+       87,     /* '%' */
+       87,     /* '&' */
+       87,     /* ''' */
+       87,     /* '(' */
+       132,    /* ')' */
+       132,    /* '*' */
+       107,    /* '+' */
+       33,     /* ',' */
+       132,    /* '-' */
+       98,     /* '.' */
+       127,    /* '/' */
+       127,    /* '0' */
+       118,    /* '1' */
+       128,    /* '2' */
+       128,    /* '3' */
+       128,    /* '4' */
+       135,    /* '5' */
+       14,     /* '6' */
+       132,    /* '7' */
+       14,     /* '8' */
+       127,    /* '9' */
+       62,     /* ':' */
+       128,    /* ';' */
+       98,     /* '<' */
+       128,    /* '=' */
+       128,    /* '>' */
+       128,    /* '?' */
+       133,    /* '@' */
+       136,    /* 'A' */
+       104,    /* 'B' */
+       132,    /* 'C' */
+       98,     /* 'D' */
+       95,     /* 'E' */
+       132,    /* 'F' */
+       159,    /* 'G' */
+       127,    /* 'H' */
+       159,    /* 'I' */
+       127,    /* 'J' */
+       159,    /* 'K' */
+       128,    /* 'L' */
+       159,    /* 'M' */
+       127,    /* 'N' */
+       168,    /* 'O' */
+       135,    /* 'P' */
+       156,    /* 'Q' */
+       125,    /* 'R' */
+       132,    /* 'S' */
+       98,     /* 'T' */
+       159,    /* 'U' */
+       127,    /* 'V' */
+       159,    /* 'W' */
+       127,    /* 'X' */
+       159,    /* 'Y' */
+       128,    /* 'Z' */
+       159,    /* '[' */
+       127,    /* '\' */
+       159,    /* ']' */
+       127,    /* '^' */
+       159,    /* '_' */
+       127,    /* '`' */
+       158,    /* 'a' */
+       128,    /* 'b' */
+       159,    /* 'c' */
+       127,    /* 'd' */
+       156,    /* 'e' */
+       125,    /* 'f' */
+       159,    /* 'g' */
+       127,    /* 'h' */
+       159,    /* 'i' */
+       127,    /* 'j' */
+       159,    /* 'k' */
+       128,    /* 'l' */
+       159,    /* 'm' */
+       127,    /* 'n' */
+       156,    /* 'o' */
+       125,    /* 'p' */
+       159,    /* 'q' */
+       127,    /* 'r' */
+       159,    /* 's' */
+       127,    /* 't' */
+       159,    /* 'u' */
+       127,    /* 'v' */
+       159,    /* 'w' */
+       128,    /* 'x' */
+       159,    /* 'y' */
+       127,    /* 'z' */
+       159,    /* '{' */
+       128,    /* '|' */
+       159,    /* '}' */
+       127,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Bookman-Light",
+       0,
+       NO
+       }, {
+       /* width table for font XBI */
+       {
+       53,     /* ' ' */
+       103,    /* '!' */
+       103,    /* '"' */
+       103,    /* '#' */
+       73,     /* '$' */
+       50,     /* '%' */
+       50,     /* '&' */
+       30,     /* ''' */
+       30,     /* '(' */
+       103,    /* ')' */
+       103,    /* '*' */
+       77,     /* '+' */
+       80,     /* ',' */
+       73,     /* '-' */
+       90,     /* '.' */
+       57,     /* '/' */
+       53,     /* '0' */
+       73,     /* '1' */
+       73,     /* '2' */
+       43,     /* '3' */
+       70,     /* '4' */
+       50,     /* '5' */
+       53,     /* '6' */
+       57,     /* '7' */
+       43,     /* '8' */
+       73,     /* '9' */
+       167,    /* ':' */
+       203,    /* ';' */
+       147,    /* '<' */
+       73,     /* '=' */
+       67,     /* '>' */
+       97,     /* '?' */
+       57,     /* '@' */
+       127,    /* 'A' */
+       90,     /* 'B' */
+       197,    /* 'C' */
+       150,    /* 'D' */
+       47,     /* 'E' */
+       103,    /* 'F' */
+       117,    /* 'G' */
+       103,    /* 'H' */
+       117,    /* 'I' */
+       103,    /* 'J' */
+       117,    /* 'K' */
+       103,    /* 'L' */
+       117,    /* 'M' */
+       103,    /* 'N' */
+       117,    /* 'O' */
+       103,    /* 'P' */
+       117,    /* 'Q' */
+       103,    /* 'R' */
+       120,    /* 'S' */
+       80,     /* 'T' */
+       113,    /* 'U' */
+       90,     /* 'V' */
+       113,    /* 'W' */
+       90,     /* 'X' */
+       113,    /* 'Y' */
+       90,     /* 'Z' */
+       113,    /* '[' */
+       90,     /* '\' */
+       53,     /* ']' */
+       47,     /* '^' */
+       53,     /* '_' */
+       47,     /* '`' */
+       53,     /* 'a' */
+       47,     /* 'b' */
+       53,     /* 'c' */
+       47,     /* 'd' */
+       120,    /* 'e' */
+       103,    /* 'f' */
+       127,    /* 'g' */
+       90,     /* 'h' */
+       127,    /* 'i' */
+       90,     /* 'j' */
+       127,    /* 'k' */
+       90,     /* 'l' */
+       127,    /* 'm' */
+       90,     /* 'n' */
+       127,    /* 'o' */
+       90,     /* 'p' */
+       107,    /* 'q' */
+       90,     /* 'r' */
+       120,    /* 's' */
+       103,    /* 't' */
+       120,    /* 'u' */
+       103,    /* 'v' */
+       120,    /* 'w' */
+       103,    /* 'x' */
+       120,    /* 'y' */
+       103,    /* 'z' */
+       110,    /* '{' */
+       100,    /* '|' */
+       97,     /* '}' */
+       87,     /* '~' */
+       50,     /* ' ' */
+       },
+       /* height table for font XBI */
+       {
+       273,    /* ' ' */
+       152,    /* '!' */
+       148,    /* '"' */
+       142,    /* '#' */
+       143,    /* '$' */
+       95,     /* '%' */
+       95,     /* '&' */
+       94,     /* ''' */
+       95,     /* '(' */
+       173,    /* ')' */
+       168,    /* '*' */
+       121,    /* '+' */
+       66,     /* ',' */
+       146,    /* '-' */
+       148,    /* '.' */
+       146,    /* '/' */
+       146,    /* '0' */
+       132,    /* '1' */
+       138,    /* '2' */
+       140,    /* '3' */
+       140,    /* '4' */
+       146,    /* '5' */
+       57,     /* '6' */
+       147,    /* '7' */
+       57,     /* '8' */
+       139,    /* '9' */
+       76,     /* ':' */
+       142,    /* ';' */
+       114,    /* '<' */
+       146,    /* '=' */
+       146,    /* '>' */
+       142,    /* '?' */
+       149,    /* '@' */
+       173,    /* 'A' */
+       125,    /* 'B' */
+       148,    /* 'C' */
+       114,    /* 'D' */
+       111,    /* 'E' */
+       164,    /* 'F' */
+       174,    /* 'G' */
+       148,    /* 'H' */
+       170,    /* 'I' */
+       141,    /* 'J' */
+       171,    /* 'K' */
+       142,    /* 'L' */
+       174,    /* 'M' */
+       148,    /* 'N' */
+       176,    /* 'O' */
+       148,    /* 'P' */
+       169,    /* 'Q' */
+       139,    /* 'R' */
+       174,    /* 'S' */
+       141,    /* 'T' */
+       174,    /* 'U' */
+       148,    /* 'V' */
+       170,    /* 'W' */
+       141,    /* 'X' */
+       171,    /* 'Y' */
+       142,    /* 'Z' */
+       174,    /* '[' */
+       148,    /* '\' */
+       174,    /* ']' */
+       148,    /* '^' */
+       170,    /* '_' */
+       141,    /* '`' */
+       171,    /* 'a' */
+       142,    /* 'b' */
+       174,    /* 'c' */
+       148,    /* 'd' */
+       169,    /* 'e' */
+       139,    /* 'f' */
+       176,    /* 'g' */
+       148,    /* 'h' */
+       172,    /* 'i' */
+       141,    /* 'j' */
+       173,    /* 'k' */
+       142,    /* 'l' */
+       176,    /* 'm' */
+       148,    /* 'n' */
+       171,    /* 'o' */
+       139,    /* 'p' */
+       172,    /* 'q' */
+       141,    /* 'r' */
+       176,    /* 's' */
+       148,    /* 't' */
+       172,    /* 'u' */
+       141,    /* 'v' */
+       173,    /* 'w' */
+       142,    /* 'x' */
+       176,    /* 'y' */
+       148,    /* 'z' */
+       171,    /* '{' */
+       175,    /* '|' */
+       170,    /* '}' */
+       141,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XBI */
+       {
+       193,    /* ' ' */
+       133,    /* '!' */
+       132,    /* '"' */
+       128,    /* '#' */
+       130,    /* '$' */
+       82,     /* '%' */
+       81,     /* '&' */
+       81,     /* ''' */
+       81,     /* '(' */
+       132,    /* ')' */
+       132,    /* '*' */
+       107,    /* '+' */
+       33,     /* ',' */
+       132,    /* '-' */
+       98,     /* '.' */
+       132,    /* '/' */
+       132,    /* '0' */
+       118,    /* '1' */
+       124,    /* '2' */
+       126,    /* '3' */
+       126,    /* '4' */
+       132,    /* '5' */
+       14,     /* '6' */
+       134,    /* '7' */
+       14,     /* '8' */
+       125,    /* '9' */
+       62,     /* ':' */
+       128,    /* ';' */
+       98,     /* '<' */
+       132,    /* '=' */
+       132,    /* '>' */
+       128,    /* '?' */
+       133,    /* '@' */
+       144,    /* 'A' */
+       103,    /* 'B' */
+       132,    /* 'C' */
+       98,     /* 'D' */
+       95,     /* 'E' */
+       132,    /* 'F' */
+       160,    /* 'G' */
+       132,    /* 'H' */
+       156,    /* 'I' */
+       125,    /* 'J' */
+       157,    /* 'K' */
+       126,    /* 'L' */
+       160,    /* 'M' */
+       132,    /* 'N' */
+       162,    /* 'O' */
+       132,    /* 'P' */
+       155,    /* 'Q' */
+       123,    /* 'R' */
+       132,    /* 'S' */
+       98,     /* 'T' */
+       160,    /* 'U' */
+       132,    /* 'V' */
+       156,    /* 'W' */
+       125,    /* 'X' */
+       157,    /* 'Y' */
+       126,    /* 'Z' */
+       160,    /* '[' */
+       132,    /* '\' */
+       160,    /* ']' */
+       132,    /* '^' */
+       156,    /* '_' */
+       125,    /* '`' */
+       157,    /* 'a' */
+       126,    /* 'b' */
+       160,    /* 'c' */
+       132,    /* 'd' */
+       155,    /* 'e' */
+       123,    /* 'f' */
+       160,    /* 'g' */
+       132,    /* 'h' */
+       156,    /* 'i' */
+       125,    /* 'j' */
+       157,    /* 'k' */
+       126,    /* 'l' */
+       160,    /* 'm' */
+       132,    /* 'n' */
+       155,    /* 'o' */
+       123,    /* 'p' */
+       156,    /* 'q' */
+       125,    /* 'r' */
+       160,    /* 's' */
+       132,    /* 't' */
+       156,    /* 'u' */
+       125,    /* 'v' */
+       157,    /* 'w' */
+       126,    /* 'x' */
+       160,    /* 'y' */
+       132,    /* 'z' */
+       157,    /* '{' */
+       126,    /* '|' */
+       156,    /* '}' */
+       125,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Bookman-LightItalic",
+       0,
+       YES
+       }, {
+       /* width table for font XBB */
+       {
+       60,     /* ' ' */
+       110,    /* '!' */
+       110,    /* '"' */
+       110,    /* '#' */
+       90,     /* '$' */
+       67,     /* '%' */
+       67,     /* '&' */
+       37,     /* ''' */
+       37,     /* '(' */
+       73,     /* ')' */
+       63,     /* '*' */
+       77,     /* '+' */
+       90,     /* ',' */
+       90,     /* '-' */
+       110,    /* '.' */
+       67,     /* '/' */
+       67,     /* '0' */
+       77,     /* '1' */
+       83,     /* '2' */
+       53,     /* '3' */
+       83,     /* '4' */
+       57,     /* '5' */
+       60,     /* '6' */
+       73,     /* '7' */
+       53,     /* '8' */
+       83,     /* '9' */
+       167,    /* ':' */
+       190,    /* ';' */
+       147,    /* '<' */
+       67,     /* '=' */
+       67,     /* '>' */
+       107,    /* '?' */
+       57,     /* '@' */
+       133,    /* 'A' */
+       103,    /* 'B' */
+       203,    /* 'C' */
+       157,    /* 'D' */
+       60,     /* 'E' */
+       110,    /* 'F' */
+       120,    /* 'G' */
+       97,     /* 'H' */
+       120,    /* 'I' */
+       97,     /* 'J' */
+       120,    /* 'K' */
+       97,     /* 'L' */
+       120,    /* 'M' */
+       97,     /* 'N' */
+       120,    /* 'O' */
+       97,     /* 'P' */
+       120,    /* 'Q' */
+       97,     /* 'R' */
+       123,    /* 'S' */
+       97,     /* 'T' */
+       120,    /* 'U' */
+       97,     /* 'V' */
+       120,    /* 'W' */
+       97,     /* 'X' */
+       120,    /* 'Y' */
+       97,     /* 'Z' */
+       120,    /* '[' */
+       97,     /* '\' */
+       67,     /* ']' */
+       60,     /* '^' */
+       67,     /* '_' */
+       60,     /* '`' */
+       67,     /* 'a' */
+       60,     /* 'b' */
+       67,     /* 'c' */
+       60,     /* 'd' */
+       123,    /* 'e' */
+       113,    /* 'f' */
+       133,    /* 'g' */
+       103,    /* 'h' */
+       133,    /* 'i' */
+       103,    /* 'j' */
+       133,    /* 'k' */
+       103,    /* 'l' */
+       133,    /* 'm' */
+       103,    /* 'n' */
+       133,    /* 'o' */
+       103,    /* 'p' */
+       110,    /* 'q' */
+       87,     /* 'r' */
+       123,    /* 's' */
+       110,    /* 't' */
+       123,    /* 'u' */
+       110,    /* 'v' */
+       123,    /* 'w' */
+       110,    /* 'x' */
+       123,    /* 'y' */
+       110,    /* 'z' */
+       117,    /* '{' */
+       103,    /* '|' */
+       107,    /* '}' */
+       93,     /* '~' */
+       57,     /* ' ' */
+       },
+       /* height table for font XBB */
+       {
+       273,    /* ' ' */
+       139,    /* '!' */
+       148,    /* '"' */
+       142,    /* '#' */
+       143,    /* '$' */
+       99,     /* '%' */
+       99,     /* '&' */
+       99,     /* ''' */
+       99,     /* '(' */
+       172,    /* ')' */
+       172,    /* '*' */
+       121,    /* '+' */
+       70,     /* ',' */
+       146,    /* '-' */
+       148,    /* '.' */
+       151,    /* '/' */
+       151,    /* '0' */
+       139,    /* '1' */
+       149,    /* '2' */
+       151,    /* '3' */
+       146,    /* '4' */
+       152,    /* '5' */
+       64,     /* '6' */
+       151,    /* '7' */
+       57,     /* '8' */
+       150,    /* '9' */
+       79,     /* ':' */
+       142,    /* ';' */
+       118,    /* '<' */
+       146,    /* '=' */
+       146,    /* '>' */
+       142,    /* '?' */
+       148,    /* '@' */
+       176,    /* 'A' */
+       125,    /* 'B' */
+       148,    /* 'C' */
+       118,    /* 'D' */
+       112,    /* 'E' */
+       161,    /* 'F' */
+       179,    /* 'G' */
+       153,    /* 'H' */
+       178,    /* 'I' */
+       152,    /* 'J' */
+       174,    /* 'K' */
+       148,    /* 'L' */
+       179,    /* 'M' */
+       153,    /* 'N' */
+       182,    /* 'O' */
+       154,    /* 'P' */
+       175,    /* 'Q' */
+       148,    /* 'R' */
+       181,    /* 'S' */
+       151,    /* 'T' */
+       179,    /* 'U' */
+       153,    /* 'V' */
+       178,    /* 'W' */
+       152,    /* 'X' */
+       174,    /* 'Y' */
+       148,    /* 'Z' */
+       179,    /* '[' */
+       153,    /* '\' */
+       179,    /* ']' */
+       151,    /* '^' */
+       178,    /* '_' */
+       150,    /* '`' */
+       176,    /* 'a' */
+       146,    /* 'b' */
+       179,    /* 'c' */
+       151,    /* 'd' */
+       175,    /* 'e' */
+       146,    /* 'f' */
+       182,    /* 'g' */
+       153,    /* 'h' */
+       181,    /* 'i' */
+       152,    /* 'j' */
+       176,    /* 'k' */
+       148,    /* 'l' */
+       182,    /* 'm' */
+       153,    /* 'n' */
+       177,    /* 'o' */
+       148,    /* 'p' */
+       181,    /* 'q' */
+       152,    /* 'r' */
+       182,    /* 's' */
+       153,    /* 't' */
+       181,    /* 'u' */
+       152,    /* 'v' */
+       176,    /* 'w' */
+       148,    /* 'x' */
+       182,    /* 'y' */
+       153,    /* 'z' */
+       174,    /* '{' */
+       184,    /* '|' */
+       178,    /* '}' */
+       150,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XBB */
+       {
+       196,    /* ' ' */
+       125,    /* '!' */
+       132,    /* '"' */
+       128,    /* '#' */
+       130,    /* '$' */
+       86,     /* '%' */
+       86,     /* '&' */
+       86,     /* ''' */
+       86,     /* '(' */
+       132,    /* ')' */
+       132,    /* '*' */
+       107,    /* '+' */
+       39,     /* ',' */
+       132,    /* '-' */
+       102,    /* '.' */
+       137,    /* '/' */
+       137,    /* '0' */
+       125,    /* '1' */
+       135,    /* '2' */
+       138,    /* '3' */
+       132,    /* '4' */
+       138,    /* '5' */
+       15,     /* '6' */
+       137,    /* '7' */
+       14,     /* '8' */
+       136,    /* '9' */
+       65,     /* ':' */
+       128,    /* ';' */
+       102,    /* '<' */
+       132,    /* '=' */
+       132,    /* '>' */
+       128,    /* '?' */
+       135,    /* '@' */
+       144,    /* 'A' */
+       105,    /* 'B' */
+       132,    /* 'C' */
+       102,    /* 'D' */
+       98,     /* 'E' */
+       132,    /* 'F' */
+       166,    /* 'G' */
+       137,    /* 'H' */
+       165,    /* 'I' */
+       136,    /* 'J' */
+       160,    /* 'K' */
+       132,    /* 'L' */
+       166,    /* 'M' */
+       137,    /* 'N' */
+       168,    /* 'O' */
+       138,    /* 'P' */
+       161,    /* 'Q' */
+       132,    /* 'R' */
+       132,    /* 'S' */
+       102,    /* 'T' */
+       166,    /* 'U' */
+       137,    /* 'V' */
+       165,    /* 'W' */
+       136,    /* 'X' */
+       160,    /* 'Y' */
+       132,    /* 'Z' */
+       166,    /* '[' */
+       137,    /* '\' */
+       166,    /* ']' */
+       137,    /* '^' */
+       165,    /* '_' */
+       136,    /* '`' */
+       162,    /* 'a' */
+       132,    /* 'b' */
+       166,    /* 'c' */
+       137,    /* 'd' */
+       161,    /* 'e' */
+       132,    /* 'f' */
+       166,    /* 'g' */
+       137,    /* 'h' */
+       165,    /* 'i' */
+       136,    /* 'j' */
+       160,    /* 'k' */
+       132,    /* 'l' */
+       166,    /* 'm' */
+       137,    /* 'n' */
+       161,    /* 'o' */
+       132,    /* 'p' */
+       165,    /* 'q' */
+       136,    /* 'r' */
+       166,    /* 's' */
+       137,    /* 't' */
+       165,    /* 'u' */
+       136,    /* 'v' */
+       160,    /* 'w' */
+       132,    /* 'x' */
+       166,    /* 'y' */
+       137,    /* 'z' */
+       160,    /* '{' */
+       132,    /* '|' */
+       165,    /* '}' */
+       136,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Bookman-Demi",
+       0,
+       NO
+       }, {
+       /* width table for font XBX */
+       {
+       53,     /* ' ' */
+       113,    /* '!' */
+       113,    /* '"' */
+       113,    /* '#' */
+       87,     /* '$' */
+       63,     /* '%' */
+       63,     /* '&' */
+       37,     /* ''' */
+       37,     /* '(' */
+       70,     /* ')' */
+       70,     /* '*' */
+       60,     /* '+' */
+       87,     /* ',' */
+       87,     /* '-' */
+       103,    /* '.' */
+       63,     /* '/' */
+       57,     /* '0' */
+       80,     /* '1' */
+       77,     /* '2' */
+       63,     /* '3' */
+       87,     /* '4' */
+       60,     /* '5' */
+       60,     /* '6' */
+       93,     /* '7' */
+       53,     /* '8' */
+       80,     /* '9' */
+       167,    /* ':' */
+       190,    /* ';' */
+       147,    /* '<' */
+       73,     /* '=' */
+       73,     /* '>' */
+       107,    /* '?' */
+       63,     /* '@' */
+       127,    /* 'A' */
+       100,    /* 'B' */
+       197,    /* 'C' */
+       153,    /* 'D' */
+       63,     /* 'E' */
+       110,    /* 'F' */
+       120,    /* 'G' */
+       113,    /* 'H' */
+       120,    /* 'I' */
+       113,    /* 'J' */
+       120,    /* 'K' */
+       113,    /* 'L' */
+       120,    /* 'M' */
+       113,    /* 'N' */
+       120,    /* 'O' */
+       113,    /* 'P' */
+       120,    /* 'Q' */
+       113,    /* 'R' */
+       117,    /* 'S' */
+       93,     /* 'T' */
+       120,    /* 'U' */
+       93,     /* 'V' */
+       120,    /* 'W' */
+       93,     /* 'X' */
+       120,    /* 'Y' */
+       93,     /* 'Z' */
+       120,    /* '[' */
+       93,     /* '\' */
+       63,     /* ']' */
+       63,     /* '^' */
+       63,     /* '_' */
+       63,     /* '`' */
+       63,     /* 'a' */
+       63,     /* 'b' */
+       63,     /* 'c' */
+       63,     /* 'd' */
+       123,    /* 'e' */
+       113,    /* 'f' */
+       127,    /* 'g' */
+       100,    /* 'h' */
+       127,    /* 'i' */
+       100,    /* 'j' */
+       127,    /* 'k' */
+       100,    /* 'l' */
+       127,    /* 'm' */
+       100,    /* 'n' */
+       127,    /* 'o' */
+       100,    /* 'p' */
+       117,    /* 'q' */
+       90,     /* 'r' */
+       123,    /* 's' */
+       113,    /* 't' */
+       123,    /* 'u' */
+       113,    /* 'v' */
+       123,    /* 'w' */
+       113,    /* 'x' */
+       123,    /* 'y' */
+       113,    /* 'z' */
+       110,    /* '{' */
+       100,    /* '|' */
+       113,    /* '}' */
+       93,     /* '~' */
+       57,     /* ' ' */
+       },
+       /* height table for font XBX */
+       {
+       272,    /* ' ' */
+       146,    /* '!' */
+       148,    /* '"' */
+       142,    /* '#' */
+       143,    /* '$' */
+       107,    /* '%' */
+       107,    /* '&' */
+       107,    /* ''' */
+       107,    /* '(' */
+       168,    /* ')' */
+       170,    /* '*' */
+       121,    /* '+' */
+       74,     /* ',' */
+       146,    /* '-' */
+       148,    /* '.' */
+       152,    /* '/' */
+       152,    /* '0' */
+       146,    /* '1' */
+       146,    /* '2' */
+       150,    /* '3' */
+       149,    /* '4' */
+       156,    /* '5' */
+       64,     /* '6' */
+       153,    /* '7' */
+       58,     /* '8' */
+       150,    /* '9' */
+       79,     /* ':' */
+       142,    /* ';' */
+       118,    /* '<' */
+       146,    /* '=' */
+       146,    /* '>' */
+       142,    /* '?' */
+       152,    /* '@' */
+       153,    /* 'A' */
+       133,    /* 'B' */
+       148,    /* 'C' */
+       118,    /* 'D' */
+       114,    /* 'E' */
+       188,    /* 'F' */
+       180,    /* 'G' */
+       155,    /* 'H' */
+       178,    /* 'I' */
+       152,    /* 'J' */
+       177,    /* 'K' */
+       151,    /* 'L' */
+       180,    /* 'M' */
+       155,    /* 'N' */
+       182,    /* 'O' */
+       158,    /* 'P' */
+       172,    /* 'Q' */
+       148,    /* 'R' */
+       181,    /* 'S' */
+       151,    /* 'T' */
+       180,    /* 'U' */
+       155,    /* 'V' */
+       178,    /* 'W' */
+       152,    /* 'X' */
+       177,    /* 'Y' */
+       152,    /* 'Z' */
+       180,    /* '[' */
+       155,    /* '\' */
+       180,    /* ']' */
+       155,    /* '^' */
+       178,    /* '_' */
+       152,    /* '`' */
+       177,    /* 'a' */
+       152,    /* 'b' */
+       180,    /* 'c' */
+       155,    /* 'd' */
+       172,    /* 'e' */
+       148,    /* 'f' */
+       182,    /* 'g' */
+       155,    /* 'h' */
+       180,    /* 'i' */
+       152,    /* 'j' */
+       179,    /* 'k' */
+       152,    /* 'l' */
+       182,    /* 'm' */
+       155,    /* 'n' */
+       174,    /* 'o' */
+       148,    /* 'p' */
+       180,    /* 'q' */
+       152,    /* 'r' */
+       182,    /* 's' */
+       155,    /* 't' */
+       180,    /* 'u' */
+       152,    /* 'v' */
+       179,    /* 'w' */
+       151,    /* 'x' */
+       182,    /* 'y' */
+       155,    /* 'z' */
+       177,    /* '{' */
+       181,    /* '|' */
+       178,    /* '}' */
+       152,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XBX */
+       {
+       196,    /* ' ' */
+       132,    /* '!' */
+       132,    /* '"' */
+       128,    /* '#' */
+       130,    /* '$' */
+       93,     /* '%' */
+       93,     /* '&' */
+       93,     /* ''' */
+       93,     /* '(' */
+       132,    /* ')' */
+       132,    /* '*' */
+       107,    /* '+' */
+       41,     /* ',' */
+       132,    /* '-' */
+       102,    /* '.' */
+       139,    /* '/' */
+       139,    /* '0' */
+       132,    /* '1' */
+       132,    /* '2' */
+       136,    /* '3' */
+       135,    /* '4' */
+       142,    /* '5' */
+       15,     /* '6' */
+       139,    /* '7' */
+       14,     /* '8' */
+       136,    /* '9' */
+       65,     /* ':' */
+       128,    /* ';' */
+       102,    /* '<' */
+       132,    /* '=' */
+       132,    /* '>' */
+       128,    /* '?' */
+       136,    /* '@' */
+       135,    /* 'A' */
+       110,    /* 'B' */
+       132,    /* 'C' */
+       102,    /* 'D' */
+       98,     /* 'E' */
+       138,    /* 'F' */
+       166,    /* 'G' */
+       139,    /* 'H' */
+       164,    /* 'I' */
+       136,    /* 'J' */
+       163,    /* 'K' */
+       135,    /* 'L' */
+       166,    /* 'M' */
+       139,    /* 'N' */
+       168,    /* 'O' */
+       142,    /* 'P' */
+       158,    /* 'Q' */
+       132,    /* 'R' */
+       132,    /* 'S' */
+       102,    /* 'T' */
+       166,    /* 'U' */
+       139,    /* 'V' */
+       164,    /* 'W' */
+       136,    /* 'X' */
+       163,    /* 'Y' */
+       135,    /* 'Z' */
+       166,    /* '[' */
+       139,    /* '\' */
+       166,    /* ']' */
+       139,    /* '^' */
+       164,    /* '_' */
+       136,    /* '`' */
+       163,    /* 'a' */
+       135,    /* 'b' */
+       166,    /* 'c' */
+       139,    /* 'd' */
+       158,    /* 'e' */
+       132,    /* 'f' */
+       166,    /* 'g' */
+       139,    /* 'h' */
+       164,    /* 'i' */
+       136,    /* 'j' */
+       163,    /* 'k' */
+       135,    /* 'l' */
+       166,    /* 'm' */
+       139,    /* 'n' */
+       158,    /* 'o' */
+       132,    /* 'p' */
+       164,    /* 'q' */
+       136,    /* 'r' */
+       166,    /* 's' */
+       139,    /* 't' */
+       164,    /* 'u' */
+       136,    /* 'v' */
+       163,    /* 'w' */
+       135,    /* 'x' */
+       166,    /* 'y' */
+       139,    /* 'z' */
+       163,    /* '{' */
+       135,    /* '|' */
+       164,    /* '}' */
+       136,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Bookman-DemiItalic",
+       0,
+       YES
+       }, {
+       /* width table for font XNR */
+       {
+       49,     /* ' ' */
+       93,     /* '!' */
+       93,     /* '"' */
+       93,     /* '#' */
+       65,     /* '$' */
+       71,     /* '%' */
+       71,     /* '&' */
+       43,     /* ''' */
+       43,     /* '(' */
+       83,     /* ')' */
+       83,     /* '*' */
+       101,    /* '+' */
+       65,     /* ',' */
+       65,     /* '-' */
+       74,     /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       167,    /* ';' */
+       133,    /* '<' */
+       56,     /* '=' */
+       50,     /* '>' */
+       111,    /* '?' */
+       52,     /* '@' */
+       130,    /* 'A' */
+       83,     /* 'B' */
+       167,    /* 'C' */
+       139,    /* 'D' */
+       52,     /* 'E' */
+       96,     /* 'F' */
+       120,    /* 'G' */
+       93,     /* 'H' */
+       120,    /* 'I' */
+       93,     /* 'J' */
+       120,    /* 'K' */
+       93,     /* 'L' */
+       120,    /* 'M' */
+       93,     /* 'N' */
+       120,    /* 'O' */
+       93,     /* 'P' */
+       120,    /* 'Q' */
+       93,     /* 'R' */
+       120,    /* 'S' */
+       74,     /* 'T' */
+       120,    /* 'U' */
+       83,     /* 'V' */
+       120,    /* 'W' */
+       83,     /* 'X' */
+       120,    /* 'Y' */
+       83,     /* 'Z' */
+       120,    /* '[' */
+       83,     /* '\' */
+       68,     /* ']' */
+       52,     /* '^' */
+       68,     /* '_' */
+       52,     /* '`' */
+       68,     /* 'a' */
+       52,     /* 'b' */
+       68,     /* 'c' */
+       52,     /* 'd' */
+       136,    /* 'e' */
+       102,    /* 'f' */
+       130,    /* 'g' */
+       83,     /* 'h' */
+       130,    /* 'i' */
+       83,     /* 'j' */
+       130,    /* 'k' */
+       83,     /* 'l' */
+       130,    /* 'm' */
+       83,     /* 'n' */
+       130,    /* 'o' */
+       83,     /* 'p' */
+       105,    /* 'q' */
+       77,     /* 'r' */
+       136,    /* 's' */
+       102,    /* 't' */
+       136,    /* 'u' */
+       102,    /* 'v' */
+       136,    /* 'w' */
+       102,    /* 'x' */
+       136,    /* 'y' */
+       102,    /* 'z' */
+       117,    /* '{' */
+       89,     /* '|' */
+       102,    /* '}' */
+       80,     /* '~' */
+       46,     /* ' ' */
+       },
+       /* height table for font XNR */
+       {
+       276,    /* ' ' */
+       149,    /* '!' */
+       148,    /* '"' */
+       149,    /* '#' */
+       150,    /* '$' */
+       95,     /* '%' */
+       95,     /* '&' */
+       95,     /* ''' */
+       95,     /* '(' */
+       176,    /* ')' */
+       176,    /* '*' */
+       120,    /* '+' */
+       76,     /* ',' */
+       152,    /* '-' */
+       151,    /* '.' */
+       145,    /* '/' */
+       145,    /* '0' */
+       132,    /* '1' */
+       143,    /* '2' */
+       135,    /* '3' */
+       135,    /* '4' */
+       152,    /* '5' */
+       63,     /* '6' */
+       145,    /* '7' */
+       53,     /* '8' */
+       145,    /* '9' */
+       72,     /* ':' */
+       149,    /* ';' */
+       111,    /* '<' */
+       152,    /* '=' */
+       152,    /* '>' */
+       149,    /* '?' */
+       151,    /* '@' */
+       167,    /* 'A' */
+       135,    /* 'B' */
+       149,    /* 'C' */
+       111,    /* 'D' */
+       105,    /* 'E' */
+       154,    /* 'F' */
+       187,    /* 'G' */
+       148,    /* 'H' */
+       187,    /* 'I' */
+       147,    /* 'J' */
+       178,    /* 'K' */
+       137,    /* 'L' */
+       187,    /* 'M' */
+       148,    /* 'N' */
+       192,    /* 'O' */
+       154,    /* 'P' */
+       180,    /* 'Q' */
+       140,    /* 'R' */
+       188,    /* 'S' */
+       144,    /* 'T' */
+       187,    /* 'U' */
+       148,    /* 'V' */
+       187,    /* 'W' */
+       147,    /* 'X' */
+       178,    /* 'Y' */
+       137,    /* 'Z' */
+       187,    /* '[' */
+       148,    /* '\' */
+       187,    /* ']' */
+       145,    /* '^' */
+       187,    /* '_' */
+       145,    /* '`' */
+       179,    /* 'a' */
+       136,    /* 'b' */
+       187,    /* 'c' */
+       145,    /* 'd' */
+       182,    /* 'e' */
+       138,    /* 'f' */
+       190,    /* 'g' */
+       148,    /* 'h' */
+       189,    /* 'i' */
+       147,    /* 'j' */
+       180,    /* 'k' */
+       137,    /* 'l' */
+       190,    /* 'm' */
+       148,    /* 'n' */
+       182,    /* 'o' */
+       140,    /* 'p' */
+       189,    /* 'q' */
+       147,    /* 'r' */
+       190,    /* 's' */
+       148,    /* 't' */
+       189,    /* 'u' */
+       147,    /* 'v' */
+       180,    /* 'w' */
+       137,    /* 'x' */
+       190,    /* 'y' */
+       148,    /* 'z' */
+       178,    /* '{' */
+       167,    /* '|' */
+       187,    /* '}' */
+       145,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XNR */
+       {
+       199,    /* ' ' */
+       111,    /* '!' */
+       132,    /* '"' */
+       135,    /* '#' */
+       137,    /* '$' */
+       81,     /* '%' */
+       81,     /* '&' */
+       81,     /* ''' */
+       81,     /* '(' */
+       138,    /* ')' */
+       138,    /* '*' */
+       106,    /* '+' */
+       32,     /* ',' */
+       138,    /* '-' */
+       105,    /* '.' */
+       132,    /* '/' */
+       132,    /* '0' */
+       118,    /* '1' */
+       129,    /* '2' */
+       121,    /* '3' */
+       121,    /* '4' */
+       138,    /* '5' */
+       14,     /* '6' */
+       131,    /* '7' */
+       14,     /* '8' */
+       131,    /* '9' */
+       58,     /* ':' */
+       135,    /* ';' */
+       95,     /* '<' */
+       138,    /* '=' */
+       138,    /* '>' */
+       135,    /* '?' */
+       137,    /* '@' */
+       141,    /* 'A' */
+       106,    /* 'B' */
+       135,    /* 'C' */
+       95,     /* 'D' */
+       92,     /* 'E' */
+       138,    /* 'F' */
+       174,    /* 'G' */
+       132,    /* 'H' */
+       173,    /* 'I' */
+       131,    /* 'J' */
+       164,    /* 'K' */
+       121,    /* 'L' */
+       174,    /* 'M' */
+       132,    /* 'N' */
+       178,    /* 'O' */
+       138,    /* 'P' */
+       166,    /* 'Q' */
+       124,    /* 'R' */
+       138,    /* 'S' */
+       95,     /* 'T' */
+       174,    /* 'U' */
+       132,    /* 'V' */
+       173,    /* 'W' */
+       131,    /* 'X' */
+       164,    /* 'Y' */
+       121,    /* 'Z' */
+       174,    /* '[' */
+       132,    /* '\' */
+       174,    /* ']' */
+       132,    /* '^' */
+       173,    /* '_' */
+       131,    /* '`' */
+       165,    /* 'a' */
+       122,    /* 'b' */
+       174,    /* 'c' */
+       132,    /* 'd' */
+       166,    /* 'e' */
+       124,    /* 'f' */
+       174,    /* 'g' */
+       132,    /* 'h' */
+       173,    /* 'i' */
+       131,    /* 'j' */
+       164,    /* 'k' */
+       121,    /* 'l' */
+       174,    /* 'm' */
+       132,    /* 'n' */
+       166,    /* 'o' */
+       124,    /* 'p' */
+       173,    /* 'q' */
+       131,    /* 'r' */
+       174,    /* 's' */
+       132,    /* 't' */
+       173,    /* 'u' */
+       131,    /* 'v' */
+       164,    /* 'w' */
+       121,    /* 'x' */
+       174,    /* 'y' */
+       132,    /* 'z' */
+       164,    /* '{' */
+       121,    /* '|' */
+       173,    /* '}' */
+       131,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-NewCenturySchlbk-Roman",
+       0,
+       NO
+       }, {
+       /* width table for font XNI */
+       {
+       55,     /* ' ' */
+       93,     /* '!' */
+       93,     /* '"' */
+       93,     /* '#' */
+       65,     /* '$' */
+       71,     /* '%' */
+       71,     /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       83,     /* ')' */
+       83,     /* '*' */
+       101,    /* '+' */
+       65,     /* ',' */
+       65,     /* '-' */
+       74,     /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       145,    /* ';' */
+       120,    /* '<' */
+       70,     /* '=' */
+       62,     /* '>' */
+       111,    /* '?' */
+       55,     /* '@' */
+       130,    /* 'A' */
+       83,     /* 'B' */
+       163,    /* 'C' */
+       130,    /* 'D' */
+       55,     /* 'E' */
+       93,     /* 'F' */
+       117,    /* 'G' */
+       96,     /* 'H' */
+       117,    /* 'I' */
+       96,     /* 'J' */
+       117,    /* 'K' */
+       96,     /* 'L' */
+       117,    /* 'M' */
+       96,     /* 'N' */
+       117,    /* 'O' */
+       96,     /* 'P' */
+       117,    /* 'Q' */
+       96,     /* 'R' */
+       120,    /* 'S' */
+       74,     /* 'T' */
+       120,    /* 'U' */
+       74,     /* 'V' */
+       120,    /* 'W' */
+       74,     /* 'X' */
+       120,    /* 'Y' */
+       74,     /* 'Z' */
+       120,    /* '[' */
+       74,     /* '\' */
+       68,     /* ']' */
+       55,     /* '^' */
+       68,     /* '_' */
+       55,     /* '`' */
+       68,     /* 'a' */
+       55,     /* 'b' */
+       68,     /* 'c' */
+       55,     /* 'd' */
+       136,    /* 'e' */
+       102,    /* 'f' */
+       130,    /* 'g' */
+       83,     /* 'h' */
+       130,    /* 'i' */
+       83,     /* 'j' */
+       130,    /* 'k' */
+       83,     /* 'l' */
+       130,    /* 'm' */
+       83,     /* 'n' */
+       130,    /* 'o' */
+       83,     /* 'p' */
+       111,    /* 'q' */
+       74,     /* 'r' */
+       136,    /* 's' */
+       102,    /* 't' */
+       136,    /* 'u' */
+       102,    /* 'v' */
+       136,    /* 'w' */
+       102,    /* 'x' */
+       136,    /* 'y' */
+       102,    /* 'z' */
+       114,    /* '{' */
+       83,     /* '|' */
+       111,    /* '}' */
+       77,     /* '~' */
+       46,     /* ' ' */
+       },
+       /* height table for font XNI */
+       {
+       276,    /* ' ' */
+       147,    /* '!' */
+       148,    /* '"' */
+       145,    /* '#' */
+       151,    /* '$' */
+       95,     /* '%' */
+       95,     /* '&' */
+       95,     /* ''' */
+       95,     /* '(' */
+       176,    /* ')' */
+       176,    /* '*' */
+       120,    /* '+' */
+       74,     /* ',' */
+       152,    /* '-' */
+       151,    /* '.' */
+       143,    /* '/' */
+       143,    /* '0' */
+       129,    /* '1' */
+       141,    /* '2' */
+       135,    /* '3' */
+       135,    /* '4' */
+       146,    /* '5' */
+       63,     /* '6' */
+       142,    /* '7' */
+       53,     /* '8' */
+       142,    /* '9' */
+       72,     /* ':' */
+       149,    /* ';' */
+       108,    /* '<' */
+       152,    /* '=' */
+       152,    /* '>' */
+       149,    /* '?' */
+       154,    /* '@' */
+       167,    /* 'A' */
+       139,    /* 'B' */
+       149,    /* 'C' */
+       108,    /* 'D' */
+       108,    /* 'E' */
+       186,    /* 'F' */
+       186,    /* 'G' */
+       145,    /* 'H' */
+       184,    /* 'I' */
+       145,    /* 'J' */
+       179,    /* 'K' */
+       137,    /* 'L' */
+       185,    /* 'M' */
+       145,    /* 'N' */
+       189,    /* 'O' */
+       148,    /* 'P' */
+       181,    /* 'Q' */
+       138,    /* 'R' */
+       188,    /* 'S' */
+       141,    /* 'T' */
+       186,    /* 'U' */
+       145,    /* 'V' */
+       184,    /* 'W' */
+       145,    /* 'X' */
+       179,    /* 'Y' */
+       137,    /* 'Z' */
+       185,    /* '[' */
+       145,    /* '\' */
+       186,    /* ']' */
+       145,    /* '^' */
+       184,    /* '_' */
+       145,    /* '`' */
+       179,    /* 'a' */
+       138,    /* 'b' */
+       185,    /* 'c' */
+       145,    /* 'd' */
+       183,    /* 'e' */
+       138,    /* 'f' */
+       188,    /* 'g' */
+       145,    /* 'h' */
+       187,    /* 'i' */
+       145,    /* 'j' */
+       182,    /* 'k' */
+       137,    /* 'l' */
+       188,    /* 'm' */
+       145,    /* 'n' */
+       183,    /* 'o' */
+       138,    /* 'p' */
+       187,    /* 'q' */
+       144,    /* 'r' */
+       188,    /* 's' */
+       145,    /* 't' */
+       187,    /* 'u' */
+       145,    /* 'v' */
+       182,    /* 'w' */
+       137,    /* 'x' */
+       188,    /* 'y' */
+       145,    /* 'z' */
+       179,    /* '{' */
+       167,    /* '|' */
+       184,    /* '}' */
+       144,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XNI */
+       {
+       199,    /* ' ' */
+       111,    /* '!' */
+       132,    /* '"' */
+       131,    /* '#' */
+       137,    /* '$' */
+       81,     /* '%' */
+       81,     /* '&' */
+       81,     /* ''' */
+       81,     /* '(' */
+       138,    /* ')' */
+       138,    /* '*' */
+       106,    /* '+' */
+       32,     /* ',' */
+       138,    /* '-' */
+       105,    /* '.' */
+       129,    /* '/' */
+       129,    /* '0' */
+       115,    /* '1' */
+       127,    /* '2' */
+       121,    /* '3' */
+       121,    /* '4' */
+       132,    /* '5' */
+       14,     /* '6' */
+       129,    /* '7' */
+       14,     /* '8' */
+       128,    /* '9' */
+       58,     /* ':' */
+       135,    /* ';' */
+       92,     /* '<' */
+       138,    /* '=' */
+       138,    /* '>' */
+       135,    /* '?' */
+       138,    /* '@' */
+       139,    /* 'A' */
+       105,    /* 'B' */
+       135,    /* 'C' */
+       92,     /* 'D' */
+       92,     /* 'E' */
+       138,    /* 'F' */
+       172,    /* 'G' */
+       129,    /* 'H' */
+       171,    /* 'I' */
+       129,    /* 'J' */
+       166,    /* 'K' */
+       121,    /* 'L' */
+       172,    /* 'M' */
+       129,    /* 'N' */
+       175,    /* 'O' */
+       132,    /* 'P' */
+       167,    /* 'Q' */
+       122,    /* 'R' */
+       138,    /* 'S' */
+       92,     /* 'T' */
+       172,    /* 'U' */
+       129,    /* 'V' */
+       171,    /* 'W' */
+       129,    /* 'X' */
+       166,    /* 'Y' */
+       121,    /* 'Z' */
+       172,    /* '[' */
+       129,    /* '\' */
+       172,    /* ']' */
+       129,    /* '^' */
+       171,    /* '_' */
+       129,    /* '`' */
+       166,    /* 'a' */
+       122,    /* 'b' */
+       172,    /* 'c' */
+       129,    /* 'd' */
+       167,    /* 'e' */
+       122,    /* 'f' */
+       172,    /* 'g' */
+       129,    /* 'h' */
+       171,    /* 'i' */
+       129,    /* 'j' */
+       166,    /* 'k' */
+       121,    /* 'l' */
+       172,    /* 'm' */
+       129,    /* 'n' */
+       167,    /* 'o' */
+       122,    /* 'p' */
+       171,    /* 'q' */
+       128,    /* 'r' */
+       172,    /* 's' */
+       129,    /* 't' */
+       171,    /* 'u' */
+       129,    /* 'v' */
+       166,    /* 'w' */
+       121,    /* 'x' */
+       172,    /* 'y' */
+       129,    /* 'z' */
+       166,    /* '{' */
+       121,    /* '|' */
+       171,    /* '}' */
+       128,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-NewCenturySchlbk-Italic",
+       0,
+       YES
+       }, {
+       /* width table for font XNB */
+       {
+       49,     /* ' ' */
+       96,     /* '!' */
+       96,     /* '"' */
+       96,     /* '#' */
+       80,     /* '$' */
+       83,     /* '%' */
+       83,     /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       83,     /* ')' */
+       83,     /* '*' */
+       101,    /* '+' */
+       80,     /* ',' */
+       80,     /* '-' */
+       83,     /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       163,    /* ';' */
+       145,    /* '<' */
+       61,     /* '=' */
+       61,     /* '>' */
+       120,    /* '?' */
+       59,     /* '@' */
+       139,    /* 'A' */
+       102,    /* 'B' */
+       167,    /* 'C' */
+       151,    /* 'D' */
+       62,     /* 'E' */
+       102,    /* 'F' */
+       126,    /* 'G' */
+       102,    /* 'H' */
+       126,    /* 'I' */
+       102,    /* 'J' */
+       126,    /* 'K' */
+       102,    /* 'L' */
+       126,    /* 'M' */
+       102,    /* 'N' */
+       126,    /* 'O' */
+       102,    /* 'P' */
+       126,    /* 'Q' */
+       102,    /* 'R' */
+       130,    /* 'S' */
+       93,     /* 'T' */
+       126,    /* 'U' */
+       96,     /* 'V' */
+       126,    /* 'W' */
+       96,     /* 'X' */
+       126,    /* 'Y' */
+       96,     /* 'Z' */
+       126,    /* '[' */
+       96,     /* '\' */
+       74,     /* ']' */
+       62,     /* '^' */
+       74,     /* '_' */
+       62,     /* '`' */
+       74,     /* 'a' */
+       62,     /* 'b' */
+       74,     /* 'c' */
+       62,     /* 'd' */
+       139,    /* 'e' */
+       114,    /* 'f' */
+       139,    /* 'g' */
+       102,    /* 'h' */
+       139,    /* 'i' */
+       102,    /* 'j' */
+       139,    /* 'k' */
+       102,    /* 'l' */
+       139,    /* 'm' */
+       102,    /* 'n' */
+       139,    /* 'o' */
+       102,    /* 'p' */
+       111,    /* 'q' */
+       83,     /* 'r' */
+       139,    /* 's' */
+       114,    /* 't' */
+       139,    /* 'u' */
+       114,    /* 'v' */
+       139,    /* 'w' */
+       114,    /* 'x' */
+       139,    /* 'y' */
+       114,    /* 'z' */
+       120,    /* '{' */
+       102,    /* '|' */
+       111,    /* '}' */
+       89,     /* '~' */
+       48,     /* ' ' */
+       },
+       /* height table for font XNB */
+       {
+       276,    /* ' ' */
+       140,    /* '!' */
+       148,    /* '"' */
+       149,    /* '#' */
+       152,    /* '$' */
+       98,     /* '%' */
+       98,     /* '&' */
+       98,     /* ''' */
+       98,     /* '(' */
+       167,    /* ')' */
+       167,    /* '*' */
+       115,    /* '+' */
+       87,     /* ',' */
+       152,    /* '-' */
+       154,    /* '.' */
+       152,    /* '/' */
+       152,    /* '0' */
+       139,    /* '1' */
+       146,    /* '2' */
+       143,    /* '3' */
+       143,    /* '4' */
+       156,    /* '5' */
+       67,     /* '6' */
+       152,    /* '7' */
+       57,     /* '8' */
+       149,    /* '9' */
+       76,     /* ':' */
+       149,    /* ';' */
+       111,    /* '<' */
+       152,    /* '=' */
+       152,    /* '>' */
+       149,    /* '?' */
+       151,    /* '@' */
+       161,    /* 'A' */
+       137,    /* 'B' */
+       149,    /* 'C' */
+       111,    /* 'D' */
+       107,    /* 'E' */
+       154,    /* 'F' */
+       191,    /* 'G' */
+       154,    /* 'H' */
+       189,    /* 'I' */
+       151,    /* 'J' */
+       184,    /* 'K' */
+       145,    /* 'L' */
+       191,    /* 'M' */
+       154,    /* 'N' */
+       193,    /* 'O' */
+       158,    /* 'P' */
+       183,    /* 'Q' */
+       148,    /* 'R' */
+       191,    /* 'S' */
+       148,    /* 'T' */
+       191,    /* 'U' */
+       154,    /* 'V' */
+       189,    /* 'W' */
+       151,    /* 'X' */
+       184,    /* 'Y' */
+       146,    /* 'Z' */
+       191,    /* '[' */
+       154,    /* '\' */
+       191,    /* ']' */
+       152,    /* '^' */
+       189,    /* '_' */
+       149,    /* '`' */
+       186,    /* 'a' */
+       142,    /* 'b' */
+       191,    /* 'c' */
+       152,    /* 'd' */
+       185,    /* 'e' */
+       146,    /* 'f' */
+       193,    /* 'g' */
+       154,    /* 'h' */
+       191,    /* 'i' */
+       151,    /* 'j' */
+       186,    /* 'k' */
+       145,    /* 'l' */
+       193,    /* 'm' */
+       154,    /* 'n' */
+       185,    /* 'o' */
+       148,    /* 'p' */
+       191,    /* 'q' */
+       151,    /* 'r' */
+       193,    /* 's' */
+       154,    /* 't' */
+       191,    /* 'u' */
+       151,    /* 'v' */
+       186,    /* 'w' */
+       145,    /* 'x' */
+       193,    /* 'y' */
+       154,    /* 'z' */
+       184,    /* '{' */
+       175,    /* '|' */
+       189,    /* '}' */
+       149,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XNB */
+       {
+       199,    /* ' ' */
+       108,    /* '!' */
+       132,    /* '"' */
+       135,    /* '#' */
+       138,    /* '$' */
+       84,     /* '%' */
+       84,     /* '&' */
+       84,     /* ''' */
+       84,     /* '(' */
+       138,    /* ')' */
+       138,    /* '*' */
+       101,    /* '+' */
+       42,     /* ',' */
+       138,    /* '-' */
+       105,    /* '.' */
+       138,    /* '/' */
+       138,    /* '0' */
+       125,    /* '1' */
+       133,    /* '2' */
+       129,    /* '3' */
+       129,    /* '4' */
+       142,    /* '5' */
+       14,     /* '6' */
+       138,    /* '7' */
+       14,     /* '8' */
+       135,    /* '9' */
+       62,     /* ':' */
+       135,    /* ';' */
+       95,     /* '<' */
+       138,    /* '=' */
+       138,    /* '>' */
+       135,    /* '?' */
+       137,    /* '@' */
+       141,    /* 'A' */
+       108,    /* 'B' */
+       135,    /* 'C' */
+       95,     /* 'D' */
+       93,     /* 'E' */
+       138,    /* 'F' */
+       177,    /* 'G' */
+       138,    /* 'H' */
+       175,    /* 'I' */
+       135,    /* 'J' */
+       170,    /* 'K' */
+       129,    /* 'L' */
+       177,    /* 'M' */
+       138,    /* 'N' */
+       179,    /* 'O' */
+       142,    /* 'P' */
+       169,    /* 'Q' */
+       132,    /* 'R' */
+       138,    /* 'S' */
+       95,     /* 'T' */
+       177,    /* 'U' */
+       138,    /* 'V' */
+       175,    /* 'W' */
+       135,    /* 'X' */
+       170,    /* 'Y' */
+       129,    /* 'Z' */
+       177,    /* '[' */
+       138,    /* '\' */
+       177,    /* ']' */
+       138,    /* '^' */
+       175,    /* '_' */
+       135,    /* '`' */
+       172,    /* 'a' */
+       128,    /* 'b' */
+       177,    /* 'c' */
+       138,    /* 'd' */
+       169,    /* 'e' */
+       132,    /* 'f' */
+       177,    /* 'g' */
+       138,    /* 'h' */
+       175,    /* 'i' */
+       135,    /* 'j' */
+       170,    /* 'k' */
+       129,    /* 'l' */
+       177,    /* 'm' */
+       138,    /* 'n' */
+       169,    /* 'o' */
+       132,    /* 'p' */
+       175,    /* 'q' */
+       135,    /* 'r' */
+       177,    /* 's' */
+       138,    /* 't' */
+       175,    /* 'u' */
+       135,    /* 'v' */
+       170,    /* 'w' */
+       129,    /* 'x' */
+       177,    /* 'y' */
+       138,    /* 'z' */
+       170,    /* '{' */
+       129,    /* '|' */
+       175,    /* '}' */
+       135,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-NewCenturySchlbk-Bold",
+       0,
+       NO
+       }, {
+       /* width table for font XNX */
+       {
+       55,     /* ' ' */
+       96,     /* '!' */
+       96,     /* '"' */
+       96,     /* '#' */
+       80,     /* '$' */
+       80,     /* '%' */
+       80,     /* '&' */
+       46,     /* ''' */
+       46,     /* '(' */
+       83,     /* ')' */
+       83,     /* '*' */
+       101,    /* '+' */
+       80,     /* ',' */
+       80,     /* '-' */
+       80,     /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       148,    /* ';' */
+       136,    /* '<' */
+       69,     /* '=' */
+       59,     /* '>' */
+       117,    /* '?' */
+       65,     /* '@' */
+       139,    /* 'A' */
+       96,     /* 'B' */
+       160,    /* 'C' */
+       142,    /* 'D' */
+       65,     /* 'E' */
+       96,     /* 'F' */
+       123,    /* 'G' */
+       111,    /* 'H' */
+       123,    /* 'I' */
+       111,    /* 'J' */
+       123,    /* 'K' */
+       111,    /* 'L' */
+       123,    /* 'M' */
+       111,    /* 'N' */
+       123,    /* 'O' */
+       111,    /* 'P' */
+       123,    /* 'Q' */
+       111,    /* 'R' */
+       126,    /* 'S' */
+       89,     /* 'T' */
+       123,    /* 'U' */
+       86,     /* 'V' */
+       123,    /* 'W' */
+       86,     /* 'X' */
+       123,    /* 'Y' */
+       86,     /* 'Z' */
+       123,    /* '[' */
+       86,     /* '\' */
+       74,     /* ']' */
+       65,     /* '^' */
+       74,     /* '_' */
+       65,     /* '`' */
+       74,     /* 'a' */
+       65,     /* 'b' */
+       74,     /* 'c' */
+       65,     /* 'd' */
+       142,    /* 'e' */
+       114,    /* 'f' */
+       139,    /* 'g' */
+       96,     /* 'h' */
+       139,    /* 'i' */
+       96,     /* 'j' */
+       139,    /* 'k' */
+       96,     /* 'l' */
+       139,    /* 'm' */
+       96,     /* 'n' */
+       139,    /* 'o' */
+       96,     /* 'p' */
+       114,    /* 'q' */
+       80,     /* 'r' */
+       139,    /* 's' */
+       114,    /* 't' */
+       139,    /* 'u' */
+       114,    /* 'v' */
+       139,    /* 'w' */
+       114,    /* 'x' */
+       139,    /* 'y' */
+       114,    /* 'z' */
+       117,    /* '{' */
+       86,     /* '|' */
+       117,    /* '}' */
+       86,     /* '~' */
+       48,     /* ' ' */
+       },
+       /* height table for font XNX */
+       {
+       276,    /* ' ' */
+       148,    /* '!' */
+       148,    /* '"' */
+       146,    /* '#' */
+       151,    /* '$' */
+       98,     /* '%' */
+       98,     /* '&' */
+       98,     /* ''' */
+       98,     /* '(' */
+       176,    /* ')' */
+       177,    /* '*' */
+       114,    /* '+' */
+       85,     /* ',' */
+       152,    /* '-' */
+       151,    /* '.' */
+       148,    /* '/' */
+       148,    /* '0' */
+       136,    /* '1' */
+       145,    /* '2' */
+       142,    /* '3' */
+       142,    /* '4' */
+       152,    /* '5' */
+       63,     /* '6' */
+       146,    /* '7' */
+       57,     /* '8' */
+       146,    /* '9' */
+       76,     /* ':' */
+       149,    /* ';' */
+       111,    /* '<' */
+       152,    /* '=' */
+       152,    /* '>' */
+       149,    /* '?' */
+       154,    /* '@' */
+       170,    /* 'A' */
+       145,    /* 'B' */
+       149,    /* 'C' */
+       111,    /* 'D' */
+       111,    /* 'E' */
+       186,    /* 'F' */
+       187,    /* 'G' */
+       150,    /* 'H' */
+       186,    /* 'I' */
+       148,    /* 'J' */
+       183,    /* 'K' */
+       144,    /* 'L' */
+       187,    /* 'M' */
+       150,    /* 'N' */
+       196,    /* 'O' */
+       154,    /* 'P' */
+       182,    /* 'Q' */
+       144,    /* 'R' */
+       188,    /* 'S' */
+       144,    /* 'T' */
+       187,    /* 'U' */
+       150,    /* 'V' */
+       186,    /* 'W' */
+       148,    /* 'X' */
+       183,    /* 'Y' */
+       144,    /* 'Z' */
+       187,    /* '[' */
+       150,    /* '\' */
+       187,    /* ']' */
+       150,    /* '^' */
+       186,    /* '_' */
+       148,    /* '`' */
+       183,    /* 'a' */
+       144,    /* 'b' */
+       187,    /* 'c' */
+       150,    /* 'd' */
+       184,    /* 'e' */
+       144,    /* 'f' */
+       190,    /* 'g' */
+       150,    /* 'h' */
+       188,    /* 'i' */
+       148,    /* 'j' */
+       185,    /* 'k' */
+       144,    /* 'l' */
+       190,    /* 'm' */
+       150,    /* 'n' */
+       184,    /* 'o' */
+       144,    /* 'p' */
+       188,    /* 'q' */
+       148,    /* 'r' */
+       190,    /* 's' */
+       150,    /* 't' */
+       188,    /* 'u' */
+       148,    /* 'v' */
+       185,    /* 'w' */
+       144,    /* 'x' */
+       190,    /* 'y' */
+       150,    /* 'z' */
+       183,    /* '{' */
+       177,    /* '|' */
+       186,    /* '}' */
+       148,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XNX */
+       {
+       199,    /* ' ' */
+       112,    /* '!' */
+       132,    /* '"' */
+       132,    /* '#' */
+       137,    /* '$' */
+       84,     /* '%' */
+       84,     /* '&' */
+       84,     /* ''' */
+       84,     /* '(' */
+       138,    /* ')' */
+       138,    /* '*' */
+       100,    /* '+' */
+       40,     /* ',' */
+       138,    /* '-' */
+       105,    /* '.' */
+       134,    /* '/' */
+       134,    /* '0' */
+       122,    /* '1' */
+       131,    /* '2' */
+       128,    /* '3' */
+       128,    /* '4' */
+       138,    /* '5' */
+       14,     /* '6' */
+       132,    /* '7' */
+       14,     /* '8' */
+       132,    /* '9' */
+       62,     /* ':' */
+       135,    /* ';' */
+       95,     /* '<' */
+       138,    /* '=' */
+       138,    /* '>' */
+       135,    /* '?' */
+       138,    /* '@' */
+       143,    /* 'A' */
+       110,    /* 'B' */
+       135,    /* 'C' */
+       95,     /* 'D' */
+       95,     /* 'E' */
+       138,    /* 'F' */
+       174,    /* 'G' */
+       134,    /* 'H' */
+       172,    /* 'I' */
+       132,    /* 'J' */
+       169,    /* 'K' */
+       128,    /* 'L' */
+       174,    /* 'M' */
+       134,    /* 'N' */
+       182,    /* 'O' */
+       138,    /* 'P' */
+       168,    /* 'Q' */
+       128,    /* 'R' */
+       138,    /* 'S' */
+       95,     /* 'T' */
+       174,    /* 'U' */
+       134,    /* 'V' */
+       172,    /* 'W' */
+       132,    /* 'X' */
+       169,    /* 'Y' */
+       128,    /* 'Z' */
+       174,    /* '[' */
+       134,    /* '\' */
+       174,    /* ']' */
+       134,    /* '^' */
+       172,    /* '_' */
+       132,    /* '`' */
+       169,    /* 'a' */
+       128,    /* 'b' */
+       174,    /* 'c' */
+       134,    /* 'd' */
+       168,    /* 'e' */
+       128,    /* 'f' */
+       174,    /* 'g' */
+       134,    /* 'h' */
+       172,    /* 'i' */
+       132,    /* 'j' */
+       169,    /* 'k' */
+       128,    /* 'l' */
+       174,    /* 'm' */
+       134,    /* 'n' */
+       168,    /* 'o' */
+       128,    /* 'p' */
+       172,    /* 'q' */
+       132,    /* 'r' */
+       174,    /* 's' */
+       134,    /* 't' */
+       172,    /* 'u' */
+       132,    /* 'v' */
+       169,    /* 'w' */
+       128,    /* 'x' */
+       174,    /* 'y' */
+       134,    /* 'z' */
+       169,    /* '{' */
+       128,    /* '|' */
+       172,    /* '}' */
+       132,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-NewCenturySchlbk-BoldItalic",
+       0,
+       YES
+       }, {
+       /* width table for font XPR */
+       {
+       46,     /* ' ' */
+       83,     /* '!' */
+       83,     /* '"' */
+       83,     /* '#' */
+       83,     /* '$' */
+       83,     /* '%' */
+       83,     /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       83,     /* ')' */
+       83,     /* '*' */
+       101,    /* '+' */
+       83,     /* ',' */
+       83,     /* '-' */
+       74,     /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       42,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       63,     /* '7' */
+       52,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       157,    /* ';' */
+       126,    /* '<' */
+       55,     /* '=' */
+       55,     /* '>' */
+       102,    /* '?' */
+       48,     /* '@' */
+       139,    /* 'A' */
+       93,     /* 'B' */
+       166,    /* 'C' */
+       138,    /* 'D' */
+       48,     /* 'E' */
+       93,     /* 'F' */
+       130,    /* 'G' */
+       83,     /* 'H' */
+       130,    /* 'I' */
+       83,     /* 'J' */
+       130,    /* 'K' */
+       83,     /* 'L' */
+       130,    /* 'M' */
+       83,     /* 'N' */
+       130,    /* 'O' */
+       83,     /* 'P' */
+       130,    /* 'Q' */
+       83,     /* 'R' */
+       118,    /* 'S' */
+       74,     /* 'T' */
+       102,    /* 'U' */
+       80,     /* 'V' */
+       102,    /* 'W' */
+       80,     /* 'X' */
+       102,    /* 'Y' */
+       80,     /* 'Z' */
+       102,    /* '[' */
+       80,     /* '\' */
+       56,     /* ']' */
+       48,     /* '^' */
+       56,     /* '_' */
+       48,     /* '`' */
+       56,     /* 'a' */
+       48,     /* 'b' */
+       56,     /* 'c' */
+       48,     /* 'd' */
+       138,    /* 'e' */
+       97,     /* 'f' */
+       131,    /* 'g' */
+       91,     /* 'h' */
+       131,    /* 'i' */
+       91,     /* 'j' */
+       131,    /* 'k' */
+       91,     /* 'l' */
+       131,    /* 'm' */
+       91,     /* 'n' */
+       131,    /* 'o' */
+       91,     /* 'p' */
+       87,     /* 'q' */
+       71,     /* 'r' */
+       130,    /* 's' */
+       100,    /* 't' */
+       130,    /* 'u' */
+       100,    /* 'v' */
+       130,    /* 'w' */
+       100,    /* 'x' */
+       130,    /* 'y' */
+       100,    /* 'z' */
+       111,    /* '{' */
+       93,     /* '|' */
+       111,    /* '}' */
+       83,     /* '~' */
+       42,     /* ' ' */
+       },
+       /* height table for font XPR */
+       {
+       268,    /* ' ' */
+       138,    /* '!' */
+       144,    /* '"' */
+       146,    /* '#' */
+       146,    /* '$' */
+       99,     /* '%' */
+       99,     /* '&' */
+       99,     /* ''' */
+       99,     /* '(' */
+       144,    /* ')' */
+       185,    /* '*' */
+       114,    /* '+' */
+       72,     /* ',' */
+       146,    /* '-' */
+       144,    /* '.' */
+       141,    /* '/' */
+       141,    /* '0' */
+       126,    /* '1' */
+       138,    /* '2' */
+       134,    /* '3' */
+       134,    /* '4' */
+       146,    /* '5' */
+       65,     /* '6' */
+       142,    /* '7' */
+       53,     /* '8' */
+       141,    /* '9' */
+       76,     /* ':' */
+       143,    /* ';' */
+       108,    /* '<' */
+       146,    /* '=' */
+       146,    /* '>' */
+       143,    /* '?' */
+       149,    /* '@' */
+       149,    /* 'A' */
+       111,    /* 'B' */
+       148,    /* 'C' */
+       108,    /* 'D' */
+       106,    /* 'E' */
+       151,    /* 'F' */
+       180,    /* 'G' */
+       143,    /* 'H' */
+       180,    /* 'I' */
+       143,    /* 'J' */
+       173,    /* 'K' */
+       136,    /* 'L' */
+       180,    /* 'M' */
+       143,    /* 'N' */
+       186,    /* 'O' */
+       148,    /* 'P' */
+       173,    /* 'Q' */
+       138,    /* 'R' */
+       184,    /* 'S' */
+       144,    /* 'T' */
+       180,    /* 'U' */
+       143,    /* 'V' */
+       180,    /* 'W' */
+       143,    /* 'X' */
+       173,    /* 'Y' */
+       136,    /* 'Z' */
+       180,    /* '[' */
+       143,    /* '\' */
+       180,    /* ']' */
+       141,    /* '^' */
+       180,    /* '_' */
+       141,    /* '`' */
+       173,    /* 'a' */
+       139,    /* 'b' */
+       180,    /* 'c' */
+       141,    /* 'd' */
+       176,    /* 'e' */
+       136,    /* 'f' */
+       181,    /* 'g' */
+       143,    /* 'h' */
+       181,    /* 'i' */
+       143,    /* 'j' */
+       175,    /* 'k' */
+       136,    /* 'l' */
+       181,    /* 'm' */
+       143,    /* 'n' */
+       175,    /* 'o' */
+       138,    /* 'p' */
+       181,    /* 'q' */
+       143,    /* 'r' */
+       181,    /* 's' */
+       143,    /* 't' */
+       181,    /* 'u' */
+       143,    /* 'v' */
+       175,    /* 'w' */
+       136,    /* 'x' */
+       181,    /* 'y' */
+       143,    /* 'z' */
+       173,    /* '{' */
+       180,    /* '|' */
+       180,    /* '}' */
+       141,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XPR */
+       {
+       186,    /* ' ' */
+       108,    /* '!' */
+       128,    /* '"' */
+       132,    /* '#' */
+       132,    /* '$' */
+       85,     /* '%' */
+       85,     /* '&' */
+       85,     /* ''' */
+       85,     /* '(' */
+       130,    /* ')' */
+       130,    /* '*' */
+       100,    /* '+' */
+       32,     /* ',' */
+       132,    /* '-' */
+       92,     /* '.' */
+       127,    /* '/' */
+       127,    /* '0' */
+       112,    /* '1' */
+       125,    /* '2' */
+       120,    /* '3' */
+       120,    /* '4' */
+       132,    /* '5' */
+       12,     /* '6' */
+       128,    /* '7' */
+       14,     /* '8' */
+       127,    /* '9' */
+       62,     /* ':' */
+       128,    /* ';' */
+       92,     /* '<' */
+       132,    /* '=' */
+       132,    /* '>' */
+       128,    /* '?' */
+       135,    /* '@' */
+       132,    /* 'A' */
+       93,     /* 'B' */
+       132,    /* 'C' */
+       92,     /* 'D' */
+       92,     /* 'E' */
+       135,    /* 'F' */
+       165,    /* 'G' */
+       127,    /* 'H' */
+       165,    /* 'I' */
+       127,    /* 'J' */
+       159,    /* 'K' */
+       120,    /* 'L' */
+       165,    /* 'M' */
+       127,    /* 'N' */
+       172,    /* 'O' */
+       132,    /* 'P' */
+       159,    /* 'Q' */
+       122,    /* 'R' */
+       132,    /* 'S' */
+       92,     /* 'T' */
+       165,    /* 'U' */
+       127,    /* 'V' */
+       165,    /* 'W' */
+       127,    /* 'X' */
+       159,    /* 'Y' */
+       120,    /* 'Z' */
+       165,    /* '[' */
+       127,    /* '\' */
+       165,    /* ']' */
+       127,    /* '^' */
+       165,    /* '_' */
+       127,    /* '`' */
+       158,    /* 'a' */
+       125,    /* 'b' */
+       165,    /* 'c' */
+       127,    /* 'd' */
+       159,    /* 'e' */
+       122,    /* 'f' */
+       165,    /* 'g' */
+       127,    /* 'h' */
+       165,    /* 'i' */
+       127,    /* 'j' */
+       159,    /* 'k' */
+       120,    /* 'l' */
+       165,    /* 'm' */
+       127,    /* 'n' */
+       159,    /* 'o' */
+       122,    /* 'p' */
+       165,    /* 'q' */
+       127,    /* 'r' */
+       165,    /* 's' */
+       127,    /* 't' */
+       165,    /* 'u' */
+       127,    /* 'v' */
+       159,    /* 'w' */
+       120,    /* 'x' */
+       165,    /* 'y' */
+       127,    /* 'z' */
+       159,    /* '{' */
+       120,    /* '|' */
+       165,    /* '}' */
+       127,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Palatino-Roman",
+       0,
+       NO
+       }, {
+       /* width table for font XPI */
+       {
+       55,     /* ' ' */
+       83,     /* '!' */
+       83,     /* '"' */
+       83,     /* '#' */
+       83,     /* '$' */
+       83,     /* '%' */
+       83,     /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       83,     /* ')' */
+       83,     /* '*' */
+       83,     /* '+' */
+       83,     /* ',' */
+       83,     /* '-' */
+       83,     /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       157,    /* ';' */
+       106,    /* '<' */
+       55,     /* '=' */
+       55,     /* '>' */
+       93,     /* '?' */
+       46,     /* '@' */
+       130,    /* 'A' */
+       74,     /* 'B' */
+       171,    /* 'C' */
+       111,    /* 'D' */
+       46,     /* 'E' */
+       83,     /* 'F' */
+       120,    /* 'G' */
+       74,     /* 'H' */
+       120,    /* 'I' */
+       74,     /* 'J' */
+       120,    /* 'K' */
+       74,     /* 'L' */
+       120,    /* 'M' */
+       74,     /* 'N' */
+       120,    /* 'O' */
+       74,     /* 'P' */
+       120,    /* 'Q' */
+       74,     /* 'R' */
+       111,    /* 'S' */
+       68,     /* 'T' */
+       102,    /* 'U' */
+       65,     /* 'V' */
+       102,    /* 'W' */
+       65,     /* 'X' */
+       102,    /* 'Y' */
+       65,     /* 'Z' */
+       102,    /* '[' */
+       65,     /* '\' */
+       55,     /* ']' */
+       46,     /* '^' */
+       55,     /* '_' */
+       46,     /* '`' */
+       55,     /* 'a' */
+       46,     /* 'b' */
+       55,     /* 'c' */
+       46,     /* 'd' */
+       130,    /* 'e' */
+       93,     /* 'f' */
+       130,    /* 'g' */
+       74,     /* 'h' */
+       130,    /* 'i' */
+       74,     /* 'j' */
+       130,    /* 'k' */
+       74,     /* 'l' */
+       130,    /* 'm' */
+       74,     /* 'n' */
+       130,    /* 'o' */
+       74,     /* 'p' */
+       93,     /* 'q' */
+       65,     /* 'r' */
+       130,    /* 's' */
+       93,     /* 't' */
+       130,    /* 'u' */
+       93,     /* 'v' */
+       130,    /* 'w' */
+       93,     /* 'x' */
+       130,    /* 'y' */
+       93,     /* 'z' */
+       111,    /* '{' */
+       83,     /* '|' */
+       111,    /* '}' */
+       74,     /* '~' */
+       42,     /* ' ' */
+       },
+       /* height table for font XPI */
+       {
+       277,    /* ' ' */
+       136,    /* '!' */
+       149,    /* '"' */
+       144,    /* '#' */
+       150,    /* '$' */
+       101,    /* '%' */
+       101,    /* '&' */
+       101,    /* ''' */
+       101,    /* '(' */
+       143,    /* ')' */
+       170,    /* '*' */
+       115,    /* '+' */
+       68,     /* ',' */
+       150,    /* '-' */
+       148,    /* '.' */
+       142,    /* '/' */
+       142,    /* '0' */
+       126,    /* '1' */
+       141,    /* '2' */
+       135,    /* '3' */
+       134,    /* '4' */
+       149,    /* '5' */
+       63,     /* '6' */
+       150,    /* '7' */
+       60,     /* '8' */
+       141,    /* '9' */
+       72,     /* ':' */
+       143,    /* ';' */
+       111,    /* '<' */
+       146,    /* '=' */
+       146,    /* '>' */
+       142,    /* '?' */
+       152,    /* '@' */
+       154,    /* 'A' */
+       117,    /* 'B' */
+       148,    /* 'C' */
+       111,    /* 'D' */
+       111,    /* 'E' */
+       194,    /* 'F' */
+       178,    /* 'G' */
+       144,    /* 'H' */
+       176,    /* 'I' */
+       143,    /* 'J' */
+       169,    /* 'K' */
+       136,    /* 'L' */
+       178,    /* 'M' */
+       144,    /* 'N' */
+       184,    /* 'O' */
+       151,    /* 'P' */
+       173,    /* 'Q' */
+       138,    /* 'R' */
+       181,    /* 'S' */
+       144,    /* 'T' */
+       177,    /* 'U' */
+       144,    /* 'V' */
+       176,    /* 'W' */
+       143,    /* 'X' */
+       169,    /* 'Y' */
+       136,    /* 'Z' */
+       177,    /* '[' */
+       144,    /* '\' */
+       177,    /* ']' */
+       144,    /* '^' */
+       176,    /* '_' */
+       143,    /* '`' */
+       169,    /* 'a' */
+       141,    /* 'b' */
+       177,    /* 'c' */
+       144,    /* 'd' */
+       174,    /* 'e' */
+       138,    /* 'f' */
+       179,    /* 'g' */
+       144,    /* 'h' */
+       178,    /* 'i' */
+       143,    /* 'j' */
+       171,    /* 'k' */
+       136,    /* 'l' */
+       179,    /* 'm' */
+       144,    /* 'n' */
+       174,    /* 'o' */
+       138,    /* 'p' */
+       181,    /* 'q' */
+       143,    /* 'r' */
+       179,    /* 's' */
+       144,    /* 't' */
+       178,    /* 'u' */
+       143,    /* 'v' */
+       171,    /* 'w' */
+       136,    /* 'x' */
+       179,    /* 'y' */
+       144,    /* 'z' */
+       169,    /* '{' */
+       179,    /* '|' */
+       179,    /* '}' */
+       143,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XPI */
+       {
+       186,    /* ' ' */
+       106,    /* '!' */
+       132,    /* '"' */
+       130,    /* '#' */
+       136,    /* '$' */
+       87,     /* '%' */
+       87,     /* '&' */
+       87,     /* ''' */
+       87,     /* '(' */
+       129,    /* ')' */
+       129,    /* '*' */
+       102,    /* '+' */
+       34,     /* ',' */
+       136,    /* '-' */
+       92,     /* '.' */
+       128,    /* '/' */
+       128,    /* '0' */
+       112,    /* '1' */
+       127,    /* '2' */
+       121,    /* '3' */
+       120,    /* '4' */
+       135,    /* '5' */
+       14,     /* '6' */
+       136,    /* '7' */
+       11,     /* '8' */
+       127,    /* '9' */
+       58,     /* ':' */
+       129,    /* ';' */
+       95,     /* '<' */
+       132,    /* '=' */
+       132,    /* '>' */
+       128,    /* '?' */
+       136,    /* '@' */
+       134,    /* 'A' */
+       99,     /* 'B' */
+       132,    /* 'C' */
+       95,     /* 'D' */
+       95,     /* 'E' */
+       135,    /* 'F' */
+       163,    /* 'G' */
+       128,    /* 'H' */
+       162,    /* 'I' */
+       127,    /* 'J' */
+       155,    /* 'K' */
+       120,    /* 'L' */
+       163,    /* 'M' */
+       128,    /* 'N' */
+       170,    /* 'O' */
+       135,    /* 'P' */
+       158,    /* 'Q' */
+       122,    /* 'R' */
+       132,    /* 'S' */
+       95,     /* 'T' */
+       163,    /* 'U' */
+       128,    /* 'V' */
+       162,    /* 'W' */
+       127,    /* 'X' */
+       155,    /* 'Y' */
+       120,    /* 'Z' */
+       163,    /* '[' */
+       128,    /* '\' */
+       163,    /* ']' */
+       128,    /* '^' */
+       162,    /* '_' */
+       127,    /* '`' */
+       155,    /* 'a' */
+       125,    /* 'b' */
+       163,    /* 'c' */
+       128,    /* 'd' */
+       158,    /* 'e' */
+       122,    /* 'f' */
+       163,    /* 'g' */
+       128,    /* 'h' */
+       162,    /* 'i' */
+       127,    /* 'j' */
+       155,    /* 'k' */
+       120,    /* 'l' */
+       163,    /* 'm' */
+       128,    /* 'n' */
+       158,    /* 'o' */
+       122,    /* 'p' */
+       165,    /* 'q' */
+       127,    /* 'r' */
+       163,    /* 's' */
+       128,    /* 't' */
+       162,    /* 'u' */
+       127,    /* 'v' */
+       155,    /* 'w' */
+       120,    /* 'x' */
+       163,    /* 'y' */
+       128,    /* 'z' */
+       155,    /* '{' */
+       120,    /* '|' */
+       165,    /* '}' */
+       127,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Palatino-Italic",
+       0,
+       YES
+       }, {
+       /* width table for font XPB */
+       {
+       46,     /* ' ' */
+       83,     /* '!' */
+       83,     /* '"' */
+       83,     /* '#' */
+       83,     /* '$' */
+       83,     /* '%' */
+       83,     /* '&' */
+       65,     /* ''' */
+       65,     /* '(' */
+       83,     /* ')' */
+       83,     /* '*' */
+       101,    /* '+' */
+       83,     /* ',' */
+       83,     /* '-' */
+       74,     /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       55,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       167,    /* ';' */
+       130,    /* '<' */
+       73,     /* '=' */
+       81,     /* '>' */
+       102,    /* '?' */
+       55,     /* '@' */
+       139,    /* 'A' */
+       93,     /* 'B' */
+       167,    /* 'C' */
+       139,    /* 'D' */
+       55,     /* 'E' */
+       102,    /* 'F' */
+       130,    /* 'G' */
+       83,     /* 'H' */
+       130,    /* 'I' */
+       83,     /* 'J' */
+       130,    /* 'K' */
+       83,     /* 'L' */
+       130,    /* 'M' */
+       83,     /* 'N' */
+       130,    /* 'O' */
+       83,     /* 'P' */
+       130,    /* 'Q' */
+       83,     /* 'R' */
+       120,    /* 'S' */
+       74,     /* 'T' */
+       102,    /* 'U' */
+       83,     /* 'V' */
+       102,    /* 'W' */
+       83,     /* 'X' */
+       102,    /* 'Y' */
+       83,     /* 'Z' */
+       102,    /* '[' */
+       83,     /* '\' */
+       65,     /* ']' */
+       55,     /* '^' */
+       65,     /* '_' */
+       55,     /* '`' */
+       65,     /* 'a' */
+       55,     /* 'b' */
+       65,     /* 'c' */
+       55,     /* 'd' */
+       139,    /* 'e' */
+       102,    /* 'f' */
+       139,    /* 'g' */
+       93,     /* 'h' */
+       139,    /* 'i' */
+       93,     /* 'j' */
+       139,    /* 'k' */
+       93,     /* 'l' */
+       139,    /* 'm' */
+       93,     /* 'n' */
+       139,    /* 'o' */
+       93,     /* 'p' */
+       102,    /* 'q' */
+       74,     /* 'r' */
+       130,    /* 's' */
+       102,    /* 't' */
+       130,    /* 'u' */
+       102,    /* 'v' */
+       130,    /* 'w' */
+       102,    /* 'x' */
+       130,    /* 'y' */
+       102,    /* 'z' */
+       111,    /* '{' */
+       93,     /* '|' */
+       111,    /* '}' */
+       83,     /* '~' */
+       42,     /* ' ' */
+       },
+       /* height table for font XPB */
+       {
+       268,    /* ' ' */
+       138,    /* '!' */
+       142,    /* '"' */
+       144,    /* '#' */
+       144,    /* '$' */
+       101,    /* '%' */
+       101,    /* '&' */
+       101,    /* ''' */
+       101,    /* '(' */
+       143,    /* ')' */
+       183,    /* '*' */
+       114,    /* '+' */
+       76,     /* ',' */
+       144,    /* '-' */
+       144,    /* '.' */
+       146,    /* '/' */
+       146,    /* '0' */
+       129,    /* '1' */
+       139,    /* '2' */
+       140,    /* '3' */
+       140,    /* '4' */
+       146,    /* '5' */
+       62,     /* '6' */
+       146,    /* '7' */
+       67,     /* '8' */
+       142,    /* '9' */
+       76,     /* ':' */
+       143,    /* ';' */
+       108,    /* '<' */
+       139,    /* '=' */
+       139,    /* '>' */
+       143,    /* '?' */
+       148,    /* '@' */
+       149,    /* 'A' */
+       109,    /* 'B' */
+       148,    /* 'C' */
+       108,    /* 'D' */
+       106,    /* 'E' */
+       148,    /* 'F' */
+       181,    /* 'G' */
+       148,    /* 'H' */
+       179,    /* 'I' */
+       144,    /* 'J' */
+       177,    /* 'K' */
+       142,    /* 'L' */
+       181,    /* 'M' */
+       148,    /* 'N' */
+       184,    /* 'O' */
+       148,    /* 'P' */
+       176,    /* 'Q' */
+       141,    /* 'R' */
+       181,    /* 'S' */
+       141,    /* 'T' */
+       181,    /* 'U' */
+       148,    /* 'V' */
+       179,    /* 'W' */
+       144,    /* 'X' */
+       177,    /* 'Y' */
+       142,    /* 'Z' */
+       181,    /* '[' */
+       148,    /* '\' */
+       181,    /* ']' */
+       146,    /* '^' */
+       179,    /* '_' */
+       142,    /* '`' */
+       179,    /* 'a' */
+       146,    /* 'b' */
+       181,    /* 'c' */
+       146,    /* 'd' */
+       178,    /* 'e' */
+       139,    /* 'f' */
+       183,    /* 'g' */
+       148,    /* 'h' */
+       181,    /* 'i' */
+       144,    /* 'j' */
+       179,    /* 'k' */
+       142,    /* 'l' */
+       182,    /* 'm' */
+       148,    /* 'n' */
+       178,    /* 'o' */
+       141,    /* 'p' */
+       181,    /* 'q' */
+       144,    /* 'r' */
+       183,    /* 's' */
+       148,    /* 't' */
+       181,    /* 'u' */
+       144,    /* 'v' */
+       179,    /* 'w' */
+       142,    /* 'x' */
+       182,    /* 'y' */
+       148,    /* 'z' */
+       177,    /* '{' */
+       185,    /* '|' */
+       180,    /* '}' */
+       143,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XPB */
+       {
+       186,    /* ' ' */
+       106,    /* '!' */
+       125,    /* '"' */
+       130,    /* '#' */
+       130,    /* '$' */
+       87,     /* '%' */
+       87,     /* '&' */
+       87,     /* ''' */
+       87,     /* '(' */
+       128,    /* ')' */
+       128,    /* '*' */
+       100,    /* '+' */
+       36,     /* ',' */
+       130,    /* '-' */
+       92,     /* '.' */
+       132,    /* '/' */
+       132,    /* '0' */
+       115,    /* '1' */
+       125,    /* '2' */
+       126,    /* '3' */
+       126,    /* '4' */
+       132,    /* '5' */
+       13,     /* '6' */
+       132,    /* '7' */
+       14,     /* '8' */
+       128,    /* '9' */
+       62,     /* ':' */
+       128,    /* ';' */
+       92,     /* '<' */
+       125,    /* '=' */
+       125,    /* '>' */
+       128,    /* '?' */
+       134,    /* '@' */
+       132,    /* 'A' */
+       92,     /* 'B' */
+       132,    /* 'C' */
+       92,     /* 'D' */
+       92,     /* 'E' */
+       132,    /* 'F' */
+       166,    /* 'G' */
+       132,    /* 'H' */
+       165,    /* 'I' */
+       128,    /* 'J' */
+       163,    /* 'K' */
+       126,    /* 'L' */
+       166,    /* 'M' */
+       132,    /* 'N' */
+       170,    /* 'O' */
+       132,    /* 'P' */
+       162,    /* 'Q' */
+       125,    /* 'R' */
+       132,    /* 'S' */
+       92,     /* 'T' */
+       166,    /* 'U' */
+       132,    /* 'V' */
+       165,    /* 'W' */
+       128,    /* 'X' */
+       163,    /* 'Y' */
+       126,    /* 'Z' */
+       166,    /* '[' */
+       132,    /* '\' */
+       166,    /* ']' */
+       132,    /* '^' */
+       165,    /* '_' */
+       128,    /* '`' */
+       165,    /* 'a' */
+       132,    /* 'b' */
+       166,    /* 'c' */
+       132,    /* 'd' */
+       162,    /* 'e' */
+       125,    /* 'f' */
+       166,    /* 'g' */
+       132,    /* 'h' */
+       165,    /* 'i' */
+       128,    /* 'j' */
+       163,    /* 'k' */
+       126,    /* 'l' */
+       166,    /* 'm' */
+       132,    /* 'n' */
+       162,    /* 'o' */
+       125,    /* 'p' */
+       165,    /* 'q' */
+       128,    /* 'r' */
+       166,    /* 's' */
+       132,    /* 't' */
+       165,    /* 'u' */
+       128,    /* 'v' */
+       163,    /* 'w' */
+       126,    /* 'x' */
+       166,    /* 'y' */
+       132,    /* 'z' */
+       163,    /* '{' */
+       126,    /* '|' */
+       165,    /* '}' */
+       128,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Palatino-Bold",
+       0,
+       NO
+       }, {
+       /* width table for font XPX */
+       {
+       55,     /* ' ' */
+       83,     /* '!' */
+       83,     /* '"' */
+       83,     /* '#' */
+       83,     /* '$' */
+       83,     /* '%' */
+       83,     /* '&' */
+       55,     /* ''' */
+       55,     /* '(' */
+       93,     /* ')' */
+       93,     /* '*' */
+       101,    /* '+' */
+       83,     /* ',' */
+       83,     /* '-' */
+       74,     /* '.' */
+       55,     /* '/' */
+       55,     /* '0' */
+       55,     /* '1' */
+       55,     /* '2' */
+       55,     /* '3' */
+       55,     /* '4' */
+       93,     /* '5' */
+       55,     /* '6' */
+       55,     /* '7' */
+       55,     /* '8' */
+       55,     /* '9' */
+       167,    /* ':' */
+       157,    /* ';' */
+       123,    /* '<' */
+       55,     /* '=' */
+       55,     /* '>' */
+       102,    /* '?' */
+       55,     /* '@' */
+       139,    /* 'A' */
+       93,     /* 'B' */
+       157,    /* 'C' */
+       130,    /* 'D' */
+       55,     /* 'E' */
+       93,     /* 'F' */
+       120,    /* 'G' */
+       93,     /* 'H' */
+       120,    /* 'I' */
+       93,     /* 'J' */
+       120,    /* 'K' */
+       93,     /* 'L' */
+       120,    /* 'M' */
+       93,     /* 'N' */
+       120,    /* 'O' */
+       93,     /* 'P' */
+       120,    /* 'Q' */
+       93,     /* 'R' */
+       114,    /* 'S' */
+       74,     /* 'T' */
+       102,    /* 'U' */
+       74,     /* 'V' */
+       102,    /* 'W' */
+       74,     /* 'X' */
+       102,    /* 'Y' */
+       74,     /* 'Z' */
+       102,    /* '[' */
+       74,     /* '\' */
+       65,     /* ']' */
+       55,     /* '^' */
+       65,     /* '_' */
+       55,     /* '`' */
+       65,     /* 'a' */
+       55,     /* 'b' */
+       65,     /* 'c' */
+       55,     /* 'd' */
+       130,    /* 'e' */
+       93,     /* 'f' */
+       139,    /* 'g' */
+       93,     /* 'h' */
+       139,    /* 'i' */
+       93,     /* 'j' */
+       139,    /* 'k' */
+       93,     /* 'l' */
+       139,    /* 'm' */
+       93,     /* 'n' */
+       139,    /* 'o' */
+       93,     /* 'p' */
+       93,     /* 'q' */
+       74,     /* 'r' */
+       130,    /* 's' */
+       93,     /* 't' */
+       130,    /* 'u' */
+       93,     /* 'v' */
+       130,    /* 'w' */
+       93,     /* 'x' */
+       130,    /* 'y' */
+       93,     /* 'z' */
+       102,    /* '{' */
+       93,     /* '|' */
+       111,    /* '}' */
+       83,     /* '~' */
+       42,     /* ' ' */
+       },
+       /* height table for font XPX */
+       {
+       270,    /* ' ' */
+       136,    /* '!' */
+       142,    /* '"' */
+       146,    /* '#' */
+       148,    /* '$' */
+       102,    /* '%' */
+       102,    /* '&' */
+       102,    /* ''' */
+       102,    /* '(' */
+       143,    /* ')' */
+       171,    /* '*' */
+       114,    /* '+' */
+       76,     /* ',' */
+       148,    /* '-' */
+       146,    /* '.' */
+       146,    /* '/' */
+       146,    /* '0' */
+       129,    /* '1' */
+       142,    /* '2' */
+       139,    /* '3' */
+       139,    /* '4' */
+       146,    /* '5' */
+       64,     /* '6' */
+       146,    /* '7' */
+       57,     /* '8' */
+       142,    /* '9' */
+       76,     /* ':' */
+       143,    /* ';' */
+       108,    /* '<' */
+       142,    /* '=' */
+       142,    /* '>' */
+       143,    /* '?' */
+       151,    /* '@' */
+       158,    /* 'A' */
+       120,    /* 'B' */
+       148,    /* 'C' */
+       108,    /* 'D' */
+       108,    /* 'E' */
+       194,    /* 'F' */
+       180,    /* 'G' */
+       148,    /* 'H' */
+       178,    /* 'I' */
+       144,    /* 'J' */
+       175,    /* 'K' */
+       141,    /* 'L' */
+       180,    /* 'M' */
+       148,    /* 'N' */
+       184,    /* 'O' */
+       148,    /* 'P' */
+       173,    /* 'Q' */
+       139,    /* 'R' */
+       181,    /* 'S' */
+       141,    /* 'T' */
+       180,    /* 'U' */
+       148,    /* 'V' */
+       178,    /* 'W' */
+       144,    /* 'X' */
+       175,    /* 'Y' */
+       141,    /* 'Z' */
+       180,    /* '[' */
+       148,    /* '\' */
+       180,    /* ']' */
+       148,    /* '^' */
+       178,    /* '_' */
+       144,    /* '`' */
+       175,    /* 'a' */
+       145,    /* 'b' */
+       180,    /* 'c' */
+       148,    /* 'd' */
+       173,    /* 'e' */
+       139,    /* 'f' */
+       182,    /* 'g' */
+       148,    /* 'h' */
+       179,    /* 'i' */
+       144,    /* 'j' */
+       177,    /* 'k' */
+       141,    /* 'l' */
+       182,    /* 'm' */
+       148,    /* 'n' */
+       174,    /* 'o' */
+       139,    /* 'p' */
+       179,    /* 'q' */
+       144,    /* 'r' */
+       182,    /* 's' */
+       148,    /* 't' */
+       179,    /* 'u' */
+       144,    /* 'v' */
+       177,    /* 'w' */
+       141,    /* 'x' */
+       182,    /* 'y' */
+       148,    /* 'z' */
+       175,    /* '{' */
+       185,    /* '|' */
+       177,    /* '}' */
+       144,    /* '~' */
+       28,     /* ' ' */
+       },
+       /* ascent table for font XPX */
+       {
+       188,    /* ' ' */
+       105,    /* '!' */
+       128,    /* '"' */
+       132,    /* '#' */
+       134,    /* '$' */
+       88,     /* '%' */
+       88,     /* '&' */
+       88,     /* ''' */
+       88,     /* '(' */
+       128,    /* ')' */
+       132,    /* '*' */
+       100,    /* '+' */
+       38,     /* ',' */
+       134,    /* '-' */
+       94,     /* '.' */
+       132,    /* '/' */
+       132,    /* '0' */
+       115,    /* '1' */
+       128,    /* '2' */
+       125,    /* '3' */
+       125,    /* '4' */
+       132,    /* '5' */
+       15,     /* '6' */
+       132,    /* '7' */
+       11,     /* '8' */
+       128,    /* '9' */
+       62,     /* ':' */
+       128,    /* ';' */
+       92,     /* '<' */
+       128,    /* '=' */
+       128,    /* '>' */
+       128,    /* '?' */
+       135,    /* '@' */
+       136,    /* 'A' */
+       98,     /* 'B' */
+       132,    /* 'C' */
+       92,     /* 'D' */
+       92,     /* 'E' */
+       135,    /* 'F' */
+       166,    /* 'G' */
+       132,    /* 'H' */
+       163,    /* 'I' */
+       128,    /* 'J' */
+       161,    /* 'K' */
+       125,    /* 'L' */
+       166,    /* 'M' */
+       132,    /* 'N' */
+       170,    /* 'O' */
+       132,    /* 'P' */
+       158,    /* 'Q' */
+       123,    /* 'R' */
+       132,    /* 'S' */
+       92,     /* 'T' */
+       166,    /* 'U' */
+       132,    /* 'V' */
+       163,    /* 'W' */
+       128,    /* 'X' */
+       161,    /* 'Y' */
+       125,    /* 'Z' */
+       166,    /* '[' */
+       132,    /* '\' */
+       166,    /* ']' */
+       132,    /* '^' */
+       163,    /* '_' */
+       128,    /* '`' */
+       161,    /* 'a' */
+       129,    /* 'b' */
+       166,    /* 'c' */
+       132,    /* 'd' */
+       158,    /* 'e' */
+       123,    /* 'f' */
+       166,    /* 'g' */
+       132,    /* 'h' */
+       163,    /* 'i' */
+       128,    /* 'j' */
+       161,    /* 'k' */
+       125,    /* 'l' */
+       166,    /* 'm' */
+       132,    /* 'n' */
+       158,    /* 'o' */
+       123,    /* 'p' */
+       163,    /* 'q' */
+       128,    /* 'r' */
+       166,    /* 's' */
+       132,    /* 't' */
+       163,    /* 'u' */
+       128,    /* 'v' */
+       161,    /* 'w' */
+       125,    /* 'x' */
+       166,    /* 'y' */
+       132,    /* 'z' */
+       161,    /* '{' */
+       125,    /* '|' */
+       163,    /* '}' */
+       128,    /* '~' */
+       14,     /* ' ' */
+       },
+
+       "Ext-Palatino-BoldItalic",
+       0,
+       YES
+       }, {
+#endif
+       /* width table for font ZD */
+       {
+       46,     /* ' ' */
+       162,    /* '!' */
+       160,    /* '"' */
+       162,    /* '#' */
+       163,    /* '$' */
+       120,    /* '%' */
+       131,    /* '&' */
+       132,    /* ''' */
+       132,    /* '(' */
+       115,    /* ')' */
+       160,    /* '*' */
+       156,    /* '+' */
+       91,     /* ',' */
+       142,    /* '-' */
+       152,    /* '.' */
+       155,    /* '/' */
+       152,    /* '0' */
+       157,    /* '1' */
+       162,    /* '2' */
+       126,    /* '3' */
+       141,    /* '4' */
+       127,    /* '5' */
+       127,    /* '6' */
+       95,     /* '7' */
+       113,    /* '8' */
+       127,    /* '9' */
+       127,    /* ':' */
+       126,    /* ';' */
+       126,    /* '<' */
+       82,     /* '=' */
+       92,     /* '>' */
+       89,     /* '?' */
+       96,     /* '@' */
+       115,    /* 'A' */
+       131,    /* 'B' */
+       131,    /* 'C' */
+       131,    /* 'D' */
+       132,    /* 'E' */
+       132,    /* 'F' */
+       132,    /* 'G' */
+       136,    /* 'H' */
+       137,    /* 'I' */
+       131,    /* 'J' */
+       140,    /* 'K' */
+       137,    /* 'L' */
+       139,    /* 'M' */
+       136,    /* 'N' */
+       138,    /* 'O' */
+       154,    /* 'P' */
+       124,    /* 'Q' */
+       120,    /* 'R' */
+       125,    /* 'S' */
+       132,    /* 'T' */
+       132,    /* 'U' */
+       116,    /* 'V' */
+       129,    /* 'W' */
+       128,    /* 'X' */
+       132,    /* 'Y' */
+       126,    /* 'Z' */
+       118,    /* '[' */
+       118,    /* '\' */
+       114,    /* ']' */
+       117,    /* '^' */
+       138,    /* '_' */
+       136,    /* '`' */
+       131,    /* 'a' */
+       131,    /* 'b' */
+       118,    /* 'c' */
+       114,    /* 'd' */
+       116,    /* 'e' */
+       115,    /* 'f' */
+       131,    /* 'g' */
+       131,    /* 'h' */
+       119,    /* 'i' */
+       132,    /* 'j' */
+       131,    /* 'k' */
+       132,    /* 'l' */
+       145,    /* 'm' */
+       127,    /* 'n' */
+       127,    /* 'o' */
+       127,    /* 'p' */
+       126,    /* 'q' */
+       126,    /* 'r' */
+       149,    /* 's' */
+       149,    /* 't' */
+       131,    /* 'u' */
+       131,    /* 'v' */
+       73,     /* 'w' */
+       23,     /* 'x' */
+       46,     /* 'y' */
+       69,     /* 'z' */
+       65,     /* '{' */
+       65,     /* '|' */
+       111,    /* '}' */
+       111,    /* '~' */
+       },
+       /* height table for font ZD */
+       {
+       153,    /* ' ' */
+       129,    /* '!' */
+       129,    /* '"' */
+       129,    /* '#' */
+       142,    /* '$' */
+       122,    /* '%' */
+       148,    /* '&' */
+       148,    /* ''' */
+       148,    /* '(' */
+       119,    /* ')' */
+       122,    /* '*' */
+       119,    /* '+' */
+       148,    /* ',' */
+       133,    /* '-' */
+       135,    /* '.' */
+       119,    /* '/' */
+       132,    /* '0' */
+       119,    /* '1' */
+       126,    /* '2' */
+       147,    /* '3' */
+       148,    /* '4' */
+       143,    /* '5' */
+       143,    /* '6' */
+       149,    /* '7' */
+       148,    /* '8' */
+       142,    /* '9' */
+       142,    /* ':' */
+       143,    /* ';' */
+       142,    /* '<' */
+       142,    /* '=' */
+       144,    /* '>' */
+       142,    /* '?' */
+       127,    /* '@' */
+       147,    /* 'A' */
+       148,    /* 'B' */
+       148,    /* 'C' */
+       148,    /* 'D' */
+       148,    /* 'E' */
+       148,    /* 'F' */
+       148,    /* 'G' */
+       148,    /* 'H' */
+       148,    /* 'I' */
+       148,    /* 'J' */
+       148,    /* 'K' */
+       147,    /* 'L' */
+       148,    /* 'M' */
+       148,    /* 'N' */
+       148,    /* 'O' */
+       148,    /* 'P' */
+       142,    /* 'Q' */
+       142,    /* 'R' */
+       142,    /* 'S' */
+       148,    /* 'T' */
+       148,    /* 'U' */
+       148,    /* 'V' */
+       148,    /* 'W' */
+       145,    /* 'X' */
+       148,    /* 'Y' */
+       142,    /* 'Z' */
+       148,    /* '[' */
+       148,    /* '\' */
+       144,    /* ']' */
+       148,    /* '^' */
+       149,    /* '_' */
+       148,    /* '`' */
+       148,    /* 'a' */
+       148,    /* 'b' */
+       147,    /* 'c' */
+       142,    /* 'd' */
+       143,    /* 'e' */
+       141,    /* 'f' */
+       148,    /* 'g' */
+       148,    /* 'h' */
+       148,    /* 'i' */
+       148,    /* 'j' */
+       148,    /* 'k' */
+       148,    /* 'l' */
+       148,    /* 'm' */
+       142,    /* 'n' */
+       142,    /* 'o' */
+       144,    /* 'p' */
+       142,    /* 'q' */
+       144,    /* 'r' */
+       145,    /* 's' */
+       145,    /* 't' */
+       148,    /* 'u' */
+       148,    /* 'v' */
+       148,    /* 'w' */
+       142,    /* 'x' */
+       142,    /* 'y' */
+       142,    /* 'z' */
+       146,    /* '{' */
+       146,    /* '|' */
+       145,    /* '}' */
+       146,    /* '~' */
+       },
+       /* ascent table for font ZD */
+       {
+       108,    /* ' ' */
+       115,    /* '!' */
+       115,    /* '"' */
+       115,    /* '#' */
+       128,    /* '$' */
+       108,    /* '%' */
+       132,    /* '&' */
+       132,    /* ''' */
+       132,    /* '(' */
+       105,    /* ')' */
+       108,    /* '*' */
+       105,    /* '+' */
+       132,    /* ',' */
+       119,    /* '-' */
+       121,    /* '.' */
+       105,    /* '/' */
+       118,    /* '0' */
+       105,    /* '1' */
+       112,    /* '2' */
+       131,    /* '3' */
+       132,    /* '4' */
+       129,    /* '5' */
+       129,    /* '6' */
+       124,    /* '7' */
+       132,    /* '8' */
+       128,    /* '9' */
+       128,    /* ':' */
+       129,    /* ';' */
+       128,    /* '<' */
+       128,    /* '=' */
+       128,    /* '>' */
+       128,    /* '?' */
+       113,    /* '@' */
+       131,    /* 'A' */
+       132,    /* 'B' */
+       132,    /* 'C' */
+       132,    /* 'D' */
+       132,    /* 'E' */
+       132,    /* 'F' */
+       132,    /* 'G' */
+       132,    /* 'H' */
+       134,    /* 'I' */
+       132,    /* 'J' */
+       132,    /* 'K' */
+       132,    /* 'L' */
+       132,    /* 'M' */
+       132,    /* 'N' */
+       132,    /* 'O' */
+       132,    /* 'P' */
+       128,    /* 'Q' */
+       128,    /* 'R' */
+       128,    /* 'S' */
+       132,    /* 'T' */
+       132,    /* 'U' */
+       132,    /* 'V' */
+       132,    /* 'W' */
+       130,    /* 'X' */
+       134,    /* 'Y' */
+       128,    /* 'Z' */
+       132,    /* '[' */
+       132,    /* '\' */
+       130,    /* ']' */
+       132,    /* '^' */
+       133,    /* '_' */
+       132,    /* '`' */
+       132,    /* 'a' */
+       132,    /* 'b' */
+       133,    /* 'c' */
+       129,    /* 'd' */
+       129,    /* 'e' */
+       127,    /* 'f' */
+       132,    /* 'g' */
+       132,    /* 'h' */
+       132,    /* 'i' */
+       132,    /* 'j' */
+       132,    /* 'k' */
+       132,    /* 'l' */
+       132,    /* 'm' */
+       128,    /* 'n' */
+       128,    /* 'o' */
+       128,    /* 'p' */
+       128,    /* 'q' */
+       128,    /* 'r' */
+       132,    /* 's' */
+       128,    /* 't' */
+       131,    /* 'u' */
+       131,    /* 'v' */
+       132,    /* 'w' */
+       128,    /* 'x' */
+       128,    /* 'y' */
+       128,    /* 'z' */
+       132,    /* '{' */
+       132,    /* '|' */
+       131,    /* '}' */
+       132,    /* '~' */
+       },
+
+       "ZapfDingbats",
+       0,
+       NO
+       }, {
+       /* width table for font ZI */
+       {
+       37,     /* ' ' */
+       47,     /* '!' */
+       37,     /* '"' */
+       73,     /* '#' */
+       73,     /* '$' */
+       113,    /* '%' */
+       130,    /* '&' */
+       40,     /* ''' */
+       43,     /* '(' */
+       37,     /* ')' */
+       70,     /* '*' */
+       87,     /* '+' */
+       37,     /* ',' */
+       47,     /* '-' */
+       37,     /* '.' */
+       57,     /* '/' */
+       73,     /* '0' */
+       73,     /* '1' */
+       73,     /* '2' */
+       73,     /* '3' */
+       73,     /* '4' */
+       73,     /* '5' */
+       73,     /* '6' */
+       73,     /* '7' */
+       73,     /* '8' */
+       73,     /* '9' */
+       43,     /* ':' */
+       40,     /* ';' */
+       87,     /* '<' */
+       87,     /* '=' */
+       87,     /* '>' */
+       63,     /* '?' */
+       117,    /* '@' */
+       103,    /* 'A' */
+       100,    /* 'B' */
+       87,     /* 'C' */
+       117,    /* 'D' */
+       103,    /* 'E' */
+       97,     /* 'F' */
+       103,    /* 'G' */
+       113,    /* 'H' */
+       63,     /* 'I' */
+       67,     /* 'J' */
+       110,    /* 'K' */
+       97,     /* 'L' */
+       140,    /* 'M' */
+       117,    /* 'N' */
+       100,    /* 'O' */
+       90,     /* 'P' */
+       100,    /* 'Q' */
+       100,    /* 'R' */
+       77,     /* 'S' */
+       83,     /* 'T' */
+       123,    /* 'U' */
+       107,    /* 'V' */
+       147,    /* 'W' */
+       93,     /* 'X' */
+       93,     /* 'Y' */
+       103,    /* 'Z' */
+       40,     /* '[' */
+       80,     /* '\' */
+       53,     /* ']' */
+       87,     /* '^' */
+       83,     /* '_' */
+       40,     /* '`' */
+       70,     /* 'a' */
+       70,     /* 'b' */
+       57,     /* 'c' */
+       73,     /* 'd' */
+       57,     /* 'e' */
+       53,     /* 'f' */
+       67,     /* 'g' */
+       73,     /* 'h' */
+       40,     /* 'i' */
+       37,     /* 'j' */
+       73,     /* 'k' */
+       40,     /* 'l' */
+       103,    /* 'm' */
+       77,     /* 'n' */
+       67,     /* 'o' */
+       73,     /* 'p' */
+       67,     /* 'q' */
+       50,     /* 'r' */
+       53,     /* 's' */
+       53,     /* 't' */
+       77,     /* 'u' */
+       73,     /* 'v' */
+       113,    /* 'w' */
+       70,     /* 'x' */
+       67,     /* 'y' */
+       73,     /* 'z' */
+       40,     /* '{' */
+       87,     /* '|' */
+       40,     /* '}' */
+       87,     /* '~' */
+       },
+       /* height table for font ZI */
+       {
+       153,    /* ' ' */
+       127,    /* '!' */
+       126,    /* '"' */
+       124,    /* '#' */
+       164,    /* '$' */
+       128,    /* '%' */
+       123,    /* '&' */
+       124,    /* ''' */
+       167,    /* '(' */
+       167,    /* ')' */
+       141,    /* '*' */
+       98,     /* '+' */
+       73,     /* ',' */
+       66,     /* '-' */
+       51,     /* '.' */
+       169,    /* '/' */
+       124,    /* '0' */
+       125,    /* '1' */
+       125,    /* '2' */
+       122,    /* '3' */
+       129,    /* '4' */
+       137,    /* '5' */
+       128,    /* '6' */
+       133,    /* '7' */
+       124,    /* '8' */
+       124,    /* '9' */
+       97,     /* ':' */
+       112,    /* ';' */
+       103,    /* '<' */
+       82,     /* '=' */
+       103,    /* '>' */
+       127,    /* '?' */
+       131,    /* '@' */
+       129,    /* 'A' */
+       130,    /* 'B' */
+       138,    /* 'C' */
+       130,    /* 'D' */
+       128,    /* 'E' */
+       150,    /* 'F' */
+       165,    /* 'G' */
+       142,    /* 'H' */
+       123,    /* 'I' */
+       143,    /* 'J' */
+       149,    /* 'K' */
+       124,    /* 'L' */
+       141,    /* 'M' */
+       166,    /* 'N' */
+       128,    /* 'O' */
+       128,    /* 'P' */
+       158,    /* 'Q' */
+       155,    /* 'R' */
+       138,    /* 'S' */
+       136,    /* 'T' */
+       126,    /* 'U' */
+       144,    /* 'V' */
+       143,    /* 'W' */
+       128,    /* 'X' */
+       154,    /* 'Y' */
+       130,    /* 'Z' */
+       166,    /* '[' */
+       122,    /* '\' */
+       166,    /* ']' */
+       141,    /* '^' */
+       34,     /* '_' */
+       140,    /* '`' */
+       98,     /* 'a' */
+       143,    /* 'b' */
+       98,     /* 'c' */
+       142,    /* 'd' */
+       98,     /* 'e' */
+       182,    /* 'f' */
+       134,    /* 'g' */
+       143,    /* 'h' */
+       133,    /* 'i' */
+       173,    /* 'j' */
+       165,    /* 'k' */
+       142,    /* 'l' */
+       97,     /* 'm' */
+       98,     /* 'n' */
+       98,     /* 'o' */
+       137,    /* 'p' */
+       150,    /* 'q' */
+       97,     /* 'r' */
+       98,     /* 's' */
+       114,    /* 't' */
+       99,     /* 'u' */
+       103,    /* 'v' */
+       104,    /* 'w' */
+       121,    /* 'x' */
+       137,    /* 'y' */
+       101,    /* 'z' */
+       165,    /* '{' */
+       148,    /* '|' */
+       165,    /* '}' */
+       74,     /* '~' */
+       },
+       /* ascent table for font ZI */
+       {
+       108,    /* ' ' */
+       112,    /* '!' */
+       112,    /* '"' */
+       110,    /* '#' */
+       126,    /* '$' */
+       112,    /* '%' */
+       107,    /* '&' */
+       110,    /* ''' */
+       125,    /* '(' */
+       125,    /* ')' */
+       127,    /* '*' */
+       85,     /* '+' */
+       43,     /* ',' */
+       52,     /* '-' */
+       35,     /* '.' */
+       127,    /* '/' */
+       108,    /* '0' */
+       111,    /* '1' */
+       108,    /* '2' */
+       108,    /* '3' */
+       111,    /* '4' */
+       121,    /* '5' */
+       112,    /* '6' */
+       116,    /* '7' */
+       108,    /* '8' */
+       108,    /* '9' */
+       82,     /* ':' */
+       82,     /* ';' */
+       89,     /* '<' */
+       68,     /* '=' */
+       89,     /* '>' */
+       112,    /* '?' */
+       112,    /* '@' */
+       113,    /* 'A' */
+       117,    /* 'B' */
+       112,    /* 'C' */
+       116,    /* 'D' */
+       112,    /* 'E' */
+       117,    /* 'F' */
+       112,    /* 'G' */
+       126,    /* 'H' */
+       109,    /* 'I' */
+       109,    /* 'J' */
+       109,    /* 'K' */
+       110,    /* 'L' */
+       125,    /* 'M' */
+       126,    /* 'N' */
+       112,    /* 'O' */
+       114,    /* 'P' */
+       112,    /* 'Q' */
+       116,    /* 'R' */
+       112,    /* 'S' */
+       122,    /* 'T' */
+       110,    /* 'U' */
+       128,    /* 'V' */
+       127,    /* 'W' */
+       112,    /* 'X' */
+       115,    /* 'Y' */
+       113,    /* 'Z' */
+       125,    /* '[' */
+       108,    /* '\' */
+       125,    /* ']' */
+       127,    /* '^' */
+       -2,     /* '_' */
+       127,    /* '`' */
+       82,     /* 'a' */
+       126,    /* 'b' */
+       82,     /* 'c' */
+       126,    /* 'd' */
+       82,     /* 'e' */
+       126,    /* 'f' */
+       82,     /* 'g' */
+       127,    /* 'h' */
+       117,    /* 'i' */
+       117,    /* 'j' */
+       126,    /* 'k' */
+       126,    /* 'l' */
+       82,     /* 'm' */
+       82,     /* 'n' */
+       82,     /* 'o' */
+       82,     /* 'p' */
+       94,     /* 'q' */
+       82,     /* 'r' */
+       82,     /* 's' */
+       98,     /* 't' */
+       83,     /* 'u' */
+       87,     /* 'v' */
+       88,     /* 'w' */
+       82,     /* 'x' */
+       83,     /* 'y' */
+       85,     /* 'z' */
+       124,    /* '{' */
+       134,    /* '|' */
+       124,    /* '}' */
+       60,     /* '~' */
+       },
+
+       "ZapfChancery-MediumItalic",
+       0,
+       YES
+       }, {
+{
+       272,    /* gclef */
+       279,    /* fclef */
+       237,    /* cclef */
+       147,    /* dblwhole */
+       145,    /* 1n */
+       118,    /* 2n */
+       112,    /* 4n */
+       84,     /* upflag */
+       84,     /* dnflag */
+       70,     /* qwhrest */
+       70,     /* dwhrest */
+       237,    /* 1rest */
+       237,    /* 2rest */
+       113,    /* 4rest */
+       127,    /* 8rest */
+       138,    /* 16rest */
+       154,    /* 32rest */
+       168,    /* 64rest */
+       181,    /* 128rest */
+       197,    /* 256rest */
+       140,    /* ll1rest */
+       140,    /* ll2rest */
+       62,     /* dot */
+       95,     /* nat */
+       120,    /* sharp */
+       104,    /* flat */
+       123,    /* dblsharp */
+       186,    /* dblflat */
+       118,    /* xnote */
+       155,    /* dwhdiamond */
+       118,    /* diamond */
+       118,    /* filldiamond */
+       145,    /* up2n */
+       145,    /* dn2n */
+       141,    /* up4n */
+       140,    /* dn4n */
+       176,    /* com */
+       176,    /* cut */
+       61,     /* begped */
+       140,    /* pedal */
+       62,     /* endped */
+       136,    /* dnbow */
+       123,    /* upbow */
+       70,     /* wedge */
+       70,     /* uwedge */
+       251,    /* ferm */
+       251,    /* uferm */
+       209,    /* sign */
+       251,    /* coda */
+       206,    /* mor */
+       206,    /* invmor */
+       204,    /* turn */
+       204,    /* invturn */
+       186,    /* acc_gt */
+       131,    /* acc_hat */
+       131,    /* acc_uhat */
+       223,    /* tr */
+       140,    /* leg */
+       154,    /* rr */
+       98,     /* dim */
+       129,    /* halfdim */
+       134,    /* triangle */
+       204,    /* measrpt */
+       151,    /* copyright */
+       216,    /* up8n */
+       140,    /* dn8n */
+       216,    /* up16n */
+       140,    /* dn16n */
+       216,    /* up32n */
+       140,    /* dn32n */
+       216,    /* up64n */
+       140,    /* dn64n */
+       216,    /* up128n */
+       140,    /* dn128n */
+       216,    /* up256n */
+       140,    /* dn256n */
+}, {
+       666,    /* gclef */
+       352,    /* fclef */
+       372,    /* cclef */
+       166,    /* dblwhole */
+       91,     /* 1n */
+       94,     /* 2n */
+       91,     /* 4n */
+       236,    /* upflag */
+       236,    /* dnflag */
+       194,    /* qwhrest */
+       111,    /* dwhrest */
+       115,    /* 1rest */
+       75,     /* 2rest */
+       284,    /* 4rest */
+       177,    /* 8rest */
+       261,    /* 16rest */
+       344,    /* 32rest */
+       386,    /* 64rest */
+       469,    /* 128rest */
+       552,    /* 256rest */
+       112,    /* ll1rest */
+       70,     /* ll2rest */
+       61,     /* dot */
+       263,    /* nat */
+       286,    /* sharp */
+       236,    /* flat */
+       122,    /* dblsharp */
+       236,    /* dblflat */
+       100,    /* xnote */
+       194,    /* dwhdiamond */
+       83,     /* diamond */
+       83,     /* filldiamond */
+       366,    /* up2n */
+       366,    /* dn2n */
+       365,    /* up4n */
+       365,    /* dn4n */
+       204,    /* com */
+       277,    /* cut */
+       116,    /* begped */
+       97,     /* pedal */
+       116,    /* endped */
+       152,    /* dnbow */
+       169,    /* upbow */
+       95,     /* wedge */
+       95,     /* uwedge */
+       166,    /* ferm */
+       166,    /* uferm */
+       255,    /* sign */
+       263,    /* coda */
+       105,    /* mor */
+       152,    /* invmor */
+       118,    /* turn */
+       119,    /* invturn */
+       119,    /* acc_gt */
+       147,    /* acc_hat */
+       147,    /* acc_uhat */
+       166,    /* tr */
+       41,     /* leg */
+       172,    /* rr */
+       151,    /* dim */
+       166,    /* halfdim */
+       140,    /* triangle */
+       213,    /* measrpt */
+       150,    /* copyright */
+       365,    /* up8n */
+       365,    /* dn8n */
+       365,    /* up16n */
+       365,    /* dn16n */
+       431,    /* up32n */
+       431,    /* dn32n */
+       498,    /* up64n */
+       498,    /* dn64n */
+       565,    /* up128n */
+       565,    /* dn128n */
+       623,    /* up256n */
+       623,    /* dn256n */
+}, {
+       430,    /* gclef */
+       102,    /* fclef */
+       186,    /* cclef */
+       83,     /* dblwhole */
+       45,     /* 1n */
+       47,     /* 2n */
+       45,     /* 4n */
+       236,    /* upflag */
+       0,      /* dnflag */
+       97,     /* qwhrest */
+       97,     /* dwhrest */
+       101,    /* 1rest */
+       55,     /* 2rest */
+       148,    /* 4rest */
+       79,     /* 8rest */
+       79,     /* 16rest */
+       162,    /* 32rest */
+       162,    /* 64rest */
+       245,    /* 128rest */
+       245,    /* 256rest */
+       98,     /* ll1rest */
+       55,     /* ll2rest */
+       30,     /* dot */
+       131,    /* nat */
+       143,    /* sharp */
+       166,    /* flat */
+       61,     /* dblsharp */
+       166,    /* dblflat */
+       50,     /* xnote */
+       97,     /* dwhdiamond */
+       41,     /* diamond */
+       41,     /* filldiamond */
+       305,    /* up2n */
+       61,     /* dn2n */
+       305,    /* up4n */
+       59,     /* dn4n */
+       102,    /* com */
+       138,    /* cut */
+       97,     /* begped */
+       91,     /* pedal */
+       97,     /* endped */
+       138,    /* dnbow */
+       140,    /* upbow */
+       83,     /* wedge */
+       81,     /* uwedge */
+       152,    /* ferm */
+       152,    /* uferm */
+       127,    /* sign */
+       131,    /* coda */
+       52,     /* mor */
+       76,     /* invmor */
+       59,     /* turn */
+       59,     /* invturn */
+       59,     /* acc_gt */
+       133,    /* acc_hat */
+       133,    /* acc_uhat */
+       152,    /* tr */
+       20,     /* leg */
+       155,    /* rr */
+       137,    /* dim */
+       152,    /* halfdim */
+       120,    /* triangle */
+       106,    /* measrpt */
+       130,    /* copyright */
+       305,    /* up8n */
+       59,     /* dn8n */
+       305,    /* up16n */
+       59,     /* dn16n */
+       372,    /* up32n */
+       59,     /* dn32n */
+       438,    /* up64n */
+       59,     /* dn64n */
+       505,    /* up128n */
+       59,     /* dn128n */
+       563,    /* up256n */
+       59,     /* dn256n */
+},
+       "mfont0",
+       0,
+       NO
+   },  {
+{
+       127,    /* dwhrighttriangle */
+       118,    /* righttriangle */
+       118,    /* fillrighttriangle */
+       127,    /* udwhrighttriangle */
+       118,    /* urighttriangle */
+       118,    /* ufillrighttriangle */
+       127,    /* dwhrectangle */
+       118,    /* rectangle */
+       118,    /* fillrectangle */
+       127,    /* dwhisostriangle */
+       118,    /* isostriangle */
+       118,    /* fillisostriangle */
+       127,    /* dwhpiewedge */
+       118,    /* piewedge */
+       118,    /* fillpiewedge */
+       127,    /* dwhsemicircle */
+       118,    /* semicircle */
+       118,    /* fillsemicircle */
+       191,    /* dwhslashhead */
+       187,    /* slashhead */
+       176,    /* fillslashhead */
+       118,    /* blankhead */
+}, {
+       166,    /* dwhrighttriangle */
+       79,     /* righttriangle */
+       79,     /* fillrighttriangle */
+       166,    /* udwhrighttriangle */
+       79,     /* urighttriangle */
+       79,     /* ufillrighttriangle */
+       166,    /* dwhrectangle */
+       75,     /* rectangle */
+       75,     /* fillrectangle */
+       166,    /* dwhisostriangle */
+       79,     /* isostriangle */
+       79,     /* fillisostriangle */
+       166,    /* dwhpiewedge */
+       79,     /* piewedge */
+       79,     /* fillpiewedge */
+       166,    /* dwhsemicircle */
+       79,     /* semicircle */
+       79,     /* fillsemicircle */
+       200,    /* dwhslashhead */
+       200,    /* slashhead */
+       186,    /* fillslashhead */
+       75,     /* blankhead */
+}, {
+       83,     /* dwhrighttriangle */
+       37,     /* righttriangle */
+       37,     /* fillrighttriangle */
+       83,     /* udwhrighttriangle */
+       41,     /* urighttriangle */
+       41,     /* ufillrighttriangle */
+       83,     /* dwhrectangle */
+       37,     /* rectangle */
+       37,     /* fillrectangle */
+       83,     /* dwhisostriangle */
+       41,     /* isostriangle */
+       41,     /* fillisostriangle */
+       83,     /* dwhpiewedge */
+       37,     /* piewedge */
+       37,     /* fillpiewedge */
+       83,     /* dwhsemicircle */
+       37,     /* semicircle */
+       37,     /* fillsemicircle */
+       100,    /* dwhslashhead */
+       100,    /* slashhead */
+       93,     /* fillslashhead */
+       37,     /* blankhead */
+},
+       "mfont1",
+       0,
+       NO
+}};
+\f
+/* table of maximum heights for each font in inches */
+
+float Maxfontheight[MAXFONTS] = {
+       (double) 178 / (double) FONTFACTOR,
+       (double) 178 / (double) FONTFACTOR,
+       (double) 178 / (double) FONTFACTOR,
+       (double) 178 / (double) FONTFACTOR,
+       (double) 184 / (double) FONTFACTOR,
+       (double) 184 / (double) FONTFACTOR,
+       (double) 184 / (double) FONTFACTOR,
+       (double) 184 / (double) FONTFACTOR,
+       (double) 164 / (double) FONTFACTOR,
+       (double) 164 / (double) FONTFACTOR,
+       (double) 168 / (double) FONTFACTOR,
+       (double) 168 / (double) FONTFACTOR,
+       (double) 185 / (double) FONTFACTOR,
+       (double) 185 / (double) FONTFACTOR,
+       (double) 185 / (double) FONTFACTOR,
+       (double) 185 / (double) FONTFACTOR,
+       (double) 178 / (double) FONTFACTOR,
+       (double) 184 / (double) FONTFACTOR,
+       (double) 188 / (double) FONTFACTOR,
+       (double) 190 / (double) FONTFACTOR,
+       (double) 184 / (double) FONTFACTOR,
+       (double) 186 / (double) FONTFACTOR,
+       (double) 188 / (double) FONTFACTOR,
+       (double) 186 / (double) FONTFACTOR,
+       (double) 189 / (double) FONTFACTOR,
+       (double) 195 / (double) FONTFACTOR,
+       (double) 191 / (double) FONTFACTOR,
+       (double) 194 / (double) FONTFACTOR,
+#ifdef EXTCHAR
+       (double) 266 / (double) FONTFACTOR,
+       (double) 265 / (double) FONTFACTOR,
+       (double) 268 / (double) FONTFACTOR,
+       (double) 269 / (double) FONTFACTOR,
+       (double) 276 / (double) FONTFACTOR,
+       (double) 276 / (double) FONTFACTOR,
+       (double) 276 / (double) FONTFACTOR,
+       (double) 276 / (double) FONTFACTOR,
+       (double) 260 / (double) FONTFACTOR,
+       (double) 260 / (double) FONTFACTOR,
+       (double) 263 / (double) FONTFACTOR,
+       (double) 263 / (double) FONTFACTOR,
+       (double) 275 / (double) FONTFACTOR,
+       (double) 275 / (double) FONTFACTOR,
+       (double) 275 / (double) FONTFACTOR,
+       (double) 275 / (double) FONTFACTOR,
+       (double) 273 / (double) FONTFACTOR,
+       (double) 273 / (double) FONTFACTOR,
+       (double) 273 / (double) FONTFACTOR,
+       (double) 272 / (double) FONTFACTOR,
+       (double) 276 / (double) FONTFACTOR,
+       (double) 276 / (double) FONTFACTOR,
+       (double) 276 / (double) FONTFACTOR,
+       (double) 276 / (double) FONTFACTOR,
+       (double) 268 / (double) FONTFACTOR,
+       (double) 277 / (double) FONTFACTOR,
+       (double) 268 / (double) FONTFACTOR,
+       (double) 270 / (double) FONTFACTOR,
+#endif
+       (double) 153 / (double) FONTFACTOR,
+       (double) 182 / (double) FONTFACTOR,
+       (double) DFLT_SIZE / (double) PPI
+};
+\f
+/* table of maximum ascents for each font in inches */
+
+float Maxfontascent[MAXFONTS] = {
+       (double) 135 / (double) FONTFACTOR,
+       (double) 136 / (double) FONTFACTOR,
+       (double) 139 / (double) FONTFACTOR,
+       (double) 136 / (double) FONTFACTOR,
+       (double) 148 / (double) FONTFACTOR,
+       (double) 148 / (double) FONTFACTOR,
+       (double) 155 / (double) FONTFACTOR,
+       (double) 155 / (double) FONTFACTOR,
+       (double) 125 / (double) FONTFACTOR,
+       (double) 125 / (double) FONTFACTOR,
+       (double) 130 / (double) FONTFACTOR,
+       (double) 130 / (double) FONTFACTOR,
+       (double) 142 / (double) FONTFACTOR,
+       (double) 142 / (double) FONTFACTOR,
+       (double) 141 / (double) FONTFACTOR,
+       (double) 141 / (double) FONTFACTOR,
+       (double) 146 / (double) FONTFACTOR,
+       (double) 141 / (double) FONTFACTOR,
+       (double) 148 / (double) FONTFACTOR,
+       (double) 145 / (double) FONTFACTOR,
+       (double) 147 / (double) FONTFACTOR,
+       (double) 146 / (double) FONTFACTOR,
+       (double) 147 / (double) FONTFACTOR,
+       (double) 146 / (double) FONTFACTOR,
+       (double) 136 / (double) FONTFACTOR,
+       (double) 136 / (double) FONTFACTOR,
+       (double) 135 / (double) FONTFACTOR,
+       (double) 137 / (double) FONTFACTOR,
+#ifdef EXTCHAR
+       (double) 186 / (double) FONTFACTOR,
+       (double) 186 / (double) FONTFACTOR,
+       (double) 189 / (double) FONTFACTOR,
+       (double) 189 / (double) FONTFACTOR,
+       (double) 199 / (double) FONTFACTOR,
+       (double) 199 / (double) FONTFACTOR,
+       (double) 199 / (double) FONTFACTOR,
+       (double) 199 / (double) FONTFACTOR,
+       (double) 179 / (double) FONTFACTOR,
+       (double) 179 / (double) FONTFACTOR,
+       (double) 179 / (double) FONTFACTOR,
+       (double) 179 / (double) FONTFACTOR,
+       (double) 196 / (double) FONTFACTOR,
+       (double) 196 / (double) FONTFACTOR,
+       (double) 199 / (double) FONTFACTOR,
+       (double) 199 / (double) FONTFACTOR,
+       (double) 193 / (double) FONTFACTOR,
+       (double) 193 / (double) FONTFACTOR,
+       (double) 196 / (double) FONTFACTOR,
+       (double) 196 / (double) FONTFACTOR,
+       (double) 199 / (double) FONTFACTOR,
+       (double) 199 / (double) FONTFACTOR,
+       (double) 199 / (double) FONTFACTOR,
+       (double) 199 / (double) FONTFACTOR,
+       (double) 186 / (double) FONTFACTOR,
+       (double) 186 / (double) FONTFACTOR,
+       (double) 186 / (double) FONTFACTOR,
+       (double) 188 / (double) FONTFACTOR,
+#endif
+       (double) 134 / (double) FONTFACTOR,
+       (double) 134 / (double) FONTFACTOR,
+       0.8 * ((double) DFLT_SIZE / (double) PPI)
+};
diff --git a/mup/mup/globals.c b/mup/mup/globals.c
new file mode 100644 (file)
index 0000000..27914c8
--- /dev/null
@@ -0,0 +1,266 @@
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2004, 2005, 2006
+ * by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ *     globals.c
+ *
+ *     This files defines all the global variables used in more than one
+ *     file, except for ones that are used only by yacc and lex.
+ */
+
+#include "structs.h"
+#include "rational.h"
+#include "globals.h"
+
+/*
+ * Define the fixed SSV structures, which accumulate attributes of the
+ * score, staffs, and voices.
+ */
+struct SSV Score;
+struct SSV Staff[MAXSTAFFS];
+struct SSV Voice[MAXSTAFFS][MAXVOICES];
+
+/*
+ * Define command line requested staff and voice visibilities.  Each value is
+ * YES or NO.
+ */
+short Staff_vis[MAXSTAFFS + 1];
+short Voice_vis[MAXSTAFFS + 1][MAXVOICES + 1];
+
+/*
+ * Define head and tail cells of the main linked list set up by the parser.
+ */
+struct MAINLL *Mainllhc_p;
+struct MAINLL *Mainlltc_p;
+
+int Optch = OPTION_MARKER;     /* character for command line options */
+int Mupmate = NO;              /* was Mup called from Mupmate? */
+int Errorcount;                /* number of errors found so far */
+int Maxverses;         /* maximum number of verse numbers used in the song */
+short Meas_num = 1;    /* count measure numbers */
+int Preproc = NO;      /* was -E specified on command line? */
+int Ppcomments = NO;   /* was -C specified on command line? */
+
+int Context = C_MUSIC;
+int Curr_family = BASE_TIMES;
+int Curr_font = FONT_TR;
+int Curr_size = DFLT_SIZE;
+int Got_some_data = NO;
+int Doing_tab_staff;   /* YES while parsing a line for a tab staff, else NO */
+int Doing_MIDI = NO;
+char *Curr_filename;
+char *Outfilename = "";
+int Vflag = NO;
+int Vcombused = NO;    /* was the voicecombine parameter ever used? */
+int CSBused = NO;      /* was cross staff beaming used in this song? */
+int CSSused = NO;      /* was cross staff stemming used in this song? */
+int CSSpass = NO;      /* YES while doing a special pass for cross staff stem*/
+
+/*
+ * Due to read ahead, we may already be on the following line when generating
+ * an error message, so need to know when to compensate by subtracting
+ * 1 from the current line number.
+ */
+int Last_was_newline = NO;
+
+/*
+ * The following table lets you conveniently find the character name of any
+ * note head type of form GF_NORMAL.  It is to be indexed like this:
+ *     headchar = Hctab [ basictime > 2 ? 3 : basictime ];
+ */
+unsigned char Hctab [] = {
+       C_DBLWHOLE,     C_1N,   C_2N,   C_4N
+};
+
+/*
+ * This table is like Hctab, but for X notes.  Note that for half notes and
+ * longer, we actually draw the note as a diamond instead of an X.
+ */
+unsigned char Xhctab[] = {
+       C_DWHDIAMOND,   C_DIAMOND,      C_DIAMOND,       C_XNOTE
+};
+
+/*
+ * This table is like Hctab, but for diamond shaped notes.
+ */
+unsigned char Dhctab[] = {
+       C_DWHDIAMOND,   C_DIAMOND,      C_DIAMOND,       C_FILLDIAMOND
+};
+
+/*
+ * The following table lets you conveniently find the character name of any
+ * rest type, whole or shorter.  It is to be indexed by log2(basictime).
+ */
+unsigned char Resttab[] = {
+       C_LL1REST, C_LL2REST, C_4REST, C_8REST, C_16REST, C_32REST, C_64REST,
+       C_128REST, C_256REST,
+};
+
+/*
+ * The following table tells how many letters up from C each note is.  It is
+ * to be indexed by (noteletter - 'a').
+ */
+int Letshift[] = { 5, 6, 0, 1, 2, 3, 4, };
+               /* a  b  c  d  e  f  g */
+
+/* the note letters in the order of the circle of fifths */
+char Circle[] = "fcgdaeb";
+
+/* internal accidental letters */
+char Acclets[] = "B&n#x";
+
+/* external accidental symbols */
+char *Acctostr[] = { "&&", "&", "", "#", "x" };
+
+/*
+ * Define strings for pedstyle = pedstar ("Ped." and the star).
+ */
+char Ped_start[] = { FONT_ZI, 18, 'P', 'e', 'd', '.', '\0' };
+char Ped_stop[] =  { FONT_ZD, 14, 'j', '\0' };
+
+/*
+ * Define the string info for standard guitar tuning.  Note that the octaves
+ * are for how it should be printed; the actual sound is an octave lower.
+ * When outputting MIDI, we check whether the tablature staff is using this
+ * default array, and if so, automatically transpose down by 12 halfsteps.
+ */
+struct STRINGINFO Guitar[DEFTABLINES] = {
+       { 'e', '\0', 0, 5 },
+       { 'b', '\0', 0, 4 },
+       { 'g', '\0', 0, 4 },
+       { 'd', '\0', 0, 4 },
+       { 'a', '\0', 0, 3 },
+       { 'e', '\0', 1, 3 },
+};
+
+/*
+ * These arrays are used to keep track of things while adjusting the pitches
+ * of notes to account for octave marks. They are indexed by staff number,
+ * so element 0 of each array is unused. Octave mark related transposition
+ * is done both in MIDI code and trantab code.
+ */
+int Octave_adjust[MAXSTAFFS+1];        /* how many octaves to adjust due to
+                                * user-specified octave marks */
+int Octave_bars[MAXSTAFFS+1];  /* how many bar lines to cross with
+                                * current Octave_adjust (if Octave_adjust is
+                                * zero, this variable is meaningless) */
+float Octave_count[MAXSTAFFS+1];/* number of counts into measure that
+                                * Octave_adjust applies in measure after
+                                * Octave_bars have gone by. (if Octave_adjust
+                                * is zero, this variable is meaningless */
+/*
+ * Define fixed location variables.  For all of these, only the absolute
+ * coordinates are used.
+ */
+float _Page    [NUMCTYPE];     /* whole page */
+float _Win     [NUMCTYPE];     /* middle (music) window */
+float _Cur     [NUMCTYPE];     /* current position */
+
+/*
+ * Define the structures for headers and footers.
+ */
+struct BLOCKHEAD Header;       /* first page header */
+struct BLOCKHEAD Footer;       /* first page footer */
+struct BLOCKHEAD Header2;      /* later page header */
+struct BLOCKHEAD Footer2;      /* later page footer */
+
+/*
+ * used by print phase to keep track of current staff locations
+ */
+float *Score_location_p;       /* score coord from FEED struct */
+float Staffs_y[MAXSTAFFS + 1]; /* absolute Y of the staffs of a score */
+
+/*
+ * While constructing a GRPSYL list of groups or lyrics, or a list of STUFF,
+ * any of which could be being defining for multiple staffs at once and/or more
+ * than one vno, keep a pointer to the list of staffs and vnos being defined.
+ * Once we gather an entire line of input, the GRPSYL list or STUFF list is
+ * cloned for each staff being defined, and the information is moved to be
+ * associated with the appropriate STAFF structs.
+ */
+struct RANGELIST *Staffrange_p;
+struct RANGELIST *Vnorange_p;
+
+/*
+ * During parse phase, this keeps track of the place (PL_ABOVE, PL_BELOW,
+ * or PL_BETWEEN) of the current thing being collected (groups, lyrics,
+ * or stuff).
+ */
+short Place;
+
+/*
+ * Snapshot of the state of pedals at the beginning of endings.
+ * The zeroth element of the array is used as a flag. If it is YES,
+ * the rest of the array contains the pedal state for each staff,
+ * YES for pedal on, NO for off. If the zeroth element is NO,
+ * the rest of the array is meaningless.
+ */
+short Ped_snapshot[MAXSTAFFS + 1];
+
+/* table to give a quick mapping from staff number to STAFF struct */
+struct MAINLL *Staffmap_p[MAXSTAFFS + 1];
+
+/* pointer to beginning of all the STAFF structs in current measure */
+struct MAINLL *List_of_staffs_p;
+
+struct SVRANGELIST *Svrangelist_p;
+
+/* beginning of the list of GRPSYL structs currently being built */
+struct GRPSYL *Curr_gs_list_p;
+
+/* If 0, no multirest in current measure yet.
+ * If 1, got a multirest.
+ * If 2, got both a multirest and music data */
+short Got_multirest;
+
+/* YES if input contained at least one group in the current measure */
+short Got_group;
+
+short Pagenum;                 /* which page we are currently printing */
+int Last_pagenum;              /* page number of the final page */
+
+/* set to YES if given font is used somewhere */
+short Font_used[MAXFONTS];
+
+/* items used when chord grids are to be printed at the end of the song */
+struct ATEND_INFO Atend_info;
+
+/*
+ * Define a variable for a staff's staffscale, and other variables which are
+ * staffscale times the corresponding macro symbol in all caps.  This is to
+ * avoid recalculating these all the time.  These variables are for use in
+ * files where a main function loops over staffs, and calls a tree of
+ * subroutines for each staff.  The main function should set these variables
+ * for the current staff, and from there on the code can use them.  Early in
+ * Mup they are initialized to their default values by doing initstructs()
+ * and set_staffscale(0), so that everywhere before the point where staff
+ * scaling begins (in restsyl.c) they are set to these default values, and
+ * code before there can call utilities that use these symbols and no scaling
+ * will result.
+ */
+float Staffscale;      /* for this staff */
+float Stdpad;          /* STDPAD on this staff */
+float Stepsize;                /* STEPSIZE on this staff */
+float Flagsep;         /* FLAGSEP on this staff */
+float Smflagsep;       /* SMFLAGSEP on this staff */
+float Tupheight;       /* TUPHEIGHT on this staff */
+
+/* define rational number constants that may be useful in multiple files */
+RATIONAL Zero = {0,1};
+RATIONAL One_fourth = {1,4};
+RATIONAL One_third = {1,3};
+RATIONAL One_half = {1,2};
+RATIONAL Two_thirds = {2,3};
+RATIONAL Three_fourths = {3,4};
+RATIONAL One = {1,1};
+RATIONAL Two = {2,1};
+RATIONAL Three = {3,1};
+RATIONAL Four = {4,1};
+
+/*
+ * Define something longer than the longest possible measure.  See the comment
+ * by the #define for MAXTSLEN.
+ */
+RATIONAL Maxtime = {(MAXTSLEN - 3) * 99 + 1, 1};
+
+int Debuglevel;                        /* bitmap of what message classes to print */
diff --git a/mup/mup/globals.h b/mup/mup/globals.h
new file mode 100644 (file)
index 0000000..f652098
--- /dev/null
@@ -0,0 +1,813 @@
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ * 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ *     globals.h
+ *
+ *     This file has externs for the global variables defined in global.c.
+ *     It also has externs for all nonstatic functions.
+ */
+
+#ifndef _GLOBALS
+#define _GLOBALS
+
+#ifdef __WATCOMC__
+#include <sys\types.h>
+#endif
+#include <string.h>
+#include <ctype.h>
+#include "structs.h"
+#ifdef VMS
+#include <unixio.h>
+#endif
+
+/*
+ * Some non-ANSI compilers may not have these defined in stdio.h, so if they
+ * aren't defined, define them now.
+ */
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+/* ====== externs for variables--see globals.c for comments about them ===== */
+
+extern struct SSV Score;
+extern struct SSV Staff[MAXSTAFFS];
+extern struct SSV Voice[MAXSTAFFS][MAXVOICES];
+
+extern short Staff_vis[MAXSTAFFS + 1];
+extern short Voice_vis[MAXSTAFFS + 1][MAXVOICES + 1];
+
+extern struct MAINLL *Mainllhc_p;
+extern struct MAINLL *Mainlltc_p;
+
+extern int Optch;
+extern int Mupmate;
+extern int Errorcount;
+extern int Maxverses;
+extern short Meas_num;
+extern int Preproc;
+extern int Ppcomments;
+
+extern int Context;
+extern int Curr_family;
+extern int Curr_font;
+extern int Curr_size;
+extern int Got_some_data;
+extern int Doing_tab_staff;
+extern int Doing_MIDI;
+extern char *Curr_filename;
+extern char *Outfilename;
+extern int Vflag;
+extern int Vcombused;
+extern int CSBused;
+extern int CSSused;
+extern int CSSpass;
+
+extern int yylineno;
+/* This 8192 must agree with YYLMAX in lex.c.  We shouldn't have to specify
+ * the size here, but at least one compiler generates bad code if we don't. */
+extern char yytext[8192];
+
+extern int Last_was_newline;
+extern unsigned char Hctab[];
+extern unsigned char Xhctab[];
+extern unsigned char Dhctab[];
+extern unsigned char Resttab[];
+extern int Letshift[];
+extern char Circle[];
+extern char Acclets[];
+extern char *Acctostr[];
+extern char Ped_start[];
+extern char Ped_stop[];
+
+extern struct STRINGINFO Guitar[DEFTABLINES];
+extern int Octave_adjust[MAXSTAFFS+1];
+extern int Octave_bars[MAXSTAFFS+1];
+extern float Octave_count[MAXSTAFFS+1];
+
+extern float _Page     [NUMCTYPE];
+extern float _Win      [NUMCTYPE];
+extern float _Cur      [NUMCTYPE];
+
+extern struct BLOCKHEAD Header;
+extern struct BLOCKHEAD Footer;
+extern struct BLOCKHEAD Header2;
+extern struct BLOCKHEAD Footer2;
+
+extern float *Score_location_p;
+extern float Staffs_y[MAXSTAFFS + 1];
+
+extern struct RANGELIST *Staffrange_p;
+extern struct RANGELIST *Vnorange_p;
+
+extern short Place;
+
+extern short Ped_snapshot[MAXSTAFFS + 1];
+
+extern struct MAINLL *Staffmap_p[MAXSTAFFS + 1];
+extern struct MAINLL *List_of_staffs_p;
+
+extern struct SVRANGELIST *Svrangelist_p;
+extern struct GRPSYL *Curr_gs_list_p;
+extern short Got_multirest;
+extern short Got_group;
+
+extern short Pagenum;
+extern int Last_pagenum;
+
+extern short Font_used[MAXFONTS];
+
+extern struct ATEND_INFO Atend_info;
+
+extern float Staffscale;
+extern float Stdpad;
+extern float Stepsize;
+extern float Flagsep;
+extern float Smflagsep;
+extern float Tupheight;
+
+extern RATIONAL Zero;
+extern RATIONAL One_fourth;
+extern RATIONAL One_third;
+extern RATIONAL One_half;
+extern RATIONAL Two_thirds;
+extern RATIONAL Three_fourths;
+extern RATIONAL One;
+extern RATIONAL Two;
+extern RATIONAL Three;
+extern RATIONAL Four;
+
+extern RATIONAL Maxtime;
+
+extern int Debuglevel;
+extern int ifdebug;
+
+/* =========== defines that depend on the above variables ============= */
+
+/* size of the actual paper, scaled so that the right amount of music fits */
+#define        PGHEIGHT        (Score.pageheight / Score.scale_factor)
+#define        PGWIDTH         (Score.pagewidth  / Score.scale_factor)
+
+/* must divide margin variables by scale to cancel out the scaling for them */
+#define EFF_TOPMARGIN  (Score.topmargin   / Score.scale_factor)
+#define EFF_BOTMARGIN  (Score.botmargin   / Score.scale_factor)
+/* right & left margins use functions eff_rightmargin() & eff_leftmargin() */
+
+/* =========== externs for global variables in generated code ============= */
+
+extern int yydebug;    /* yacc debug flag */
+extern FILE *yyin;     /* where lex will read from */
+
+/* =========== externs for functions ============= */
+
+#ifdef __STDC__
+#include <stdlib.h>
+#include <unistd.h>
+#else
+/* UNIX utilities that don't appear in official header files in SV_R3 */
+extern char *malloc();
+extern char *calloc();
+extern char *realloc();
+extern void free();
+
+extern void exit();
+extern int abs();
+extern int atoi();
+extern double atof();
+extern void qsort();
+extern long strtol();
+#endif
+
+/* abshorz.c */
+extern void abshorz P((void));
+
+/* absvert.c */
+extern void absvert P((void));
+
+/* assign.c */
+extern void assign_int P((int var, int value, struct MAINLL *mainll_item_p));
+extern void assign_float P((int var, double value,
+               struct MAINLL *mainll_item_p));
+extern void assign_vscheme P((int numvoices, int vtype,
+               struct MAINLL *mainll_item_p));
+extern void assign_key P((int num, int acc, int minor,
+               struct MAINLL *mainll_item_p));
+extern void assign_string P((int var, char *string,
+               struct MAINLL *mainll_item_p));
+extern void assign_unit P((int unittype, struct MAINLL *mainll_p));
+extern char *copy_string P((char *string, int font, int size));
+extern void assign_timesig P(( struct MAINLL *mainll_item_p, int invisible,
+               char **next_alternation_p));
+extern void assign_font P((int var, int value, struct MAINLL *mainll_item_p));
+extern void new_staffset P((void));
+extern void add_staffset P((int start, int end, char *label1, char *label2));
+extern void set_staffset P((int var, struct MAINLL *mainll_item_p));
+extern void new_barstlist P((void));
+extern void add_barst P((int start, int end));
+extern void set_barstlist P((struct MAINLL *mainll_item_p));
+extern void new_beamlist P((void));
+extern void add_beamlist P((RATIONAL value));
+extern void set_beamlist P((struct MAINLL *mainll_item_p));
+extern void asgn_stafflines P((int numlines, int printclef,
+               struct MAINLL *mainll_item_p));
+extern void set_font P((int var, int value, struct MAINLL *mll_p));
+extern void add_tab_string_info P((int pitch, int accidental, int nticks,
+               int octave, struct SSV *ssv_p));
+extern void set_mnum P((struct BAR *bar_p, int mnum));
+extern void assign_2floats P((int var, double value1, double value2,
+               struct MAINLL *mainll_item_p));
+extern void chkmargin P((double topmargin, double botmargin, double leftmargin,
+               double rightmargin));
+extern double adjust2inches P((double value));
+extern void begin_subbeam P((void));
+extern void end_subbeam P((void));
+extern void assign_vcombine P((int qualifier, struct MAINLL * mainll_p));
+
+/* beaming.c */
+extern void setbeamloc P((struct GRPSYL *curr_grp_p,
+               struct GRPSYL *last_grp_p));
+extern int has_cust_beaming P((struct GRPSYL *grpsyl_p));
+extern void do_beaming P((struct GRPSYL *grpsyl_p, int grpsize, int staffno,
+               int vno));
+extern void set_alt_beams P((struct GRPSYL *grpsyl_p));
+extern int chk_crossbeam P((struct GRPSYL *gs_p, struct MAINLL *mll_p));
+
+/* beamstem.c */
+extern void beamstem P((void));
+
+/* brac.c */
+extern int brac_check P((struct STAFFSET *bracelist_p, int nbrace,
+                struct STAFFSET *bracklist_p, int nbrack));
+extern int pr_brac P((int is_restart, double x_offset, struct MAINLL *mll_p));
+extern double width_left_of_score P((struct MAINLL *mll_p));
+extern double pwidth_left_of_score P((struct MAINLL *mll_p,
+               struct MAINLL *prev_feed_mll_p));
+
+/* charinfo.c */
+extern double height P((int font, int size, int ch));
+extern double width P((int font, int size, int ch));
+extern double ascent P((int font, int size, int ch));
+extern double descent P((int font, int size, int ch));
+extern char *fix_string P((char *string, int font, int size, char *fname,
+               int lineno));
+extern char *mc_num2name P((int code, int font));
+extern unsigned char mc_name2num P((char *name, char *fname, int lineno,
+               int *size_p, int *font_p));
+extern int str2mfont P((int str));
+extern int mfont2str P((int mfont));
+#ifdef EXTCHAR
+extern char *ext_num2name P((int code));
+#endif
+extern int is_music_symbol P((char *str));
+extern double strascent P((char *str));
+extern double strdescent P((char *str));
+extern double strheight P((char *str));
+extern double strwidth P((char *str));
+extern char *tranchstr P((char *chordstring, int staffno));
+extern int restchar P((int basictime));
+extern char *dashstr P((char *str));
+extern void end_fontsize P((char *str, int *font_p, int *size_p));
+extern char *ascii_str P((char *str, int verbose, int pagenum, int textmod));
+extern char *split_string P((char *string, double desired_width));
+extern int adj_size P((int size, double factor, char *filename, int lineno));
+extern char *resize_string P((char *string, double factor, char *filename,
+               int lineno));
+extern double left_width P((char *));
+extern char *acc_trans P((char *string));
+extern char *modify_chstr P((char *string, int modifier));
+extern int is_ital_font P((int font));
+extern double circled_dimensions P((char *str, float* height_p, float *width_p,
+               float *ascent_adjust, float *x_offset_p));
+extern char *get_reh_string P((char *string, int staffnum));
+
+/* check.c */
+extern int rangecheck P((int n, int min, int max, char *name));
+extern int frangecheck P((double n, double min, double max, char *name));
+extern int power_of2check P((int n, char *name));
+extern int contextcheck P((int validcontext, char *action));
+extern char *contextname P((int cont));
+extern void check_at_least1visible P((void));
+extern void chk_vis_feed P((void));
+extern void chk_interval P((int inttype, int intnum));
+extern void used_check P((struct MAINLL *mll_p, int var, char *name));
+extern int l_rangecheck P((int num, int min, int max, char *name, char *fname,
+               int lineno));
+extern void combine_rests P((int c));
+extern char *markname P((int mark));
+extern void chk_order P((struct SSV *ssv_p, int place));
+extern int erangecheck P((int n, int min, int max, int empty_value,
+               char *name));
+extern void chk_x_arg P((char *x_arg, int *start_p, int *end_p));
+extern void extract P((int start, int end));
+
+/* debug.c */
+extern char *stype_name P((int stype));
+extern void print_mainll P((void));
+
+/* errors.c */
+extern void ufatal P((char *format, ...));
+extern void pfatal P((char *format, ...));
+extern void l_ufatal P((char *filename, int lineno, char *format, ...));
+extern void l_pfatal P((char *filename, int lineno, char *format, ...));
+extern void l_no_mem P((char *filename, int lineno));
+extern void cant_open P((char *filename));
+extern void warning P((char *format, ...));
+extern void l_yyerror P((char *fname, int lineno, char *format, ...));
+extern void l_warning P((char *filename, int lineno, char *format, ...));
+extern void debug P((int level, char *format, ...));
+extern int debug_on P((int level));
+extern void doraterr P((int code));
+extern void error_exit P((void));
+extern void print_offending_line P((char *filename, int lineno));
+
+/* font.c */
+extern double fontascent P((int font, int size));
+extern double fontdescent P((int font, int size));
+extern double fontheight P((int font, int size));
+extern void parse_font_file P((char *filename));
+extern int lookup_font P((char *fontname));
+extern int font_index P((int font));
+extern char *fontnum2name P((int font));
+
+/* fontdata.c */
+extern struct FONTINFO Fontinfo[MAXFONTS];
+extern float Maxfontheight[MAXFONTS];
+extern float Maxfontascent[MAXFONTS];
+
+/* gram.y */
+extern int yyparse P((void));
+extern int yyerror P((char *msg));
+
+/* grpsyl.c */
+extern struct GRPSYL *newGRPSYL P((int grp_or_syl));
+extern void copy_attributes P((struct GRPSYL *newgrp_p,
+               struct GRPSYL *oldgrp_p));
+extern struct TIMELIST *copy_timeunit P((struct GRPSYL *newgrp_p,
+               struct GRPSYL *oldgrp_p, struct TIMELIST *timelist_p));
+extern void copy_notes P((struct GRPSYL *newgrp_p, struct GRPSYL *oldgrp_p));
+extern void link_notegroup P((struct GRPSYL *newgrp_p,
+               struct GRPSYL *last_grp_p));
+extern void add_note P((struct GRPSYL *grpsyl_p, int pitch, int accidental,
+               int octave, int nticks, int has_paren, char *bend_string));
+#ifdef __STDC__
+extern int notecomp P((const void *item1_p, const void *item2_p));
+#else
+extern int notecomp P((char *item1_p, char *item2_p));
+#endif
+extern int reconstruct_basictime P((RATIONAL fulltime));
+extern int recalc_dots P((RATIONAL fulltime, int basictime));
+extern void clone_withlist P((struct GRPSYL *newgrp_p,
+               struct GRPSYL *oldgrp_p));
+extern char *stringname P((int stringno, int staffno));
+extern char *format_string_name P((int letter, int accidental,
+               int nticks));
+extern void do_bar P((int bartype));
+extern void begin_tuplet P((void));
+extern void end_tuplet P((int tupcont, RATIONAL tuptime, int printtup,
+               int tupside));
+extern void check4barline_at_end P((void));
+extern void add_multirest P((int nummeas));
+extern struct GRPSYL *clone_gs_list P((struct GRPSYL *list_p,
+               int copy_noteinfo));
+extern void add_slurto P((struct GRPSYL *grpsyl_p, int pitch, int octave,
+               int note_index, int slurstyle));
+extern void free_grpsyls P((struct GRPSYL *gs_p));
+extern void resize_notelist P((struct GRPSYL *gs_p));
+extern void add_meas_space P((struct GRPSYL **gs_p_p, int staff, int voice));
+extern int is_mrpt P((struct GRPSYL *gs_p));
+extern void report_mix_error P((void));
+extern void free_notelist P((struct GRPSYL *gs_p));
+extern void begin_slur P((struct GRPSYL *grpsyl_p, int note_index));
+extern void set_slurdir P((struct GRPSYL *grpsyl_p, int note_index, int dir));
+extern int has_pickup P((void));
+extern struct GRPSYL *expandgrp P((struct GRPSYL *grpsyl_p,
+               struct TIMELIST *timelist_p));
+extern RATIONAL calcfulltime P((RATIONAL basictime, int dots));
+
+/* lex.l */
+extern void chk_ifdefs P((void));
+extern int save_macro P((FILE *file));
+extern int yylex P((void));
+extern void get_parameters P((char *macname));
+extern int get_mac_arguments P((char *macname, int num_args));
+extern void pushback P((int c));
+extern void begin_raw P(());
+extern void end_raw P(());
+extern void new_lexbuff P((FILE *file));
+extern void del_lexbuff P((void));
+
+/* locvar.c */
+extern void fix_locvars P((void));
+
+/* lyrics.c */
+extern void lyr_verse P((int begin, int end));
+extern void proc_lyrics P((struct GRPSYL *grpsyl_p, char *lyrstring));
+extern void attach_lyrics2staffs P((struct MAINLL *mll_staffs_p));
+extern void sylwidth P((char *lyrstring, float *wid_b4_syl_p,
+               float *wid_real_syl_p, float *wid_after_syl_p));
+extern void set_maxverses P((void));
+extern struct SSV *get_lyr_dflt_timeunit_ssv P((void));
+extern void setlyrfont P((int staffno, int font));
+extern void setlyrsize P((int staffno, int size));
+extern void lyr_compensate P((struct GRPSYL *gs_p));
+extern struct GRPSYL *derive_lyrtime P((void));
+extern void lyr_new_bar P((void));
+
+/* macros.c */
+extern int not_in_mac P((int inc_dec));
+extern void mac_error P((void));
+extern void includefile P((char *fname));
+extern int popfile P((void));
+extern void cmdline_macro P((char *macdef));
+extern void define_macro P((char *macname));
+extern void undef_macro P((char *macname));
+extern void call_macro P((char *macname));
+extern int is_defined P((char *macname, int paramtoo));
+#ifndef unix
+extern void mac_cleanup P((void));
+#endif
+extern void add_parameter P((char *macname, char *param_name));
+extern void set_parm_value P((char *macname, char *argbuff, int argnum));
+extern char *add2argbuff P((char *argbuff, int c));
+extern FILE *find_file P((char **filename_p));
+extern void preproc P((void));
+
+/* main.c */
+extern int onpagelist P((int pagenum));
+extern int yywrap P((void));
+extern int last_page P((void));
+
+/* mainlist.c */
+extern struct MAINLL *newMAINLLstruct P((int structtype, int lineno));
+extern void insertMAINLL P((struct MAINLL *info_p, struct MAINLL *where));
+extern void unlinkMAINLL P((struct MAINLL *which_p));
+
+/* map.c */
+extern void begin_map P((void));
+extern void end_map P((void));
+extern void map_item P((void));
+extern void save_map P((void));
+extern struct SSV *get_dflt_timeunit_ssv P((void));
+extern void reset_input_style P((void));
+extern int input_style P((int staff, int voice));
+extern void merge_dup_notes P((struct GRPSYL *gs_p, int n));
+extern void link_groups P((void));
+extern int is_tab_range P((void));
+extern int timelists_equal P((struct TIMELIST *tlist1_p,
+               struct TIMELIST *tlist2_p));
+
+/* mkchords.c */
+extern void makechords P((void));
+
+/* midi.c */
+extern void gen_midi P((char *midifilename));
+extern UINT32B write_delta P((int mfile));
+extern int voice_used P((int staffno, int vno));
+
+/* midiutil.c */
+extern void fix_track_size P((int mfile, long track_start, long track_size));
+extern int parse_octave P((char *string, int place, char *fname, int lineno));
+extern int clocks P((int num));
+extern int getkeyword P((char *string, char **key_p, int *leng_p,
+               char **arg_p_p));
+extern int matches P((char *key, int leng, char *cmd));
+extern int hexdig P((int ch));
+extern UINT32B midi_wrstring P((int mfile, char *str, int internalform));
+extern UINT32B wr_varlength P((int mfile, UINT32B num));
+extern UINT32B midi_keysig P((int mfile, int sharps, int is_minor));
+extern UINT32B midi_timesig P((int mfile));
+extern void add_rest P((struct GRPSYL *gs_p, RATIONAL fulltime));
+extern struct GRPSYL *grp_before P((struct GRPSYL *gs_p, struct MAINLL *mll_p,
+                int staffno, int v));
+extern void midi_squeeze P((void));
+extern void guitar_transpose P((void));
+extern void other_voice_accidentals P((struct STAFF *staff_p));
+extern void mv_midi_items P((struct MAINLL *mll_p,
+               struct MAINLL *topstaff_mll_p));
+extern int get_param P((char *arg, char *inputfile, int inputlineno,
+               int *parmnum_p, int *parmval_p));
+
+/* nxtstrch.c */
+extern double backsp_width P((int size));
+extern int next_str_char P((char **str_p, int *font_p, int *size_p));
+extern int nxt_str_char P((char **str_p, int *font_p, int *size_p,
+               int *textfont_p, double *vertical_p, double *horizontal_p,
+               int *in_pile_p, int slash));
+extern double align_distance P((char *string, int font, int size));
+extern double pile_width P((void));
+extern int pile_size P((int size, int in_pile));
+
+/* parstssv.c */
+extern struct TIMEDSSV *tssv_create P((int context));
+extern void tssv_update P((struct TIMEDSSV *timedssv_p, int param, int value));
+extern void tssv_setgrpsyl P((struct GRPSYL *gs_p));
+extern void tssv_line P((void));
+extern struct TIMEDSSV *tssv_sort P((void));
+
+/* parstuff.c */
+extern void chk_stuff_header P((int size, int modifier, int place,
+               int dist_usage));
+extern void add_stuff_item P((double start_count, double start_steps,
+               int gracebackup, char *string, int bars, double count,
+               int dist, int dist_usage));
+extern int string_is_sym P((char *string, int sym, int font));
+extern void attach_stuff P((void));
+extern void meas_stuff_chk P((void));
+extern void chk4dangling_til_clauses P((char *boundary_desc));
+extern struct STUFF *newSTUFF P((char *string, int dist, int dist_usage,
+               double start_count, double start_steps, int gracebackup,
+               int bars, double count, int stuff_type, int modifier,
+               int place, char *inputfile, int inputlineno));
+extern void reset_ped_state P((void));
+extern void set_reh_string P((struct BAR *bar_p, int fontfamily, int font,
+               int size, char *string));
+extern void set_stuff_type P((int stuff_type));
+extern int dflt_place P((void));
+extern void ped_endings P((int endingloc));
+extern void multi_stuff P((int nmeas));
+extern int get_stuff_type P((void));
+extern char *stuff_modifier P((int modifier));
+extern char *pad_string P((char *string, int modifier));
+extern void connect_stuff P((struct STAFF *staff_p, struct STUFF *stufflist_p));
+extern void init_reh P((int rehnumber, char *rehletter,
+               struct MAINLL *mainbar_p));
+
+/* phrase.c */
+extern void phrase_points P((struct MAINLL *mll_p, struct STUFF *stuff_p));
+extern void tieslur_points P((struct MAINLL *mll_p, struct STUFF *stuff_p));
+extern void bend_points P((struct MAINLL *mll_p, struct STUFF *stuff_p));
+extern void tabslur_points P((struct MAINLL *mll_p, struct STUFF *stuff_p));
+
+/* plutils.c */
+extern struct GRPSYL *nextnongrace P((struct GRPSYL *gs_p)); 
+extern struct GRPSYL *prevnongrace P((struct GRPSYL *gs_p));
+extern struct GRPSYL *nextglobnongrace P((struct GRPSYL *gs_p,
+               struct MAINLL **mll_p_p)); 
+extern struct GRPSYL *prevglobnongrace P((struct GRPSYL *gs_p,
+               struct MAINLL **mll_p_p));
+extern int drmo P((int num));
+extern double tieslurpad P((struct STAFF *staff_p, struct GRPSYL *gs_p));
+extern int hasspace P((struct GRPSYL *gs_p, RATIONAL vtime, RATIONAL vtime2));
+extern struct GRPSYL *closestgroup P((double count, struct GRPSYL *firstgs_p,
+               int timeden));
+extern int chkallspace P((struct MAINLL *msbeg_p, struct STUFF *stuff_p,
+               int vno));
+extern int allspace P((int vno, struct MAINLL *msbeg_p, RATIONAL begtime,
+               struct MAINLL *msend_p, RATIONAL endtime));
+extern struct MAINLL *getendstuff P((struct MAINLL *mainll_p,
+               struct STUFF *stuff_p, int *timeden_p));
+extern void accdimen P((struct NOTE *note_p, float *ascent_p, float *descent_p,
+               float *width_p));
+extern double staffvertspace P((int s));
+extern double halfstaffhi P((int s));
+extern RATIONAL ratbend P((struct NOTE *note_p));
+extern double notehorz P((struct GRPSYL *gs_p, struct NOTE *note_p, int coord));
+extern int allsmall P((struct GRPSYL *gs1_p, struct GRPSYL *gs2_p));
+extern void finalstemadjust P((struct GRPSYL *gs_p));
+extern double getstemshift P((struct GRPSYL *gs_p));
+extern int vscheme_voices P((int vscheme));
+extern struct MAINLL *chmgrp2staffm P((struct MAINLL *mll_p,
+               struct GRPSYL *gs_p));
+extern void shiftgs P((struct GRPSYL *gs_p, double shift));
+extern double nearestline P((double offset));
+extern void vfyoffset P((struct GRPSYL *g_p[]));
+extern double adjslope P((struct GRPSYL *g_p, double oldslope, int betweencsb));
+extern double eos_bar_adjust P((struct BAR *bar_p));
+extern double curve_y_at_x P((struct CRVLIST *first_p, double x));
+extern double findcubic P((struct CRVLIST *left_p, struct CRVLIST *right_p,
+               float *a_p, float *b_p, float *c_p));
+extern double solvecubic P((double a, double b, double c, double d,
+               double lo, double hi, double thresh));
+extern int css_affects_stemtip P((struct GRPSYL *gs1_p));
+extern struct CHORD *gs2ch P((struct MAINLL *mll_p, struct GRPSYL *gs_p));
+extern int css_affects_tieslurbend P((struct STUFF *stuff_p, struct MAINLL *mll_p));
+extern int css_affects_phrase P((struct STUFF *stuff_p, struct MAINLL *mll_p));
+extern struct GRPSYL *nextsimilar P((struct GRPSYL *gs_p));
+extern struct GRPSYL *prevsimilar P((struct GRPSYL *gs_p));
+extern double stemroom P((struct GRPSYL *gs_p));
+
+/* print.c */
+extern void print_music P((void));
+extern void do_linetype P((int ltype));
+extern void draw_line P((double x1, double y1, double x2, double y2));
+extern void pr_muschar P((double x, double y, int ch, int size, int font));
+extern double pr_clefsig P((struct MAINLL *mll_p, struct CLEFSIG *clefsig_p,
+               int really_print));
+extern void pr_string P((double x, double y, char *string, int justify,
+               char *fname, int lineno));
+extern void end_curve P((int ncoord, double x, double y));
+extern void outcoord P((double val));
+extern void draw_wavy P((double x1, double y1, double x2, double y2));
+extern void do_pr_brac P((double x, double y1, double y2, int which));
+extern void pr_linenum P((char *inputfile, int inputlineno));
+extern void do_moveto P((double x, double y));
+extern void do_line P((double x, double y));
+extern void do_fill P((void));
+extern void do_stroke P((void));
+extern void do_curveto P((double x1, double y1, double x2, double y2,
+               double x3, double y3));
+extern void do_newpath P((void));
+extern void do_closepath P((void));
+extern void trailer P((void));
+extern void do_closepath P((void));
+extern void do_whitebox P((double x1, double y1, double x2, double y2));
+extern void draw_prop_line P((double x1, double y1, double x2, double y2,
+               int size, int ltype));
+extern void do_grid P((double x, double y, double space, struct GRID *grid_p,
+               int staff));
+extern void newpage P((struct MAINLL *mll_p));
+extern void pr_feed P((struct MAINLL *main_feed_p));
+extern double pr_clef P((int staffno, double x, int really_print, int size));
+
+/* prntdata.c */
+extern void pr_staff P((struct MAINLL *mll_p));
+extern int tupdir P((struct GRPSYL *gs_p, struct STAFF *staff_p));
+extern char *num2str P((int num));
+extern char *mrnum P((struct STAFF *staff_p, double *x_p, double *y_offset_p,
+               double *height_p, double *width_p));
+extern int tupgetsbrack P((struct GRPSYL *gs_p));
+extern char *tupnumsize P((struct GRPSYL *gs_p, float *west_p,
+               float *east_p, float *height_p, struct STAFF *staff_p));
+extern int pbeamside P((struct GRPSYL *gs_p, struct GRPSYL *first_p));
+extern struct GRPSYL *nxtbmgrp P((struct GRPSYL *gs_p, struct GRPSYL *first_p,
+               struct GRPSYL *endnext_p));
+extern struct GRPSYL *prevbmgrp P((struct GRPSYL *gs_p,
+               struct GRPSYL *first_p));
+extern double end_bm_offset P((struct GRPSYL *top_first_p, struct GRPSYL *end_p,
+               int basictime));
+extern void pr_slashes P((struct GRPSYL *grpsyl_p, double x, double y,
+               double sign, double offset, double y_tilt));
+extern void pr_tab_groups P((struct GRPSYL *gs_p, struct MAINLL *mll_p));
+extern void pr_withlist P((struct GRPSYL *gs_p));
+extern void pr_mrpt P((struct GRPSYL *gs_p, struct STAFF *staff_p));
+extern void pr_multirest P((struct GRPSYL *gs_p, struct STAFF *staff_p));
+
+/* prntmisc.c */
+extern void pr_endings P((struct MAINLL *main_feed_p));
+extern int has_ending P((int staffno));
+extern void pr_ped_char P((struct STUFF *stuff_p, int staffno));
+extern void pr_ped_bar P((struct MAINLL *mll_p, struct BAR *bar_p));
+extern void pr_phrase P((struct CRVLIST *crvlist_p, int linetype, int tapered,
+               int staffno));
+extern void pr_allcurve P((float x[], float y[], int num, double cwid,
+               int tapered));
+extern void saveped P((struct MAINLL *mll_p, struct BAR *bar_p));
+extern double ped_offset P((void));
+extern void pr_bend P((struct CRVLIST *crvlist_p));
+extern void pr_tabslur P((struct CRVLIST *crvlist_p, int ts_style));
+extern void pr_sm_bend P((double x, double y));
+extern void pr_atend P((void));
+
+/* prnttab.c */
+extern char *fret_string P((struct NOTE *note_p, struct GRPSYL *gs_p));
+extern char *bend_string P((struct NOTE *note_p));
+extern void pr_tab_groups P((struct GRPSYL *gs_p, struct MAINLL *mll_p));
+extern double pr_tabclef P((int staffno, double x, int really_print, int size));
+
+/* prolog.c */
+extern void ps_prolog P((void));
+
+/* range.c */
+extern void begin_range P((int place));
+extern void save_staff_range P((int beginstaffno, int endstaffno));
+extern void save_vno_range P((int begin, int end));
+extern void free_rlists P((void));
+extern void chk_range_type P((int has_ampersand));
+extern void create_staffs P((void));
+extern void all P((void));
+extern void free_staffrange P((void));
+extern void free_vnorange P((void));
+extern int is_tab_staff P((int staffno));
+extern int leadstaff P((void));
+extern void add_to_sv_list P((void));
+extern void free_sv_list P((struct SVRANGELIST *svlist_p));
+extern void begin_sv_list P((void));
+
+/* relvert.c */
+extern void relvert P((void));
+
+/* restsyl.c */
+extern void restsyl P((void));
+
+/* roll.c */
+extern void newROLLINFO P((void));
+extern void setrolldir P((int dir));
+extern void rollparam P((int topstaff, int topvoice, int botstaff,
+               int botvoice));
+extern void rolloffset P((double offset));
+extern void do_rolls P((struct MAINLL *mll_p));
+extern void print_roll P((struct GRPSYL *gs_p));
+extern int gets_roll P((struct GRPSYL *gs_p, struct STAFF *staff_p, int v));
+
+/* setgrps.c */
+extern void setgrps P((void));
+
+/* setnotes.c */
+extern void setnotes P((void));
+
+/* ssv.c */
+extern void initstructs P((void));
+extern void zapssv P((struct SSV *s_p));
+extern struct SSV *svpath P((int s, int field));
+extern struct SSV *vvpath P((int s, int v, int field));
+extern void asgnssv P((struct SSV *i_p));
+extern void setssvstate P((struct MAINLL *mainll_p));
+
+/* stuff.c */
+extern void stuff P((void));
+
+/* symtbl.c */
+extern void init_symtbl P((void));
+extern void addsym P((char *symname, float *coordlist_p, int coordtype));
+extern float *symval P((char *symname, float **ref_p_p));
+extern struct COORD_INFO *find_coord P((float *key));
+extern void add_coord P((float *coordlist_p, int coordtype));
+extern struct GRID *findgrid P((char *name));
+extern void add_grid P((char *name, char *griddef));
+extern struct GRID *nextgrid P((struct GRID *grid_p));
+extern void set_win_coord P((float *coord_p));
+extern void add_shape P((char *name, char *shapes));
+extern int nheadchar P((int headshape, int basictime, int stemdir,
+               int *font_p));
+extern int get_shape_num P((char *shapename));
+extern double stem_yoff P((int headch, int font, int stemdir));
+extern void remember_tsig_params P((struct MAINLL *mll_p));
+extern void upd_ref P((float *old_p, float *new_p));
+extern void rep_inpcoord P((struct INPCOORD *old_inpcoord_p,
+               struct INPCOORD *new_inpcoord_p));
+
+/* tie.c */
+extern void tie P((void));
+extern void tie_carry P((void));
+extern struct GRPSYL *find_1st_grp_in_nxt_measure P((struct MAINLL *mll_p,
+               int vno));
+extern struct GRPSYL *find_next_group P((struct MAINLL *mll_p,
+               struct GRPSYL *gs_p, char *type));
+extern struct NOTE *find_matching_note P((struct GRPSYL *gs_p,
+               int letter, int octave, char *type_p));
+
+/* trantab.c */
+extern void tab2tabnote P((void));
+
+/* trnspose.c */
+extern void transgroups P((void));
+extern char *tranchnote P((int letter, int acc, int staffno));
+extern int eff_key P((int staff));
+extern void totaltrans P((int s, int *type_p, int *num_p));
+
+/* undrscre.c */
+extern int spread_extender P((struct GRPSYL *gs_p, struct MAINLL *mll_p,
+               int verse, int sylplace, int really_print));
+extern int has_extender P((char *syl));
+extern void cont_extender P((struct MAINLL *mll_p, int sylplace,
+               int verseno));
+extern int last_char P((char *str));
+
+/* utils.c */
+extern void set_cur P((double x, double y));
+extern void set_win P((double n, double s, double e, double w));
+extern double width_barline P((struct BAR *bar_p));
+extern double width_clefsig P((struct CLEFSIG *clefsig_p));
+extern int clefchar P((int clef));
+extern void calc_headfoot_height P((void));
+extern int numbeams P((int btime));
+extern int acc2char P((int acc));
+extern double inpc_x P((struct INPCOORD *inpcoord_p, char *fname, int lineno));
+extern double inpc_y P((struct INPCOORD *inpcoord_p, char *fname, int lineno));
+extern double find_y_stem P((struct GRPSYL *gs_p));
+extern double find_x_stem P((struct GRPSYL *gs_p));
+extern double width_keysig P((int sharps, int naturals));
+extern struct GRPSYL *nextgrpsyl P((struct GRPSYL *gs_p,
+               struct MAINLL **mll_p_p));
+extern struct GRPSYL *prevgrpsyl P((struct GRPSYL *gs_p,
+               struct MAINLL **mll_p_p));
+extern void octave_transpose P((struct STAFF *staff_p, struct MAINLL *mll_p,
+               int vno, int normdir));
+extern int eff_acc P((struct GRPSYL *gs_p, struct NOTE *note_p,
+               struct MAINLL *mll_p));
+extern int acc_from_keysig P((int letter, int staffno, struct MAINLL *mll_p));
+extern void set_staffscale P((int s));
+extern void gridsize P((struct GRID *grid_p, int staff, float *north_ptr,
+               float *south_ptr, float *east_ptr, float *west_ptr));
+extern double gridspace P((int staff));
+extern void gridinfo P((struct GRID *grid_p, int staff, int *frets_p,
+               int *fretnum_p, int *numvert_p, int *topfret_p));
+extern double clefspace P((int prevclef, double prevscale, int curclef,
+               double curscale, int measnum));
+extern double eff_rightmargin P((struct MAINLL *mainll_p));
+extern double eff_leftmargin P((struct MAINLL *mainll_p));
+extern short *findprimes P((int max));
+extern short *factor P((int num));
+extern double clefwidth P((int clef, int is_small));
+extern int clefvert P((int clef, int is_small, float *north_p, float *south_p));
+extern double widest_head P((struct GRPSYL *gs_p));
+extern void calc_block_heights P((void));
+
+#endif
diff --git a/mup/mup/grpsyl.c b/mup/mup/grpsyl.c
new file mode 100644 (file)
index 0000000..fee4085
--- /dev/null
@@ -0,0 +1,3427 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions for building up lists of GRPSYL structs,
+ * error checking them, etc. These functions are called at parse
+ * time from gram.y */
+
+
+#include <string.h>
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+/* 1-line staff allows for default pitch on first chord of measure. However,
+ * at the time we are gathering note information, it may not be known whether
+ * we are on a 1-line staff or not, so it is temporarily set to PP_NO_PITCH,
+ * then later if we have a 1-line staff, it gets converted to default of C4 */
+#define DFLT_PITCH     'c'
+#define DFLT_OCT       4
+
+/* how many NOTE structs to allocate at a time. We don't know in advance
+ * how many we'll need, so get a bunch and realloc as necessary. */
+#define NOTE_CHUNK (4)
+
+static int Tuplet_state = NOITEM;      /* current tuplet state */
+static struct GRPSYL *Tuplet_list_p;   /* first GRPSYL in a tuplet group */
+static short Slur_begin;       /* slurtolist index at which <> began */
+
+/* static functions */
+static void clone_notelist P((struct GRPSYL *new_p, struct GRPSYL *old_p,
+               int copy_acc_etc));
+static void finish_bar P((void));
+static void restart_bar P((void));
+static void fix_grpsyl_list P((struct MAINLL *mainll_item_p));
+static void fix_a_group_list P((struct GRPSYL *grpsyllist_p, int staffno,
+               int vno, char *fname, int lineno, int mrptnum,
+               struct TIMEDSSV * tssv_p));
+static void chk_a_syl_list P((struct GRPSYL *grpsyl_p, char *fname,
+               int lineno));
+
+/* change relative octaves to absolute */
+static void resolve_octaves P((struct GRPSYL *grpsyl_item_p,
+               int default_octave));
+static void fix_frets P((struct GRPSYL *grpsyl_item_p));
+static int string_number P((struct STRINGINFO *stringinfo_p, int nstrings,
+               int letter, int accidental, int nticks));
+
+static void check_grace P((struct GRPSYL *grpsyl_item_p, char *fname,
+               int lineno));
+static void fix_strlist P((struct GRPSYL *gs_p, int font, int size,
+               char *fname, int lineno));
+static void check4missing_voices P((struct MAINLL *list_p));
+static void fix_mrpt P((struct MAINLL *mll_p));
+static int chk_mrpt_ssv_interactions P((struct SSV *ssv_p, struct GRPSYL *gs_p,
+               int staffno));
+static int is_ms P((struct GRPSYL *gs_p));
+static int voices_override P((int staff, int field));
+static void sort_notes P((struct GRPSYL *grpsyl_p, char *fname, int lineno));
+static int parse_bend_string P((char *bendstring));
+static void check_bends P((struct GRPSYL *gs_p, struct MAINLL *mll_p));
+\f
+
+/* allocate a new GRPSYL struct and return a pointer to it */
+
+struct GRPSYL *
+newGRPSYL(grp_or_syl)
+
+int grp_or_syl;                /* GS_GROUP or GS_SYLLABLE */
+
+{
+       struct GRPSYL *new_p;
+
+
+       /* allocate a new structure */
+       CALLOC(GRPSYL, new_p, 1);
+
+       /* fill in default values */
+       new_p->grpsize = GS_NORMAL;
+       new_p->grpvalue = GV_NORMAL;
+       new_p->grpcont = GC_NOTES;
+       new_p->beamloc = NOITEM;
+       new_p->breakbeam = NO;
+       new_p->tuploc = NOITEM;
+       new_p->grpsyl = (short) grp_or_syl;
+       new_p->roll = NOITEM;
+       new_p->inputfile = Curr_filename;
+       new_p->inputlineno = (short) yylineno;
+       new_p->normwith = YES;
+       new_p->stemdir = (short) UNKNOWN;
+       new_p->beamto = CS_SAME;
+       new_p->stemto = CS_SAME;
+       /* default to no user-specified stem length */
+       new_p->stemlen = STEMLEN_UNKNOWN;
+       /* default to no user-specified rest dist */
+       new_p->restdist = NORESTDIST;
+       /* default to no user-specified syllable position */
+       new_p->sylposition = NOSYLPOSITION;
+       /* no clef change before this group */
+       new_p->clef = NOCLEF;
+       /* by default, placement will figure out the note head shape */
+       new_p->headshape = HS_UNKNOWN;
+       /* let Mup figure out angle for beams */
+       new_p->beamslope = NOBEAMANGLE;
+       /* everything else zero-ed is proper default */
+
+       return(new_p);
+}
+\f
+
+/* Copy group attributes (grpsize, grpvalue, "with" list, etc)
+ * from one GRPSYL to another */
+
+void
+copy_attributes(newgrp_p, oldgrp_p)
+
+struct GRPSYL *newgrp_p;       /* copy info into this one */
+struct GRPSYL *oldgrp_p;       /* copy from this one */
+
+{
+       if (oldgrp_p == 0) {
+               yyerror("empty [] not allowed on the first chord of a measure");
+               return;
+       }
+
+       newgrp_p->grpvalue = oldgrp_p->grpvalue;
+       newgrp_p->grpsize = oldgrp_p->grpsize;
+       newgrp_p->headshape = oldgrp_p->headshape;
+       newgrp_p->stemdir = oldgrp_p->stemdir;
+       newgrp_p->stemlen = oldgrp_p->stemlen;
+       newgrp_p->ho_usage = oldgrp_p->ho_usage;
+       newgrp_p->ho_value = oldgrp_p->ho_value;
+
+       clone_withlist(newgrp_p, oldgrp_p);
+
+       if (oldgrp_p->slash_alt > 0) {
+               newgrp_p->slash_alt = oldgrp_p->slash_alt;
+       }
+       newgrp_p->padding = oldgrp_p->padding;
+       /* restdist is only used for rests, but easiest to just always copy,
+        * since grpcont hasn't been set yet.  */
+       newgrp_p->restdist = oldgrp_p->restdist;
+}
+\f
+
+/* make a copy of withlist */
+
+void
+clone_withlist(newgrp_p, oldgrp_p)
+
+struct GRPSYL *newgrp_p;
+struct GRPSYL *oldgrp_p;
+
+{
+       register int n;         /* index through with list */
+
+
+       newgrp_p->nwith = oldgrp_p->nwith;
+       if (oldgrp_p->nwith > 0) {
+               MALLOCA(char *, newgrp_p->withlist, oldgrp_p->nwith);
+               for (n = 0; n < oldgrp_p->nwith; n++) {
+                       newgrp_p->withlist[n] =
+                                       copy_string(oldgrp_p->withlist[n] + 2,
+                                       Curr_font, Curr_size);
+               }
+       }
+}
+\f
+
+/* Copy timeunit info from one GRPSYL to another,
+ * or use default if source is NULL. If needed to use default timeunit,
+ * and that included additive times, returns pointer to the list of those
+ * times, else return NULL. */
+
+struct TIMELIST *
+copy_timeunit(newgrp_p, oldgrp_p, timelist_p)
+
+struct GRPSYL *newgrp_p;       /* copy info into here */
+struct GRPSYL *oldgrp_p;       /* copy from here. If NULL, use default value */
+struct TIMELIST *timelist_p;   /* If non-null use this instead of oldgrp_p */
+
+{
+       struct SSV *ssv_p;
+
+       ssv_p = 0;
+
+       if (oldgrp_p == (struct GRPSYL *) 0) {
+
+               /* use default timeunit. Have to figure out differently for
+                * lyrics than notes, because for lyrics the voice depends
+                * on the lyrics place. */
+               if (newgrp_p->grpsyl == GS_GROUP) {
+                       ssv_p = get_dflt_timeunit_ssv();
+               }
+               else {
+                       ssv_p = get_lyr_dflt_timeunit_ssv();
+               }
+               newgrp_p->fulltime = ssv_p->timeunit;
+
+               newgrp_p->basictime = reconstruct_basictime(newgrp_p->fulltime);
+               newgrp_p->dots = recalc_dots(newgrp_p->fulltime,
+                                                       newgrp_p->basictime);
+               return(ssv_p->timelist_p);
+       }
+
+       else {
+               RATIONAL basictime;
+
+               newgrp_p->basictime = oldgrp_p->basictime;
+               newgrp_p->dots = oldgrp_p->dots;
+
+               /* actual time value is (2 * basictime)
+                *      - (basic_time x 1/2 to the (dots) power) */
+               /* can't just copy the fulltime from oldgrp, because that
+                * may have been altered if it was a tuplet */
+               if (newgrp_p->basictime == 0) {
+                       /* strange case of double whole, stored as zero */
+                       basictime.n = 2;
+                       basictime.d = 1;
+               }
+               else if (newgrp_p->basictime == -1) {
+                       /* strange case of quad whole, stored as -1 */
+                       basictime.n = 4;
+                       basictime.d = 1;
+               }
+               else {
+                       basictime.n = 1;
+                       basictime.d = newgrp_p->basictime;
+               }
+
+               newgrp_p->fulltime = calcfulltime(basictime, newgrp_p->dots);
+       }
+
+       /* note that tuplet values are dealt with in end_tuplet(). Once we
+        * collect an entire tuplet, we can go through and multiply
+        * the fulltimes by the appropriate amount */
+       return(timelist_p);
+}
+\f
+
+/* copy notes (list of NOTE structs) from one GRPSYL to another, along with
+ * a few group attributes that should be copied when a GRPSYL is copied. */
+
+void
+copy_notes(newgrp_p, oldgrp_p)
+
+struct GRPSYL *newgrp_p;       /* copy into here */
+struct GRPSYL *oldgrp_p;       /* copy from here */
+
+{
+       /* first GRPSYL in bar must have notes specified */
+       if (oldgrp_p == (struct GRPSYL *) 0) {
+               add_note(newgrp_p, PP_NO_PITCH, '\0', DFLT_OCT, 0, NO, (char *) 0);
+               newgrp_p->notelist [ newgrp_p->nnotes ].tie = NO;
+               newgrp_p->notelist [ newgrp_p->nnotes ].notesize = GS_NORMAL;
+       }
+
+       else {
+               /* there was a previous GRPSYL -- use it for defaults */
+               newgrp_p->grpcont = oldgrp_p->grpcont;
+               clone_notelist(newgrp_p, oldgrp_p, NO);
+               newgrp_p->is_meas = oldgrp_p->is_meas;
+               newgrp_p->uncompressible = oldgrp_p->uncompressible;
+       }
+}
+\f
+
+/* once the info about a group has been gathered,
+ * add it to list of GRPSYL structs */
+
+void
+link_notegroup(newgrp_p, last_grp_p)
+
+struct GRPSYL *newgrp_p;               /* one to add on */
+struct GRPSYL *last_grp_p;             /* one to add it onto */
+
+{
+       int n;
+
+       debug(4, "link_notegroup file=%s line=%d", newgrp_p->inputfile,
+                               newgrp_p->inputlineno);
+
+       if (last_grp_p == (struct GRPSYL *) 0) {
+               /* first one: we need to keep a pointer to this one to
+                * link onto one or more STAFF structs later */
+               Curr_gs_list_p = newgrp_p;
+       }
+
+       else {
+               /* link onto list */
+               last_grp_p->next = newgrp_p;
+       }
+       newgrp_p->prev = last_grp_p;
+
+       /* fill in tuplet information, based on current state. Adjust tuplet
+        * state if necessary for use with later groups */
+       newgrp_p->tuploc = (short) Tuplet_state;
+       if (Tuplet_state == STARTITEM) {
+               Tuplet_list_p = newgrp_p;
+               Tuplet_state = INITEM;
+       }
+
+       /* We don't have a quad whole note character,
+        * so don't allow 1/4 on notes */
+       if (EQ(newgrp_p->fulltime, Four)) {
+               for (n = 0; n < newgrp_p->nnotes; n++) {
+                       if (newgrp_p->notelist[n].letter >= 'a' &&
+                                       newgrp_p->notelist[n].letter <= 'g') {
+                               yyerror("1/4 not allowed on notes");
+                               break;
+                       }
+               }
+       }
+
+       /* dist is only allowed on rests */
+       if (newgrp_p->restdist != NORESTDIST) {
+               for (n = 0; n < newgrp_p->nnotes; n++) {
+                       if (newgrp_p->notelist[n].letter != PP_REST) {
+                               yyerror("dist only allowed on rests");
+                       }
+               }
+       }
+}
+\f
+
+/* make a copy of a linked list of GRPSYL structs and return a pointer to it */
+/* Note that while this function is called for both groups and syllables,
+ * lyric syllables are not copied by this function. Lyrics syllables are
+ * handled in lyrics.c  */
+
+struct GRPSYL *
+clone_gs_list(list_p, copy_noteinfo)
+
+struct GRPSYL *list_p; /* the list to be cloned */
+int copy_noteinfo;     /* if YES, copy notes and with lists */
+
+{
+       struct GRPSYL *new_p, *newlist_p;
+       struct GRPSYL *prev_p = (struct GRPSYL *) 0;    /* to remember last one,
+                                to know where to link on current one */
+
+
+
+       /* walk down the existing list */
+       for (newlist_p = (struct GRPSYL *) 0; list_p != (struct GRPSYL *) 0;
+                                       list_p = list_p->next) {
+
+               /* allocate space for copy of list element and fill it in */
+               MALLOC(GRPSYL, new_p, 1);
+
+               (void) memcpy(new_p, list_p, sizeof(struct GRPSYL) );
+
+               /* we can't just copy the links--they have to be recalculated */
+               if (newlist_p == (struct GRPSYL *) 0) {
+
+                       /* first in new list: keep track of where list begins,
+                        * since we need to return this value, and keep track
+                        * of where we are, so we can link the next element
+                        * onto this one, which will be its prev element */
+                       newlist_p = new_p;
+                       prev_p = new_p;
+               }
+
+               else {
+                       prev_p->next = new_p;
+                       new_p->prev = prev_p;
+                       prev_p = new_p;
+               }
+
+               if (copy_noteinfo == YES) {
+                       /* also need to make copies of the notelist, since
+                        * they contain COORDS that are unique
+                       * for each instance */
+                       clone_notelist(new_p, list_p, YES);
+
+                       /* with lists cannot be shared,
+                        * because otherwise fix_string
+                        * could get called on an already fixed string. */
+                       clone_withlist(new_p, list_p);
+               }
+       }
+
+       return(newlist_p);
+}
+\f
+
+/* make a copy of the notelist in one GRPSYL struct into another */
+
+static void
+clone_notelist(new_p, old_p, copy_acc_etc)
+
+struct GRPSYL *new_p;  /* copy into here */
+struct GRPSYL *old_p;  /* from here */
+int copy_acc_etc;      /* if YES, copy accidentals.  If just reusing a
+                        * group on the same staff, we don't want to
+                        * copy these things */
+
+{
+       register int n;         /* index through note list */
+
+
+       /* mark the number of notes in the new list */
+       new_p->nnotes = old_p->nnotes;
+
+       /* copy cross-staff stem info */
+       new_p->stemto = old_p->stemto;
+       new_p->stemto_idx = old_p->stemto_idx;
+
+       if (old_p->nnotes > 0) {
+
+               /* allocate new memory and copy from old to new */
+               MALLOC(NOTE, new_p->notelist, old_p->nnotes);
+
+               (void)memcpy((char *) new_p->notelist, (char *) old_p->notelist,
+                       (unsigned) (old_p->nnotes * sizeof(struct NOTE)));
+
+       }
+
+       else if ((new_p->grpsyl == GS_GROUP) && (new_p->grpcont == GC_NOTES) &&
+                               is_mrpt(new_p) == NO) {
+               yyerror("tried to use previous chord for defaults, but it had no notes");
+               return;
+       }
+
+       for (n = 0; n < old_p->nnotes; n++) {
+
+               if (copy_acc_etc == YES) {
+                       new_p->notelist[n].nslurto = old_p->notelist[n].nslurto;
+                       /* It isn't necessarily safe to share slurto lists.
+                        * In particular, if multiple staffs are specified,
+                        * and they have different clefs, the default octave
+                        * will be different. So make a copy to be safe. */
+                       if (new_p->notelist[n].nslurto > 0) {
+                               MALLOC(SLURTO, new_p->notelist[n].slurtolist, 
+                                               new_p->notelist[n].nslurto);
+                               memcpy(new_p->notelist[n].slurtolist,
+                                       old_p->notelist[n].slurtolist,
+                                       sizeof(struct SLURTO) *
+                                       old_p->notelist[n].nslurto);
+                       }
+                       else {
+                               new_p->notelist[n].slurtolist = (struct SLURTO *) 0;
+                       }
+               }
+               else {
+                       new_p->notelist[n].nslurto = 0;
+                       new_p->notelist[n].slurtolist = (struct SLURTO *) 0;
+                       new_p->notelist[n].is_bend = NO;
+                       new_p->notelist[n].smallbend = NO;
+               }
+
+               /* alloc space for coordinates */
+               MALLOCA(float, new_p->notelist[n].c, NUMCTYPE);
+       }
+
+       /* if a note that was cloned had an accidental on it,
+        * the clone doesn't need the accidental since we are in
+        * the same measure. Ties also do not get copied. But on tab staff,
+        * the accidental does need to get copied since it's part of the
+        * name of the string. */
+       for (n = 0; n < old_p->nnotes; n++) {
+               if(copy_acc_etc == NO) {
+                       if (Doing_tab_staff == NO) {
+                               new_p->notelist[n].accidental = '\0';
+                               new_p->notelist[n].acc_has_paren = NO;
+                       }
+                       new_p->notelist[n].tie = NO;
+               }
+       }
+}
+\f
+
+/* add a NOTE to a list of notes off a GRPSYL */
+
+void
+add_note(grpsyl_p, pitch, accidental, octave, nticks, has_paren, bendstring)
+
+struct GRPSYL *grpsyl_p;       /* what group to associate note with */
+int    pitch;                  /* 'a' to 'g' */
+                               /* can also be pseudo-pitches for rest, space and rpt */
+int    accidental;             /* '\0', '#', '&', 'n', 'x', or 'B' */
+int    octave;                 /* octave for normal staffs,
+                                * fret for tab staffs, uncompressibility
+                                * for space pseudo-notes */
+int nticks;                    /* number of tick marks, for tab staffs */
+int has_paren;                 /* YES if accidental has parentheses (for
+                                * non-tab staffs) or if fret has parentheses
+                                * (for tab staffs) */
+char *bendstring;              /* bend specification, or null if no bend */
+
+{
+       register int index;             /* into notelist */
+
+
+       if (grpsyl_p->nnotes == 0) {
+               /* first time--need to allocate */
+               CALLOC(NOTE, grpsyl_p->notelist, NOTE_CHUNK);
+       }
+
+       /* see if overflowed and thus need to re-allocate more space */
+       else if ((grpsyl_p->nnotes % NOTE_CHUNK) == 0) {
+               REALLOC(NOTE, grpsyl_p->notelist, grpsyl_p->nnotes + NOTE_CHUNK);
+               memset((void *) (& grpsyl_p->notelist[grpsyl_p->nnotes]),
+                       0, NOTE_CHUNK * sizeof(struct NOTE));
+       }
+
+       /* find index into notelist where we put this note */
+       index = grpsyl_p->nnotes;
+
+       /* allocate space for coordinates. The coordinates must be in a
+        * malloc-ed array and not a static array. At one point, we thought
+        * we could save a few bytes by changing back to array, but that
+        * would be a lot of work. The reason is that the
+        * coordinates are pointed to whenever there is a location tag on a
+        * note. The array must not move or else the location tag reference
+        * would be wrong. Since we qsort the notes later on, the coords would
+        * move if they were a static array rather than a malloc-ed array.
+        * In order to allow moving them, we'd have to keep track of all note
+        * location tags for much longer than we currently do, and then go
+        * back and change their values when notes are sorted. It would require
+        * finding entries in a hash table by other than their key (i.e,
+        * require a linear search or another whole indexing scheme), and
+        * also require either going back to patch up any lines, curves, and
+        * prints that used the coords, or delaying their definition by saving
+        * lots of information around. */
+       MALLOCA(float, grpsyl_p->notelist[index].c, NUMCTYPE);
+
+       grpsyl_p->notelist [ index ].letter = (short) pitch;
+       grpsyl_p->notelist [ index ].accidental = (char) accidental;
+       grpsyl_p->notelist [ index ].acc_has_paren = has_paren;
+       if (Doing_tab_staff == YES && pitch >= 'a' && pitch <= 'g') {
+               int fret;
+
+               fret = octave;
+
+               /* do error checks */
+               if (accidental != '\0' && accidental != '#' && accidental != '&') {
+                       yyerror("accidental on tab staff can only be # or &");
+               }
+
+               if (fret == NOFRET && bendstring == (char *) 0) {
+                       yyerror("a fret number and/or bend must be specified");
+                       /* put in something valid so later functions won't
+                        * complain */
+                       fret = MINFRET;
+               }
+               else if ((fret < MINFRET || fret > MAXFRET) && fret != NOFRET) {
+                       l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                               "invalid fret number %d, must be %d-%d or have a bend",
+                               fret, MINFRET, MAXFRET);
+                       fret = MINFRET;
+               }
+
+               /* Cram fret and nticks in stepsup field for now. Later
+                * we will put fret in its proper place, but right now that
+                * is used for something else */
+               TMP_SAVE( (&(grpsyl_p->notelist[index])), nticks, fret);
+
+               /* cram the bend info into octave field */
+               grpsyl_p->notelist [ index ].octave
+                               = parse_bend_string(bendstring);
+       }
+       else {
+               if (nticks > 0) {
+                       yyerror("' not allowed on non-tablature staff");
+               }
+               grpsyl_p->notelist [ index ].octave = (short) octave;
+       }
+       grpsyl_p->notelist [ index ].nslurto = 0;
+       grpsyl_p->notelist [ index ].tie = NO;
+       grpsyl_p->notelist [ index ].tiestyle = L_NORMAL;
+       grpsyl_p->notelist [ index ].tiedir = UNKNOWN;
+       grpsyl_p->notelist [ index ].slurtolist = (struct SLURTO *)0;
+       grpsyl_p->notelist [ index ].notesize = GS_NORMAL;
+
+       /* don't need to initialize anything else in NOTE */
+
+       (grpsyl_p->nnotes)++;
+}
+\f
+
+/* once an entire chord is gathered, release any extra space gotten for
+ * notes */
+
+void
+resize_notelist(gs_p)
+
+struct GRPSYL *gs_p;
+
+{
+       int extra;      /* how many extra NOTE structs there are */
+
+
+       extra = NOTE_CHUNK - (gs_p->nnotes % NOTE_CHUNK);
+
+       if (extra > 0 && extra < NOTE_CHUNK) {
+               /* release extra NOTE space */
+               REALLOC(NOTE, gs_p->notelist, gs_p->nnotes);
+       }
+}
+\f
+
+/* when we get to a bar line, we have to go back and rearrange things and
+ * do some error checks that couldn't be done until we had everything
+ * collected. All the non-STAFF structures have to be put after the STAFFs.
+ */
+
+void
+do_bar(bartype)
+
+int bartype;
+
+{
+       struct MAINLL *mll_p;           /* to walk through list */
+       static short firstbar = YES;    /* if first time this func was called */
+       short v;                        /* voice number */
+       short found_above_for[MAXSTAFFS+1];     /* how many times this staff 
+                                        * was succesfully matched up with a
+                                        * "bm with staff below" */
+       int i;                          /* index though above array */
+       int other_staff;                /* other staff for cross-staff beam */
+       int with_above;                 /* how many "bm with staff above"
+                                        * found on current staff */
+
+
+       debug(2, "do_bar");
+
+       /* The "restart" is a strange thing only vaguely like a regular bar,
+        * so handle it separately */
+       if (bartype == RESTART) {
+               restart_bar();
+               return;
+       }
+
+       if (List_of_staffs_p == (struct MAINLL *) 0) {
+               yyerror("empty measure");
+               return;
+       }
+
+       /* Make sure all voices are present; fill in measure space for
+        * any that are missing */
+       check4missing_voices(List_of_staffs_p);
+
+       /* attach all the lyrics to the right places */
+       attach_lyrics2staffs(List_of_staffs_p);
+
+       /* set up all the cross-staff beams */
+       for (i = 1; i <= MAXSTAFFS; i++) {
+               found_above_for[i] = 0;
+       }
+       for (mll_p = List_of_staffs_p; mll_p != (struct MAINLL *) 0;
+                               mll_p = mll_p->next) {
+
+               if (mll_p->str != S_STAFF) {
+                       break;
+               }
+
+               with_above = 0;
+               /* check every group of every voice */
+               for (v = 0; v < MAXVOICES; v++) {
+                       struct GRPSYL *gs_p;
+
+                       /* Only check visible voices */
+                       if (vvpath(mll_p->u.staff_p->staffno, v+1, VISIBLE)->visible == NO) {
+                               continue;
+                       }
+
+                       for (gs_p = mll_p->u.staff_p->groups_p[v];
+                                       gs_p != (struct GRPSYL *) 0;
+                                       gs_p = gs_p->next) {
+
+                               /* if this is the first group in a cross-staff
+                                * beam, take care to that */
+                               if (gs_p->beamloc == STARTITEM &&
+                                               gs_p->beamto == CS_BELOW) {
+                                       /* before calling chk_crossbeams, make
+                                        * sure the gs_p we are passing has its
+                                        * vno set properly, since normally
+                                        * that doesn't happen till later.
+                                        * Maybe this cross-staff stuff should
+                                        * be done later, but I don't want to
+                                        * move it without a lot of thought to
+                                        * make sure that wouldn't break
+                                        * something, so this will work for now.
+                                        */
+                                       gs_p->vno = v;
+                                       other_staff = chk_crossbeam(gs_p, mll_p);
+                                       if (other_staff > 0) {
+                                               (found_above_for[other_staff])++;
+                                       }
+                               }
+                               else if (gs_p->beamloc == STARTITEM &&
+                                               gs_p->beamto == CS_ABOVE) {
+                                       with_above++;
+                               }
+                       }
+               }
+               if (found_above_for[mll_p->u.staff_p->staffno] < with_above) {
+                       l_yyerror(mll_p->inputfile, mll_p->inputlineno,
+                               "'bm with staff above' has no visible matching 'bm with staff below' (may be missing, invisible, or on wrong voice)");
+               }
+       }
+
+       /* if first measure, check if "pickup" measure. If so, it doesn't
+        * count toward measure number */
+       if (firstbar == YES && bartype != INVISBAR) {
+               if (has_pickup() == YES) {
+                       /* don't count pickup measure */
+                       Meas_num--;
+               }
+               /* set flag so we won't check again */
+               firstbar = NO;
+       }
+
+       /* increment measure number for rehearsal numbers */
+       if (bartype != INVISBAR && Got_multirest == 0) {
+               Meas_num++;
+       }
+
+       finish_bar();
+}
+\f
+
+/* Returns YES if piece begins with a pickup measure. */
+
+int
+has_pickup()
+{
+       int v;                  /* voice index */
+       struct MAINLL *mll_p;   /* to step through main list */
+
+       /* go through each voice of each staff looking for non-space */
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
+                                                       mll_p = mll_p->next) {
+
+               /* Measures where the entire measure is compressible space
+                * and which end with an invisbar were probably just for the
+                * purpose of kludging in a funny time signature or something
+                * like that, so we ignore those measures while checking for a
+                * pickup measure.
+                */
+               if (mll_p->str == S_BAR && mll_p->u.bar_p->bartype != INVISBAR) {
+                       /* got through entire first measure */
+                       break;
+               }
+               if (mll_p->str != S_STAFF) {
+                       continue;
+               }
+
+               for (v = 0; v < MAXVOICES; v++) {
+                       if (mll_p->u.staff_p->groups_p[v] != 0 &&
+                                               (mll_p->u.staff_p->groups_p[v]
+                                               ->grpcont != GC_SPACE ||
+                                               mll_p->u.staff_p->groups_p[v]
+                                               ->uncompressible == YES) ) {
+                               /* Found a voice that exists,
+                                * but begins with a non-space or an
+                                * uncompressible space. So it's not a pickup */
+                               return(NO);
+                       }
+               }
+       }
+       return(YES);
+}
+\f
+
+/* Do final cleanup in preparation for next bar of input */
+
+static void
+finish_bar()
+
+{
+       struct MAINLL *mll_p;
+
+       /* Walk thru the list, fixing everything that is left to fix */
+       for (mll_p = List_of_staffs_p; mll_p != (struct MAINLL *) 0;
+                               mll_p = mll_p->next) {
+
+               if (mll_p->str == S_BAR) {
+                       break;
+               }
+
+               if (mll_p->str == S_STAFF) {
+                       /* Walk down each GRPSYL list and
+                        * look for various errors and fix up things that
+                        * couldn't be determined before */
+                       fix_grpsyl_list(mll_p);
+
+                       /* Set the visibility attribute for staff */
+                       mll_p->u.staff_p->visible =
+                                       (svpath(mll_p->u.staff_p->staffno,
+                                       VISIBLE))->visible;
+               }
+
+       }
+
+       /* add padding etc for any rolls in the measure */
+       do_rolls(Mainlltc_p);
+
+       /* in case things are screwed up because of user input errors,
+        * reset tuplet state. */
+       Tuplet_state = NOITEM;
+
+       /* do measure level checks on "stuff" */
+       meas_stuff_chk();
+
+       /* get ready for next measure */
+       List_of_staffs_p = (struct MAINLL *) 0;
+       Got_multirest = 0;
+       Got_group = NO;
+       reset_input_style();
+       lyr_new_bar();
+}
+\f
+
+/* A "restart" is a funny sort of bar.
+ * We create a measure of space before it. */
+
+static void
+restart_bar()
+
+{
+       struct MAINLL *mll_p;
+       struct MAINLL *mainbar_p;       /* the restart */
+
+       if (List_of_staffs_p != 0) {
+               yyerror("restart cannot be preceeded by music data");
+               return;
+       }
+       if (Got_some_data == NO) {
+               yyerror("restart cannot be used at the beginning");
+               return;
+       }
+
+       /* It doesn't make sense to begin a repeat right before a restart,
+        * so block that. */
+       for (mll_p = Mainlltc_p->prev; mll_p != (struct MAINLL *) 0;
+                                                       mll_p = mll_p->prev) {
+               if (mll_p->str == S_BAR) {
+                       if (mll_p->u.bar_p->bartype == REPEATSTART) {
+                               yyerror("repeatstart not allowed immediately before restart");
+                       }
+                       else if (mll_p->u.bar_p->bartype == REPEATBOTH) {
+                               yyerror("repeatboth not allowed immediately before restart");
+                       }
+                       break;
+               }
+       }
+
+       /* save the bar so we can move after the staffs */
+       mainbar_p = Mainlltc_p;
+       /* create a "measure" of all space */
+       create_staffs();
+       check4missing_voices(List_of_staffs_p);
+       /* move the restart BAR after the empty measure */
+       unlinkMAINLL(mainbar_p);
+       insertMAINLL(mainbar_p, Mainlltc_p);
+       finish_bar();
+}
+\f
+
+/* walk down the linked lists of GRPSYLs and fix everything that is left to
+ * fix: font/size, octaves, default timeunits, etc */
+
+static void
+fix_grpsyl_list(mainll_item_p)
+
+struct MAINLL *mainll_item_p;
+
+{
+       register int v;
+       struct STAFF *staff_p;
+       struct MAINLL *mll_p;           /* for finding timed SSVs */
+       struct TIMEDSSV *tssv_p;
+       int numvoices;
+
+
+       /* error checks */
+       if (mainll_item_p->str != S_STAFF) {
+               pfatal("wrong struct type passed to fix_grpsyl_list()");
+       }
+       staff_p = mainll_item_p->u.staff_p;
+
+
+       /* verify voice is valid for current vscheme */
+       numvoices = vscheme_voices(svpath(staff_p->staffno,VSCHEME)->vscheme);
+       if (staff_p->groups_p[1] != (struct GRPSYL *) 0 && numvoices == 1) {
+               l_yyerror(staff_p->groups_p[1]->inputfile,
+                               staff_p->groups_p[1]->inputlineno,
+                               "can't have voice 2 when vscheme=1");
+       }
+       if (staff_p->groups_p[2] != (struct GRPSYL *) 0 && numvoices < 3) {
+               l_yyerror(staff_p->groups_p[2]->inputfile,
+                               staff_p->groups_p[2]->inputlineno,
+                               "can't have voice 3 unless vscheme is 3o or 3f");
+       }
+
+       /* Determine if there are timed SSVs to deal with */
+       tssv_p = 0;
+       for (mll_p = mainll_item_p; mll_p != 0; mll_p = mll_p->next) {
+               if (mll_p->str == S_BAR) {
+                       tssv_p = mll_p->u.bar_p->timedssv_p;
+                       break;
+               }
+       }
+
+       /* fix the GROUPS */
+       for (v = 0; v < MAXVOICES; v++) {
+               if (staff_p->groups_p[v] != (struct GRPSYL *) 0) {
+                       if (tssv_p != 0) {
+                               setssvstate(mainll_item_p);
+                       }
+                       fix_a_group_list(staff_p->groups_p[v],
+                               staff_p->staffno, v + 1,
+                               staff_p->groups_p[v]->inputfile,
+                               staff_p->groups_p[v]->inputlineno,
+                               staff_p->mrptnum,
+                               tssv_p);
+
+                       /* on tablature staffs, must deal with bends */
+                       if (is_tab_staff(staff_p->staffno) == YES) {
+                               check_bends(staff_p->groups_p[v], mainll_item_p);
+                       }
+               }
+       }
+
+       /* make sure timed SSVs are all up to date at end of measure */
+       for (  ; tssv_p != 0; tssv_p = tssv_p->next) {
+               asgnssv(&tssv_p->ssv);
+       }
+
+       /* then check syllables */
+       for (v = 0; v < staff_p->nsyllists; v++) {
+               chk_a_syl_list(staff_p->syls_p[v],
+                               staff_p->syls_p[v]->inputfile,
+                               staff_p->syls_p[v]->inputlineno);
+       }
+}
+\f
+
+/* walk through a list of GRPSYLs (GROUPs, not SYLLABLESs), and fix up things
+ * like octaves, etc */
+
+
+static void
+fix_a_group_list(grpsyllist_p, staffno, vno, fname, lineno, mrptnum, tssv_p)
+
+struct GRPSYL *grpsyllist_p;
+int staffno;
+int vno;               /* voice number */
+char *fname;           /* file name for error messages */
+int lineno;            /* input line number, for error messages */
+int mrptnum;           /* to decide whether to run fix_string or not */
+struct TIMEDSSV *tssv_p;       /* points to any timed SSVs in this measure */
+
+{
+       int font, size;
+       int n;                  /* index through notelist */
+       RATIONAL total_time;    /* to add up all fulltimes in current voice/verse */
+       short default_octave;
+       struct GRPSYL *grpsyl_p;
+       struct GRPSYL *gs_p;            /* for walking through grace runs */
+       int nn;
+
+
+
+       if (grpsyllist_p == (struct GRPSYL *) 0) {
+               /* this is un undefined voice, so nothing to do */
+               return;
+       }
+
+       debug(4, "fix_a_group_list file=%s lineno=%d staffno=%d vno=%d",
+                       grpsyllist_p->inputfile, grpsyllist_p->inputlineno,
+                       staffno, vno);
+
+       /* will need to fix up the font and size of strings in the
+        * "with" lists, so figure out
+        * which font and size to use for that */
+       font = (svpath(staffno, FONT))->font
+                               + (svpath(staffno, FONTFAMILY))->fontfamily;
+       size = (svpath(staffno, SIZE))->size;
+
+       /* initialize total time for this voice in this meas */
+       total_time = Zero;
+
+       /* find default octave for this staff/voice */
+       default_octave = (vvpath(staffno, vno, DEFOCT))->defoct;
+
+       grpsyl_p = grpsyllist_p;
+
+       Doing_tab_staff = is_tab_staff(staffno);
+
+       /* do each group */
+       for (   ; grpsyl_p != (struct GRPSYL *) 0; grpsyl_p = grpsyl_p->next) {
+
+               /* fill in staffno and vno */
+               grpsyl_p->staffno = (short) staffno;
+               grpsyl_p->vno = (short) vno;
+
+               /* Apply any timed SSVs */
+               while (tssv_p != 0 && LE(tssv_p->time_off, total_time)) {
+                       asgnssv(&tssv_p->ssv);
+                       tssv_p = tssv_p->next;
+                       /* the default octave might have changed,
+                        * so look it up again.
+                        */
+                       default_octave = (vvpath(staffno, vno, DEFOCT))->defoct;
+               }
+               /* if no pitch given on first group of measure, use default
+                * pitch if 1-line staff, otherwise error */
+               if (grpsyl_p->nnotes == 1 && grpsyl_p->notelist[0].letter
+                                                               == PP_NO_PITCH) {
+                       if (svpath(staffno, STAFFLINES)->stafflines == 1 &&
+                                       Doing_tab_staff == NO) {
+                               grpsyl_p->notelist[0].letter = DFLT_PITCH;
+                       }
+                       else {
+                               l_yyerror(fname, lineno,
+                                       "must have note(s) specified for first group in bar");
+                       }
+               }
+
+               /* make sure "with" lists are in right size/font */
+               /* When groups are copied to expand measure repeats for
+                * MIDI purposes, any 'with' lists would already be in
+                * internal format, so we don't want to try to fix them,
+                * but otherwise strings need to be put in internal format */
+               if (mrptnum == 0) {
+                       fix_strlist(grpsyl_p, font, size, fname, lineno);
+               }
+
+               if (mrptnum == 0) {
+                       if (Doing_tab_staff == YES) {
+                               /* determine proper STRINGNO and FRETNO information */
+                               fix_frets(grpsyl_p);
+                       }
+                       else {
+                               /* take care of relative octaves */
+                               resolve_octaves(grpsyl_p, default_octave);
+                       }
+               }
+
+               if (svpath(staffno, STAFFLINES)->stafflines == 1
+                                               && grpsyl_p->nnotes > 1) {
+                       l_warning(fname, lineno,
+                               "more than one note in chord on 1-line staff");
+               }
+
+               /* put notes in order top to bottom */
+               sort_notes(grpsyl_p, fname, lineno);
+
+               /* if group is small notes, mark each note as small */
+               if (grpsyl_p->grpsize != GS_NORMAL) {
+
+                       for (n = 0; n < grpsyl_p->nnotes; n++) {
+
+                               grpsyl_p->notelist[n].notesize
+                                                       = grpsyl_p->grpsize;
+                       }
+               }
+
+#ifdef GRPSMALL
+       /* at first we thought we should mark the whole group small if all
+        * notes were small, but later decided not, so this is ifdef-ed out */
+               /* on the other hand, if all notes are explicitly marked
+                * small, make the whole group small. This is handy in case,
+                * for example, the user uses ? instead of [cue] on a
+                * single-note group */
+               else if (grpsyl_p->grpcont == GC_NOTES) {
+                       int numsmall;   /* how many small notes */
+
+                       for (numsmall = n = 0; n < grpsyl_p->nnotes; n++) {
+                               if (grpsyl_p->notelist[n].notesize
+                                                               == GS_SMALL) {
+                                       numsmall++;
+                               }
+                       }
+                       if (grpsyl_p->nnotes > 0 &&
+                                               numsmall == grpsyl_p->nnotes) {
+                               grpsyl_p->grpsize = GS_SMALL;
+                       }
+               }
+#endif
+
+               /* error check rests */
+               if (grpsyl_p->grpcont == GC_REST) {
+                       if ( (grpsyl_p->prev != (struct GRPSYL *) 0)
+                                       && (grpsyl_p->prev->grpcont
+                                       == GC_NOTES)
+                                       && (grpsyl_p->prev->grpvalue
+                                       == GV_ZERO) ) {
+                               l_yyerror(fname, lineno,
+                                       "can't have grace notes before rest");
+                       }
+
+                       /* We used to disallow stemdir on rests, but it could
+                        * come from an earlier []... and doesn't really hurt;
+                        * it doesn't matter which direction the non-existent
+                        * stem is, so we silently ignore.
+                        */
+                       if (IS_STEMLEN_KNOWN(grpsyl_p->stemlen)) {
+                               /* Might be just from a [ ]... on an earlier
+                                * group, and doesn't really hurt anything,
+                                * so silently ignore.
+                                */
+                               grpsyl_p->stemlen = 0.0;
+                       }
+               }
+
+               /* error check space */
+               else if (grpsyl_p->grpcont == GC_SPACE) {
+                       if (IS_STEMLEN_KNOWN(grpsyl_p->stemlen)) {
+                               grpsyl_p->stemlen = 0.0;
+                       }
+               }
+
+               /* error check measure repeats */
+               if (is_mrpt(grpsyl_p) == YES) {
+                       if (grpsyl_p->nwith != 0
+                                       || grpsyl_p->grpvalue != GV_NORMAL
+                                       || grpsyl_p->headshape != HS_UNKNOWN
+                                       || grpsyl_p->grpsize != GS_NORMAL
+                                       || IS_STEMLEN_KNOWN(grpsyl_p->stemlen)
+                                       || grpsyl_p->stemdir != UNKNOWN
+                                       || grpsyl_p->slash_alt > 0) {
+                               l_yyerror(fname, lineno,
+                                       "can't specify items in [ ] with measure repeat (except padding and tag)");
+                       }
+                       if (grpsyl_p->slash_alt < 0) {
+                               l_yyerror(fname, lineno,
+                                       "can't specify alt with measure repeat");
+                       }
+                       if (grpsyl_p->tie == YES) {
+                               l_yyerror(fname, lineno,
+                                       "can't specify tie with measure repeat");
+                       }
+               }
+               /* grace notes need special handling */
+               if (grpsyl_p->grpvalue == GV_ZERO && is_mrpt(grpsyl_p) == NO) {
+
+                       /* grace notes really take no time */
+                       grpsyl_p->fulltime = Zero;
+
+                       /* do some error checks */
+                       check_grace(grpsyl_p, fname, lineno);
+
+                       /* if more than one grace note in a row, beam them */
+                       if (grpsyl_p->beamloc == NOITEM
+                                               && grpsyl_p->basictime > 4) {
+
+                               /* if there is another grace following, will
+                                * need to beam them */
+                               if ((grpsyl_p->next != (struct GRPSYL *)0) &&
+                                               (grpsyl_p->next->grpvalue
+                                               == GV_ZERO) &&
+                                               (grpsyl_p->next->basictime
+                                               > 4) ) {
+
+                                       /* mark the first one as STARTITEM */
+                                       grpsyl_p->beamloc = STARTITEM;
+
+                                       /* mark intermediates, if any,
+                                        * as INITEM, and last in run
+                                        * of grace as ENDITEM */
+                                       for (gs_p = grpsyl_p->next;
+                                                       gs_p->next
+                                                       != (struct GRPSYL *) 0;
+                                                       gs_p = gs_p->next) {
+                                               if (gs_p->next->grpvalue
+                                                               == GV_ZERO &&
+                                                               gs_p->next->basictime
+                                                               > 4) {
+                                                       gs_p->beamloc = INITEM;
+                                               }
+                                               else {
+                                                       gs_p->beamloc = ENDITEM;
+                                                       break;
+                                               }
+                                       }
+                                       if (gs_p->next == (struct GRPSYL *) 0){
+                                               /* grace at end of measure is
+                                                * illegal, but we catch that
+                                                * in check_grace(). So just
+                                                * mark the beam as ended */
+                                               gs_p->beamloc = ENDITEM;
+                                       }
+                               }
+                       }
+               }
+
+               /* if this group is alternating with the next, need to
+                * adjust fulltimes to be 1/2 of their current values. */
+               if (grpsyl_p->slash_alt < 0 && is_mrpt(grpsyl_p) == NO) {
+                       /* need to error check first. First, there must
+                        * be another group in this measure. Moreover, it
+                        * must have the same fulltime value, and both
+                        * must be either NORMAL or SMALL size.  Also, the
+                        * next group can't have an alt. */
+                       if (grpsyl_p->next == (struct GRPSYL *) 0) {
+                               l_yyerror(fname, lineno,
+                                       "cannot specify 'alt' on last group in measure");
+                               continue;
+                       }
+
+                       else if (grpsyl_p->next->grpvalue == GV_ZERO ||
+                                       grpsyl_p->grpvalue == GV_ZERO) {
+                               l_yyerror(fname, lineno,
+                                       "can't use 'alt' on grace notes");
+                       }
+
+                       else if ( ! EQ(grpsyl_p->fulltime,
+                                               grpsyl_p->next->fulltime) ) {
+                               l_yyerror(fname, lineno,
+                                       "groups in 'alt' pair must have identical time values");
+                       }
+
+                       else if (grpsyl_p->next->grpsize
+                                       != grpsyl_p->grpsize) {
+                               l_yyerror(fname, lineno,
+                                       "can't mix normal and cue notes for 'alt'");
+                       }
+
+                       else if (grpsyl_p->next->slash_alt < 0) {
+                               l_yyerror(fname, lineno,
+                                       "can't have 'alt' on consecutive chords");
+
+                       }
+
+                       else if (grpsyl_p->next->slash_alt > 0) {
+                               l_yyerror(fname, lineno,
+                                       "can't have 'slash' on second chord of 'alt' pair");
+                       }
+
+                       else if (grpsyl_p->grpcont != GC_NOTES ||
+                                       grpsyl_p->next->grpcont != GC_NOTES) {
+                               l_yyerror(fname, lineno,
+                                       "'alt' must be preceeded and followed by notes, not rest or space");
+                       }
+
+                       else {
+                               grpsyl_p->fulltime =
+                                               rdiv(grpsyl_p->fulltime, Two);
+                               grpsyl_p->next->fulltime =
+                                               rdiv(grpsyl_p->next->fulltime, Two);
+                       }
+
+                       if (grpsyl_p->stemdir != grpsyl_p->next->stemdir) {
+                               l_yyerror(fname, lineno,
+                                       "'alt' pair chords must have identical stem directions");
+                       }
+
+                       if (grpsyl_p->beamto != CS_SAME) {
+                               l_yyerror(fname, lineno,
+                                       "'alt' not allowed on cross-staff beams");
+                       }
+               }
+               else if (grpsyl_p->grpvalue != GV_ZERO &&
+                                               grpsyl_p->slash_alt > 0 &&
+                                               is_mrpt(grpsyl_p) == NO) {
+
+                       /* need to make sure number of slashes is valid */
+                       /* figure out how many actual chords are represented
+                        * by the slashed chord */
+                       switch (grpsyl_p->basictime) {
+                       case 0:
+                               nn = 16;
+                               break;
+                       case 1:
+                               nn = 8;
+                               break;
+                       case 2:
+                               nn = 4;
+                               break;
+                       default:
+                               nn = 2;
+                               break;
+                       }
+                       /* multiply by two for each additional slash beyond
+                        * the first. We shouldn't really need this IF, since
+                        * if should be okay to shift by 0, but for some reason,
+                        * on my system, if slash_alt is 1 and the optimizer
+                        * is run on this code, the following "if (n == 0)"
+                        * statement doesn't work right. It works fine if
+                        * the optimizer isn't run! (YIKES!!!!) */
+                       if (grpsyl_p->slash_alt >  1) {
+                               nn = nn << (grpsyl_p->slash_alt - 1);
+                       }
+
+                       if (nn == 0) {
+                               /* shifted left into oblivion */
+                               yyerror("too many slashes");
+                       }
+                       /* We are okay as long as the number of dots is no
+                        * more than the number of zero bits on the right end
+                        * of the number. If there are more, user is trying
+                        * to subdivide too much, so disallow */
+                       else if (drmo(nn) < grpsyl_p->dots) {
+                               yyerror("illegal number of slashes");
+                       }
+
+                       if (grpsyl_p->beamto != CS_SAME) {
+                               l_yyerror(fname, lineno,
+                                       "'slash' not allowed on cross-staff beams");
+                       }
+               }
+
+               /* check for unclosed custom beams */
+               if (grpsyl_p->next == (struct GRPSYL *) 0 &&
+                               (grpsyl_p->beamloc == STARTITEM ||
+                               grpsyl_p->beamloc == INITEM) ) {
+                       yyerror("missing ebm");
+               }
+
+               if (grpsyl_p->is_meas == YES && (grpsyl_p->prev != 0 ||
+                                               grpsyl_p->next != 0) ) {
+                       yyerror("measure duration item must be the only thing in the measure");
+               }
+
+               /* add up the total time in the measure */
+               total_time = radd(total_time, grpsyl_p->fulltime);
+       }
+
+       /* check for not equal to time signature. */
+       if ( NE(total_time, Score.time) && (grpsyllist_p->is_meas == NO
+                       || grpsyllist_p->next != 0) ) {
+               l_yyerror(fname, lineno,
+                       "time in measure (%ld/%ld) does not add up to time signature",
+                       total_time.n, total_time.d);
+       }
+
+       /* set up any beaming */
+       if (has_cust_beaming(grpsyllist_p) == NO) {
+               do_beaming(grpsyllist_p, GS_NORMAL, staffno, vno);
+               do_beaming(grpsyllist_p, GS_SMALL, staffno, vno);
+       }
+       set_alt_beams(grpsyllist_p);
+
+       for (grpsyl_p = grpsyllist_p; grpsyl_p != (struct GRPSYL *) 0;
+                                               grpsyl_p = grpsyl_p->next) {
+               /* We only allow specifying slope for beam on first group
+                * of a beam. To be very certain of avoiding any possiblity
+                * of floating point roundoff errors,
+                * we compare for being close to NOBEAMANGLE.
+                */
+               if (fabs(grpsyl_p->beamslope - NOBEAMANGLE) > 0.01) {
+                       if (grpsyl_p->beamloc != STARTITEM) {
+                               l_yyerror(fname, lineno,
+                                       "slope can only be specified on the first chord of a beam");
+                       }
+                       else if (grpsyl_p->grpcont == GC_SPACE) {
+                               if (grpsyl_p->beamto != CS_SAME) {
+                                       l_yyerror(fname, lineno,
+                                       "on cross-staff beam, specify slope on staff with notes, not with space");
+                               }
+                               else {
+                                       /* Don't think it should really be
+                                        * possible to get here... */
+                                       l_yyerror(fname, lineno,
+                                       "slope can't be specified on space");
+                               }
+                       }
+               }
+       }
+}
+\f
+
+/* make sure all the syllable times add up to time signature */
+
+static void
+chk_a_syl_list(grpsyl_p, fname, lineno)
+
+struct GRPSYL *grpsyl_p;       /* list to check */
+char *fname;                   /* file name for error messages */
+int lineno;                    /* input line for error messages */
+
+{
+       RATIONAL total_time;
+
+
+       total_time = Zero;
+
+       for (   ; grpsyl_p != (struct GRPSYL *) 0; grpsyl_p = grpsyl_p->next) {
+               total_time = radd(total_time, grpsyl_p->fulltime);
+       }
+
+       /* check for not equal to time signature. */
+       if ( NE(total_time, Score.time) ) {
+               l_yyerror(fname, lineno,
+                       "time in measure (%ld/%ld) does not add up to time signature",
+                       total_time.n, total_time.d);
+       }
+}
+\f
+
+/* resolve all the relative octaves to absolute octaves.
+ * Here's the deal: if the relative octave is negative,
+ * add (the negative value) to the default to get the
+ * real octave. If the relative is >= USE_DFLT_OCTAVE,
+ * add (octave - USE_DFLT_OCT) to the default to get the real
+ * value. Otherwise the relative is the absolute.  */
+
+static void
+resolve_octaves(grpsyl_item_p, default_octave)
+
+struct GRPSYL *grpsyl_item_p;  /* GRPSYL containing notes to resolve */
+int default_octave;            /* default octave to use */
+
+{
+       register int n;         /* walk through note list */
+       register int sl;        /* walk through slurtolist */
+       int octave;
+       struct NOTE *note_p;    /* current note */
+
+
+       for (n = 0; n < grpsyl_item_p->nnotes; n++) {
+
+               note_p = &(grpsyl_item_p->notelist[n]);
+               octave = note_p->octave;
+
+               if (octave < 0) {
+                       /* add (the negative value) to default octave */
+                       note_p->octave = (short)(default_octave + octave);
+               }
+               else if (octave >= USE_DFLT_OCTAVE) {
+                       /* this means 0 or more to add to default octave */
+                       note_p->octave = (short)(default_octave + octave
+                                                       - USE_DFLT_OCTAVE);
+               }
+               else if (octave > MAXOCTAVE) {
+                       l_yyerror(grpsyl_item_p->inputfile,
+                               grpsyl_item_p->inputlineno,
+                               "octave %d out of range (%d-%d)",
+                               octave, MINOCTAVE, MAXOCTAVE);
+               }
+
+               /* also adjust any slurto */
+               if (note_p->nslurto > 0) {
+                       for (sl = note_p->nslurto - 1; sl >= 0; sl--) {
+                               octave = note_p->slurtolist[sl].octave;
+                               if (octave < 0) {
+                                       note_p->slurtolist[sl].octave =
+                                                       default_octave + octave;
+                               }
+                               else if (octave >= USE_DFLT_OCTAVE) {
+                                       note_p->slurtolist[sl].octave =
+                                                       default_octave + octave
+                                                       - USE_DFLT_OCTAVE;
+                               }
+                       }
+               }
+       }
+}
+\f
+
+/* given a fulltime value, figure out what its basictime value was.
+ * Here's the deal: First we find the power of 2 that is less than or
+ * equal to the numerator of fulltime. Then we take that number over the
+ * denominator of fulltime and reduce to lowest terms. The new denominator
+ * is the basictime. Note that this won't work for tuplets, but we don't
+ * call this for tuplets, so we're safe... */
+
+int
+reconstruct_basictime(fulltime)
+
+RATIONAL fulltime;     /* find the basic time of this */
+
+{
+       RATIONAL newtime;       /* RATIONAL of basictime */
+
+
+       if (fulltime.n < 0) {
+               pfatal("negative fulltime numerator");
+       }
+
+       /* guess MAXBASICTIME and work down by powers of 2
+        * till we get <= fulltime numerator */
+       for (newtime.n = MAXBASICTIME; newtime.n > fulltime.n; newtime.n >>= 1) {
+               ;
+       }
+       newtime.d = fulltime.d;
+       rred( &newtime );
+
+       /* special case -- double whole basictime is 0 */
+       if (EQ(newtime, Two)) {
+               return(0);
+       }
+       /* special case -- quad whole basictime is -1 */
+       else if (EQ(newtime, Four)) {
+               return(-1);
+       }
+       else {
+               return ( (int) newtime.d);
+       }
+}
+\f
+
+/* Given a fulltime and basictime,
+ * figure out how many dots there must have been.
+ * Start with basictime as a RATIONAL. If equal to fulltime, fine, we are
+ * done. Otherwise, keep adding 50% of previous value until it is equal.
+ * The number of times we have to do this is the number of dots */
+
+int
+recalc_dots(fulltime, basictime)
+
+RATIONAL fulltime;
+int basictime;
+
+{
+       RATIONAL rat_basictime;
+       RATIONAL halftime;      /* half of previous note or dot */
+       int dots;
+
+       if (basictime == 0) {
+               /* special case of double whole */
+               rat_basictime.n = 2;
+               rat_basictime.d = 1;
+       }
+       else if (basictime == -1) {
+               /* special case of quad whole */
+               rat_basictime.n = 4;
+               rat_basictime.d = 1;
+       }
+       else {
+               rat_basictime.n = 1;
+               rat_basictime.d = basictime;
+       }
+
+       halftime = rmul(rat_basictime, One_half);
+       for (dots = 0; LT(rat_basictime, fulltime); dots++) {
+               rat_basictime = radd(rat_basictime, halftime);
+               halftime = rmul(halftime, One_half);
+       }
+       return(dots);
+}
+\f
+
+/* make sure all the GRPSYL fields for a grace group are valid */
+
+static void
+check_grace(grpsyl_item_p, fname, lineno)
+
+struct GRPSYL *grpsyl_item_p;  /* which grace group to check */
+char *fname;                   /* file name for error messages */
+int lineno;                    /* in input, for error messages */
+
+{
+       int n;          /* index through notelist  */
+
+       if (grpsyl_item_p->dots != 0) {
+               l_yyerror(fname, lineno, "can't have dots on grace notes");
+       }
+
+       else if (grpsyl_item_p->slash_alt == 1) {
+               if ( (grpsyl_item_p->prev != (struct GRPSYL *) 0
+                               && grpsyl_item_p->prev->grpvalue == GV_ZERO)
+                               || (grpsyl_item_p->next != (struct GRPSYL *) 0
+                               && grpsyl_item_p->next->grpvalue == GV_ZERO)) {
+                       l_yyerror(fname, lineno,
+                               "slash only allowed on single grace note");
+               }
+       }
+
+       else if (grpsyl_item_p->slash_alt > 1) {
+               l_yyerror(fname, lineno, "only 1 slash allowed on grace note");
+       }
+
+       if (grpsyl_item_p->basictime < 4) {
+               l_yyerror(fname, lineno,
+                               "grace note must be quarter note or shorter");
+       }
+
+       /* can't mix quarter grace notes (which don't have stems) with
+        * shorter grace notes (that do have stems and get beamed) */
+       if (grpsyl_item_p->basictime == 4 &&
+                       ((grpsyl_item_p->prev != (struct GRPSYL *) 0
+                       && grpsyl_item_p->prev->grpvalue == GV_ZERO
+                       && grpsyl_item_p->prev->basictime > 4) ||
+                       (grpsyl_item_p->next != (struct GRPSYL *) 0
+                       && grpsyl_item_p->next->grpvalue == GV_ZERO
+                       && grpsyl_item_p->next->basictime > 4))) {
+               l_yyerror(fname, lineno,
+                               "can't mix quarter and shorter grace notes");
+               /* set to shorter to avoid any future error messages */
+               grpsyl_item_p->basictime = 8;
+       }
+
+       if (is_tab_staff(grpsyl_item_p->staffno) == YES) {
+               for (n = 0; n < grpsyl_item_p->nnotes; n++) {
+                       if (HASBEND(grpsyl_item_p->notelist[n])) {
+                               l_yyerror(fname, lineno,
+                                       "can't have bend on grace note");
+                               break;
+                       }
+               }
+       }
+       else if (grpsyl_item_p->prev != (struct GRPSYL *) 0) {
+               
+               for (n = 0; n < grpsyl_item_p->prev->nnotes; n++) {
+                       if (grpsyl_item_p->prev->notelist[n].is_bend) {
+                               l_yyerror(fname, lineno,
+                                       "can't have bend on grace note");
+                               break;
+                       }
+               }
+       }
+
+
+       if (grpsyl_item_p->next == (struct GRPSYL *) 0) {
+               l_yyerror(fname, lineno,
+                               "grace note cannot be last thing in measure");
+       }
+
+       if (grpsyl_item_p->beamloc == STARTITEM) {
+               l_yyerror(fname, lineno,
+                               "custom beaming not allowed on grace notes");
+       }
+
+       if (grpsyl_item_p->stemdir != UNKNOWN) {
+               l_warning(fname, lineno,
+                               "stem direction not allowed on grace notes");
+       }
+
+       /* Only first and last in a series of grace are allowed
+        * to have stem length specified, and then both have to be.
+        * If this one is first of a series, do the check.
+        */
+       if ( (grpsyl_item_p->prev == 0
+                       || grpsyl_item_p->prev->grpvalue != GV_ZERO)
+                       && grpsyl_item_p->next != 0
+                       && grpsyl_item_p->next->grpvalue == GV_ZERO) {
+               struct GRPSYL *gs_p;
+               for (gs_p = grpsyl_item_p->next;
+                                       gs_p->next != 0 &&
+                                       gs_p->next->grpvalue == GV_ZERO;
+                                       gs_p = gs_p->next) {
+                       if (gs_p->stemlen != STEMLEN_UNKNOWN) {
+                               l_warning(fname, lineno,
+                                       "stem length cannot be specified in the middle of a series of grace notes");
+                               gs_p->stemlen = STEMLEN_UNKNOWN;
+                       }
+               }
+               if ( (gs_p->stemlen == STEMLEN_UNKNOWN) !=
+                               (grpsyl_item_p->stemlen == STEMLEN_UNKNOWN) ) {
+                       l_warning(fname, lineno,
+                               "stem length must be specified on both first and last grace or on neither");
+                       gs_p->stemlen = STEMLEN_UNKNOWN;
+                       grpsyl_item_p->stemlen = STEMLEN_UNKNOWN;
+               }
+       }
+}
+\f
+
+/* given a GRPSYL struct, fill in the font and size for all the
+ * strings in the with list */
+
+static void
+fix_strlist(gs_p, font, size, fname, lineno)
+
+struct GRPSYL *gs_p;   /* fix all with lists in this list of GRPSYLS */
+int font;              /* set their default font to this */
+int size;              /* set their default size to this */
+char *fname;           /* file name for error messages */
+int lineno;            /* input line number for error messages */
+
+{
+       register int n;
+
+
+       if (gs_p->grpcont != GC_NOTES && gs_p->nwith > 0) {
+               l_warning(fname, lineno,
+                               " 'with' items on rest or space ignored");
+               gs_p->nwith = 0;
+               return;
+       }
+
+       for (n = 0; n < gs_p->nwith; n++) {
+               (void) fix_string(gs_p->withlist[n], font, size,
+                                                       fname, lineno);
+       }
+}
+\f
+
+/* when a tuplet begins, mark tuplet state accordingly, and keep track to
+ * mark subsequent notes till the end of the tuplet. */
+
+void
+begin_tuplet()
+
+{
+       if ((Tuplet_state == INITEM) || (Tuplet_state == STARTITEM)) {
+               yyerror("nested tuplets not allowed");
+               return;
+       }
+
+       /* just remember we are starting a tuplet. When we actual get
+        * a note, we will mark it appropriately (in link_notegroup() ) */
+       Tuplet_state = STARTITEM;
+}
+\f
+
+/* once we reach the end of a tuplet, adjust all the time values */
+
+void
+end_tuplet(tupcont, tuptime, printtup, tupside)
+
+int tupcont;           /* number to print on top of tuplet */
+RATIONAL tuptime;      /* what time value to stuff tuplet into. If 0,
+                        * then use the next lower power of 2 of tupcont */
+int printtup;          /* one of the PT_* values, specifying whether to print
+                        * number and bracket */
+int tupside;           /* side at which to print number/bracket */
+
+{
+       RATIONAL mult_factor;   /* how much to adjust due to tuplet */
+       int num_non_grace = 0;  /* how many non-grace notes in tuplet */
+       int factor;             /* numerator of mult_factor */
+       RATIONAL tot_time;      /* total time taken by tuplet by adding up
+                                * the un-adjusted times. */
+       struct GRPSYL *gs_p;    /* walk through tuplet list */
+
+
+
+       /* future notes that come in are not in this tuplet */
+       Tuplet_state = NOITEM;
+
+       if (tupcont <= 1) {
+               yyerror("tuplet number must be greater than 1");
+               return;
+       }
+
+       if ( (printtup == PT_NEITHER) && (tupside != PL_UNKNOWN) ) {
+               l_warning(Curr_filename, yylineno,
+                       "when tuplet number is not printed, tuplet side is ignored");
+       }
+
+       if (EQ(tuptime, Zero)) {
+               /* this means user didn't specify, so we have to use
+                * the next lower power of two */
+               if ( (tupcont & (tupcont - 1)) == 0) {
+                       yyerror("if tuplet number is a power of 2, tuplet time must be given as well");
+                       return;
+               }
+
+               /* guess MAXBASICTIME, then keep taking the next
+                * lower power of 2  until we get under the tupcont:
+                * that's the right value to use */
+               for (factor = MAXBASICTIME; factor > tupcont; factor >>= 1) {
+                       ;
+               }
+               /* determine what to multiple each fulltime by */
+               mult_factor.n = factor;
+               mult_factor.d = tupcont;
+               rred(&mult_factor);
+       }
+       else {
+               /* figure out adjustment based on user-specified amount of
+                * time the tuplet is supposed to take */
+               tot_time = Zero;
+               for (gs_p = Tuplet_list_p; gs_p != (struct GRPSYL *) 0;
+                                               gs_p = gs_p->next) {
+                       if (gs_p->grpvalue != GV_ZERO) {
+                               tot_time = radd(tot_time, gs_p->fulltime);
+                       }
+               }
+               rred(&tuptime);
+               rred(&tot_time);
+               mult_factor = rdiv(tuptime, tot_time);
+               rred(&mult_factor);
+
+               /* if factor is <= 1/2 or >= 2, the user must have specified
+                * the wrong note lengths */
+               if (LE(mult_factor, One_half) || GE(mult_factor, Two)) {
+                       yyerror("illegal tuplet: values couldn't add up to specified tuplet time value");
+               }
+       }
+
+       /* go through the list, filling in tupcont, tuptime, and adjusting
+        * fulltime of each note */
+       for (  ; Tuplet_list_p != (struct GRPSYL *) 0;
+                                       Tuplet_list_p = Tuplet_list_p->next) {
+
+               Tuplet_list_p->tupcont = (short) tupcont;
+               Tuplet_list_p->printtup = printtup;
+               Tuplet_list_p->tupside = tupside;
+
+               if (Tuplet_list_p->grpvalue != GV_ZERO) {
+                       num_non_grace++;
+                       if (Tuplet_list_p->next != (struct GRPSYL *) 0 ||
+                                       num_non_grace >= 1) {
+                               /* adjust fulltime */
+                               Tuplet_list_p->fulltime =
+                                               rmul(Tuplet_list_p->fulltime,
+                                               mult_factor);
+                       }
+               }
+               else if (num_non_grace == 0) {
+                       /* don't include leading grace notes in tuplet */
+                       Tuplet_list_p->tuploc = NOITEM;
+                       Tuplet_list_p->next->tuploc = STARTITEM;
+               }
+
+               /* if this is the end of the list, mark end of tuplet */
+               if (Tuplet_list_p->next == (struct GRPSYL *) 0) {
+
+                       if (Tuplet_list_p->grpvalue == GV_ZERO) {
+                               yyerror("can't end tuplet with grace note");
+                       }
+
+                       if(num_non_grace == 1) {
+                               Tuplet_list_p->tuploc = LONEITEM;
+                               break;
+                       }
+                       else {
+                               Tuplet_list_p->tuploc = ENDITEM;
+                       }
+               }
+       }
+}
+\f
+
+/* check that all voices are actually present in a measure, add a measure
+ * space for any that are missing. Also make sure any measure repeats
+ * are correct: if more than one voice and one is a measure repeat,
+ * either all must be measure repeats, or those that aren't must be
+ * measure spaces, in which case the spaces are turned into measure repeats.
+ * Also fill in the mrptnum field of measure repeat STAFF
+ * to be the count of repeated measures.
+ */
+
+static void
+check4missing_voices(list_p)
+
+struct MAINLL *list_p; /* list of STAFFs */
+
+{
+       register int s;         /* walk through staff list */
+       int v;                  /* index through voices */
+       int numvoices;          /* how many voices on current staff */
+
+
+       debug(4, "check4missing_voices");
+
+       if (list_p == (struct MAINLL *) 0) {
+               pfatal("null list passed to check4missing_voices()");
+       }
+
+       /* check each staff */
+       for ( s = 1; s <= Score.staffs; s++) {
+
+               if (list_p->str != S_STAFF || list_p->u.staff_p->staffno != s) {
+                       if (Errorcount > 0) {
+                               /* if the input is garbage, we might get called
+                                * with strange things in the main list. We
+                                * would have already exclaimed about
+                                * the errors, so don't bother to try to
+                                * deal with the mess, just return */
+                               return;
+                       }
+                       else {
+                               /* if input was good, we shouldn't get here */
+                               pfatal("info about staff %d not in list", s);
+                       }
+               }
+
+               /* insert space for any missing voices */
+               numvoices = vscheme_voices(svpath(s, VSCHEME)->vscheme);
+               for (v = 0; v < numvoices; v++) {
+                       if (list_p->u.staff_p->groups_p[v]
+                                               == (struct GRPSYL *) 0) {
+                               add_meas_space( &(list_p->u.staff_p->groups_p[v]),
+                                                       s, v + 1);
+                       }
+               }
+
+               /* fix up any measure repeats */
+               fix_mrpt(list_p);
+
+               if (list_p->next != (struct MAINLL *) 0) {
+                       list_p = list_p->next;
+               }
+       }
+}
+\f
+
+/* fill in measure space for empty voice */
+
+void
+add_meas_space(gs_p_p, staff, voice)
+
+struct GRPSYL **gs_p_p;        /* where to put space */
+int staff;
+int voice;
+
+{
+       struct GRPSYL *grpsyl_p;
+
+
+       grpsyl_p = newGRPSYL(GS_GROUP);
+       *gs_p_p = grpsyl_p;
+
+       grpsyl_p->staffno = (short) staff;
+       grpsyl_p->vno = (short) voice;
+       grpsyl_p->basictime = -1;
+       grpsyl_p->is_meas = YES;
+
+       /* We are creating a line that doesn't appear in the user's input.
+        * However, if we make it an anonymous line, if this grpsyl ever
+        * gets referenced to print an error message (which it might--
+        * like if user tries to tie something into this generated measure
+        * space) the user will have no clue as to where the problem is in
+        * their input. So put in the current file/line which will point to
+        * the bar line at the end of the measure, which will at least point
+        * the user to the right general area. */
+       grpsyl_p->inputfile = Curr_filename;
+       grpsyl_p->inputlineno = (short) yylineno;
+       grpsyl_p->grpcont = GC_SPACE;
+
+       /* in another place, one compiler didn't fill in properly
+        * when I assigned Score.time directly in one step, so to
+        * take no chances, do numerator and denominator separately */
+       grpsyl_p->fulltime.n = Score.time.n;
+       grpsyl_p->fulltime.d = Score.time.d;
+}
+\f
+/* given a MAINLL that points to a STAFF, check if that staff is a measure
+ * repeat, and if so, validate and normalize it
+ */
+
+static void
+fix_mrpt(mll_p)
+
+struct MAINLL *mll_p;  /* points to a STAFF */
+
+{
+       struct GRPSYL *gs_voice_p[MAXVOICES];   /* groups for each voice */
+       struct GRPSYL *prevgrp_p;
+       struct STAFF *staff_p;
+       struct MAINLL *prevmll_p;               /* measure being repeated */
+       int voice_is_mrpt[MAXVOICES];           /* boolean for each voice */
+       int found_mrpt;
+       int found_non_mrpt;                     /* something other than mrpt or ms */
+       int staff;
+       int v;
+
+
+       /* find out if any voice is a measure repeat */
+       found_mrpt = NO;
+       found_non_mrpt = NO;
+       for (v = 0; v < MAXVOICES; v++) {
+               gs_voice_p[v] = mll_p->u.staff_p->groups_p[v];
+               voice_is_mrpt[v] = is_mrpt(gs_voice_p[v]);
+               if (voice_is_mrpt[v] == YES) {
+                       found_mrpt = YES;
+               }
+               else if (is_ms(gs_voice_p[v]) == NO) {
+                       found_non_mrpt = YES;
+               }
+       }
+
+       /* if none are a measure repeat, we are done */
+       if (found_mrpt == NO) {
+               return;
+       }
+
+       /* At least one must be a meas repeat. If the others aren't
+        * either also a measure repeat or a measure space, user error. */
+       if (found_non_mrpt == YES) {
+               l_yyerror(gs_voice_p[0]->inputfile, gs_voice_p[0]->inputlineno,
+                       "if one voice is mrpt, other voices cannot contain notes or rests");
+               return;
+       }
+
+       staff_p = mll_p->u.staff_p;
+       staff = staff_p->staffno;
+
+       /* At this point, we have at least one voice that is mrpt, and
+        * any other voices that exist are either mrpt or ms.
+        * Find the previous measure to find out how many measures of
+        * mrpt we have in a row, to fill in the mrptnum field.
+        * But before calling prevgrpsyl(), need to make sure the staffno and
+        * vno are filled in on the GRSPYL we pass to it, since we're so early
+        * in parsing that hasn't happened yet, but prevgrpsyl() needs them.
+        * We use the GRPSYL for voice 1, since we know that always exists.
+        */
+       gs_voice_p[0]->staffno = staff;
+       gs_voice_p[0]->vno = 1;
+       prevmll_p = mll_p;
+       if ((prevgrp_p = prevgrpsyl(gs_voice_p[0], &prevmll_p)) == (struct GRPSYL *) 0) {
+               /* We fell off the top of the main list */
+               l_yyerror(gs_voice_p[0]->inputfile, gs_voice_p[0]->inputlineno,
+                               "mrpt cannot be used on the first measure");
+
+               /* Force to measure space, so that if there are subsequent
+                * mrpt measures, they don't give more errors; no reason
+                * to complain more than once */
+               for (v = 0; v < MAXVOICES; v++) {
+                       if (gs_voice_p[v] != (struct GRPSYL *) 0) {
+                               gs_voice_p[v]->grpcont = GC_SPACE;
+                       }
+               }
+               return;
+       }
+
+       /* Having a mrpt after a multirest doesn't make sense. At best,
+        * it is ambiguous: should we repeat the multirest or the last
+        * measure of rest? If the former, we have big problems if one
+        * staff has a mrpt and another doesn't. If it's the latter, why
+        * doesn't the user just use mr? That would be smaller and clearer. */
+       if (prevgrp_p->basictime < -1) {
+               l_yyerror(gs_voice_p[0]->inputfile, gs_voice_p[0]->inputlineno,
+                               "mrpt cannot be used in measure after multirest");
+               for (v = 0; v < MAXVOICES; v++) {
+                       if (gs_voice_p[v] != (struct GRPSYL *) 0) {
+                               gs_voice_p[v]->grpcont = GC_SPACE;
+                       }
+               }
+               return;
+       }
+
+       if (is_mrpt(prevgrp_p) == YES) {
+               /* Our current one must be numbered
+                * one more than the previous one */
+               staff_p->mrptnum = prevmll_p->u.staff_p->mrptnum + 1;
+       }
+       else {
+               /* if this happens to be the first mrpt, it is numbered "2" */
+               staff_p->mrptnum = 2;
+       }
+
+       /* Certain parameter changes are not allowed in the middle of
+        * runs of measure repeats because they cause the contents of 
+        * the measure to be too different to make sense. These
+        * include changes in time signature, defoct, transpose.
+        * So back up from the mrpt measure to its preceeding measure,
+        * checking for any SSVs that might have something illegal in them.
+        */
+       for (mll_p = mll_p->prev; mll_p != prevmll_p; mll_p = mll_p->prev) {
+
+               if (mll_p->str == S_SSV) {
+                       if (chk_mrpt_ssv_interactions(mll_p->u.ssv_p,
+                                               gs_voice_p[0], staff) == NO) {
+                               /* Force to measure space, so that if
+                                * there are subsequent mrpt measures,
+                                * they don't give more errors; no reason
+                                * to complain more than once */
+                               for (v = 0; v < MAXVOICES; v++) {
+                                       if (gs_voice_p[v] != (struct GRPSYL *) 0) {
+                                               gs_voice_p[v]->grpcont = GC_SPACE;
+                                       }
+                               }
+                               return;
+                       }
+               }
+       }
+
+       /* If doing MIDI, expand the measure repeat to what it is repeating */
+       if (Doing_MIDI == YES) {
+               for (v = 0; v < MAXVOICES; v++) {
+                       struct GRPSYL *g_p;
+
+                       free_grpsyls(staff_p->groups_p[v]);
+                       /* Note that the notelist does need to be copied,
+                        * (arg 2 == YES) because even though coords
+                        * are not used in MIDI, vcombine code may delete
+                        * the list, so it cannot be shared across groups.
+                        */
+                       staff_p->groups_p[v] = clone_gs_list(
+                                       prevmll_p->u.staff_p->groups_p[v], YES);
+                       /* The cloned list may already have breakbeam set,
+                        * which will confuse has_cust_beaming(). For MIDI
+                        * purposes, we don't care about beams anyway,
+                        * much less subbeams, and breakbeam will get set
+                        * properly later anyway on these groups,
+                        * so just set to NO here. */
+                       for (g_p = staff_p->groups_p[v]; g_p != 0; g_p = g_p->next) {
+                               g_p->breakbeam = NO;
+                       }
+               }
+       }
+       else {
+               /* We force all to GC_NOTES to make sure they are all mrpt,
+                * even if some were originally ms. */
+               for (v = 0; v < MAXVOICES; v++) {
+                       if (gs_voice_p[v] != (struct GRPSYL *) 0) {
+                               gs_voice_p[v]->grpcont = GC_NOTES;
+                       }
+               }
+       }
+}
+\f
+
+/* given an SSV found while searching up the main list for a measure repeat
+ * defining measure, figure out whether having a measure repeat is valid or
+ * not. Some SSV changes alter things so much that a measure repeat no longer
+ * makes sense, so we block it. Return YES if all seems well, NO if not.
+ */
+
+/* Here is the list of things we do NOT allow user to change between a
+ * mrpt and the (earlier) measure that defines it */
+static struct Disallowed_ssv_fields {
+       int     field;          /* index of the field in SSV "used" array */
+       char *  name;           /* to use in error message */
+} mrpt_ssv_list[] = {
+       { TIME,                 "time" },
+       { DEFOCT,               "defoct" },
+       { CLEF,                 "clef" },
+       { TRANSPOSITION,        "transpose" },
+       { ADDTRANSPOSITION,     "addtranspose" },
+       { NUMSTAFF,             "staffs" },
+       { 0,                    (char *) 0 }    /* end the list */
+};
+
+static int
+chk_mrpt_ssv_interactions(ssv_p, gs_p, staffno)
+
+struct SSV *ssv_p;
+struct GRPSYL *gs_p;
+int staffno;
+
+{
+       int ret = YES;  /* return value after all checks */
+       int err = NO;   /* did we find error this time through loop? */
+       int field;      /* index into used array in SSV */
+       int i;          /* loop through list of disallowed things */
+
+
+       /* check all possible thing that we don't allow. Complain about
+        * as many errors as we find. Some of these things only occur in
+        * score or score/staff context, but it's easier to just make
+        * the code very general; if the field isn't used, things will still
+        * work just fine.
+        */
+       for (i = 0; mrpt_ssv_list[i].name != (char *) 0; i++) {
+               field = mrpt_ssv_list[i].field;
+               err = NO;
+
+               switch (ssv_p->context) {
+
+               case C_SCORE:
+                       /* for things that can be overriden on staff
+                        * and/or voice, the score one will only apply
+                        * if there isn't an override in effect */
+                       if (ssv_p->used[field] == YES) {
+                               if (Staff[staffno-1].used[field] == YES) {
+                                       /* overridden by staff, so ignore */
+                                       break;
+                               }
+                               if (voices_override(staffno, field) == YES) {
+                                       /* overridden by all voices; ignore */
+                                       break;
+                               }
+                               err = YES;
+                       }
+                       break;
+
+               case C_STAFF:
+               case C_VOICE:
+                       if (ssv_p->staffno != staffno) {
+                               /* This applies to some other staff. Since this
+                                * SSV is totally irrrelevant, we can return,
+                                * rather than loop through checking for other
+                                * possible errors. */
+                               return(YES);
+                       }
+                       if (ssv_p->used[field] == YES) {
+                               if (ssv_p->context == C_STAFF &&
+                                               voices_override(staffno, field) == YES) {
+                                       /* overridden on all voices, so ignore */
+                                       break;
+                               }
+                               err = YES;
+                       }
+                       break;
+
+               default:
+                       pfatal("bad context in mrpt/ssv check");
+                       break;
+               }
+
+               if (err == YES) {
+                       /* this field change not allowed */
+                       l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                               "can't use mrpt after %s change",
+                               mrpt_ssv_list[i].name);
+                       ret = NO;
+               }
+       }
+
+       return(ret);
+}
+\f
+
+/* Returns YES if the given SSV field is overriden by all voices
+ * on the given staff, NO if not. */
+
+static int
+voices_override(staff, field)
+
+int staff;     /* check this staff */
+int field;     /* check this field */
+
+{
+       int numvoices;
+       int v;
+
+       numvoices = vscheme_voices(svpath(staff, VSCHEME)->vscheme);
+       for (v = 0; v < numvoices; v++) {
+               if (Voice[staff - 1][v].used[field] == NO) {
+                       /* this voice does not override */
+                       return(NO);
+               }
+       }
+       return(YES);
+}
+\f
+
+/* return YES if given GRPSYL represents a measure repeat */
+
+int
+is_mrpt(gs_p)
+
+struct GRPSYL *gs_p;
+
+{
+       return (gs_p != (struct GRPSYL *) 0 && gs_p->is_meas == YES 
+               && gs_p->grpcont == GC_NOTES && gs_p->nnotes == 0) ? YES : NO;
+}
+
+/* return YES if given GRPSYL represents a measure space */
+
+static int
+is_ms(gs_p)
+struct GRPSYL *gs_p;
+
+{
+       /* non-existent is like measure space */
+       if (gs_p == (struct GRPSYL *) 0) {
+               return(YES);
+       }
+       return (gs_p->is_meas == YES && gs_p->grpcont == GC_SPACE) ? YES : NO;
+}
+\f
+
+/* sort the notes to be top to bottom */
+
+static void
+sort_notes(grpsyl_p, fname, lineno)
+
+struct GRPSYL *grpsyl_p;       /* sort the notes off this GRPSYL */
+char *fname;                   /* file name for error messages */
+int lineno;                    /* input line number */
+
+{
+       register int n;
+       struct NOTE *highest_p; /* note with highest pitch on a staff */
+       struct NOTE *lowest_p;  /* note with lowest pitch on a staff */
+       int othervis = -1;              /* staff number of adjacent visible staff */
+
+
+       if (grpsyl_p->nnotes < 2) {
+               /* nothing to sort! */
+               return;
+       }
+
+       /* If have cross-staff stemming, do extra error checks */
+       if (grpsyl_p->stemto != CS_SAME) {
+
+               if (Doing_tab_staff == YES) {
+                       l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                       "stemming with another staff is not allowed on a tablature staff");
+               }
+               else if (svpath(grpsyl_p->staffno, STAFFLINES)->stafflines != 5) {
+                       l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                       "stemming to another staff only allowed from a 5-line staff");
+               }
+               if (input_style(grpsyl_p->staffno, grpsyl_p->vno)
+                                       == IS_CHORD_INPUT) {
+                       l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                       "stemming to another staff not allowed on chord-at-a-time input");
+               }
+
+               if (grpsyl_p->stemto == CS_ABOVE) {
+                       for (othervis = grpsyl_p->staffno - 1; othervis > 0; othervis--) {
+                               if (svpath(othervis, VISIBLE)->visible == YES) {
+                                       if (svpath(grpsyl_p->staffno, STAFFLINES)->stafflines != 5
+                                                   || is_tab_staff(othervis)) {
+                                               l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                                               "for stem with staff above, preceeding visible staff must be a normal 5-line staff");
+                                       }
+                                       break;
+                               }
+                       }
+                       if (othervis <= 0) {
+                               l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                               "can't stem with above from top visible staff");
+                       }
+               }
+               else if (grpsyl_p->stemto == CS_BELOW) {
+                       for (othervis = grpsyl_p->staffno + 1; othervis <= Score.staffs; othervis++) {
+                               if (svpath(othervis, VISIBLE)->visible == YES) {
+                                       if (svpath(grpsyl_p->staffno, STAFFLINES)->stafflines != 5
+                                                   || is_tab_staff(othervis)) {
+                                               l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                                               "for stem with staff below, following visible staff must be a normal 5-line staff");
+                                       }
+                                       break;
+                               }
+                       }
+                       if (othervis >= Score.staffs + 1) {
+                               l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                               "can't stem with below from bottom visible staff");
+                       }
+               }
+
+               /* The two staffs must have the same staffscale.
+                * Use floating point comparision for "close enough" */
+               if (othervis > 0 && othervis <= Score.staffs) {
+                       if (fabs(svpath(othervis,STAFFSCALE)->staffscale -
+                       svpath(grpsyl_p->staffno, STAFFSCALE)->staffscale) > 0.001) {
+                               l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                               "staff being stemed to must have same staffscale");
+                       }
+               }
+       }
+
+       /* If this group is stemmed to another staff,
+        * we have to make sure the notes on the two staffs don't overlap,
+        * since we can't handle duplicate notes,
+        * and it's kind of silly anyway.
+        * At this point, the stemto_idx will be at the first
+        * "other staff" note. In the case of stem with above,
+        * we need to adjust that to be at the last normal staff group,
+        * because that is the convention we use. In any case, once
+        * we verify there is no overlap, we can go ahead and sort the
+        * group as usual, since we know that will end up sorting each
+        * staff's notes properly.
+        */
+       if (grpsyl_p->stemto == CS_ABOVE) {
+               /* Find highest note on normal staff */
+               if (grpsyl_p->stemto_idx == 0) {
+                       /* no notes at all on normal staff */
+                       highest_p = 0;
+                       n = 0;
+               }
+               else {
+                       highest_p = &(grpsyl_p->notelist[0]);
+                       for (n = 1; n < grpsyl_p->stemto_idx; n++) {
+                               if (notecomp(&(grpsyl_p->notelist[n]), highest_p) > 0) {
+                                       highest_p = &(grpsyl_p->notelist[n]);
+                               }
+                       }
+               }
+               /* Find lowest note on above staff */
+               if (grpsyl_p->stemto_idx == grpsyl_p->nnotes) {
+                       /* Actually, we don't currently allow this case
+                        * (blocked in parsing code),
+                        * but if we ever do, this code should handle it...
+                        */
+                       lowest_p = 0;
+               }
+               else {
+                       lowest_p = &(grpsyl_p->notelist[n]);
+                       for ( ; n < grpsyl_p->nnotes; n++) {
+                               if (notecomp(&(grpsyl_p->notelist[n]), lowest_p) < 0) {
+                                       lowest_p = &(grpsyl_p->notelist[n]);
+                               }
+                       }
+               }
+               /* Make sure there is no overlap */
+               if (highest_p != 0 && lowest_p != 0 &&
+                                       notecomp(highest_p, lowest_p) <= 0) {
+                       l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                       "the 'with above' notes are not allowed to overlap with notes on the normal staff");
+               }
+
+               /* With CS_ABOVE, the index is supposed to point to the last on
+                * the normal, so adjust to do that. */
+               grpsyl_p->stemto_idx = grpsyl_p->nnotes - grpsyl_p->stemto_idx - 1;
+       }
+       else if (grpsyl_p->stemto == CS_BELOW) {
+               /* Do analogous for below */
+               /* Find lowest note on normal staff */
+               if (grpsyl_p->stemto_idx == 0) {
+                       /* no notes at all on normal staff */
+                       lowest_p = 0;
+                       n = 0;
+               }
+               else {
+                       lowest_p = &(grpsyl_p->notelist[0]);
+                       for (n = 1; n < grpsyl_p->stemto_idx; n++) {
+                               if (notecomp(&(grpsyl_p->notelist[n]), lowest_p) < 0) {
+                                       lowest_p = &(grpsyl_p->notelist[n]);
+                               }
+                       }
+               }
+               /* Find highest note on below staff */
+               if (grpsyl_p->stemto_idx == grpsyl_p->nnotes) {
+                       highest_p = 0;
+                       n = 0;
+               }
+               else {
+                       highest_p = &(grpsyl_p->notelist[n]);
+                       for (n++ ; n < grpsyl_p->nnotes; n++) {
+                               if (notecomp(&(grpsyl_p->notelist[n]), highest_p) > 0) {
+                                       highest_p = &(grpsyl_p->notelist[n]);
+                               }
+                       }
+               }
+               /* Make sure there is no overlap */
+               if (highest_p != 0 && lowest_p != 0 &&
+                                       notecomp(highest_p, lowest_p) <= 0) {
+                       l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                       "the 'with below' notes are not allowed to overlap with notes on the normal staff");
+               }
+       }
+
+       /* sort top to bottom */
+       qsort( (char *) grpsyl_p->notelist, (unsigned int) grpsyl_p->nnotes,
+                                       sizeof (struct NOTE), notecomp);
+
+       /* now that they are sorted, check for duplicates. */
+       for (n = 0; n < grpsyl_p->nnotes - 1; n++) {
+               if (notecomp(&(grpsyl_p->notelist[n]),
+                                       &(grpsyl_p->notelist[n+1])) == 0) {
+                       /* For voice-at-a-time, duplicate is an error.
+                        * For chord-at-a-time, we merge them, except that
+                        * for tablature, if the frets don't match we
+                        * can't merge them. */
+                       if (input_style(grpsyl_p->staffno, grpsyl_p->vno)
+                                       == IS_VOICE_INPUT ||
+                                       (Doing_tab_staff == YES &&
+                                       grpsyl_p->notelist[n].FRETNO !=
+                                       grpsyl_p->notelist[n+1].FRETNO)
+                                       ) {
+                               if (Doing_tab_staff == YES) {
+                                       struct STRINGINFO *strinfo_p;
+
+                                       strinfo_p = &(svpath(grpsyl_p->staffno,
+                                               STAFFLINES)->strinfo[ (int)
+                                               grpsyl_p->notelist[n].STRINGNO]);
+                                       l_yyerror(fname, lineno,
+                                               "string %s occurred more than once in a single chord",
+                                               format_string_name(
+                                               strinfo_p->letter,
+                                               strinfo_p->accidental,
+                                               strinfo_p->nticks));
+                               }
+                               else {
+                                       l_yyerror(fname, lineno,
+                                               "pitch %c%d occurred more than once in a single chord",
+                                               grpsyl_p->notelist[n].letter,
+                                               grpsyl_p->notelist[n].octave);
+                               }
+                       }
+                       else {
+                               merge_dup_notes(grpsyl_p, n);
+                               /* in case there was more than one duplicate,
+                                * arrange to check this same one again,
+                                * against the group that has taken the place
+                                * of the removed group (if any) */
+                               n--;
+                       }
+               }
+       }
+}
+\f
+
+/* Compare notes. Return 1 if first is lower, -1 if higher, 0 if same.
+ * For tablature, this just compares the strings; for non-tablature,
+ * it just compares pitch and octave, not counting accidentals. */
+
+int
+notecomp(item1_p, item2_p)
+
+#ifdef __STDC__
+const void *item1_p;           /* the notes to compare */
+const void *item2_p;
+#else
+char *item1_p;         /* the notes to compare */
+char *item2_p;
+#endif
+
+{
+       struct NOTE *note1_p;
+       struct NOTE *note2_p;
+
+       /* cast to proper type */
+       note1_p = (struct NOTE *) item1_p;
+       note2_p = (struct NOTE *) item2_p;
+
+       if (Doing_tab_staff == YES) {
+               /* for tablature, just need to compare the string numbers. */
+               if (note1_p->STRINGNO < note2_p->STRINGNO) {
+                       return(-1);
+               }
+               else if (note1_p->STRINGNO > note2_p->STRINGNO) {
+                       return(1);
+               }
+               else {
+                       return(0);
+               }
+       }
+
+       /* first compare octaves */
+       if ( note1_p->octave < note2_p->octave) {
+               return(1);
+       }
+
+       if (note1_p->octave > note2_p->octave) {
+               return(-1);
+       }
+       
+       /* if same octaves, compare pitches */
+       if (Letshift[note1_p->letter - 'a'] < Letshift[note2_p->letter - 'a']) {
+               return(1);
+       }
+
+       if (Letshift[note1_p->letter - 'a'] > Letshift[note2_p->letter - 'a']) {
+               return(-1);
+       }
+
+       return(0);
+}
+\f
+
+/* Make sure data ends with some kind of bar line (which can optionally
+ * be followed by blocks). Start at end of  main list and go backwards.
+ * If we hit a S_BAR, then all is well.
+ * If we hit a S_STAFF first or beginning of list, we have a problem.
+ * Also does error checks on any FEED at the end of the piece.
+ * It does a similar check on any FEED at the beginning. (It doesn't
+ * really fit the name of the function, but keeps the checks together.)
+ */
+
+void
+check4barline_at_end()
+
+{
+       struct MAINLL *list_p;  /* walk through main list */
+       int saw_block = NO;     /* if saw an S_BLOCKHEAD */
+
+
+       /* first check for FEED at the beginning */
+       for (list_p = Mainllhc_p; list_p != (struct MAINLL *) NULL;
+                               list_p = list_p->next) {
+               if (list_p->str == S_STAFF) {
+                       /* no user-supplied feed at beginning */
+                       break;
+               }
+               else if (list_p->str == S_FEED) {
+                       /* rightmargin applies to previous feed,
+                        * but there is no previous feed to the first score */
+                       if (list_p->u.feed_p->rightmargin >= 0.0) {
+                               l_warning(list_p->inputfile, list_p->inputlineno,
+                                       "rightmargin on newscore at beginning of piece is ignored");
+                       }
+                       /* Note: we probably ought to give a
+                        * warning for pagefeed here and ignore it,
+                        * to be like at the end of a piece.
+                        * But this was inadvertently allowed in the past
+                        * (it produces a blank page),
+                        * so we leave it that way
+                        * for backward compatibility.
+                        */
+               }
+       }
+
+       for (list_p = Mainlltc_p; list_p != (struct MAINLL *) NULL;
+                               list_p = list_p->prev) {
+
+               if (list_p->str == S_BAR) {
+                       /* found BAR before STAFF. Good. */
+                       /* if user forgot to end an ending, do it for them */
+                       if (list_p->u.bar_p->endingloc == INITEM) {
+                               list_p->u.bar_p->endingloc = ENDITEM;
+                       }
+                       else if (list_p->u.bar_p->endingloc == STARTITEM) {
+                               l_yyerror(list_p->inputfile, list_p->inputlineno,
+                                       "can't begin ending on final bar line");
+                       }
+
+                       if (list_p->u.bar_p->bartype == RESTART) {
+                               l_yyerror(list_p->inputfile, list_p->inputlineno,
+                                       "final bar line cannot be a restart");
+                       }
+                       return;
+               }
+
+               else if (list_p->str == S_STAFF) {
+                       /* Oh-oh. No ending bar line */
+                       yyerror("ending bar line missing");
+                       return;
+               }
+
+               else if (list_p->str == S_BLOCKHEAD) {
+                       saw_block = YES;
+               }
+               else if (list_p->str == S_FEED) {
+                       if (list_p->u.feed_p->leftmargin >= 0.0) {
+                               l_warning(list_p->inputfile, list_p->inputlineno,
+                                       "leftmargin on newscore at end of piece is ignored");
+                       }
+               }
+       }
+
+       /* if we are here, we went all through the list */
+       if (saw_block == NO) {
+               yyerror("no music data or blocks found in input");
+       }
+}
+\f
+
+/* when user wants a multi-rest, create a STAFF for each staff. Then for
+ * each of them, fill in a GRPSYL with basictime as the negative of the
+ * number of measure, and fulltime as the length of a measure. Attach this
+ * GRPSYL as the only item off of voice 1, and to other voices as well,
+ * if there are other voice and we are doing MIDI. */
+
+void
+add_multirest(nummeas)
+
+int nummeas;           /* how many measures in the multi-rest */
+
+{
+       register int s;         /*staff index */
+       struct GRPSYL *new_p;   /* newly allocated GRPSYL for multirest */
+       int v;                  /* voice index */
+       int numvoices;
+
+
+       /* if already have notes in this measure, user goofed */
+       if (Got_group == YES) {
+               report_mix_error();
+               return;
+       }
+
+       if (Got_multirest == 1) {
+               yyerror("can't have consecutive multirests (maybe missing bar?)");
+               return;
+       }
+
+       /* we could allow up to 32767 and still fit in a short, but huge
+        * numbers can lead to rational overflow in midi, and who in their
+        * right mind would want that many measures of multirest anyway? */
+       if (rangecheck(nummeas, 2, MAXMULTINUM, "multirest measures") == NO) {
+               return;
+       }
+
+       /* create all the staffs and fill them in */
+       create_staffs();
+       for (s = 1; s <= Score.staffs; s++) {
+               numvoices = vscheme_voices(svpath(s, VSCHEME)->vscheme);
+               for (v = 0; v < numvoices; v++) {
+                       if (v == 0 || Doing_MIDI == YES) {
+                               Staffmap_p[s]->u.staff_p->groups_p[v] = new_p
+                                               = newGRPSYL(GS_GROUP);
+                               new_p->grpcont = GC_REST;
+                               new_p->basictime = -nummeas;
+                               new_p->fulltime = Score.time;
+                       }
+               }
+       }
+
+       Got_multirest = 1;
+       Got_some_data = YES;
+
+       /* update measure numbers for rehearsal mark and stuff use */
+       Meas_num += nummeas;
+       multi_stuff(nummeas);
+}
+\f
+
+/* this function gets called when we discover user has mixed multi-rest and
+ * music data in a single measure. If we've already reported this on the
+ * current measure, Got_multirest will be 2, so we just return,
+ * otherwise report it and set Got_multirest to 2 */
+
+void
+report_mix_error()
+
+{
+       if (Got_multirest != 2) {
+               yyerror( "can't mix music data and multi-rest in same measure");
+               Got_multirest = 2;
+       }
+}
+\f
+
+/* Recursively free a list of GRPSYLs. If this is a GS_GROUP,
+ * also free the withlist and notelist if they exist,
+ * and anything hanging off the notelist. If this is a GS_SYLLABLE, anything
+ * that is hanging of the grpsyl will NOT be freed.
+ */
+
+void
+free_grpsyls(gs_p)
+
+struct GRPSYL *gs_p;           /* what to free */
+
+{
+       int n;                  /* to index through lists */
+
+       if (gs_p == (struct GRPSYL *) 0) {
+               /* end of recursion */
+               return;
+       }
+
+       if (gs_p->grpsyl == GS_GROUP) {
+               free_notelist(gs_p);
+
+               /* free the withlist */
+               for (n = 0; n < gs_p->nwith; n++) {
+                       if (gs_p->withlist[n] != (char *) 0) {
+                               FREE(gs_p->withlist[n]);
+                       }
+               }
+               if (gs_p->withlist != (char **) 0 && gs_p->nwith > 0) {
+                       FREE(gs_p->withlist);
+               }
+       }
+
+       free_grpsyls(gs_p->next);
+       FREE(gs_p);
+}
+\f
+
+/* Free things off of NOTEs in the notelist, if any, plus the list itself */
+
+void
+free_notelist(gs_p)
+
+struct GRPSYL *gs_p;
+
+{
+       int n;
+
+       for (n = 0; n < gs_p->nnotes; n++) {
+               /* free coordinate array, if any */
+               if (gs_p->notelist[n].c != (float *) 0) {
+                       FREE(gs_p->notelist[n].c);
+               }
+
+               /* free any slurto lists */
+               if (gs_p->notelist[n].slurtolist != (struct SLURTO *) 0) {
+                       FREE(gs_p->notelist[n].slurtolist);
+               }
+       }
+
+       /* free the notelist itself, if any */
+       if (gs_p->notelist != (struct NOTE *) 0 && gs_p->nnotes > 0) {
+               FREE(gs_p->notelist);
+       }
+}
+\f
+
+/* add a slurto note to list */
+
+void
+add_slurto(grpsyl_p, pitch, octave, note_index, slurstyle)
+
+struct GRPSYL *grpsyl_p;       /* what group to associate slurto with */
+int    pitch;                  /* 'a' to 'g' */
+int    octave;
+int    note_index;             /* which note in the chord to slur from */
+int    slurstyle;              /* L_NORMAL, L_DOTTED, or L_DASHED */
+
+{
+       struct NOTE *note_p;    /* note to attach to */
+
+
+       if (note_index < 0) {
+               /* user tried to slur from a rest or something like that */
+               yyerror("no note to slur from");
+               return;
+       }
+
+       note_p = &(grpsyl_p->notelist [ note_index ]);
+       if (note_p->nslurto == 0) {
+               /* first time--need to allocate */
+               MALLOC(SLURTO, note_p->slurtolist, 1);
+       }
+
+       /* else re-allocate more space */
+       else {
+               REALLOC(SLURTO, note_p->slurtolist, note_p->nslurto + 1);
+       }
+
+       note_p->slurtolist [ note_p->nslurto ].letter = (char) pitch;
+       note_p->slurtolist [ note_p->nslurto ].octave = (short) octave;
+       note_p->slurtolist [ note_p->nslurto ].slurstyle = (short) slurstyle;
+       /* we'll fix up this value later when we know the right one */
+       note_p->slurtolist [ note_p->nslurto ].slurdir = (short) UNKNOWN;
+
+       (note_p->nslurto)++;
+}
+\f
+
+/* At the beginning of a <> which indicates slurs,
+ * save which slurtolist index we are are on.
+ * When at the end of the slur, we will discover if the user specified a
+ * bend direction for the slurs, and if so, have to go back and fill in
+ * that direction for all the slurtolist items from the saved index to
+ * the end of the list. This is needed since user may have several <>
+ * items with different directions, e.g.,
+ *     a<c+>up<g>down<e>
+ */
+
+void
+begin_slur(grpsyl_p, note_index)
+
+struct GRPSYL *grpsyl_p;
+int note_index;
+
+{
+       if (grpsyl_p == 0 || note_index < 0 || note_index >= grpsyl_p->nnotes) {
+               /* must have been bad input */
+               return;
+       }
+       Slur_begin = grpsyl_p->notelist[note_index].nslurto;
+}
+
+/* At the end of a slur, either <> style or "slur" keyword style,
+ * go back and fill in the bulge direction. If note_index is -1,
+ * this is a "slur" that applies to all notes of the group, and
+ * there should be one slurto item on each note.
+ */
+
+void
+set_slurdir(grpsyl_p, note_index, dir)
+
+struct GRPSYL *grpsyl_p;
+int note_index;                /* which note's slurtolist to use */
+int dir;               /* UP, DOWN, UNKNOWN */
+
+{
+       int n;
+       int i;
+
+       if (note_index == -1) {
+               for (n = 0; n < grpsyl_p->nnotes; n++) {
+                       if (grpsyl_p->notelist[n].nslurto >= 1) {
+                               grpsyl_p->notelist[n]
+                                       .slurtolist[grpsyl_p->notelist[n].nslurto-1]
+                                       .slurdir = dir;
+                       }
+                       /* If no slurto, should already have
+                        * error generated elsewhere */
+               }
+       }
+       else {
+               for (i = Slur_begin; i < grpsyl_p->notelist[note_index].nslurto; i++) {
+                       grpsyl_p->notelist[note_index].slurtolist[i].slurdir = dir;
+               }
+       }
+}
+\f
+
+/* given a bend string, return what should be crammed into the
+ * octave field to save this info, using the TABOCT macro. If the string
+ * is incomprehensible, print error, and do what we can. */
+
+/* define states for the simple parser */
+#define DOING_INTEGER          1
+#define DOING_NUMERATOR                2
+#define DOING_DENOMINATOR      3
+#define GOT_ERROR              4
+
+static int
+parse_bend_string(bendstring)
+
+char *bendstring;
+
+{
+       int intpart = 0;        /* integer part of bend */
+       int num = 0, den = 1;   /* numerator and denominator
+                                * of fractional part of bend */
+
+
+       /* if null string, easy to parse */
+       if (bendstring == (char *) 0) {
+               return (TABOCT(0, 0, 0));
+       }
+
+       /* string is in internal format, so skip first 2 bytes, plus any
+        * leading white space */
+       for (bendstring += 2; *bendstring != '\0'; bendstring++) {
+               if (isgraph(*bendstring)) {
+                       break;
+               }
+       }
+
+       /* the text "full" is a special case */
+       if (strcmp(bendstring, "full") == 0) {
+               intpart = 1;
+       }
+       else {
+               /* the text better be a number and/or fractional part,
+                * so parse that */
+               int state;      /* DOING_INTEGER, DOING_NUMERATOR,
+                                * DOING_DENOMINATOR, or GOT_ERROR */
+
+               for (state = DOING_INTEGER;
+                               *bendstring != '\0' && state < GOT_ERROR;
+                               bendstring++) {
+
+                       if (isdigit(*bendstring)) {
+                               /* add to the correct item */
+                               switch(state) {
+                               case DOING_INTEGER:
+                                       intpart = (intpart * 10) + (*bendstring - '0');
+                                       break;
+                               case DOING_NUMERATOR:
+                                       num = (num * 10) + (*bendstring - '0');
+                                       break;
+                               case DOING_DENOMINATOR:
+                                       den = (den * 10) + (*bendstring - '0');
+                                       break;
+                               default:
+                                       pfatal("bad state in parse_bend_string");
+                                       break;
+                               }
+                       }
+
+                       /* handle white space */
+                       else if (*bendstring == ' ' || *bendstring == '\t') {
+                               if (state == DOING_INTEGER) {
+                                       /* end of integer part */
+                                       state = DOING_NUMERATOR;
+                               }
+                               /* ignore any other white space */
+                       }
+
+                       else if (*bendstring == '/') {
+                               /* starting parsing of denominator */
+                               den = 0;
+
+                               switch (state) {
+
+                               case DOING_INTEGER:
+                                       /* oops. what we thought was the integer
+                                        * part was really the numerator of the
+                                        * fractional part. Adjust accordingly. */
+                                       num = intpart;
+                                       intpart = 0;
+                                       state = DOING_DENOMINATOR;
+                                       break;
+
+                               case DOING_NUMERATOR:
+                                       state = DOING_DENOMINATOR;
+                                       break;
+
+                               case DOING_DENOMINATOR:
+                                       yyerror("more than one / in bend string");
+                                       state = GOT_ERROR;
+                                       break;
+
+                               default:
+                                       pfatal("bad state in parse_bend_string");
+                                       break;
+                               }
+                       }
+
+                       else {
+                               yyerror("invalid character in bend string");
+                               state = GOT_ERROR;
+                       }
+               }
+       }
+
+       /* make sure we can fit them in our cramped space */
+       (void) rangecheck(intpart, MINBENDINT, MAXBENDINT,
+                                       "integer part of bend");
+       (void) rangecheck(num, MINBENDNUM, MAXBENDNUM,
+                                       "numerator of bend fraction");
+       (void) rangecheck(den, MINBENDDEN, MAXBENDDEN,
+                                       "denominator of bend fraction");
+
+       return (TABOCT(intpart, num, den));
+}
+\f
+
+/* given a tablature GRPSYL, look up the proper string number based on the
+ * letter/accidental that is currently there, and fill in the STRINGNO and
+ * FRETNO fields with their correct values. The slurto items also get
+ * their string letter/accidental values translated to string number. */
+
+static void
+fix_frets(grpsyl_item_p)
+
+struct GRPSYL *grpsyl_item_p;
+
+{
+       int n;                  /* index through note list */
+       int s;                  /* index through slurto */
+       struct NOTE *note_p;    /* current note */
+       struct STRINGINFO *string_info_p;       /* string translation table,
+                                * to map between pitch/accidental and
+                                * string number */
+       int nstrings;           /* how many strings there are */
+
+
+       /* find appropriate string mapping table and its size */
+       string_info_p = Staff[grpsyl_item_p->staffno - 1].strinfo;
+       nstrings = Staff[grpsyl_item_p->staffno - 1].stafflines;
+
+       /* for each note, translate to string number, and put fret in its
+        * proper field */
+       for (n = 0; n < grpsyl_item_p->nnotes; n++) {
+               /* get pointer to the current note in the group */
+               note_p = &(grpsyl_item_p->notelist[n]);
+
+               /* doing mapping from pitch/accidental to string number */
+               note_p->STRINGNO = string_number(string_info_p, nstrings,
+                       note_p->letter, note_p->accidental, TMP_NTICKS(note_p));
+
+               /* fill in the correct fret number, now that its space is
+                * available */
+               note_p->FRETNO = TMP_FRET(note_p);
+               note_p->stepsup = 0;    /* no longer need this temp space */
+
+               /* also fix up any slurto items */
+               for (s = 0; s < note_p->nslurto; s++) {
+                       if (note_p->slurtolist[s].octave == USE_DFLT_OCTAVE) {
+                               note_p->slurtolist[s].STRINGNO
+                                                       = note_p->STRINGNO;
+                       }
+               }
+       }
+}
+\f
+
+/* look up a letter/acc/nticks combination in the string_info_p table of
+ * size nstrings, and return the index of the string that matched. If none
+ * match, print an error and return 0. However, if the pitch is PP_NO_PITCH,
+ * don't print the error, because an error would already have been printed
+ * earlier, and it just adds confusion to print another one.
+ * Also don't complain about rest and space, because they are legal.
+ */
+
+static int
+string_number(string_info_p, nstrings, letter, accidental, nticks)
+
+struct STRINGINFO *string_info_p;      /* string translation table */
+int nstrings;                          /* number of entries in table */
+int letter;
+int accidental;
+int nticks;                            /* number of ' marks */
+
+{
+       register int i;
+
+       if (string_info_p == (struct STRINGINFO *) 0) {
+               pfatal("null stringinfo");
+       }
+
+       /* look through string_info list for a matching string */
+       for (i = 0; i < nstrings; i++) {
+               if (string_info_p[i].letter == letter &&
+                               string_info_p[i].accidental == accidental &&
+                               string_info_p[i].nticks == nticks) {
+                       /* found it. return its index */
+                       return(i);
+               }
+       }
+
+       /* If letter is PP_NO_PITCH, that means user failed to put a letter
+        * for the first group in the measure. We would have already
+        * exclaimed about that in fix_a_grpsyl_list(), so rather than
+        * generate lots more messages due to the same error,
+        * just silently return the default string of 0.
+        * Rests, spaces, and rpts are also fine--they will get converted to
+        * groups later. Otherwise the error message is needed. */
+       if (letter >= 'a' && letter <= 'g') {
+               /* no match found */
+               l_yyerror(Curr_filename, yylineno, "no '%s' string",
+                               format_string_name(letter, accidental, nticks));
+       }
+
+       /* use string 0 as default, to have something to return */
+       return(0);
+}
+\f
+
+/* given a string number and staff number, return the text representation
+ * of that string. Returns pointer to static area. */
+
+char *
+stringname(stringno, staffno)
+
+int stringno;
+int staffno;
+
+{
+       struct STRINGINFO *stringinfo_p;
+
+
+       /* make sure we have a valid string number */
+       if (stringno < 0 || stringno >= Staff[staffno - 1].stafflines) {
+               pfatal("string number %d out of range", stringno);
+       }
+
+       /* get pointer to proper table entry for this string */
+       stringinfo_p = & (Staff[staffno - 1].strinfo[stringno] );
+
+       /* return text representation */
+       return(format_string_name(stringinfo_p->letter,
+                       stringinfo_p->accidental,
+                       stringinfo_p->nticks));
+}
+\f
+
+/* to print some ticks, print as much of this string as necessary */
+static char tickstring[MAXTICKS + 1];
+
+/* given string letter, accidental, and number of tick marks, return
+ * pointer to static area that contains the text representation of the
+ * string name */
+
+char *
+format_string_name(letter, accidental, nticks)
+
+int letter;
+int accidental;
+int nticks;
+
+{
+       static char name[MAXTICKS + 3]; /* this is what will get returned */
+       int tickoffset = 1;     /* where in name that ticks begin */
+       int i;
+
+       /* fill in string letter plus accidental if any */
+       name[0] = (char) letter;
+       if (accidental != 0) {
+               name[1] = (char) accidental;
+               tickoffset++;
+       }
+
+       /* first time through, fill in maximum number of ticks. This makes
+        * it possible to have the right number, even if MAXTICKS changes
+        * some day */
+       if (tickstring[0] == '\0') {
+               for (i = 0; i < MAXTICKS; i++) {
+                       tickstring[i] = '\'';
+               }
+       }
+
+       /* add appropriate number of ticks to name */
+       (void) sprintf(name + tickoffset, tickstring + strlen(tickstring) - nticks);
+
+       return(name);
+}
+\f
+
+/* given a list of grpsyls, check that every non-prebend bend has a previous
+ * groups which contains the same string as the bend is on. Also disallow
+ * slashes on groups that just have a bend. */
+
+static void
+check_bends(gs_p, mll_p)
+
+struct GRPSYL *gs_p;
+struct MAINLL *mll_p;
+
+{
+       int n;                          /* notelist index */
+       int ns;                         /* slurto index */
+       struct GRPSYL *prevgrp_p;       /* previous group in same staff/voice */
+       struct NOTE *prevnote_p;        /* note in previous group */
+       int has_bend, has_prebend;      /* YES or NO */
+       struct MAINLL *nmll_p;
+
+
+       /* check each group in the list */
+       for (  ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+
+               /* check each note in the group */
+               has_bend = has_prebend = NO;
+               for (n = 0; n < gs_p->nnotes; n++) {
+
+                       if (HASBEND(gs_p->notelist[n])
+                                       && gs_p->notelist[n].FRETNO == NOFRET) {
+
+                               /* this is a non-prebend bend, so it needs to
+                                * be checked. Find the previous group */
+                               has_prebend = YES;
+                               nmll_p = mll_p;
+                               if ((prevgrp_p = prevgrpsyl(gs_p, &nmll_p))
+                                               != (struct GRPSYL *) 0) {
+
+                                       /* find the matching note (string),
+                                        * If not found, the function will
+                                        * print an error. */
+                                       prevnote_p =
+                                               find_matching_note(prevgrp_p,
+                                               gs_p->notelist[n].letter,
+                                               gs_p->notelist[n].octave,
+                                               "bend");
+
+                                       if (prevnote_p == (struct NOTE *) 0) {
+                                               continue;
+                                       }
+
+                                       /* previous group not allowed to have
+                                        * slide other than inward nowhere */
+                                       for (ns = 0; ns < prevnote_p->nslurto;
+                                                                       ns++) {
+                                               switch (prevnote_p->slurtolist
+                                                               [ns].octave) {
+                                               case IN_UPWARD:
+                                               case IN_DOWNWARD:
+                                                       /* these are okay */
+                                                       break;
+                                               default:
+                                                       l_yyerror(gs_p->inputfile,
+                                                       gs_p->inputlineno,
+                                                       "can't have bend on note following a slide");
+                                                       break;
+                                               }
+                                       }
+                               }
+                               else {
+                                       yyerror("can't do bend--no previous group");
+                                       continue;
+                               }
+
+                               /* slashes are not allowed on bend groups */
+                               if (gs_p->slash_alt != 0) {
+                                       yyerror("slash not allowed with bend");
+                                       gs_p->slash_alt = 0;
+                               }
+                       }
+                       else if (HASBEND(gs_p->notelist[n])
+                                       && gs_p->notelist[n].FRETNO != NOFRET) {
+                               has_bend = YES;
+                       }
+               }
+
+               if (has_bend == YES && has_prebend == YES) {
+                       yyerror("mixture of prebend and bend not allowed on the same chord");
+               }
+       }
+}
+\f
+
+/*
+ * When the input includes additive time values like 2+8 or 2.+32
+ * on groups, we need to create a group for each extra time value.
+ * For notes, the groups are all tied together to make them effectively
+ * a single group. If there are any subtractions in the list of time values,
+ * we have no way to determine what time values the user really wants,
+ * so we keep using as big as possible (including dots) until we get enough.
+ * Should be called with the group currently last in the GRPSYL list.
+ * Returns the (possibly new) last group.
+ */
+
+struct GRPSYL *
+expandgrp(grpsyl_p, timelist_p)
+
+struct GRPSYL *grpsyl_p;       /* the first group; pattern to clone */
+struct TIMELIST *timelist_p;   /* the list of additional time values */
+
+{
+       struct GRPSYL *gs_p;    /* group being processed */
+       struct TIMELIST *tl_p;  /* index through list to check for subtracts */
+       int had_neg;            /* YES if there was at least one subtraction */
+       RATIONAL totaltime;     /* all times added together */
+       int n;                  /* index through notelist */
+
+
+       if (timelist_p == 0) {
+               /* nothing to expand */
+               return(grpsyl_p);
+       }
+
+       /* disallow on grace */
+       if (grpsyl_p->grpvalue == GV_ZERO) {
+               yyerror("can't use additive time values on grace notes");
+               return(grpsyl_p);
+       }
+       /* disallow if alt on group */
+       if (grpsyl_p->slash_alt < 0) {
+               yyerror("can't use additive time values and alt on same chord");
+               return(grpsyl_p);
+       }
+
+       /* If there were any subtraction, need to do that differently
+        * than if all are additions. Check if any subtractions, and
+        * add up total time in case we need it. */
+       for (had_neg = NO, totaltime = grpsyl_p->fulltime, tl_p = timelist_p;
+                                       tl_p != 0; tl_p = tl_p->next) {
+               if (MI(tl_p->fulltime)) {
+                       had_neg = YES;
+               }
+               totaltime = radd(totaltime, tl_p->fulltime);
+       }
+       if (had_neg == YES) {
+               /* It's impossible to know what time values the user
+                * really wants us to use, so we keep using the largest
+                * possible values until we get enough, using as many
+                * dots as possible along the way.
+                */
+               RATIONAL try;   /* The time value we're currently attempting
+                                * to use; will be used if remaining time
+                                * is at least this long, else take half
+                                * and try again. */
+               int needgrp;    /* YES if need to alloc a new group.
+                                * (Have one group to start with,
+                                * so first time through loop don't need
+                                * to allocate.) */
+
+               /* We start with double whole, and keep using smaller times
+                * from there until we get enough, using dots if possible.
+                * I suppose for rests we really *should* start with quad
+                * whole rather than double whole, but since we don't know
+                * what the user really wants anyway, and the cases where
+                * this would make a difference are so rare, and since the
+                * user can always specify exactly what they do want,
+                * don't bother. (They'll just get two double whole rests.) */
+               gs_p = grpsyl_p;
+               for (needgrp = NO, try = Two; PL(totaltime);   ) {
+                       if (GE(totaltime, try)) {
+                               /* We can use this trial time value */
+                               if (needgrp == YES) {
+                                       gs_p->next = clone_gs_list(gs_p, YES);
+                                       gs_p->next->prev = gs_p;
+                                       gs_p = gs_p->next;
+                                       /* If the original group started a beam,
+                                        * added groups must be inside */
+                                       if (gs_p->beamloc == STARTITEM) {
+                                               gs_p->beamloc = INITEM;
+                                       }
+                               }
+                               gs_p->fulltime = try;
+                               gs_p->dots = 0;
+                               gs_p->basictime = reconstruct_basictime(gs_p->fulltime);
+                               totaltime = rsub(totaltime, try);
+                               if (GE(totaltime, try)) {
+                                       /* Total time is so long we can use
+                                        * another one of this time value. */
+                                       needgrp = YES;
+                                       continue;
+                               }
+                       }
+                       else {
+                               /* Trial time is too long. Try half as much. */
+                               try = rdiv(try, Two);
+                               continue;
+                       }
+
+                       /* If still some time left, see if we can add one
+                        * or more dots to use up more time. */
+                       for (try = rdiv(try, Two); GE(totaltime, try);
+                                                       try = rdiv(try, Two)) {
+                               (gs_p->dots)++;
+                               gs_p->fulltime = radd(gs_p->fulltime,
+                                                               try);
+                               totaltime = rsub(totaltime, try);
+                       }
+                       needgrp = YES;
+               }
+       }
+
+       else {           /* (No subtractions) */
+               /* We will add a group for each added time value */
+               for (gs_p = grpsyl_p; timelist_p != 0;
+                                               timelist_p = timelist_p->next) {
+                       /* Make a copy the GRPSYL. This function is to be called
+                        * with the group currently at the end of a list,
+                        * so the "list" being cloned is only a single group,
+                        * but might as well use the existing function... */
+                       gs_p->next = clone_gs_list(gs_p, YES);
+                       gs_p->next->prev = gs_p;
+                       gs_p = gs_p->next;
+                       /* Now fix up the time values in the cloned group */
+                       gs_p->fulltime = timelist_p->fulltime;
+                       gs_p->basictime = reconstruct_basictime(gs_p->fulltime);
+                       gs_p->dots = recalc_dots(gs_p->fulltime,
+                                               gs_p->basictime);
+                       /* If the original group started a beam,
+                        * added groups must be inside */
+                       if (gs_p->beamloc == STARTITEM) {
+                               gs_p->beamloc = INITEM;
+                       }
+               }
+       }
+
+       /* We need to tie the note groups together. Rests are not yet in
+        * final form, so have to look for PP_REST. */
+       if (grpsyl_p->grpcont == GC_NOTES && (grpsyl_p->nnotes != 1
+                               || grpsyl_p->notelist[0].letter != PP_REST)) {
+               for (gs_p = grpsyl_p; gs_p->next != 0; gs_p = gs_p->next) {
+                       gs_p->tie = YES;
+                       for (n = 0; n < gs_p->nnotes; n++) {
+                               gs_p->notelist[n].tie = YES;
+                       }
+               }
+               /* tied-to notes accidentals must be implied, not explicit */
+               for (n = 0; n < grpsyl_p->nnotes; n++) {
+                       if (grpsyl_p->notelist[n].accidental != '\0') {
+                               struct GRPSYL *ngs_p;
+                               for (ngs_p = grpsyl_p->next; ngs_p != 0;
+                                                       ngs_p = ngs_p->next) {
+                                       ngs_p->notelist[n].accidental = '\0';
+                               }
+                       }
+               }
+       }
+       return(gs_p);
+}
+\f
+
+/*
+ * Given a RATIONAL basictime and number of dots,
+ * return the corresponding fulltime. That is calculated by 
+ *     (2 * basictime) - (basictime x 1/2 to the (dots) power)
+ */
+
+RATIONAL
+calcfulltime(basictime, dots)
+
+RATIONAL basictime;
+int dots;
+
+{
+       return( rsub (rmul(Two, basictime), rmul(basictime, rrai(One_half, dots))) );
+}
diff --git a/mup/mup/ifgram.c b/mup/mup/ifgram.c
new file mode 100644 (file)
index 0000000..e516f07
--- /dev/null
@@ -0,0 +1,1697 @@
+/* A Bison parser, made from ifgram.y, by GNU bison 1.75.  */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* Written by Richard Stallman by simplifying the original so called
+   ``semantic'' parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON        1
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+/* If NAME_PREFIX is specified substitute the variables and functions
+   names.  */
+#define yyparse ifparse
+#define yylex   iflex
+#define yyerror iferror
+#define yylval  iflval
+#define yychar  ifchar
+#define yydebug ifdebug
+#define yynerrs ifnerrs
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     ICT_AND = 258,
+     ICT_BITAND = 259,
+     ICT_BITCOMPLEMENT = 260,
+     ICT_BITOR = 261,
+     ICT_BITXOR = 262,
+     ICT_COLON = 263,
+     ICT_DIVIDE = 264,
+     ICT_END = 265,
+     ICT_ERROR = 266,
+     ICT_EQ = 267,
+     ICT_FALSE = 268,
+     ICT_GT = 269,
+     ICT_GE = 270,
+     ICT_LPAREN = 271,
+     ICT_LE = 272,
+     ICT_LT = 273,
+     ICT_MINUS = 274,
+     ICT_MOD = 275,
+     ICT_MULT = 276,
+     ICT_NE = 277,
+     ICT_NOT = 278,
+     ICT_OR = 279,
+     ICT_PLUS = 280,
+     ICT_QUESTION = 281,
+     ICT_RPAREN = 282,
+     ICT_SHLEFT = 283,
+     ICT_SHRIGHT = 284,
+     ICT_TRUE = 285,
+     ICT_VALUE = 286
+   };
+#endif
+#define ICT_AND 258
+#define ICT_BITAND 259
+#define ICT_BITCOMPLEMENT 260
+#define ICT_BITOR 261
+#define ICT_BITXOR 262
+#define ICT_COLON 263
+#define ICT_DIVIDE 264
+#define ICT_END 265
+#define ICT_ERROR 266
+#define ICT_EQ 267
+#define ICT_FALSE 268
+#define ICT_GT 269
+#define ICT_GE 270
+#define ICT_LPAREN 271
+#define ICT_LE 272
+#define ICT_LT 273
+#define ICT_MINUS 274
+#define ICT_MOD 275
+#define ICT_MULT 276
+#define ICT_NE 277
+#define ICT_NOT 278
+#define ICT_OR 279
+#define ICT_PLUS 280
+#define ICT_QUESTION 281
+#define ICT_RPAREN 282
+#define ICT_SHLEFT 283
+#define ICT_SHRIGHT 284
+#define ICT_TRUE 285
+#define ICT_VALUE 286
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 2 "ifgram.y"
+
+/* Copyright 2005 by Arkkra Enterprises */
+/* All rights reserved. */
+
+/* This is a "mini-parser" that handles "if" clauses.
+ * It uses a buffer containing a compressed form of the user's input.
+ * The compressed format is described in lex.c  above add_ifclause().
+ * This tries to follow the ANSI C preprocessor rules as much as is reasonable.
+ * It uses C operator precedences and associativity.
+ * We do use 32-bit ints rather than longs to try to avoid any
+ * incompatibilities if someone creates a Mup file on a 32-bit machine
+ * and then tries to run it on 64-bit or vice-versa.
+ */
+
+#include "defines.h"
+#include "globals.h"
+
+#define YYDEBUG 1
+
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+#ifndef YYSTYPE
+typedef int yystype;
+# define YYSTYPE yystype
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+#ifndef YYLTYPE
+typedef struct yyltype
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+} yyltype;
+# define YYLTYPE yyltype
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 213 of /usr/share/bison/yacc.c.  */
+#line 185 "ifgram.tab.c"
+
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# if YYSTACK_USE_ALLOCA
+#  define YYSTACK_ALLOC alloca
+# else
+#  ifndef YYSTACK_USE_ALLOCA
+#   if defined (alloca) || defined (_ALLOCA_H)
+#    define YYSTACK_ALLOC alloca
+#   else
+#    ifdef __GNUC__
+#     define YYSTACK_ALLOC __builtin_alloca
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning. */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+#  if defined (__STDC__) || defined (__cplusplus)
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T size_t
+#  endif
+#  define YYSTACK_ALLOC malloc
+#  define YYSTACK_FREE free
+# endif
+#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+
+
+#if (! defined (yyoverflow) \
+     && (! defined (__cplusplus) \
+        || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short yyss;
+  YYSTYPE yyvs;
+  };
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE))                                \
+      + YYSTACK_GAP_MAX)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)             \
+      do                                       \
+       {                                       \
+         register YYSIZE_T yyi;                \
+         for (yyi = 0; yyi < (Count); yyi++)   \
+           (To)[yyi] = (From)[yyi];    \
+       }                                       \
+      while (0)
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)                                       \
+    do                                                                 \
+      {                                                                        \
+       YYSIZE_T yynewbytes;                                            \
+       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
+       Stack = &yyptr->Stack;                                          \
+       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX;   \
+       yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                        \
+    while (0)
+
+#endif
+
+#if defined (__STDC__) || defined (__cplusplus)
+   typedef signed char yysigned_char;
+#else
+   typedef short yysigned_char;
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL  19
+#define YYLAST   327
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS  32
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS  4
+/* YYNRULES -- Number of rules. */
+#define YYNRULES  32
+/* YYNRULES -- Number of states. */
+#define YYNSTATES  62
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   286
+
+#define YYTRANSLATE(X) \
+  ((unsigned)(X) <= YYMAXUTOK ? yytranslate[X] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const unsigned char yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const unsigned char yyprhs[] =
+{
+       0,     0,     3,     6,     8,    10,    14,    17,    20,    23,
+      26,    30,    34,    38,    42,    46,    50,    54,    58,    62,
+      66,    70,    74,    78,    82,    86,    90,    94,    98,   104,
+     106,   108,   110
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yysigned_char yyrhs[] =
+{
+      33,     0,    -1,    34,    10,    -1,    11,    -1,     1,    -1,
+      16,    34,    27,    -1,    23,    34,    -1,     5,    34,    -1,
+      19,    34,    -1,    25,    34,    -1,    34,    21,    34,    -1,
+      34,     9,    34,    -1,    34,    20,    34,    -1,    34,    25,
+      34,    -1,    34,    19,    34,    -1,    34,    28,    34,    -1,
+      34,    29,    34,    -1,    34,    18,    34,    -1,    34,    17,
+      34,    -1,    34,    14,    34,    -1,    34,    15,    34,    -1,
+      34,    12,    34,    -1,    34,    22,    34,    -1,    34,     4,
+      34,    -1,    34,     7,    34,    -1,    34,     6,    34,    -1,
+      34,    24,    34,    -1,    34,     3,    34,    -1,    34,    26,
+      34,     8,    34,    -1,    31,    -1,    35,    -1,    30,    -1,
+      13,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const unsigned short yyrline[] =
+{
+       0,    68,    68,    73,    79,    87,    92,    98,   104,   111,
+     118,   124,   138,   150,   156,   162,   168,   174,   180,   186,
+     192,   198,   204,   210,   216,   222,   228,   234,   240,   246,
+     252,   259,   264
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE
+/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "ICT_AND", "ICT_BITAND", 
+  "ICT_BITCOMPLEMENT", "ICT_BITOR", "ICT_BITXOR", "ICT_COLON", 
+  "ICT_DIVIDE", "ICT_END", "ICT_ERROR", "ICT_EQ", "ICT_FALSE", "ICT_GT", 
+  "ICT_GE", "ICT_LPAREN", "ICT_LE", "ICT_LT", "ICT_MINUS", "ICT_MOD", 
+  "ICT_MULT", "ICT_NE", "ICT_NOT", "ICT_OR", "ICT_PLUS", "ICT_QUESTION", 
+  "ICT_RPAREN", "ICT_SHLEFT", "ICT_SHRIGHT", "ICT_TRUE", "ICT_VALUE", 
+  "$accept", "ifclause", "expr", "boolval", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const unsigned short yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const unsigned char yyr1[] =
+{
+       0,    32,    33,    33,    33,    34,    34,    34,    34,    34,
+      34,    34,    34,    34,    34,    34,    34,    34,    34,    34,
+      34,    34,    34,    34,    34,    34,    34,    34,    34,    34,
+      34,    35,    35
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const unsigned char yyr2[] =
+{
+       0,     2,     2,     1,     1,     3,     2,     2,     2,     2,
+       3,     3,     3,     3,     3,     3,     3,     3,     3,     3,
+       3,     3,     3,     3,     3,     3,     3,     3,     5,     1,
+       1,     1,     1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const unsigned char yydefact[] =
+{
+       0,     4,     0,     3,    32,     0,     0,     0,     0,    31,
+      29,     0,     0,    30,     7,     0,     8,     6,     9,     1,
+       0,     0,     0,     0,     0,     2,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       5,    27,    23,    25,    24,    11,    21,    19,    20,    18,
+      17,    14,    12,    10,    22,    26,    13,     0,    15,    16,
+       0,    28
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yysigned_char yydefgoto[] =
+{
+      -1,    11,    12,    13
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -9
+static const short yypact[] =
+{
+      37,    -9,   185,    -9,    -9,   185,   185,   185,   185,    -9,
+      -9,     2,    66,    -9,    -9,    93,    -9,    -9,    -9,    -9,
+     185,   185,   185,   185,   185,    -9,   185,   185,   185,   185,
+     185,   185,   185,   185,   185,   185,   185,   185,   185,   185,
+      -9,   205,   268,   228,   250,    -9,   285,   298,   298,   298,
+     298,    31,    -9,    -9,   285,   174,    31,   120,    -8,    -8,
+     185,   147
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yysigned_char yypgoto[] =
+{
+      -9,    -9,    -2,    -9
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, parse error.  */
+#define YYTABLE_NINF -1
+static const unsigned char yytable[] =
+{
+      14,    24,    19,    15,    16,    17,    18,     0,     0,     0,
+       0,    31,    32,    33,     0,     0,     0,    36,    41,    42,
+      43,    44,    45,     0,    46,    47,    48,    49,    50,    51,
+      52,    53,    54,    55,    56,    57,    58,    59,     1,     0,
+      24,     0,     2,     0,     0,     0,     0,     0,     3,     0,
+       4,    32,    33,     5,     0,     0,     6,     0,    61,     0,
+       7,     0,     8,     0,     0,     0,     0,     9,    10,    20,
+      21,     0,    22,    23,     0,    24,    25,     0,    26,     0,
+      27,    28,     0,    29,    30,    31,    32,    33,    34,     0,
+      35,    36,    37,     0,    38,    39,    20,    21,     0,    22,
+      23,     0,    24,     0,     0,    26,     0,    27,    28,     0,
+      29,    30,    31,    32,    33,    34,     0,    35,    36,    37,
+      40,    38,    39,    20,    21,     0,    22,    23,    60,    24,
+       0,     0,    26,     0,    27,    28,     0,    29,    30,    31,
+      32,    33,    34,     0,    35,    36,    37,     0,    38,    39,
+      20,    21,     0,    22,    23,     0,    24,     0,     0,    26,
+       0,    27,    28,     0,    29,    30,    31,    32,    33,    34,
+       0,    35,    36,    37,     0,    38,    39,    20,    21,     0,
+      22,    23,     0,    24,     0,     0,    26,     0,    27,    28,
+       2,    29,    30,    31,    32,    33,    34,     0,     4,    36,
+       0,     5,    38,    39,     6,     0,     0,     0,     7,    21,
+       8,    22,    23,     0,    24,     9,    10,    26,     0,    27,
+      28,     0,    29,    30,    31,    32,    33,    34,     0,     0,
+      36,     0,    21,    38,    39,    23,     0,    24,     0,     0,
+      26,     0,    27,    28,     0,    29,    30,    31,    32,    33,
+      34,     0,     0,    36,    21,     0,    38,    39,     0,    24,
+       0,     0,    26,     0,    27,    28,     0,    29,    30,    31,
+      32,    33,    34,     0,     0,    36,     0,    24,    38,    39,
+      26,     0,    27,    28,     0,    29,    30,    31,    32,    33,
+      34,     0,     0,    36,    24,     0,    38,    39,     0,    27,
+      28,     0,    29,    30,    31,    32,    33,    24,     0,     0,
+      36,     0,     0,    38,    39,     0,     0,    31,    32,    33,
+       0,     0,     0,    36,     0,     0,    38,    39
+};
+
+static const yysigned_char yycheck[] =
+{
+       2,     9,     0,     5,     6,     7,     8,    -1,    -1,    -1,
+      -1,    19,    20,    21,    -1,    -1,    -1,    25,    20,    21,
+      22,    23,    24,    -1,    26,    27,    28,    29,    30,    31,
+      32,    33,    34,    35,    36,    37,    38,    39,     1,    -1,
+       9,    -1,     5,    -1,    -1,    -1,    -1,    -1,    11,    -1,
+      13,    20,    21,    16,    -1,    -1,    19,    -1,    60,    -1,
+      23,    -1,    25,    -1,    -1,    -1,    -1,    30,    31,     3,
+       4,    -1,     6,     7,    -1,     9,    10,    -1,    12,    -1,
+      14,    15,    -1,    17,    18,    19,    20,    21,    22,    -1,
+      24,    25,    26,    -1,    28,    29,     3,     4,    -1,     6,
+       7,    -1,     9,    -1,    -1,    12,    -1,    14,    15,    -1,
+      17,    18,    19,    20,    21,    22,    -1,    24,    25,    26,
+      27,    28,    29,     3,     4,    -1,     6,     7,     8,     9,
+      -1,    -1,    12,    -1,    14,    15,    -1,    17,    18,    19,
+      20,    21,    22,    -1,    24,    25,    26,    -1,    28,    29,
+       3,     4,    -1,     6,     7,    -1,     9,    -1,    -1,    12,
+      -1,    14,    15,    -1,    17,    18,    19,    20,    21,    22,
+      -1,    24,    25,    26,    -1,    28,    29,     3,     4,    -1,
+       6,     7,    -1,     9,    -1,    -1,    12,    -1,    14,    15,
+       5,    17,    18,    19,    20,    21,    22,    -1,    13,    25,
+      -1,    16,    28,    29,    19,    -1,    -1,    -1,    23,     4,
+      25,     6,     7,    -1,     9,    30,    31,    12,    -1,    14,
+      15,    -1,    17,    18,    19,    20,    21,    22,    -1,    -1,
+      25,    -1,     4,    28,    29,     7,    -1,     9,    -1,    -1,
+      12,    -1,    14,    15,    -1,    17,    18,    19,    20,    21,
+      22,    -1,    -1,    25,     4,    -1,    28,    29,    -1,     9,
+      -1,    -1,    12,    -1,    14,    15,    -1,    17,    18,    19,
+      20,    21,    22,    -1,    -1,    25,    -1,     9,    28,    29,
+      12,    -1,    14,    15,    -1,    17,    18,    19,    20,    21,
+      22,    -1,    -1,    25,     9,    -1,    28,    29,    -1,    14,
+      15,    -1,    17,    18,    19,    20,    21,     9,    -1,    -1,
+      25,    -1,    -1,    28,    29,    -1,    -1,    19,    20,    21,
+      -1,    -1,    -1,    25,    -1,    -1,    28,    29
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const unsigned char yystos[] =
+{
+       0,     1,     5,    11,    13,    16,    19,    23,    25,    30,
+      31,    33,    34,    35,    34,    34,    34,    34,    34,     0,
+       3,     4,     6,     7,     9,    10,    12,    14,    15,    17,
+      18,    19,    20,    21,    22,    24,    25,    26,    28,    29,
+      27,    34,    34,    34,    34,    34,    34,    34,    34,    34,
+      34,    34,    34,    34,    34,    34,    34,    34,    34,    34,
+       8,    34
+};
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok                (yyerrstatus = 0)
+#define yyclearin      (yychar = YYEMPTY)
+#define YYEMPTY                -2
+#define YYEOF          0
+
+#define YYACCEPT       goto yyacceptlab
+#define YYABORT                goto yyabortlab
+#define YYERROR                goto yyerrlab1
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL         goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                 \
+do                                                             \
+  if (yychar == YYEMPTY && yylen == 1)                         \
+    {                                                          \
+      yychar = (Token);                                                \
+      yylval = (Value);                                                \
+      yychar1 = YYTRANSLATE (yychar);                          \
+      YYPOPSTACK;                                              \
+      goto yybackup;                                           \
+    }                                                          \
+  else                                                         \
+    {                                                          \
+      yyerror ("syntax error: cannot back up");                        \
+      YYERROR;                                                 \
+    }                                                          \
+while (0)
+
+#define YYTERROR       1
+#define YYERRCODE      256
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+   are run).  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)           \
+  Current.first_line   = Rhs[1].first_line;      \
+  Current.first_column = Rhs[1].first_column;    \
+  Current.last_line    = Rhs[N].last_line;       \
+  Current.last_column  = Rhs[N].last_column;
+#endif
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#define YYLEX  yylex ()
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                       \
+do {                                           \
+  if (yydebug)                                 \
+    YYFPRINTF Args;                            \
+} while (0)
+# define YYDSYMPRINT(Args)                     \
+do {                                           \
+  if (yydebug)                                 \
+    yysymprint Args;                           \
+} while (0)
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YYDSYMPRINT(Args)
+#endif /* !YYDEBUG */
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef        YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#if YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+\f
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined (__GLIBC__) && defined (_STRING_H)
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+#   if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+#   else
+yystrlen (yystr)
+     const char *yystr;
+#   endif
+{
+  register const char *yys = yystr;
+
+  while (*yys++ != '\0')
+    continue;
+
+  return yys - yystr - 1;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+#   if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+#   else
+yystpcpy (yydest, yysrc)
+     char *yydest;
+     const char *yysrc;
+#   endif
+{
+  register char *yyd = yydest;
+  register const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+#endif /* !YYERROR_VERBOSE */
+
+\f
+
+#if YYDEBUG
+/*-----------------------------.
+| Print this symbol on YYOUT.  |
+`-----------------------------*/
+
+static void
+#if defined (__STDC__) || defined (__cplusplus)
+yysymprint (FILE* yyout, int yytype, YYSTYPE yyvalue)
+#else
+yysymprint (yyout, yytype, yyvalue)
+    FILE* yyout;
+    int yytype;
+    YYSTYPE yyvalue;
+#endif
+{
+  /* Pacify ``unused variable'' warnings.  */
+  (void) yyvalue;
+
+  if (yytype < YYNTOKENS)
+    {
+      YYFPRINTF (yyout, "token %s (", yytname[yytype]);
+# ifdef YYPRINT
+      YYPRINT (yyout, yytoknum[yytype], yyvalue);
+# endif
+    }
+  else
+    YYFPRINTF (yyout, "nterm %s (", yytname[yytype]);
+
+  switch (yytype)
+    {
+      default:
+        break;
+    }
+  YYFPRINTF (yyout, ")");
+}
+#endif /* YYDEBUG. */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+static void
+#if defined (__STDC__) || defined (__cplusplus)
+yydestruct (int yytype, YYSTYPE yyvalue)
+#else
+yydestruct (yytype, yyvalue)
+    int yytype;
+    YYSTYPE yyvalue;
+#endif
+{
+  /* Pacify ``unused variable'' warnings.  */
+  (void) yyvalue;
+
+  switch (yytype)
+    {
+      default:
+        break;
+    }
+}
+
+\f
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+   into yyparse.  The argument should have type void *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   to the proper pointer type.  */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+#  define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL
+# else
+#  define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+# endif
+#else /* !YYPARSE_PARAM */
+# define YYPARSE_PARAM_ARG
+# define YYPARSE_PARAM_DECL
+#endif /* !YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+# ifdef YYPARSE_PARAM
+int yyparse (void *);
+# else
+int yyparse (void);
+# endif
+#endif
+
+
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of parse errors so far.  */
+int yynerrs;
+
+
+int
+yyparse (YYPARSE_PARAM_ARG)
+     YYPARSE_PARAM_DECL
+{
+  
+  register int yystate;
+  register int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yychar1 = 0;
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  short        yyssa[YYINITDEPTH];
+  short *yyss = yyssa;
+  register short *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  register YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK   (yyvsp--, yyssp--)
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
+  /* When reducing, the number of symbols on the RHS of the reduced
+     rule.  */
+  int yylen;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;            /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed. so pushing a state here evens the stacks.
+     */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyssp >= yyss + yystacksize - 1)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+       /* Give user a chance to reallocate the stack. Use copies of
+          these so that the &'s don't force the real ones into
+          memory.  */
+       YYSTYPE *yyvs1 = yyvs;
+       short *yyss1 = yyss;
+
+
+       /* Each stack pointer address is followed by the size of the
+          data in use in that stack, in bytes.  This used to be a
+          conditional around just the two extra args, but that might
+          be undefined if yyoverflow is a macro.  */
+       yyoverflow ("parser stack overflow",
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+
+                   &yystacksize);
+
+       yyss = yyss1;
+       yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyoverflowlab;
+# else
+      /* Extend the stack our own way.  */
+      if (yystacksize >= YYMAXDEPTH)
+       goto yyoverflowlab;
+      yystacksize *= 2;
+      if (yystacksize > YYMAXDEPTH)
+       yystacksize = YYMAXDEPTH;
+
+      {
+       short *yyss1 = yyss;
+       union yyalloc *yyptr =
+         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+       if (! yyptr)
+         goto yyoverflowlab;
+       YYSTACK_RELOCATE (yyss);
+       YYSTACK_RELOCATE (yyvs);
+
+#  undef YYSTACK_RELOCATE
+       if (yyss1 != yyssa)
+         YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                 (unsigned long int) yystacksize));
+
+      if (yyssp >= yyss + yystacksize - 1)
+       YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with.  */
+
+  if (yychar <= 0)             /* This means end of input.  */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;          /* Don't call YYLEX any more.  */
+
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE (yychar);
+
+      /* We have to keep this `#if YYDEBUG', since we use variables
+        which are defined only if `YYDEBUG' is set.  */
+      YYDPRINTF ((stderr, "Next token is "));
+      YYDSYMPRINT ((stderr, yychar1, yylval));
+      YYDPRINTF ((stderr, "\n"));
+    }
+
+  /* If the proper action on seeing token YYCHAR1 is to reduce or to
+     detect an error, take that action.  */
+  yyn += yychar1;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yychar1)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+       goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+  YYDPRINTF ((stderr, "Shifting token %d (%s), ",
+             yychar, yytname[yychar1]));
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+
+#if YYDEBUG
+  /* We have to keep this `#if YYDEBUG', since we use variables which
+     are defined only if `YYDEBUG' is set.  */
+  if (yydebug)
+    {
+      int yyi;
+
+      YYFPRINTF (stderr, "Reducing via rule %d (line %d), ",
+                yyn - 1, yyrline[yyn]);
+
+      /* Print the symbols being reduced, and their result.  */
+      for (yyi = yyprhs[yyn]; yyrhs[yyi] >= 0; yyi++)
+       YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);
+      YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+    }
+#endif
+  switch (yyn)
+    {
+        case 2:
+#line 69 "ifgram.y"
+    {
+               return(yyvsp[-1] ? YES : NO);
+       }
+    break;
+
+  case 3:
+#line 75 "ifgram.y"
+    {
+               pfatal("if clause parser received unknown token type");
+       }
+    break;
+
+  case 4:
+#line 81 "ifgram.y"
+    {
+               l_yyerror(Curr_filename, yylineno, "syntax error in 'if' condition");
+               return(NO);
+       }
+    break;
+
+  case 5:
+#line 88 "ifgram.y"
+    {
+               yyval = yyvsp[-1];
+       }
+    break;
+
+  case 6:
+#line 94 "ifgram.y"
+    {
+               yyval = !(yyvsp[0]);
+       }
+    break;
+
+  case 7:
+#line 100 "ifgram.y"
+    {
+               yyval = ~(yyvsp[0]);
+       }
+    break;
+
+  case 8:
+#line 106 "ifgram.y"
+    {
+               /* unary minus */
+               yyval = -(yyvsp[0]);
+       }
+    break;
+
+  case 9:
+#line 113 "ifgram.y"
+    {
+               /* unary plus. Not very useful, but ANSI C supports it... */
+               yyval = (yyvsp[0]);
+       }
+    break;
+
+  case 10:
+#line 120 "ifgram.y"
+    {
+               yyval = yyvsp[-2] * yyvsp[0];
+       }
+    break;
+
+  case 11:
+#line 126 "ifgram.y"
+    {
+               if (yyvsp[0] == 0) {
+                       yyerror("attempt to divide by 0");
+                       /* gcc appears to return the numerator in this case,
+                        * so we do the same */
+                       yyval = yyvsp[-2];
+               }
+               else {
+                       yyval = yyvsp[-2] / yyvsp[0];
+               }
+       }
+    break;
+
+  case 12:
+#line 140 "ifgram.y"
+    {
+               if (yyvsp[0] == 0) {
+                       yyerror("attempt to modulo by 0");
+                       yyval = yyvsp[-2];
+               }
+               else {
+                       yyval = yyvsp[-2] % yyvsp[0];
+               }
+       }
+    break;
+
+  case 13:
+#line 152 "ifgram.y"
+    {
+               yyval = yyvsp[-2] + yyvsp[0];
+       }
+    break;
+
+  case 14:
+#line 158 "ifgram.y"
+    {
+               yyval = yyvsp[-2] - yyvsp[0];
+       }
+    break;
+
+  case 15:
+#line 164 "ifgram.y"
+    {
+               yyval = yyvsp[-2] << yyvsp[0];
+       }
+    break;
+
+  case 16:
+#line 170 "ifgram.y"
+    {
+               yyval = yyvsp[-2] >> yyvsp[0];
+       }
+    break;
+
+  case 17:
+#line 176 "ifgram.y"
+    {
+               yyval = (yyvsp[-2] < yyvsp[0]);
+       }
+    break;
+
+  case 18:
+#line 182 "ifgram.y"
+    {
+               yyval = (yyvsp[-2] <= yyvsp[0]);
+       }
+    break;
+
+  case 19:
+#line 188 "ifgram.y"
+    {
+               yyval = (yyvsp[-2] > yyvsp[0]);
+       }
+    break;
+
+  case 20:
+#line 194 "ifgram.y"
+    {
+               yyval = (yyvsp[-2] >= yyvsp[0]);
+       }
+    break;
+
+  case 21:
+#line 200 "ifgram.y"
+    {
+               yyval = (yyvsp[-2] == yyvsp[0]);
+       }
+    break;
+
+  case 22:
+#line 206 "ifgram.y"
+    {
+               yyval = (yyvsp[-2] != yyvsp[0]);
+       }
+    break;
+
+  case 23:
+#line 212 "ifgram.y"
+    {
+               yyval = yyvsp[-2] & yyvsp[0];
+       }
+    break;
+
+  case 24:
+#line 218 "ifgram.y"
+    {
+               yyval = yyvsp[-2] ^ yyvsp[0];
+       }
+    break;
+
+  case 25:
+#line 224 "ifgram.y"
+    {
+               yyval = yyvsp[-2] | yyvsp[0];
+       }
+    break;
+
+  case 26:
+#line 230 "ifgram.y"
+    {
+               yyval = yyvsp[-2] || yyvsp[0];
+       }
+    break;
+
+  case 27:
+#line 236 "ifgram.y"
+    {
+               yyval = yyvsp[-2] && yyvsp[0];
+       }
+    break;
+
+  case 28:
+#line 242 "ifgram.y"
+    {
+               yyval = ( yyvsp[-4] ? yyvsp[-2] : yyvsp[0] );
+       }
+    break;
+
+  case 29:
+#line 248 "ifgram.y"
+    {
+               yyval = yyvsp[0];
+       }
+    break;
+
+  case 30:
+#line 254 "ifgram.y"
+    {
+               yyval = yyvsp[0];
+       }
+    break;
+
+  case 31:
+#line 260 "ifgram.y"
+    {
+               yyval = 1;
+       }
+    break;
+
+  case 32:
+#line 266 "ifgram.y"
+    {
+               yyval = 0;
+       }
+    break;
+
+
+    }
+
+/* Line 1016 of /usr/share/bison/yacc.c.  */
+#line 1335 "ifgram.tab.c"
+\f
+  yyvsp -= yylen;
+  yyssp -= yylen;
+
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "state stack now");
+      while (yyssp1 != yyssp)
+       YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (YYPACT_NINF < yyn && yyn < YYLAST)
+       {
+         YYSIZE_T yysize = 0;
+         int yytype = YYTRANSLATE (yychar);
+         char *yymsg;
+         int yyx, yycount;
+
+         yycount = 0;
+         /* Start YYX at -YYN if negative to avoid negative indexes in
+            YYCHECK.  */
+         for (yyx = yyn < 0 ? -yyn : 0;
+              yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+           if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+             yysize += yystrlen (yytname[yyx]) + 15, yycount++;
+         yysize += yystrlen ("parse error, unexpected ") + 1;
+         yysize += yystrlen (yytname[yytype]);
+         yymsg = (char *) YYSTACK_ALLOC (yysize);
+         if (yymsg != 0)
+           {
+             char *yyp = yystpcpy (yymsg, "parse error, unexpected ");
+             yyp = yystpcpy (yyp, yytname[yytype]);
+
+             if (yycount < 5)
+               {
+                 yycount = 0;
+                 for (yyx = yyn < 0 ? -yyn : 0;
+                      yyx < (int) (sizeof (yytname) / sizeof (char *));
+                      yyx++)
+                   if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+                     {
+                       const char *yyq = ! yycount ? ", expecting " : " or ";
+                       yyp = yystpcpy (yyp, yyq);
+                       yyp = yystpcpy (yyp, yytname[yyx]);
+                       yycount++;
+                     }
+               }
+             yyerror (yymsg);
+             YYSTACK_FREE (yymsg);
+           }
+         else
+           yyerror ("parse error; also virtual memory exhausted");
+       }
+      else
+#endif /* YYERROR_VERBOSE */
+       yyerror ("parse error");
+    }
+  goto yyerrlab1;
+
+
+/*----------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action.  |
+`----------------------------------------------------*/
+yyerrlab1:
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+        error, discard it.  */
+
+      /* Return failure if at end of input.  */
+      if (yychar == YYEOF)
+        {
+         /* Pop the error token.  */
+          YYPOPSTACK;
+         /* Pop the rest of the stack.  */
+         while (yyssp > yyss)
+           {
+             YYDPRINTF ((stderr, "Error: popping "));
+             YYDSYMPRINT ((stderr,
+                           yystos[*yyssp],
+                           *yyvsp));
+             YYDPRINTF ((stderr, "\n"));
+             yydestruct (yystos[*yyssp], *yyvsp);
+             YYPOPSTACK;
+           }
+         YYABORT;
+        }
+
+      YYDPRINTF ((stderr, "Discarding token %d (%s).\n",
+                 yychar, yytname[yychar1]));
+      yydestruct (yychar1, yylval);
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+
+  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+       {
+         yyn += YYTERROR;
+         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+           {
+             yyn = yytable[yyn];
+             if (0 < yyn)
+               break;
+           }
+       }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+       YYABORT;
+
+      YYDPRINTF ((stderr, "Error: popping "));
+      YYDSYMPRINT ((stderr,
+                   yystos[*yyssp], *yyvsp));
+      YYDPRINTF ((stderr, "\n"));
+
+      yydestruct (yystos[yystate], *yyvsp);
+      yyvsp--;
+      yystate = *--yyssp;
+
+
+#if YYDEBUG
+      if (yydebug)
+       {
+         short *yyssp1 = yyss - 1;
+         YYFPRINTF (stderr, "Error: state stack now");
+         while (yyssp1 != yyssp)
+           YYFPRINTF (stderr, " %d", *++yyssp1);
+         YYFPRINTF (stderr, "\n");
+       }
+#endif
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  YYDPRINTF ((stderr, "Shifting error token, "));
+
+  *++yyvsp = yylval;
+
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*----------------------------------------------.
+| yyoverflowlab -- parser overflow comes here.  |
+`----------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+  return yyresult;
+}
+
+
+#line 272 "ifgram.y"
+
+
+/* This is a pointer to the buffer containing the clause in compressed form.
+ * A call to set_ifclause_buffer() sets this to point to an actual array */
+static unsigned char * Buffer;
+
+/* Our current position in Buffer */
+static int Offset;
+
+/* length of Buffer */
+static int Length;
+
+
+
+/* To use this mini-parser, put the clause in compressed internal form
+ * in an array, and pass that array and its length to this function,
+ * then call ifparse().
+ */
+
+void
+set_ifclause_buffer(buff, len)
+
+unsigned char * buff;
+int len;
+
+{
+       Buffer = buff;
+       Length = len;
+       Offset = 0;
+}
+
+
+/* The compressed if-clause format is described in lex.c above add_ifclause().
+ * Since it's very simple (everything except numbers
+ * are single character tokens), we have a hand-coded lexer.
+ * It maps the compressed format tokens to bison tokens.
+ */
+
+int
+iflex()
+{
+       if (Offset == Length) {
+               return(ICT_END);
+       }
+
+       switch(Buffer[Offset++]) {
+
+       case '(':
+               return(ICT_LPAREN);
+       case ')':
+               return(ICT_RPAREN);
+
+       case '!':
+               return(ICT_NOT);
+       case '~':
+               return(ICT_BITCOMPLEMENT);
+
+       case '*':
+               return(ICT_MULT);
+       case '/':
+               return(ICT_DIVIDE);
+       case '%':
+               return(ICT_MOD);
+
+       case '+':
+               return(ICT_PLUS);
+       case '-':
+               return(ICT_MINUS);
+
+       case 'l':
+               return(ICT_SHLEFT);
+       case 'r':
+               return(ICT_SHRIGHT);
+
+       case '<':
+               return(ICT_LT);
+       case '>':
+               return(ICT_GT);
+       case 'L':
+               return(ICT_LE);
+       case 'G':
+               return(ICT_GE);
+
+       case 'E':
+               return(ICT_EQ);
+       case 'N':
+               return(ICT_NE);
+
+       case '&':
+               return(ICT_BITAND);
+
+       case '^':
+               return(ICT_BITXOR);
+
+       case '|':
+               return(ICT_BITOR);
+
+       case 'a':
+               return(ICT_AND);
+
+       case 'o':
+               return(ICT_OR);
+
+       case '?':
+               return(ICT_QUESTION);
+       case ':':
+               return(ICT_COLON);
+
+       case 'T':
+               return(ICT_TRUE);
+       case 'F':
+               return(ICT_FALSE);
+       case '#':
+               iflval = ((Buffer[Offset] << 24) & 0xff000000)
+                       | ((Buffer[Offset+1] << 16) & 0xff0000)
+                       | ((Buffer[Offset+2] << 8) & 0xff00)
+                       | (Buffer[Offset+3] & 0xff);
+               Offset += 4;
+               return(ICT_VALUE);
+
+       default:
+               return(ICT_ERROR);
+       }
+}      
+
+
+
+/* Error message printer for syntax/semantic errors in 'if' clauses.
+ * WARNING: bison appears to somehow use yyerror even when using a prefix
+ * other than yy. So if this function calls yyerror, it gets into an
+ * infinite loop! So don't do that...
+ */
+
+int
+iferror(msg)
+
+char * msg;
+
+{
+       l_yyerror(Curr_filename, yylineno, msg);
+       return(0);
+}
+
+
diff --git a/mup/mup/lex.c b/mup/mup/lex.c
new file mode 100644 (file)
index 0000000..dc303ea
--- /dev/null
@@ -0,0 +1,5059 @@
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else  /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator).  This
+ * avoids problems with code like:
+ *
+ *     if ( condition_holds )
+ *             yyless( 5 );
+ *     else
+ *             do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+               *yy_cp = yy_hold_char; \
+               YY_RESTORE_YY_MORE_OFFSET \
+               yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+               YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+               } \
+       while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+       {
+       FILE *yy_input_file;
+
+       char *yy_ch_buf;                /* input buffer */
+       char *yy_buf_pos;               /* current position in input buffer */
+
+       /* Size of input buffer in bytes, not including room for EOB
+        * characters.
+        */
+       yy_size_t yy_buf_size;
+
+       /* Number of characters read into yy_ch_buf, not including EOB
+        * characters.
+        */
+       int yy_n_chars;
+
+       /* Whether we "own" the buffer - i.e., we know we created it,
+        * and can realloc() it to grow it, and should free() it to
+        * delete it.
+        */
+       int yy_is_our_buffer;
+
+       /* Whether this is an "interactive" input source; if so, and
+        * if we're using stdio for input, then we want to use getc()
+        * instead of fread(), to make sure we stop fetching input after
+        * each newline.
+        */
+       int yy_is_interactive;
+
+       /* Whether we're considered to be at the beginning of a line.
+        * If so, '^' rules will be active on the next match, otherwise
+        * not.
+        */
+       int yy_at_bol;
+
+       /* Whether to try to fill the input buffer when we reach the
+        * end of it.
+        */
+       int yy_fill_buffer;
+
+       int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+       /* When an EOF's been seen but there's still some text to process
+        * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+        * shouldn't try reading from the input source any more.  We might
+        * still have a bunch of tokens to match, though, because of
+        * possible backing-up.
+        *
+        * When we actually see the EOF, we change the status to "new"
+        * (via yyrestart()), so that the user can continue scanning by
+        * just pointing yyin at a new input file.
+        */
+#define YY_BUFFER_EOF_PENDING 2
+       };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars;         /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1;                /* whether we need to initialize */
+static int yy_start = 0;       /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+       { \
+       if ( ! yy_current_buffer ) \
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+       yy_current_buffer->yy_is_interactive = is_interactive; \
+       }
+
+#define yy_set_bol(at_bol) \
+       { \
+       if ( ! yy_current_buffer ) \
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+       yy_current_buffer->yy_at_bol = at_bol; \
+       }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char yytext[];
+
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+       yytext_ptr = yy_bp; \
+       yyleng = (int) (yy_cp - yy_bp); \
+       yy_hold_char = *yy_cp; \
+       *yy_cp = '\0'; \
+       if ( yyleng + yy_more_offset >= YYLMAX ) \
+               YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \
+       yy_flex_strncpy( &yytext[yy_more_offset], yytext_ptr, yyleng + 1 ); \
+       yyleng += yy_more_offset; \
+       yy_prev_more_offset = yy_more_offset; \
+       yy_more_offset = 0; \
+       yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 311
+#define YY_END_OF_BUFFER 312
+static yyconst short int yy_accept[1176] =
+    {   0,
+        0,    0,    0,    0,    0,    0,  312,  310,  309,   45,
+       43,  308,   54,   55,   99,  100,  306,   52,   53,  279,
+       58,   47,   57,   91,  145,   40,   40,   40,   46,   42,
+      259,   41,  258,   90,  304,   48,  310,   49,   86,  310,
+      310,   98,   98,   98,   98,   98,   98,   98,  103,  103,
+      103,  103,  103,   94,  101,  103,  103,  103,   95,   96,
+      103,   97,  103,  103,  102,   50,   51,   87,  298,  296,
+      296,  285,  285,  285,  293,  293,  285,  298,  285,  295,
+      298,  298,  298,  285,  311,   56,   44,  106,  306,  280,
+      265,   40,    0,    0,  260,  261,  304,    0,  307,    0,
+
+      264,  105,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,   81,    0,    0,    0,    0,    0,    0,
+        0,    0,  210,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,   63,   64,  281,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,  266,  267,    0,  144,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,  133,    0,    0,   76,    0,    0,    0,
+
+        0,    0,    0,    0,    0,  291,  283,  293,    0,  286,
+      288,  290,  289,  287,  295,    0,    0,    0,  284,    0,
+       56,   92,   93,    0,    0,    0,  305,    0,    0,   75,
+       80,    0,   16,    0,  111,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,   59,    0,  146,    0,    0,    0,
+        0,   14,    0,    0,    0,    0,    0,  273,   83,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,  228,    0,    0,    0,    0,   78,  122,    0,    0,
+
+       22,    0,    0,    0,    0,   20,    0,    0,    0,    0,
+        0,    0,  121,    0,    0,    0,    0,    0,   85,    0,
+        0,    0,    0,    0,   18,    0,    0,    0,    0,    0,
+        0,  119,    0,    0,    0,    0,    0,    1,  104,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,  180,    0,   65,  275,    0,    0,   32,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,  292,    0,    0,    0,    0,    0,    0,
+      253,    0,    0,    0,    0,    0,    0,  256,    0,    0,
+        0,    0,    2,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,  245,    0,    0,    0,    0,    0,    0,
+        0,    0,   62,    0,  162,    0,    0,   77,  257,    0,
+      302,    0,    0,    0,   82,    0,    0,  205,  238,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    4,    0,    0,    0,  136,    0,    0,  132,
+        0,    0,    0,    0,    0,  278,    0,  123,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,  277,    0,    0,    0,  157,    0,    0,   68,    0,
+
+        0,    0,    0,    0,    0,    0,  229,    0,   34,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,  174,
+      129,    0,  127,   71,    0,    0,    0,  282,    0,   72,
+        0,    0,    0,    0,    0,    0,    0,    0,   73,    0,
+       36,    0,    0,    0,    0,  214,  221,    0,  135,    0,
+        0,  270,    0,    0,    0,    0,  134,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,  303,    0,    0,
+        0,    0,    0,    0,   60,    0,   37,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,  235,    0,
+        0,  204,    0,    0,   23,    0,    0,    0,   21,    0,
+
+       38,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+      268,    0,    0,    0,  216,    0,    0,  139,    0,    0,
+        0,    0,    0,    0,    0,    0,  137,  193,   25,    0,
+       79,   84,    0,   26,    0,    0,    0,    0,    0,  254,
+        5,    0,   24,    0,    0,    0,    0,  209,  246,    0,
+        0,   27,    0,    0,   61,    0,  297,    0,    0,    0,
+        0,    0,    0,    0,  219,    0,    0,    0,    0,    0,
+        0,    0,    0,   33,    0,    0,  138,    0,    0,  147,
+        0,    0,  131,  112,    0,  154,    0,    0,  130,    0,
+
+      117,    0,  124,    0,    0,    0,    0,   29,    0,    0,
+        0,    0,    0,    0,    0,   28,    0,    0,    0,    0,
+      211,    0,    0,    0,  236,    0,    0,  203,  107,    0,
+      128,    0,    0,  269,    0,    0,    0,    0,    0,    0,
+      276,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,  274,    0,    0,    0,  141,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,  148,    0,    0,    0,    0,    0,
+        0,    0,    0,  248,    0,    0,    0,    0,    0,    0,
+      247,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,   74,    0,    9,    0,   35,    0,  222,    0,    0,
+      215,    7,    0,    0,  263,    0,    0,   89,    0,    0,
+        0,    0,  262,    0,    0,   88,  163,    0,    0,  272,
+        0,    0,    0,   31,    0,    0,    0,    0,    0,  220,
+        0,   30,    0,    0,    0,  301,    0,    0,    0,    0,
+        0,    0,    0,    0,  233,    0,    0,    0,  109,    0,
+        0,    0,    0,    0,    0,  153,  190,    0,    0,    0,
+        0,    0,    0,    0,  218,    0,   19,    0,    0,    0,
+        0,    0,  166,    0,    0,    0,  118,    0,    0,    0,
+        0,    0,    0,  251,    0,    0,    0,    0,  194,    0,
+
+        0,    0,    0,    0,    0,    0,  249,  300,    0,  231,
+      149,    0,    0,    0,    0,  271,    0,    0,  255,  223,
+        0,    0,    0,    0,    3,    0,    0,    0,    0,    0,
+        0,    0,  299,    0,  165,    0,    0,    0,    0,    0,
+        0,    0,    0,  168,    0,    0,    0,    0,    0,    0,
+        0,  301,    0,  116,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,  108,    0,    0,    0,    0,
+        0,  189,    0,  202,    0,   11,    0,    0,  217,  207,
+        0,    0,    0,  213,    0,    0,    0,    0,    0,    0,
+      159,  171,  152,    0,  160,    0,  158,    0,    0,    0,
+
+        0,  182,    0,    0,  300,  150,    0,    0,    0,  294,
+        0,    0,   17,    0,  196,  230,    0,    0,  185,    0,
+      234,  161,  164,    0,   67,  299,  299,    0,    0,   66,
+      125,    0,  170,    0,    0,    0,    0,  192,    0,    0,
+        0,    8,    0,    0,  142,  208,    0,    0,    0,    0,
+        0,    0,    0,  110,    0,  151,  237,    0,  173,  227,
+        0,  201,    0,  143,    0,    0,  120,    0,  114,    0,
+        0,    0,    0,    0,    0,    0,  183,    0,    0,  184,
+      197,  232,    0,  294,  294,  294,  224,    0,    6,  225,
+        0,    0,   70,   15,   69,    0,  239,    0,    0,  179,
+
+        0,  206,   39,    0,    0,  187,    0,  240,  155,    0,
+        0,    0,   10,  175,  200,    0,  140,    0,  115,    0,
+        0,    0,    0,  172,  191,    0,    0,    0,    0,    0,
+        0,  212,    0,    0,    0,  126,   12,  199,    0,  243,
+      242,    0,    0,    0,  113,  169,  177,  188,  195,  156,
+      181,  198,  226,  186,   13,  250,    0,    0,    0,  252,
+        0,  176,    0,    0,    0,  167,  178,    0,    0,    0,
+        0,  241,    0,  244,    0
+    } ;
+
+static yyconst int yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    4,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    5,    1,    1,    1,    1,
+        1,    2,    6,    7,    8,    1,    9,   10,   11,   12,
+       13,   14,   15,   16,   17,   18,   19,   20,   21,   22,
+       23,   24,   23,   23,   23,   25,   23,   26,   27,   28,
+       29,   30,   31,    1,   32,   32,   32,   32,   32,   32,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       34,   35,   36,   37,   38,   39,   40,   41,   42,   43,
+
+       44,   45,   46,   47,   48,   49,   50,   51,   52,   53,
+       54,   55,   56,   57,   58,   59,   60,   61,   62,   63,
+       64,   65,   66,   67,   68,   69,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst int yy_meta[70] =
+    {   0,
+        1,    2,    3,    4,    1,    1,    4,    1,    1,    1,
+        1,    1,    5,    1,    1,    1,    1,    1,    1,    6,
+        6,    6,    6,    6,    6,    1,    1,    1,    1,    1,
+        1,    6,    7,    1,    1,    1,    1,    7,    8,    9,
+        9,    9,    9,    9,    9,   10,   10,   10,   10,   10,
+       10,   10,   10,   10,   10,   10,   10,   10,   10,   10,
+       10,   10,   10,   10,   10,    1,    1,    1,    1
+    } ;
+
+static yyconst short int yy_base[1184] =
+    {   0,
+        0,    0,   69,    0, 1446, 1445, 1451, 1454, 1454, 1454,
+     1447, 1454, 1454, 1454, 1454, 1439, 1437, 1454, 1454, 1454,
+     1454, 1454, 1454, 1454,  120,  120,  127,  133, 1454, 1454,
+     1419, 1454, 1416, 1454,  139, 1454,  163, 1454, 1454,    0,
+      166,  133,  151,  166,  181,  129,  176, 1388,  188,  130,
+     1384, 1399,  199,  200,  215,  148,  211, 1454,  230,  229,
+      242,  126,  247,  209, 1389, 1454, 1454, 1454, 1454, 1454,
+     1454, 1412, 1454, 1430,  286,  292,  168, 1410,  243,  298,
+     1394, 1384, 1389, 1368, 1427, 1454, 1454, 1454, 1422, 1454,
+     1454,  304,  230, 1375, 1454, 1454,  318,  300, 1454, 1428,
+
+     1454,    0,  265,  176, 1376, 1386,  153, 1388, 1381, 1386,
+      275,  241, 1371, 1454,  294, 1384, 1372, 1369, 1368, 1366,
+     1362, 1374, 1454,  227, 1373,  302, 1358, 1364, 1369,  312,
+      126, 1353, 1359, 1359, 1352, 1366, 1367,  298, 1349,  281,
+     1362,  314, 1354,  307, 1361, 1454, 1454,  188,  158, 1363,
+     1344, 1337,  319,  321, 1347, 1342, 1349,  335,  326, 1337,
+      325, 1454, 1454, 1334, 1454,  323, 1343, 1335, 1334, 1345,
+     1347,  342,  344, 1333, 1349,  332, 1340, 1341,  347, 1340,
+      340, 1326,  356, 1344, 1318,  357, 1327,  363, 1333, 1329,
+     1338, 1325,  362, 1322,  364,  372, 1454, 1322, 1317, 1326,
+
+     1331,  355, 1328,  322, 1317, 1454, 1454,  402,    0, 1454,
+     1454, 1454, 1454, 1454,  411, 1325, 1326, 1324, 1454, 1360,
+     1454, 1454, 1454, 1322,  407,  416, 1454, 1304, 1305, 1454,
+     1309, 1311, 1309, 1307,  371, 1301, 1306, 1303, 1294, 1313,
+     1311, 1303,  386, 1308, 1309, 1304, 1307, 1289, 1290, 1304,
+     1300, 1292, 1286, 1284, 1454, 1280, 1454, 1293, 1298,  393,
+     1286, 1289, 1277, 1287, 1275, 1280, 1280, 1288, 1454, 1286,
+      409, 1277, 1287, 1269, 1286, 1266, 1265, 1270, 1280, 1278,
+     1260, 1274, 1275, 1256, 1272, 1271, 1271,  401, 1265, 1261,
+     1252, 1454, 1266, 1266, 1249, 1267, 1454, 1247, 1261, 1256,
+
+     1249, 1244, 1253, 1235, 1251, 1244, 1245, 1237,  403,  412,
+     1234, 1250, 1252, 1252, 1244, 1246, 1232, 1238, 1454, 1243,
+     1246, 1241, 1244,  400, 1238, 1242, 1233, 1221, 1220, 1225,
+     1231,  398, 1232, 1231, 1215, 1226, 1221, 1454, 1454, 1220,
+     1213, 1212, 1224, 1209, 1211, 1208, 1207, 1218, 1210, 1208,
+     1205, 1197, 1204, 1454, 1454, 1213, 1205,  242, 1202, 1213,
+     1209, 1193, 1207, 1198, 1201, 1206, 1200, 1193, 1181, 1187,
+     1199, 1195, 1182,    0, 1192, 1191, 1185, 1196, 1192, 1178,
+     1454, 1170, 1189, 1173, 1172, 1186, 1170, 1454, 1170, 1165,
+     1182, 1175, 1176, 1171, 1182, 1167, 1177,  415, 1175, 1174,
+
+     1173, 1173, 1164, 1454, 1160, 1165, 1170, 1167, 1166, 1169,
+     1155, 1165, 1454, 1153, 1454, 1147, 1160, 1454, 1454, 1155,
+     1454, 1162, 1148,  318, 1454, 1160, 1140, 1454, 1153, 1153,
+     1154, 1151,  415, 1139, 1142,  418, 1148, 1149, 1145, 1145,
+     1128, 1129, 1454, 1138, 1134, 1126, 1131, 1131, 1137, 1454,
+     1138, 1122, 1125, 1117, 1122, 1454, 1118, 1454, 1126, 1131,
+     1108, 1127, 1130, 1127, 1124, 1120, 1122, 1104, 1120, 1106,
+     1111,  419,  419, 1102, 1109, 1113, 1107, 1098, 1112, 1097,
+     1101, 1096, 1094, 1092, 1106, 1109, 1089, 1107, 1106,  429,
+     1086, 1454, 1100, 1099, 1098, 1454, 1094, 1096, 1454, 1099,
+
+     1093,  417, 1091, 1082, 1088, 1077,  379, 1089, 1454, 1092,
+     1073, 1079, 1084, 1070, 1068, 1085, 1084, 1080, 1079, 1454,
+     1454, 1078, 1454, 1454, 1077, 1067, 1074, 1454, 1067, 1063,
+     1076, 1057, 1061, 1067, 1058, 1068, 1046,  421, 1055, 1064,
+     1454, 1048, 1066, 1048, 1052, 1454, 1454, 1059, 1454, 1051,
+     1044, 1057, 1055, 1045, 1053, 1053, 1454, 1052, 1037, 1049,
+     1033, 1043, 1042, 1046, 1030, 1030, 1043, 1454, 1039, 1026,
+     1028,  434, 1025, 1034, 1454, 1023,  443, 1035, 1034, 1020,
+     1029, 1016, 1027, 1071, 1014, 1028, 1029, 1024, 1046, 1025,
+     1026, 1454, 1008, 1006, 1454, 1003, 1010, 1003, 1454, 1003,
+
+     1454, 1007, 1005, 1011, 1002,  998, 1010,  996, 1008, 1000,
+      991, 1009,  985, 1007, 1002,  997,  996,  995,  984,  984,
+     1454,  197,  998,  995, 1454,  998,  995,  984,  992,  977,
+      969,  974,  972,  973,  975,  964,  975, 1454,  431,  972,
+     1454, 1454,  972,  433,  980,  976,  962,  963,  972, 1454,
+     1454,  966, 1454,  961,  962,  972, 1013, 1454, 1454,  966,
+      962, 1454,  960,  951, 1454,  966, 1454,  965,  951,  954,
+      958,  946,  964,  950, 1454,  951,  947,  936,  942,  945,
+      957,  943,  949,  456,  935,  943, 1454,  944,  948, 1454,
+      933,  941,  488, 1454,  986, 1454,  929,  932,  490,  926,
+
+     1454,  936,  925,  924,  941,  928,  928,  956,  916,  932,
+      916,  934,  926,  929,  912,  948,  929,  920,  927,  477,
+     1454,  922,  919,  910, 1454,  909,  891, 1454,  453,  890,
+     1454,  884,  893, 1454,  873,  887,  873,  865,  129,  285,
+     1454,  338,  450,  440,  441,  455,  451,  435,  458,  449,
+      448,  464,  449,  456,  453, 1454,  465,  457,  455, 1454,
+      459,  468,  476,  480,  463,  471,  473,  486,  487,  484,
+      476,  476,  483,  492,  491,  481,  482,  484,  491,  481,
+      493,  496,  489,  519,  543,  497,  507,  508,  495,  511,
+     1454,  512,  498,  500,  516,  504,  518,  519,  509,  514,
+
+      523,  513,  517, 1454,  521, 1454,  530, 1454,  527,  514,
+     1454, 1454,  515,  572, 1454,  526,  530, 1454,  577,  533,
+      528,  580, 1454,  532,  536, 1454, 1454,  532,  527, 1454,
+      541,  540,  545, 1454,  542,  532,  548,  542,  550, 1454,
+      536, 1454,  541,  555,  545,  581,  597,  550,  567,  557,
+      569,  565,  563,  570,  575,  566,  564,  563, 1454,  580,
+      585,  583,  570,  575,  566, 1454, 1454,  573,  588,  591,
+      577,  583,  596,  587, 1454,  599, 1454,  585,  597,  595,
+      607,  604, 1454,  596,  598,  593, 1454,  612,  602,  598,
+      613,  602,  614, 1454,  606,  617,  621,  607, 1454,  606,
+
+      616,  606,  622,  608,  620,  611, 1454,  650,  632, 1454,
+     1454,  633,  677,  634,  626, 1454,  641,  642, 1454, 1454,
+      642,  643,  646,  634, 1454,  639,  636,  630,  636,  637,
+      637,  654,  691,  655, 1454,  640,  657,  656,  640,  661,
+      655,  705,  654, 1454,  664,  674,  662,  676,  677,  682,
+      679,  710,  734, 1454,  683,  683,  680,  689,  685,  674,
+      686,  696,  688,  687,  690, 1454,  694,  692,  696,  708,
+      694, 1454,  707, 1454,  708, 1454,  699,  710, 1454, 1454,
+      703,  700,  709, 1454,  702,  719,  723,  716,  705,  720,
+     1454, 1454, 1454,  723, 1454,  717, 1454,  710,  711,  723,
+
+      731, 1454,  720,  730,  755, 1454,  738,  780,  782,  787,
+      729,  737, 1454,  750, 1454, 1454,  738,  753, 1454,  751,
+     1454, 1454, 1454,  741, 1454, 1454,  796,  756,  744, 1454,
+     1454,  751, 1454,  739,  802,  754,  763, 1454,  763,  753,
+      753, 1454,  778,    0, 1454, 1454,  770,  778,  766,  782,
+      774,  765,  791, 1454,  768, 1454, 1454,  774, 1454, 1454,
+      776, 1454,  781, 1454,  778,  785, 1454,  792, 1454,  783,
+      788,  791,  795,  786,  801,  802, 1454,  793,  794, 1454,
+     1454, 1454,  847,  849, 1454,  851, 1454,  797, 1454, 1454,
+      812,  809, 1454, 1454, 1454,  814, 1454,    0,  811, 1454,
+
+      800, 1454, 1454,  803,  856, 1454,  812,  821, 1454,  808,
+      824,  816, 1454, 1454, 1454,  830, 1454,  811, 1454,  813,
+      829,  815,  822, 1454, 1454,  823,  824,  815,  837,  825,
+      830, 1454,  877,  832,  828, 1454, 1454, 1454,  847,  843,
+     1454,  835,  844,  839, 1454, 1454, 1454, 1454, 1454, 1454,
+     1454, 1454, 1454, 1454, 1454, 1454,  848,  841,  854, 1454,
+      851, 1454,  853,  849,  846, 1454, 1454,  848,  852,  837,
+      851, 1454,  839, 1454, 1454,  903,  908,  918,  927,  930,
+      938,  945,  955
+    } ;
+
+static yyconst short int yy_def[1184] =
+    {   0,
+     1175,    1, 1175,    3, 1176, 1176, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1177,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1178, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+
+     1175, 1177, 1175, 1179, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1180, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1178,
+     1175, 1175, 1175, 1175, 1175, 1179, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1180, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1181,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1182, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1181, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1183, 1175, 1175,
+
+     1175, 1175, 1175, 1175, 1182, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1183, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175,    0, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175
+    } ;
+
+static yyconst short int yy_nxt[1524] =
+    {   0,
+        8,    9,   10,   11,   12,   13,   14,   15,    8,   16,
+       17,   18,   19,   20,   21,   22,   23,   24,   25,   26,
+       27,   26,   26,   26,   28,   29,   30,   31,   32,   33,
+       34,   35,   35,   36,   37,   38,   39,   40,   41,   42,
+       43,   44,   45,   46,   47,   48,   49,   50,   51,   52,
+       53,   54,   55,   56,   57,   58,   59,   60,   61,   62,
+       63,   64,   65,   58,   58,   66,    8,   67,   68,   69,
+       70,   71,   69,   69,   72,   69,   69,   73,   74,   69,
+       73,   73,   73,   73,   73,   73,   73,   73,   75,   76,
+       76,   76,   76,   76,   73,   69,   77,   78,   79,   73,
+
+       80,   80,   69,   69,   69,   73,   69,   69,   69,   69,
+       69,   81,   82,   69,   69,   69,   69,   69,   69,   69,
+       69,   69,   69,   69,   69,   69,   69,   83,   69,   69,
+       69,   69,   69,   69,   69,   84,   69,   73,   90,   92,
+       92,   92,   92,   92,   92,   93,   92,   92,   92,   92,
+       92,   92,   92,   92,   92,   92,   92,   92,   97,   97,
+       97,   97,   97,   97,   98,   99,  100,  103,  862,  134,
+       97,   97,   91,  105,  148,  106,   97,  225,  196,  135,
+      197,  136,  149,  107,  265,  108,  137,  266,  150,  168,
+      111,   94,  109,  110,  112,  210,  211,  104,  104,  288,
+
+      169,  113,  114,  230,  115,  118,  170,  116,  171,  119,
+      117,  231,  120,  121,  227,  101,  122,  123,  289,  124,
+      127,  128,  125,  138,  129,  126,  139,  143,  130,  140,
+      286,  144,  141,  162,  131,  145,  753,  132,  153,  157,
+      287,  146,  154,  158,  133,  147,  155,  159,  202,  163,
+      172,  222,  160,  223,  173,  203,  204,  174,  164,  161,
+      754,  175,  156,  509,  176,  165,  103,  177,  166,  178,
+      183,  213,  214,  179,  167,  184,  185,  180,  252,  186,
+      237,  191,  187,  181,  182,  192,  253,  188,  198,  193,
+      189,  238,  190,  510,  199,  194,  104,  104,  195,  239,
+
+      200,   98,   99,  100,  201,  208,  208,  208,  208,  208,
+      208,  208,  208,  208,  208,  208,  208,  215,  215,  215,
+      215,  215,  215,   92,   92,   92,   92,   92,   92,  215,
+      215,  235,  236,  276,  277,  215,  863,   97,   97,   97,
+       97,   97,   97,  273,  241,  255,  283,  242,  209,   97,
+       97,  261,  243,  279,  274,   97,  244,  284,  256,  293,
+      257,  280,  568,  262,  371,  295,  296,  281,  305,  263,
+      569,  294,  264,  297,  302,  308,  311,  303,  306,  298,
+      372,  312,  309,  318,  319,  864,  324,  320,  328,  329,
+      337,  338,  321,  332,  322,  340,  344,  333,  323,  304,
+
+      325,  334,  348,  359,  335,  354,  349,  360,  225,  341,
+      345,  368,  355,  356,  361,  369,  346,  225,  385,  362,
+      357,  208,  208,  208,  208,  208,  208,  386,  387,  363,
+      215,  215,  215,  215,  215,  215,  651,  395,  652,  477,
+      411,  486,  215,  215,  396,  227,  412,  440,  215,  422,
+      460,  441,  423,  462,  227,  487,  424,  478,  547,  576,
+      461,  580,  613,  614,  548,  615,  463,  645,  634,  464,
+      635,  677,  577,  706,  646,  581,  616,  806,  720,  678,
+      617,  707,  711,  773,  712,  769,  636,  774,  770,  814,
+      775,  822,  852,  865,  866,  867,  868,  853,  869,  870,
+
+      871,  872,  873,  874,  713,  875,  876,  807,  846,  846,
+      854,  877,  878,  879,  880,  815,  881,  823,  882,  883,
+      884,  887,  888,  885,  889,  890,  891,  892,  893,  894,
+      895,  896,  897,  899,  898,  900,  901,  886,  902,  903,
+      904,  905,  906,  907,  785,  816,  817,  824,  825,  909,
+      910,  911,  912,  913,  914,  915,  818,  916,  826,  917,
+      918,  919,  920,  921,  922,  923,  924,  925,  926,  927,
+      928,  929,  930,  814,  908,  908,  931,  932,  819,  934,
+      935,  822,  936,  937,  938,  939,  940,  941,  942,  943,
+      944,  945,  946,  947,  948,  949,  950,  951,  953,  815,
+
+      952,  952,  952,  952,  952,  952,  954,  823,  933,  933,
+      955,  956,  952,  952,  957,  958,  959,  960,  952,  961,
+      963,  964,  965,  966,  967,  968,  969,  970,  971,  816,
+      817,  972,  962,  973,  974,  975,  976,  824,  825,  977,
+      818,  978,  979,  980,  981,  982,  983,  984,  826,  985,
+      986,  987,  988,  989,  990,  991,  992,  993,  994,  995,
+      996,  997,  998,  999, 1000, 1001, 1002, 1003, 1004, 1005,
+     1005, 1005, 1005, 1005, 1005, 1006, 1007, 1011, 1008, 1008,
+     1012, 1005, 1005, 1013, 1014, 1015, 1016, 1005, 1009, 1017,
+     1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1028, 1029,
+
+     1030, 1031, 1026, 1032, 1033, 1034, 1035, 1036, 1010, 1010,
+     1027, 1027, 1027, 1027, 1027, 1027, 1037, 1038, 1039, 1040,
+     1041, 1042, 1027, 1027, 1043, 1045, 1046, 1047, 1027,  952,
+      952,  952,  952,  952,  952,  953, 1048, 1049, 1050, 1051,
+     1044,  952,  952, 1052, 1053, 1054, 1055,  952, 1056, 1057,
+     1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067,
+     1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077,
+     1078, 1079, 1080, 1081, 1005, 1005, 1005, 1005, 1005, 1005,
+     1082, 1008, 1008, 1083, 1083, 1087, 1005, 1005, 1084, 1084,
+     1088, 1009, 1005, 1089, 1090, 1091, 1092, 1093, 1094, 1085,
+
+     1095, 1096, 1097, 1035, 1099, 1100, 1101, 1026, 1098, 1102,
+     1103, 1010, 1010, 1010, 1010, 1027, 1027, 1027, 1027, 1027,
+     1027, 1104, 1106, 1107, 1108, 1109, 1110, 1027, 1027, 1111,
+     1112, 1113, 1114, 1027, 1115, 1116, 1117, 1118, 1119, 1120,
+     1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1083, 1083,
+     1084, 1084, 1084, 1084, 1129, 1130, 1131, 1132, 1134, 1135,
+     1136, 1085, 1137, 1085, 1138, 1139, 1140, 1141, 1142, 1143,
+     1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1010, 1010,
+     1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161,
+     1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171,
+
+     1172, 1173, 1174,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,  102,  102,  861,  102,  102,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220,  226,  860,
+      859,  858,  226,  226,  226,  374,  857,  856,  374, 1086,
+     1086,  855, 1086, 1086, 1086, 1105, 1105,  851,  850, 1105,
+     1105, 1105, 1105, 1105, 1105, 1133, 1133,  849,  848, 1133,
+     1133, 1133, 1133, 1133, 1133,  847,  845,  844,  843,  842,
+      841,  840,  839,  838,  837,  836,  835,  834,  833,  832,
+      831,  830,  829,  828,  827,  821,  820,  819,  813,  812,
+      811,  810,  809,  808,  805,  804,  803,  802,  801,  800,
+
+      799,  798,  797,  796,  795,  794,  793,  792,  791,  790,
+      789,  788,  787,  786,  785,  784,  783,  782,  781,  780,
+      779,  778,  777,  776,  772,  771,  768,  767,  766,  765,
+      764,  763,  762,  761,  760,  759,  758,  757,  756,  755,
+      752,  751,  750,  749,  748,  747,  746,  745,  744,  743,
+      742,  741,  740,  739,  738,  737,  736,  735,  734,  733,
+      732,  731,  730,  729,  728,  727,  726,  725,  724,  723,
+      722,  721,  720,  719,  718,  717,  716,  715,  714,  710,
+      709,  708,  705,  704,  703,  702,  701,  700,  699,  698,
+      697,  696,  695,  694,  693,  692,  691,  690,  689,  688,
+
+      687,  686,  685,  684,  683,  682,  681,  680,  679,  676,
+      675,  674,  673,  672,  671,  670,  669,  668,  667,  666,
+      665,  664,  663,  662,  661,  660,  659,  658,  657,  656,
+      655,  654,  653,  650,  649,  648,  647,  644,  643,  642,
+      641,  640,  639,  638,  637,  633,  632,  631,  630,  629,
+      628,  627,  626,  625,  624,  623,  622,  621,  620,  619,
+      618,  612,  611,  610,  609,  608,  607,  606,  605,  604,
+      603,  602,  601,  600,  599,  598,  597,  596,  595,  594,
+      593,  592,  591,  590,  589,  588,  587,  586,  585,  584,
+      583,  582,  579,  578,  575,  574,  573,  572,  571,  570,
+
+      567,  566,  565,  564,  563,  562,  561,  560,  559,  558,
+      557,  556,  555,  554,  553,  552,  551,  550,  549,  546,
+      545,  544,  543,  542,  541,  540,  539,  538,  537,  536,
+      535,  534,  533,  532,  531,  530,  529,  528,  527,  526,
+      525,  524,  523,  522,  521,  520,  519,  518,  517,  516,
+      515,  514,  513,  512,  511,  508,  507,  506,  505,  504,
+      503,  502,  501,  500,  499,  498,  497,  496,  495,  494,
+      493,  492,  491,  490,  489,  488,  485,  484,  483,  482,
+      481,  480,  479,  476,  475,  474,  473,  472,  471,  470,
+      469,  468,  467,  466,  465,  459,  458,  457,  456,  455,
+
+      454,  453,  452,  451,  450,  449,  448,  447,  446,  445,
+      444,  443,  442,  286,  439,  438,  437,  436,  435,  434,
+      433,  432,  431,  430,  429,  428,  427,  426,  425,  421,
+      420,  419,  418,  417,  416,  415,  414,  413,  410,  409,
+      408,  407,  406,  405,  404,  403,  402,  401,  400,  399,
+      398,  397,  394,  393,  392,  391,  390,  389,  388,  384,
+      383,  382,  381,  380,  379,  378,  221,  377,  376,  375,
+      373,  370,  367,  366,  365,  364,  358,  353,  352,  351,
+      350,  347,  343,  342,  339,  336,  331,  330,  327,  326,
+      317,  316,  315,  314,  313,  310,  307,  301,  300,  299,
+
+      292,  291,  290,  285,  282,  278,  275,  272,  271,  270,
+      269,  268,  267,  260,  259,  258,  254,  251,  250,  249,
+      248,  247,  246,  245,  240,  234,  233,  232,  229,  228,
+       99,  224,   89,  221,  219,  218,  217,  216,  212,  207,
+      206,  205,  152,  151,  142,   96,   95,   89,   88,   87,
+     1175,   86,   86,    7, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175
+    } ;
+
+static yyconst short int yy_chk[1524] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,   25,   26,
+       26,   26,   26,   26,   26,   27,   27,   27,   27,   27,
+       27,   27,   28,   28,   28,   28,   28,   28,   35,   35,
+       35,   35,   35,   35,   37,   37,   37,   41,  739,   46,
+       35,   35,   25,   42,   50,   42,   35,  104,   62,   46,
+       62,   46,   50,   42,  131,   42,   46,  131,   50,   56,
+       43,   28,   42,   42,   43,   77,   77,   41,   41,  149,
+
+       56,   43,   43,  107,   43,   44,   56,   43,   56,   44,
+       43,  107,   44,   44,  104,   37,   44,   44,  149,   44,
+       45,   45,   44,   47,   45,   44,   47,   49,   45,   47,
+      148,   49,   47,   55,   45,   49,  622,   45,   53,   54,
+      148,   49,   53,   54,   45,   49,   53,   54,   64,   55,
+       57,   93,   54,   93,   57,   64,   64,   57,   55,   54,
+      622,   57,   53,  358,   57,   55,  103,   57,   55,   59,
+       60,   79,   79,   59,   55,   60,   60,   59,  124,   60,
+      112,   61,   60,   59,   59,   61,  124,   60,   63,   61,
+       60,  112,   60,  358,   63,   61,  103,  103,   61,  112,
+
+       63,   98,   98,   98,   63,   75,   75,   75,   75,   75,
+       75,   76,   76,   76,   76,   76,   76,   80,   80,   80,
+       80,   80,   80,   92,   92,   92,   92,   92,   92,   80,
+       80,  111,  111,  140,  140,   80,  740,   97,   97,   97,
+       97,   97,   97,  138,  115,  126,  144,  115,   75,   97,
+       97,  130,  115,  142,  138,   97,  115,  144,  126,  153,
+      126,  142,  424,  130,  204,  154,  154,  142,  159,  130,
+      424,  153,  130,  154,  158,  161,  166,  158,  159,  154,
+      204,  166,  161,  172,  172,  742,  173,  172,  176,  176,
+      181,  181,  172,  179,  172,  183,  186,  179,  172,  158,
+
+      173,  179,  188,  195,  179,  193,  188,  195,  225,  183,
+      186,  202,  193,  193,  196,  202,  186,  226,  235,  196,
+      193,  208,  208,  208,  208,  208,  208,  235,  235,  196,
+      215,  215,  215,  215,  215,  215,  507,  243,  507,  324,
+      260,  332,  215,  215,  243,  225,  260,  288,  215,  271,
+      309,  288,  271,  310,  226,  332,  271,  324,  398,  433,
+      309,  436,  472,  472,  398,  473,  310,  502,  490,  310,
+      490,  538,  433,  572,  502,  436,  473,  684,  720,  538,
+      473,  572,  577,  644,  577,  639,  490,  644,  639,  693,
+      644,  699,  729,  743,  744,  745,  746,  729,  747,  748,
+
+      749,  750,  751,  752,  577,  753,  754,  684,  720,  720,
+      729,  755,  757,  758,  759,  693,  761,  699,  762,  763,
+      764,  765,  766,  764,  767,  768,  769,  770,  771,  772,
+      773,  774,  775,  776,  775,  777,  778,  764,  779,  780,
+      781,  782,  783,  784,  785,  693,  693,  699,  699,  786,
+      787,  788,  789,  790,  792,  793,  693,  794,  699,  795,
+      796,  797,  798,  799,  800,  801,  802,  803,  805,  807,
+      809,  810,  813,  814,  785,  785,  816,  817,  819,  820,
+      821,  822,  824,  825,  828,  829,  831,  832,  833,  835,
+      836,  837,  838,  839,  841,  843,  844,  845,  847,  814,
+
+      846,  846,  846,  846,  846,  846,  848,  822,  819,  819,
+      849,  850,  846,  846,  851,  852,  853,  854,  846,  855,
+      856,  857,  858,  860,  861,  862,  863,  864,  865,  814,
+      814,  868,  855,  869,  870,  871,  872,  822,  822,  873,
+      814,  874,  876,  878,  879,  880,  881,  882,  822,  884,
+      885,  886,  888,  889,  890,  891,  892,  893,  895,  896,
+      897,  898,  900,  901,  902,  903,  904,  905,  906,  908,
+      908,  908,  908,  908,  908,  909,  912,  914,  913,  913,
+      915,  908,  908,  917,  918,  921,  922,  908,  913,  923,
+      924,  926,  927,  928,  929,  930,  931,  932,  934,  936,
+
+      937,  938,  933,  939,  940,  941,  942,  943,  913,  913,
+      933,  933,  933,  933,  933,  933,  945,  946,  947,  948,
+      949,  950,  933,  933,  951,  955,  956,  957,  933,  952,
+      952,  952,  952,  952,  952,  953,  958,  959,  960,  961,
+      953,  952,  952,  962,  963,  964,  965,  952,  967,  968,
+      969,  970,  971,  973,  975,  977,  978,  981,  982,  983,
+      985,  986,  987,  988,  989,  990,  994,  996,  998,  999,
+     1000, 1001, 1003, 1004, 1005, 1005, 1005, 1005, 1005, 1005,
+     1007, 1008, 1008, 1009, 1009, 1011, 1005, 1005, 1010, 1010,
+     1012, 1008, 1005, 1014, 1017, 1018, 1020, 1024, 1028, 1010,
+
+     1029, 1032, 1034, 1035, 1036, 1037, 1039, 1027, 1035, 1040,
+     1041, 1008, 1008, 1009, 1009, 1027, 1027, 1027, 1027, 1027,
+     1027, 1043, 1047, 1048, 1049, 1050, 1051, 1027, 1027, 1052,
+     1053, 1055, 1058, 1027, 1061, 1063, 1065, 1066, 1068, 1070,
+     1071, 1072, 1073, 1074, 1075, 1076, 1078, 1079, 1083, 1083,
+     1084, 1084, 1086, 1086, 1088, 1091, 1092, 1096, 1099, 1101,
+     1104, 1084, 1105, 1086, 1107, 1108, 1110, 1111, 1112, 1116,
+     1118, 1120, 1121, 1122, 1123, 1126, 1127, 1128, 1083, 1083,
+     1129, 1130, 1131, 1133, 1134, 1135, 1139, 1140, 1142, 1143,
+     1144, 1157, 1158, 1159, 1161, 1163, 1164, 1165, 1168, 1169,
+
+     1170, 1171, 1173, 1176, 1176, 1176, 1176, 1176, 1176, 1176,
+     1176, 1176, 1176, 1177, 1177,  738, 1177, 1177, 1178, 1178,
+     1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1179,  737,
+      736,  735, 1179, 1179, 1179, 1180,  733,  732, 1180, 1181,
+     1181,  730, 1181, 1181, 1181, 1182, 1182,  727,  726, 1182,
+     1182, 1182, 1182, 1182, 1182, 1183, 1183,  724,  723, 1183,
+     1183, 1183, 1183, 1183, 1183,  722,  719,  718,  717,  716,
+      715,  714,  713,  712,  711,  710,  709,  708,  707,  706,
+      705,  704,  703,  702,  700,  698,  697,  695,  692,  691,
+      689,  688,  686,  685,  683,  682,  681,  680,  679,  678,
+
+      677,  676,  674,  673,  672,  671,  670,  669,  668,  666,
+      664,  663,  661,  660,  657,  656,  655,  654,  652,  649,
+      648,  647,  646,  645,  643,  640,  637,  636,  635,  634,
+      633,  632,  631,  630,  629,  628,  627,  626,  624,  623,
+      620,  619,  618,  617,  616,  615,  614,  613,  612,  611,
+      610,  609,  608,  607,  606,  605,  604,  603,  602,  600,
+      598,  597,  596,  594,  593,  591,  590,  589,  588,  587,
+      586,  585,  584,  583,  582,  581,  580,  579,  578,  576,
+      574,  573,  571,  570,  569,  567,  566,  565,  564,  563,
+      562,  561,  560,  559,  558,  556,  555,  554,  553,  552,
+
+      551,  550,  548,  545,  544,  543,  542,  540,  539,  537,
+      536,  535,  534,  533,  532,  531,  530,  529,  527,  526,
+      525,  522,  519,  518,  517,  516,  515,  514,  513,  512,
+      511,  510,  508,  506,  505,  504,  503,  501,  500,  498,
+      497,  495,  494,  493,  491,  489,  488,  487,  486,  485,
+      484,  483,  482,  481,  480,  479,  478,  477,  476,  475,
+      474,  471,  470,  469,  468,  467,  466,  465,  464,  463,
+      462,  461,  460,  459,  457,  455,  454,  453,  452,  451,
+      449,  448,  447,  446,  445,  444,  442,  441,  440,  439,
+      438,  437,  435,  434,  432,  431,  430,  429,  427,  426,
+
+      423,  422,  420,  417,  416,  414,  412,  411,  410,  409,
+      408,  407,  406,  405,  403,  402,  401,  400,  399,  397,
+      396,  395,  394,  393,  392,  391,  390,  389,  387,  386,
+      385,  384,  383,  382,  380,  379,  378,  377,  376,  375,
+      373,  372,  371,  370,  369,  368,  367,  366,  365,  364,
+      363,  362,  361,  360,  359,  357,  356,  353,  352,  351,
+      350,  349,  348,  347,  346,  345,  344,  343,  342,  341,
+      340,  337,  336,  335,  334,  333,  331,  330,  329,  328,
+      327,  326,  325,  323,  322,  321,  320,  318,  317,  316,
+      315,  314,  313,  312,  311,  308,  307,  306,  305,  304,
+
+      303,  302,  301,  300,  299,  298,  296,  295,  294,  293,
+      291,  290,  289,  287,  286,  285,  284,  283,  282,  281,
+      280,  279,  278,  277,  276,  275,  274,  273,  272,  270,
+      268,  267,  266,  265,  264,  263,  262,  261,  259,  258,
+      256,  254,  253,  252,  251,  250,  249,  248,  247,  246,
+      245,  244,  242,  241,  240,  239,  238,  237,  236,  234,
+      233,  232,  231,  229,  228,  224,  220,  218,  217,  216,
+      205,  203,  201,  200,  199,  198,  194,  192,  191,  190,
+      189,  187,  185,  184,  182,  180,  178,  177,  175,  174,
+      171,  170,  169,  168,  167,  164,  160,  157,  156,  155,
+
+      152,  151,  150,  145,  143,  141,  139,  137,  136,  135,
+      134,  133,  132,  129,  128,  127,  125,  122,  121,  120,
+      119,  118,  117,  116,  113,  110,  109,  108,  106,  105,
+      100,   94,   89,   85,   84,   83,   82,   81,   78,   74,
+       72,   65,   52,   51,   48,   33,   31,   17,   16,   11,
+        7,    6,    5, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+     1175, 1175, 1175
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+static int yy_more_offset = 0;
+static int yy_prev_more_offset = 0;
+#define yymore() (yy_more_offset = yy_flex_strlen( yytext ))
+#define YY_NEED_STRLEN
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET \
+       { \
+       yy_more_offset = yy_prev_more_offset; \
+       yyleng -= yy_more_offset; \
+       }
+#ifndef YYLMAX
+#define YYLMAX 8192
+#endif
+
+char yytext[YYLMAX];
+char *yytext_ptr;
+#line 1 "lex.l"
+#define INITIAL 0
+#line 3 "lex.l"
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ * 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* lexer for music publication program. Recognizes and returns all the
+ * tokens needed by yacc. */
+
+#include <errno.h>
+#include "rational.h"
+#include "ytab.h"
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+/* In order to reduce the number of terminal symbols so yacc wouldn't blow
+ * up, we mapped several similar tokens to the same return code. The
+ * yylval variable is then used to say which specific one of the set
+ * was actually in the input. Bison doesn't have the number of tokens
+ * restriction, but grouping related tokens is still useful. */
+extern YYSTYPE yylval;
+
+
+#define YY_INPUT(buf,result,max_size) \
+       { \
+               int c = getc(yyin); \
+               if (c == '\n') { \
+                       Last_was_newline = YES; \
+                       yylineno += not_in_mac(1); \
+               } \
+               else { \
+                       Last_was_newline = NO; \
+               } \
+               if (c == EOF || c == 0) { \
+                        result = YY_NULL; \
+               } else { \
+                       buf[0] = c; \
+                       result = 1; \
+               } \
+       } \
+
+/* list of Flex buffers for includes/macros */
+struct Lexbuffer {
+       YY_BUFFER_STATE buff;
+       struct Lexbuffer *next;
+};
+static struct Lexbuffer *Lexlist;
+
+/* We add a newline at end of input, to avoid cryptic error message
+ * if user didn't end the file with a newline. */
+static YY_BUFFER_STATE Eof_newline = 0;
+
+/* The compressed form of an "if" clause is stored here,
+ * then passed to a mini-parser. */
+unsigned char Ifclause_buff[1024];
+int If_length;                 /* how much of Ifclause_buffer is used */
+static void add_ifclause P((int token));
+static void addnum_ifclause P((int value));
+static void addnumstr_ifclause P((char *numtoken));
+extern void set_ifclause_buffer P((unsigned char * buffer, int length));
+extern int ifparse P((void));
+static void bad_input P((char *where));
+
+int yylineno;
+
+
+static int If_count = 0;       /* how many if, ifdef, and ifndef constructs in progress */
+static int If_errs;            /* to try to deduce missing 'then' */
+static int Escapedquotes = 0;
+static int Raw_string = NO;    /* YES if doing raw string (not expanding
+                                * any non-ASCII into Mup escapes) */
+
+static int get_a_param P((char *macname));
+static void skipwhite P((void));
+static void to_eol P((void));
+static int skip2else P((void));
+static int oddbs P((void));
+static void embedquotes P((void));
+static void xpand_non_ascii P((void));
+static void ignore P((void));
+#define IF_CLAUSE 1
+#define STRING 2
+
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines.  This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+       if ( yy_current_buffer->yy_is_interactive ) \
+               { \
+               int c = '*', n; \
+               for ( n = 0; n < max_size && \
+                            (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+                       buf[n] = (char) c; \
+               if ( c == '\n' ) \
+                       buf[n++] = (char) c; \
+               if ( c == EOF && ferror( yyin ) ) \
+                       YY_FATAL_ERROR( "input in flex scanner failed" ); \
+               result = n; \
+               } \
+       else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+                 && ferror( yyin ) ) \
+               YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+       YY_USER_ACTION
+
+YY_DECL
+       {
+       register yy_state_type yy_current_state;
+       register char *yy_cp, *yy_bp;
+       register int yy_act;
+
+#line 91 "lex.l"
+
+
+
+       if ( yy_init )
+               {
+               yy_init = 0;
+
+#ifdef YY_USER_INIT
+               YY_USER_INIT;
+#endif
+
+               if ( ! yy_start )
+                       yy_start = 1;   /* first start state */
+
+               if ( ! yyin )
+                       yyin = stdin;
+
+               if ( ! yyout )
+                       yyout = stdout;
+
+               if ( ! yy_current_buffer )
+                       yy_current_buffer =
+                               yy_create_buffer( yyin, YY_BUF_SIZE );
+
+               yy_load_buffer_state();
+               }
+
+       while ( 1 )             /* loops until end-of-file is reached */
+               {
+               yy_cp = yy_c_buf_p;
+
+               /* Support of yytext. */
+               *yy_cp = yy_hold_char;
+
+               /* yy_bp points to the position in yy_ch_buf of the start of
+                * the current run.
+                */
+               yy_bp = yy_cp;
+
+               yy_current_state = yy_start;
+yy_match:
+               do
+                       {
+                       register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+                       if ( yy_accept[yy_current_state] )
+                               {
+                               yy_last_accepting_state = yy_current_state;
+                               yy_last_accepting_cpos = yy_cp;
+                               }
+                       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                               {
+                               yy_current_state = (int) yy_def[yy_current_state];
+                               if ( yy_current_state >= 1176 )
+                                       yy_c = yy_meta[(unsigned int) yy_c];
+                               }
+                       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+                       ++yy_cp;
+                       }
+               while ( yy_base[yy_current_state] != 1454 );
+
+yy_find_action:
+               yy_act = yy_accept[yy_current_state];
+               if ( yy_act == 0 )
+                       { /* have to back up */
+                       yy_cp = yy_last_accepting_cpos;
+                       yy_current_state = yy_last_accepting_state;
+                       yy_act = yy_accept[yy_current_state];
+                       }
+
+               YY_DO_BEFORE_ACTION;
+
+
+do_action:     /* This label is used only to access EOF actions. */
+
+
+               switch ( yy_act )
+       { /* beginning of action switch */
+                       case 0: /* must back up */
+                       /* undo the effects of YY_DO_BEFORE_ACTION */
+                       *yy_cp = yy_hold_char;
+                       yy_cp = yy_last_accepting_cpos;
+                       yy_current_state = yy_last_accepting_state;
+                       goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 93 "lex.l"
+{ yylval.intval = FONT_TR; return(T_FONT); }
+       YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 94 "lex.l"
+{ yylval.intval = FONT_TB; return(T_FONT); }
+       YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 95 "lex.l"
+{ yylval.intval = FONT_TX; return(T_FONT); }
+       YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 96 "lex.l"
+{ yylval.intval = FONT_TI; return(T_FONT); }
+       YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 98 "lex.l"
+{ yylval.intval = BASE_TIMES; return(T_FFAMILY); }
+       YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 99 "lex.l"
+{ yylval.intval = BASE_AVANTGARDE; return(T_FFAMILY); }
+       YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 100 "lex.l"
+{ yylval.intval = BASE_COURIER; return(T_FFAMILY); }
+       YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 101 "lex.l"
+{ yylval.intval = BASE_HELVETICA; return(T_FFAMILY); }
+       YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 102 "lex.l"
+{ yylval.intval = BASE_BOOKMAN; return(T_FFAMILY); }
+       YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 103 "lex.l"
+{ yylval.intval = BASE_NEWCENTURY; return(T_FFAMILY); }
+       YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 104 "lex.l"
+{ yylval.intval = BASE_PALATINO; return(T_FFAMILY); }
+       YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 106 "lex.l"
+{
+                       /* set up include using filename with quotes stripped */
+                       yytext[yyleng - 1] = '\0';
+                       includefile(strchr(yytext, '"') + 1);
+               }
+       YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 112 "lex.l"
+{
+                       yytext[yyleng - 1] = '\0';
+                       parse_font_file(strchr(yytext, '"') + 1);
+               }
+       YY_BREAK
+case 14:
+#line 118 "lex.l"
+case 15:
+YY_RULE_SETUP
+#line 118 "lex.l"
+{ yylval.intval = DIMINISHED; return(T_XPOS_INT); }
+       YY_BREAK
+case 16:
+#line 120 "lex.l"
+case 17:
+YY_RULE_SETUP
+#line 120 "lex.l"
+{ yylval.intval = AUGMENTED; return(T_XPOS_INT); }
+       YY_BREAK
+case 18:
+#line 122 "lex.l"
+case 19:
+YY_RULE_SETUP
+#line 122 "lex.l"
+{ yylval.intval = PERFECT; return(T_XPOS_INT); }
+       YY_BREAK
+case 20:
+#line 124 "lex.l"
+case 21:
+YY_RULE_SETUP
+#line 124 "lex.l"
+{ yylval.intval = MINOR; return(T_XPOS_INT); }
+       YY_BREAK
+case 22:
+#line 126 "lex.l"
+case 23:
+YY_RULE_SETUP
+#line 126 "lex.l"
+{ yylval.intval = MAJOR; return(T_XPOS_INT); }
+       YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 128 "lex.l"
+return(T_TITLE);
+       YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 130 "lex.l"
+return(T_SCORE);
+       YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 131 "lex.l"
+return(T_STAFF);
+       YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 132 "lex.l"
+return(T_VOICE);
+       YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 133 "lex.l"
+{ yylval.intval = C_HEADER; return(T_BLOCKHEAD); }
+       YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 134 "lex.l"
+{ yylval.intval = C_FOOTER; return(T_BLOCKHEAD); }
+       YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 135 "lex.l"
+{ yylval.intval = C_HEAD2; return(T_BLOCKHEAD); }
+       YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 136 "lex.l"
+{ yylval.intval = C_FOOT2; return(T_BLOCKHEAD); }
+       YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 137 "lex.l"
+{ yylval.intval = C_TOP; return(T_BLOCKHEAD); }
+       YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 138 "lex.l"
+{ yylval.intval = C_BOT; return(T_BLOCKHEAD); }
+       YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 139 "lex.l"
+{ yylval.intval = C_TOP2; return(T_BLOCKHEAD); }
+       YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 140 "lex.l"
+{ yylval.intval = C_BOT2; return(T_BLOCKHEAD); }
+       YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 141 "lex.l"
+{ yylval.intval = C_BLOCK; return(T_BLOCKHEAD); }
+       YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 142 "lex.l"
+return(T_GRIDS);
+       YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 143 "lex.l"
+return(T_MUSIC);
+       YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 144 "lex.l"
+return(T_HEADSHAPES);
+       YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 146 "lex.l"
+return(T_NUMBER);
+       YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 148 "lex.l"
+return(T_EQUAL);
+       YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 149 "lex.l"
+return(T_SEMICOLON);
+       YY_BREAK
+case 43:
+#line 151 "lex.l"
+case 44:
+#line 152 "lex.l"
+case 45:
+YY_RULE_SETUP
+#line 152 "lex.l"
+return(T_NEWLINE);
+       YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 153 "lex.l"
+return(T_COLON);
+       YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 154 "lex.l"
+return(T_COMMA);
+       YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 155 "lex.l"
+return(T_LBRACKET);
+       YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 156 "lex.l"
+return(T_RBRACKET);
+       YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 157 "lex.l"
+return(T_LBRACE);
+       YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 158 "lex.l"
+return(T_RBRACE);
+       YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 159 "lex.l"
+return(T_LPAREN);
+       YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 160 "lex.l"
+return(T_RPAREN);
+       YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 161 "lex.l"
+return(T_EXCLAM);
+       YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 163 "lex.l"
+{ BEGIN STRING; yymore(); }
+       YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 164 "lex.l"
+{
+                       /* string: handle embedded backslashed quotes */
+                       if (yytext[yyleng-2] == '\\' && oddbs() == YES) {
+                               Escapedquotes++;
+                               yymore();
+                       }
+                       else {
+                               embedquotes();
+                               BEGIN 0;
+                               xpand_non_ascii();
+                               if (yyleng > YYLMAX) {
+                                       l_ufatal(Curr_filename, yylineno,
+                                                       "text string too long");
+                               }
+                               return(T_STRING);
+                       }
+               }
+       YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 182 "lex.l"
+return(T_DASH);
+       YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 183 "lex.l"
+return(T_PLUS);
+       YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 185 "lex.l"
+return(T_CUE);
+       YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 186 "lex.l"
+return(T_GRACE);
+       YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 187 "lex.l"
+return(T_XNOTE);
+       YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 188 "lex.l"
+return(T_DIAM);
+       YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 189 "lex.l"
+return(T_HO);
+       YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 190 "lex.l"
+return(T_HS);
+       YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 191 "lex.l"
+{ yylval.intval = L_NORMAL; return(T_TIE); }
+       YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 192 "lex.l"
+{ yylval.intval = L_DOTTED; return(T_TIE); }
+       YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 193 "lex.l"
+{ yylval.intval = L_DASHED; return(T_TIE); }
+       YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 194 "lex.l"
+{ yylval.intval = L_NORMAL; return(T_SLUR); }
+       YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 195 "lex.l"
+{ yylval.intval = L_DOTTED; return(T_SLUR); }
+       YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 196 "lex.l"
+{ yylval.intval = L_DASHED; return(T_SLUR); }
+       YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 197 "lex.l"
+return(T_WITH);
+       YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 198 "lex.l"
+{ yylval.intval = PL_ABOVE; return(T_PLACE); }
+       YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 199 "lex.l"
+{ yylval.intval = PL_BELOW; return(T_PLACE); }
+       YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 200 "lex.l"
+{ yylval.intval = PL_BETWEEN; return(T_PLACE); }
+       YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 201 "lex.l"
+return(T_ALL);
+       YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 202 "lex.l"
+return(T_UP);
+       YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 203 "lex.l"
+return(T_DOWN);
+       YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 204 "lex.l"
+return(T_LEN);
+       YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 205 "lex.l"
+return(T_SLASHMARK);
+       YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 206 "lex.l"
+return(T_ALT);
+       YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 207 "lex.l"
+return(T_BM);
+       YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 208 "lex.l"
+return(T_ESBM);
+       YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 209 "lex.l"
+return(T_EBM);
+       YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 210 "lex.l"
+return(T_SLOPE);
+       YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 211 "lex.l"
+{ yylval.intval = PAD; return(T_PAD); }
+       YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 213 "lex.l"
+return(T_HAT);
+       YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 214 "lex.l"
+{ yylval.intval = L_NORMAL; return(T_TILDE); }
+       YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 215 "lex.l"
+{ yylval.intval = L_DOTTED; return(T_TILDE); }
+       YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 216 "lex.l"
+{ yylval.intval = L_DASHED; return(T_TILDE); }
+       YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 217 "lex.l"
+return(T_QUESTION);
+       YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 219 "lex.l"
+return(T_DOT);
+       YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 220 "lex.l"
+{ yylval.intval = 2; return(T_MULTIWHOLE); }
+       YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 221 "lex.l"
+{ yylval.intval = 4; return(T_MULTIWHOLE); }
+       YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 223 "lex.l"
+return(T_LET_M);
+       YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 224 "lex.l"
+return(T_LET_R);
+       YY_BREAK
+case 96:
+YY_RULE_SETUP
+#line 225 "lex.l"
+return(T_LET_S);
+       YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 226 "lex.l"
+return(T_LET_U);
+       YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 227 "lex.l"
+return(T_PITCH);
+       YY_BREAK
+case 99:
+YY_RULE_SETUP
+#line 228 "lex.l"
+return(T_SHARP);
+       YY_BREAK
+case 100:
+YY_RULE_SETUP
+#line 229 "lex.l"
+return(T_AMPERSAND);
+       YY_BREAK
+case 101:
+YY_RULE_SETUP
+#line 230 "lex.l"
+return(T_LET_N);
+       YY_BREAK
+case 102:
+YY_RULE_SETUP
+#line 231 "lex.l"
+return(T_LET_X);
+       YY_BREAK
+case 103:
+YY_RULE_SETUP
+#line 232 "lex.l"
+return(T_LETTER);      /* all letters not used for something special */
+       YY_BREAK
+case 104:
+YY_RULE_SETUP
+#line 233 "lex.l"
+return(T_RPT);
+       YY_BREAK
+case 105:
+YY_RULE_SETUP
+#line 234 "lex.l"
+return(T_LVAR);        /* multi-character location variable names */
+       YY_BREAK
+case 106:
+YY_RULE_SETUP
+#line 235 "lex.l"
+return(T_DBLFLAT);
+       YY_BREAK
+case 107:
+YY_RULE_SETUP
+#line 237 "lex.l"
+return(T_LYRICS);
+       YY_BREAK
+case 108:
+YY_RULE_SETUP
+#line 239 "lex.l"
+{ yylval.intval = NO; return(T_SCOREFEED); }
+       YY_BREAK
+case 109:
+YY_RULE_SETUP
+#line 240 "lex.l"
+{ yylval.intval = YES; return(T_SCOREFEED); }
+       YY_BREAK
+case 110:
+YY_RULE_SETUP
+#line 242 "lex.l"
+return(T_MULTIREST);
+       YY_BREAK
+case 111:
+YY_RULE_SETUP
+#line 244 "lex.l"
+{ yylval.intval = SINGLEBAR; return(T_BARTYPE); }
+       YY_BREAK
+case 112:
+YY_RULE_SETUP
+#line 245 "lex.l"
+{ yylval.intval = DOUBLEBAR; return(T_BARTYPE); }
+       YY_BREAK
+case 113:
+YY_RULE_SETUP
+#line 246 "lex.l"
+{ yylval.intval = REPEATSTART; return(T_BARTYPE); }
+       YY_BREAK
+case 114:
+YY_RULE_SETUP
+#line 247 "lex.l"
+{ yylval.intval = REPEATEND; return(T_BARTYPE); }
+       YY_BREAK
+case 115:
+YY_RULE_SETUP
+#line 248 "lex.l"
+{ yylval.intval = REPEATBOTH; return(T_BARTYPE); }
+       YY_BREAK
+case 116:
+YY_RULE_SETUP
+#line 249 "lex.l"
+{ yylval.intval = INVISBAR; return(T_BARTYPE); }
+       YY_BREAK
+case 117:
+YY_RULE_SETUP
+#line 250 "lex.l"
+{ yylval.intval = ENDBAR; return(T_BARTYPE); }
+       YY_BREAK
+case 118:
+YY_RULE_SETUP
+#line 251 "lex.l"
+{ yylval.intval = RESTART; return(T_BARTYPE); }
+       YY_BREAK
+case 119:
+#line 254 "lex.l"
+case 120:
+YY_RULE_SETUP
+#line 254 "lex.l"
+return(T_REHEARSAL);
+       YY_BREAK
+case 121:
+YY_RULE_SETUP
+#line 255 "lex.l"
+return(T_NUM);
+       YY_BREAK
+case 122:
+YY_RULE_SETUP
+#line 256 "lex.l"
+return(T_LET);
+       YY_BREAK
+case 123:
+YY_RULE_SETUP
+#line 257 "lex.l"
+return(T_MNUM);
+       YY_BREAK
+case 124:
+YY_RULE_SETUP
+#line 259 "lex.l"
+return(T_ENDING);
+       YY_BREAK
+case 125:
+YY_RULE_SETUP
+#line 260 "lex.l"
+return(T_ENDENDING);
+       YY_BREAK
+case 126:
+YY_RULE_SETUP
+#line 262 "lex.l"
+return(T_HIDECHANGES);
+       YY_BREAK
+case 127:
+YY_RULE_SETUP
+#line 264 "lex.l"
+{ yylval.intval = L_WIDE; return(T_LINETYPE); }
+       YY_BREAK
+case 128:
+YY_RULE_SETUP
+#line 265 "lex.l"
+{ yylval.intval = L_MEDIUM; return(T_LINETYPE); }
+       YY_BREAK
+case 129:
+YY_RULE_SETUP
+#line 266 "lex.l"
+{ yylval.intval = L_WAVY; return(T_LINETYPE); }
+       YY_BREAK
+case 130:
+YY_RULE_SETUP
+#line 267 "lex.l"
+{ yylval.intval = L_DOTTED; return(T_LINETYPE); }
+       YY_BREAK
+case 131:
+YY_RULE_SETUP
+#line 268 "lex.l"
+{ yylval.intval = L_DASHED; return(T_LINETYPE); }
+       YY_BREAK
+case 132:
+YY_RULE_SETUP
+#line 270 "lex.l"
+return(T_LINE);
+       YY_BREAK
+case 133:
+YY_RULE_SETUP
+#line 271 "lex.l"
+return(T_TO);
+       YY_BREAK
+case 134:
+YY_RULE_SETUP
+#line 272 "lex.l"
+return(T_CURVE);
+       YY_BREAK
+case 135:
+YY_RULE_SETUP
+#line 273 "lex.l"
+return(T_BULGE);
+       YY_BREAK
+case 136:
+YY_RULE_SETUP
+#line 275 "lex.l"
+{ yylval.intval = J_LEFT; return(T_PRINTTYPE); }
+       YY_BREAK
+case 137:
+YY_RULE_SETUP
+#line 276 "lex.l"
+{ yylval.intval = J_RIGHT; return(T_PRINTTYPE); }
+       YY_BREAK
+case 138:
+YY_RULE_SETUP
+#line 277 "lex.l"
+{ yylval.intval = J_CENTER; return(T_PRINTTYPE); }
+       YY_BREAK
+case 139:
+YY_RULE_SETUP
+#line 278 "lex.l"
+{ yylval.intval = J_NONE; return(T_PRINTTYPE); }
+       YY_BREAK
+case 140:
+YY_RULE_SETUP
+#line 279 "lex.l"
+{ return(T_POSTSCRIPT); }
+       YY_BREAK
+case 141:
+YY_RULE_SETUP
+#line 280 "lex.l"
+{ yylval.intval = J_RAGPARA; return(T_PARATYPE); }
+       YY_BREAK
+case 142:
+YY_RULE_SETUP
+#line 281 "lex.l"
+{ yylval.intval = J_JUSTPARA; return(T_PARATYPE); }
+       YY_BREAK
+case 143:
+YY_RULE_SETUP
+#line 282 "lex.l"
+return(T_PARAGRAPH);
+       YY_BREAK
+case 144:
+YY_RULE_SETUP
+#line 283 "lex.l"
+return(T_NL); 
+       YY_BREAK
+case 145:
+YY_RULE_SETUP
+#line 285 "lex.l"
+return(T_SLASH);
+       YY_BREAK
+case 146:
+YY_RULE_SETUP
+#line 286 "lex.l"
+return(T_CUT);
+       YY_BREAK
+case 147:
+YY_RULE_SETUP
+#line 287 "lex.l"
+return(T_COMMON);
+       YY_BREAK
+case 148:
+YY_RULE_SETUP
+#line 289 "lex.l"
+{ yylval.intval = NUMSTAFF; return(T_NUMVAR); }
+       YY_BREAK
+case 149:
+YY_RULE_SETUP
+#line 290 "lex.l"
+{ yylval.intval = VSCHEME; return(T_VVAR); }
+       YY_BREAK
+case 150:
+YY_RULE_SETUP
+#line 291 "lex.l"
+{ yylval.intval = VCOMBINE; return(T_VCOMBINE); }
+       YY_BREAK
+case 151:
+YY_RULE_SETUP
+#line 292 "lex.l"
+{ yylval.intval = VC_NOOVERLAP; return(T_VCOMBVAL); }
+       YY_BREAK
+case 152:
+YY_RULE_SETUP
+#line 293 "lex.l"
+{ yylval.intval = VC_SHAREONE; return(T_VCOMBVAL); }
+       YY_BREAK
+case 153:
+YY_RULE_SETUP
+#line 294 "lex.l"
+{ yylval.intval = VC_OVERLAP; return(T_VCOMBVAL); }
+       YY_BREAK
+case 154:
+YY_RULE_SETUP
+#line 295 "lex.l"
+{ yylval.intval = DEFOCT; return(T_NUMVAR); }
+       YY_BREAK
+case 155:
+YY_RULE_SETUP
+#line 296 "lex.l"
+{ yylval.intval = LYRICSSIZE; return(T_NUMVAR); }
+       YY_BREAK
+case 156:
+YY_RULE_SETUP
+#line 297 "lex.l"
+{ yylval.intval = SYLPOSITION; return(T_NUMVAR); }
+       YY_BREAK
+case 157:
+YY_RULE_SETUP
+#line 298 "lex.l"
+{ yylval.intval = SIZE; return(T_NUMVAR); }
+       YY_BREAK
+case 158:
+YY_RULE_SETUP
+#line 299 "lex.l"
+{ yylval.intval = MINSTSEP; return(T_NUMVAR); }
+       YY_BREAK
+case 159:
+YY_RULE_SETUP
+#line 300 "lex.l"
+{ yylval.intval = MINSCPAD; return(T_SCOREPAD); }
+       YY_BREAK
+case 160:
+YY_RULE_SETUP
+#line 301 "lex.l"
+{ yylval.intval = STAFFPAD; return(T_NUMVAR); }
+       YY_BREAK
+case 161:
+YY_RULE_SETUP
+#line 302 "lex.l"
+{ yylval.intval = CHORDDIST; return(T_NUMVAR); }
+       YY_BREAK
+case 162:
+YY_RULE_SETUP
+#line 303 "lex.l"
+{ yylval.intval = DIST; return(T_NUMVAR); }
+       YY_BREAK
+case 163:
+YY_RULE_SETUP
+#line 304 "lex.l"
+{ yylval.intval = DYNDIST; return(T_NUMVAR); }
+       YY_BREAK
+case 164:
+YY_RULE_SETUP
+#line 305 "lex.l"
+{
+                       l_yyerror(Curr_filename, yylineno,
+                               "'crescdist' has been renamed 'dyndist'");
+                       yylval.intval = DYNDIST;
+                       return(T_NUMVAR);
+               }
+       YY_BREAK
+case 165:
+YY_RULE_SETUP
+#line 311 "lex.l"
+{ yylval.intval = DIVISION; return(T_NUMVAR); }
+       YY_BREAK
+case 166:
+YY_RULE_SETUP
+#line 312 "lex.l"
+{ yylval.intval = RELEASE; return(T_NUMVAR); }
+       YY_BREAK
+case 167:
+YY_RULE_SETUP
+#line 313 "lex.l"
+{ yylval.intval = PANELSPERPAGE; return(T_NUMVAR); }
+       YY_BREAK
+case 168:
+YY_RULE_SETUP
+#line 314 "lex.l"
+{ yylval.intval = GRIDFRET; return(T_NUMVAR); }
+       YY_BREAK
+case 169:
+YY_RULE_SETUP
+#line 315 "lex.l"
+{ yylval.intval = RESTCOMBINE; return(T_NUMVAR); }
+       YY_BREAK
+case 170:
+YY_RULE_SETUP
+#line 316 "lex.l"
+{ yylval.intval = FIRSTPAGE; return(T_NUMVAR); }
+       YY_BREAK
+case 171:
+YY_RULE_SETUP
+#line 317 "lex.l"
+{ yylval.intval = MINSCSEP; return(T_SCORESEP); }
+       YY_BREAK
+case 172:
+YY_RULE_SETUP
+#line 318 "lex.l"
+{ yylval.intval = STAFFLINES; return(T_STAFFLINES); }
+       YY_BREAK
+case 173:
+YY_RULE_SETUP
+#line 319 "lex.l"
+{ yylval.intval = ONTHELINE; return(T_YESNOVAR); }
+       YY_BREAK
+case 174:
+YY_RULE_SETUP
+#line 320 "lex.l"
+{ yylval.intval = WARN; return(T_YESNOVAR); }
+       YY_BREAK
+case 175:
+YY_RULE_SETUP
+#line 321 "lex.l"
+{ yylval.intval = NUMBERMRPT; return(T_YESNOVAR); }
+       YY_BREAK
+case 176:
+YY_RULE_SETUP
+#line 322 "lex.l"
+{ yylval.intval = PRINTMULTNUM; return(T_YESNOVAR); }
+       YY_BREAK
+case 177:
+YY_RULE_SETUP
+#line 323 "lex.l"
+{ yylval.intval = RESTSYMMULT; return(T_YESNOVAR); }
+       YY_BREAK
+case 178:
+YY_RULE_SETUP
+#line 324 "lex.l"
+{ yylval.intval = GRIDSWHEREUSED; return(T_YESNOVAR); }
+       YY_BREAK
+case 179:
+YY_RULE_SETUP
+#line 325 "lex.l"
+{ yylval.intval = GRIDSATEND; return(T_YESNOVAR); }
+       YY_BREAK
+case 180:
+YY_RULE_SETUP
+#line 326 "lex.l"
+return(T_TAB);
+       YY_BREAK
+case 181:
+YY_RULE_SETUP
+#line 327 "lex.l"
+{ yylval.intval = TABWHITEBOX; return(T_YESNOVAR); }
+       YY_BREAK
+case 182:
+YY_RULE_SETUP
+#line 328 "lex.l"
+{ yylval.intval = TIMEUNIT; return(T_TIMEUNIT); }
+       YY_BREAK
+case 183:
+YY_RULE_SETUP
+#line 329 "lex.l"
+{ yylval.intval = SWINGUNIT; return(T_SWINGUNIT); }
+       YY_BREAK
+case 184:
+YY_RULE_SETUP
+#line 330 "lex.l"
+{ yylval.intval = TOPMARGIN; return(T_FNUMVAR); }
+       YY_BREAK
+case 185:
+YY_RULE_SETUP
+#line 331 "lex.l"
+{ yylval.intval = BOTMARGIN; return(T_FNUMVAR); }
+       YY_BREAK
+case 186:
+YY_RULE_SETUP
+#line 332 "lex.l"
+{ yylval.intval = BOTMARGIN; return(T_FNUMVAR); }
+       YY_BREAK
+case 187:
+YY_RULE_SETUP
+#line 333 "lex.l"
+{ yylval.intval = LEFTMARGIN; return(T_FNUMVAR); }
+       YY_BREAK
+case 188:
+YY_RULE_SETUP
+#line 334 "lex.l"
+{ yylval.intval = RIGHTMARGIN; return(T_FNUMVAR); }
+       YY_BREAK
+case 189:
+YY_RULE_SETUP
+#line 335 "lex.l"
+{ yylval.intval = PACKFACT; return(T_FNUMVAR); }
+       YY_BREAK
+case 190:
+YY_RULE_SETUP
+#line 336 "lex.l"
+{ yylval.intval = PACKEXP; return(T_FNUMVAR); }
+       YY_BREAK
+case 191:
+YY_RULE_SETUP
+#line 337 "lex.l"
+{ yylval.intval = STAFFSCALE; return(T_FNUMVAR); }
+       YY_BREAK
+case 192:
+YY_RULE_SETUP
+#line 338 "lex.l"
+{ yylval.intval = GRIDSCALE; return(T_FNUMVAR); }
+       YY_BREAK
+case 193:
+YY_RULE_SETUP
+#line 339 "lex.l"
+{ yylval.intval = SCALE_FACTOR; return(T_FNUMVAR); }
+       YY_BREAK
+case 194:
+YY_RULE_SETUP
+#line 340 "lex.l"
+{ yylval.intval = STEMLEN; return(T_FNUMVAR); }
+       YY_BREAK
+case 195:
+YY_RULE_SETUP
+#line 341 "lex.l"
+{ yylval.intval = STEMSHORTEN; return(T_FNUMVAR); }
+       YY_BREAK
+case 196:
+YY_RULE_SETUP
+#line 342 "lex.l"
+{ yylval.intval = BEAMSLOPE; return(T_2FNUMVAR); }
+       YY_BREAK
+case 197:
+YY_RULE_SETUP
+#line 343 "lex.l"
+{ yylval.intval = TRANSPOSITION; return(T_TRANSPOSE); }
+       YY_BREAK
+case 198:
+YY_RULE_SETUP
+#line 344 "lex.l"
+{ yylval.intval = ADDTRANSPOSITION; return(T_TRANSPOSE); }
+       YY_BREAK
+case 199:
+YY_RULE_SETUP
+#line 345 "lex.l"
+{ yylval.intval = LYRICSALIGN; return(T_FNUMVAR); }
+       YY_BREAK
+case 200:
+YY_RULE_SETUP
+#line 346 "lex.l"
+{ yylval.intval = PAGEHEIGHT; return(T_FNUMVAR); }
+       YY_BREAK
+case 201:
+YY_RULE_SETUP
+#line 347 "lex.l"
+{ yylval.intval = PAGEWIDTH; return(T_FNUMVAR); }
+       YY_BREAK
+case 202:
+YY_RULE_SETUP
+#line 348 "lex.l"
+{ return(T_PSVAR); }
+       YY_BREAK
+case 203:
+YY_RULE_SETUP
+#line 349 "lex.l"
+{ yylval.intval = PS_LETTER; return(T_PAGESIZE); }
+       YY_BREAK
+case 204:
+YY_RULE_SETUP
+#line 350 "lex.l"
+{ yylval.intval = PS_LEGAL; return(T_PAGESIZE); }
+       YY_BREAK
+case 205:
+YY_RULE_SETUP
+#line 351 "lex.l"
+{ yylval.intval = PS_FLSA; return(T_PAGESIZE); }
+       YY_BREAK
+case 206:
+YY_RULE_SETUP
+#line 352 "lex.l"
+{ yylval.intval = PS_HALFLETTER; return(T_PAGESIZE); }
+       YY_BREAK
+case 207:
+YY_RULE_SETUP
+#line 353 "lex.l"
+{ yylval.intval = O_PORTRAIT; return(T_ORIENTATION); }
+       YY_BREAK
+case 208:
+YY_RULE_SETUP
+#line 354 "lex.l"
+{ yylval.intval = O_LANDSCAPE; return(T_ORIENTATION); }
+       YY_BREAK
+case 209:
+YY_RULE_SETUP
+#line 355 "lex.l"
+{ yylval.intval = UNITS; return(T_UNITS); }
+       YY_BREAK
+case 210:
+YY_RULE_SETUP
+#line 356 "lex.l"
+{ yylval.intval = CM; return(T_UNITTYPE); }
+       YY_BREAK
+case 211:
+YY_RULE_SETUP
+#line 357 "lex.l"
+{ yylval.intval = INCHES; return(T_UNITTYPE); }
+       YY_BREAK
+case 212:
+YY_RULE_SETUP
+#line 359 "lex.l"
+{ yylval.intval = ENDINGSTYLE; return(T_ENDSTYLE); }
+       YY_BREAK
+case 213:
+YY_RULE_SETUP
+#line 360 "lex.l"
+{ yylval.intval = REHSTYLE; return(T_REH_STYLE); }
+       YY_BREAK
+case 214:
+YY_RULE_SETUP
+#line 361 "lex.l"
+{ yylval.intval = RS_BOXED; return(T_REHTYPE); }
+       YY_BREAK
+case 215:
+YY_RULE_SETUP
+#line 362 "lex.l"
+{ yylval.intval = RS_CIRCLED; return(T_REHTYPE); }
+       YY_BREAK
+case 216:
+YY_RULE_SETUP
+#line 363 "lex.l"
+{ yylval.intval = RS_PLAIN; return(T_REHTYPE); }
+       YY_BREAK
+case 217:
+YY_RULE_SETUP
+#line 364 "lex.l"
+{ yylval.intval = PEDSTYLE; return(T_PEDSTYLE); }
+       YY_BREAK
+case 218:
+YY_RULE_SETUP
+#line 365 "lex.l"
+return(T_PEDSTAR);
+       YY_BREAK
+case 219:
+YY_RULE_SETUP
+#line 366 "lex.l"
+{ yylval.intval = ENDING_BARRED; return(T_ENDTYPE); }
+       YY_BREAK
+case 220:
+YY_RULE_SETUP
+#line 367 "lex.l"
+{ yylval.intval = ENDING_GROUPED; return(T_ENDTYPE); }
+       YY_BREAK
+case 221:
+YY_RULE_SETUP
+#line 369 "lex.l"
+{ yylval.intval = BRACELIST; return(T_RANGELISTVAR); }
+       YY_BREAK
+case 222:
+YY_RULE_SETUP
+#line 370 "lex.l"
+{ yylval.intval = BRACKLIST; return(T_RANGELISTVAR); }
+       YY_BREAK
+case 223:
+YY_RULE_SETUP
+#line 371 "lex.l"
+{ yylval.intval = BARSTLIST; return(T_BARSTLISTVAR); }
+       YY_BREAK
+case 224:
+YY_RULE_SETUP
+#line 372 "lex.l"
+{ yylval.intval = PL_ABOVE; return(T_ORDER); }
+       YY_BREAK
+case 225:
+YY_RULE_SETUP
+#line 373 "lex.l"
+{ yylval.intval = PL_BELOW; return(T_ORDER); }
+       YY_BREAK
+case 226:
+YY_RULE_SETUP
+#line 374 "lex.l"
+{ yylval.intval = PL_BETWEEN; return(T_ORDER); }
+       YY_BREAK
+case 227:
+YY_RULE_SETUP
+#line 375 "lex.l"
+return(T_OTHERTEXT);
+       YY_BREAK
+case 228:
+YY_RULE_SETUP
+#line 376 "lex.l"
+{ yylval.intval = SHARPS; return(T_KEY); }
+       YY_BREAK
+case 229:
+YY_RULE_SETUP
+#line 377 "lex.l"
+{ yylval.intval = TIME; return(T_TIME); }
+       YY_BREAK
+case 230:
+YY_RULE_SETUP
+#line 378 "lex.l"
+{ yylval.intval = BEAMSTLIST; return(T_RATNUMLISTVAR); }
+       YY_BREAK
+case 231:
+YY_RULE_SETUP
+#line 379 "lex.l"
+{ yylval.intval = VISIBLE; return(T_VISVAR); }
+       YY_BREAK
+case 232:
+YY_RULE_SETUP
+#line 380 "lex.l"
+{ return(T_WHEREUSED); }
+       YY_BREAK
+case 233:
+YY_RULE_SETUP
+#line 381 "lex.l"
+{ yylval.intval = MEASNUM; return(T_YESNOVAR); }
+       YY_BREAK
+case 234:
+YY_RULE_SETUP
+#line 382 "lex.l"
+{ yylval.intval = CANCELKEY; return(T_YESNOVAR); }
+       YY_BREAK
+case 235:
+YY_RULE_SETUP
+#line 383 "lex.l"
+{ yylval.intval = LABEL; return(T_STRVAR); }
+       YY_BREAK
+case 236:
+YY_RULE_SETUP
+#line 384 "lex.l"
+{ yylval.intval = LABEL2; return(T_STRVAR); }
+       YY_BREAK
+case 237:
+YY_RULE_SETUP
+#line 385 "lex.l"
+{ yylval.intval = NOTEHEADS; return(T_STRVAR); }
+       YY_BREAK
+case 238:
+YY_RULE_SETUP
+#line 386 "lex.l"
+{ yylval.intval = FONT; return(T_FONTVAR); }
+       YY_BREAK
+case 239:
+YY_RULE_SETUP
+#line 387 "lex.l"
+{ yylval.intval = FONTFAMILY; return(T_FAMILY); }
+       YY_BREAK
+case 240:
+YY_RULE_SETUP
+#line 388 "lex.l"
+{ yylval.intval = LYRICSFONT; return(T_FONTVAR); }
+       YY_BREAK
+case 241:
+YY_RULE_SETUP
+#line 389 "lex.l"
+{ yylval.intval = LYRICSFAMILY; return(T_FAMILY); }
+       YY_BREAK
+case 242:
+YY_RULE_SETUP
+#line 390 "lex.l"
+{ yylval.intval = MEASNUMSIZE; return(T_NUMVAR); }
+       YY_BREAK
+case 243:
+YY_RULE_SETUP
+#line 391 "lex.l"
+{ yylval.intval = MEASNUMFONT; return(T_FONTVAR); }
+       YY_BREAK
+case 244:
+YY_RULE_SETUP
+#line 392 "lex.l"
+{ yylval.intval = MEASNUMFAMILY; return(T_FAMILY); }
+       YY_BREAK
+case 245:
+YY_RULE_SETUP
+#line 393 "lex.l"
+{ yylval.intval = CLEF; return(T_CLEFVAR); }
+       YY_BREAK
+case 246:
+YY_RULE_SETUP
+#line 394 "lex.l"
+{ return(T_UNSET); }
+       YY_BREAK
+case 247:
+YY_RULE_SETUP
+#line 396 "lex.l"
+{ yylval.intval = TREBLE_8A; return(T_CLEF); }
+       YY_BREAK
+case 248:
+YY_RULE_SETUP
+#line 397 "lex.l"
+{ yylval.intval = TREBLE; return(T_CLEF); }
+       YY_BREAK
+case 249:
+YY_RULE_SETUP
+#line 398 "lex.l"
+{ yylval.intval = TREBLE_8; return(T_CLEF); }
+       YY_BREAK
+case 250:
+YY_RULE_SETUP
+#line 399 "lex.l"
+{ yylval.intval = FRENCHVIOLIN; return(T_CLEF); }
+       YY_BREAK
+case 251:
+YY_RULE_SETUP
+#line 400 "lex.l"
+{ yylval.intval = SOPRANO; return(T_CLEF); }
+       YY_BREAK
+case 252:
+YY_RULE_SETUP
+#line 401 "lex.l"
+{ yylval.intval = MEZZOSOPRANO; return(T_CLEF); }
+       YY_BREAK
+case 253:
+YY_RULE_SETUP
+#line 402 "lex.l"
+{ yylval.intval = ALTO; return(T_CLEF); }
+       YY_BREAK
+case 254:
+YY_RULE_SETUP
+#line 403 "lex.l"
+{ yylval.intval = TENOR; return(T_CLEF); }
+       YY_BREAK
+case 255:
+YY_RULE_SETUP
+#line 404 "lex.l"
+{ yylval.intval = BARITONE; return(T_CLEF); }
+       YY_BREAK
+case 256:
+YY_RULE_SETUP
+#line 405 "lex.l"
+{ yylval.intval = BASS; return(T_CLEF); }
+       YY_BREAK
+case 257:
+YY_RULE_SETUP
+#line 406 "lex.l"
+{ return(T_DRUM); }
+       YY_BREAK
+case 258:
+YY_RULE_SETUP
+#line 408 "lex.l"
+return(T_R_ANGLE);
+       YY_BREAK
+case 259:
+YY_RULE_SETUP
+#line 409 "lex.l"
+{ yylval.intval = L_NORMAL; return(T_L_ANGLE); }
+       YY_BREAK
+case 260:
+YY_RULE_SETUP
+#line 410 "lex.l"
+{ return(T_L_DBLANGLE); }
+       YY_BREAK
+case 261:
+YY_RULE_SETUP
+#line 411 "lex.l"
+{ return(T_R_DBLANGLE); }
+       YY_BREAK
+case 262:
+YY_RULE_SETUP
+#line 412 "lex.l"
+{ yylval.intval = L_DOTTED; return(T_L_ANGLE); }
+       YY_BREAK
+case 263:
+YY_RULE_SETUP
+#line 413 "lex.l"
+{ yylval.intval = L_DASHED; return(T_L_ANGLE); }
+       YY_BREAK
+case 264:
+YY_RULE_SETUP
+#line 414 "lex.l"
+{ yylval.intval = IN_DOWNWARD; return(T_NOWHERE_SLIDE); }
+       YY_BREAK
+case 265:
+YY_RULE_SETUP
+#line 415 "lex.l"
+{ yylval.intval = IN_UPWARD; return(T_NOWHERE_SLIDE); }
+       YY_BREAK
+case 266:
+YY_RULE_SETUP
+#line 416 "lex.l"
+{ yylval.intval = OUT_UPWARD; return(T_NOWHERE_SLIDE); }
+       YY_BREAK
+case 267:
+YY_RULE_SETUP
+#line 417 "lex.l"
+{ yylval.intval = OUT_DOWNWARD; return(T_NOWHERE_SLIDE); }
+       YY_BREAK
+case 268:
+YY_RULE_SETUP
+#line 419 "lex.l"
+return(T_PEDAL);
+       YY_BREAK
+case 269:
+YY_RULE_SETUP
+#line 420 "lex.l"
+return(T_MUSSYM);
+       YY_BREAK
+case 270:
+YY_RULE_SETUP
+#line 421 "lex.l"
+{ yylval.intval = TM_CHORD; return(T_MODIFIER); }
+       YY_BREAK
+case 271:
+YY_RULE_SETUP
+#line 422 "lex.l"
+{ yylval.intval = TM_ANALYSIS; return(T_MODIFIER); }
+       YY_BREAK
+case 272:
+YY_RULE_SETUP
+#line 423 "lex.l"
+{ yylval.intval = TM_FIGBASS; return(T_MODIFIER); }
+       YY_BREAK
+case 273:
+YY_RULE_SETUP
+#line 424 "lex.l"
+{ yylval.intval = TM_DYN; return(T_MODIFIER); }
+       YY_BREAK
+case 274:
+YY_RULE_SETUP
+#line 425 "lex.l"
+return(T_PHRASE);
+       YY_BREAK
+case 275:
+YY_RULE_SETUP
+#line 426 "lex.l"
+return(T_TIL);
+       YY_BREAK
+case 276:
+YY_RULE_SETUP
+#line 427 "lex.l"
+return(T_OCTAVE);
+       YY_BREAK
+case 277:
+YY_RULE_SETUP
+#line 428 "lex.l"
+return(T_ROLL);
+       YY_BREAK
+case 278:
+YY_RULE_SETUP
+#line 429 "lex.l"
+return(T_MIDI);
+       YY_BREAK
+case 279:
+YY_RULE_SETUP
+#line 431 "lex.l"
+return(T_STAR);
+       YY_BREAK
+case 280:
+YY_RULE_SETUP
+#line 433 "lex.l"
+to_eol();
+       YY_BREAK
+case 281:
+YY_RULE_SETUP
+#line 435 "lex.l"
+{
+                               If_length = 0;
+                               If_errs = 0;
+                               BEGIN IF_CLAUSE;
+                       }
+       YY_BREAK
+case 282:
+YY_RULE_SETUP
+#line 440 "lex.l"
+{
+                               /* End of 'if' clause'. Set back to the
+                                * normal lexer. Call the mini-paser on
+                                * the compressed form of the clause we
+                                * have just gotten
+                                */
+                               BEGIN 0;
+                               set_ifclause_buffer(Ifclause_buff, If_length);
+                               if (ifparse() == YES) {
+                                       If_count++;
+                               }
+                               else {
+                                       /* skip ifdef-ed part */
+                                       if (skip2else() == YES) {
+                                               /* found an else */
+                                               If_count++;
+                                       }
+                                       /* if found an endif instead,
+                                        * we just continue */
+                               }
+                       }
+       YY_BREAK
+case 283:
+YY_RULE_SETUP
+#line 461 "lex.l"
+{ add_ifclause('a'); }
+       YY_BREAK
+case 284:
+YY_RULE_SETUP
+#line 462 "lex.l"
+{ add_ifclause('o'); }
+       YY_BREAK
+case 285:
+YY_RULE_SETUP
+#line 463 "lex.l"
+{ add_ifclause(yytext[0]); }
+       YY_BREAK
+case 286:
+YY_RULE_SETUP
+#line 464 "lex.l"
+{ add_ifclause('l'); }
+       YY_BREAK
+case 287:
+YY_RULE_SETUP
+#line 465 "lex.l"
+{ add_ifclause('r'); }
+       YY_BREAK
+case 288:
+YY_RULE_SETUP
+#line 466 "lex.l"
+{ add_ifclause('L'); }
+       YY_BREAK
+case 289:
+YY_RULE_SETUP
+#line 467 "lex.l"
+{ add_ifclause('G'); }
+       YY_BREAK
+case 290:
+YY_RULE_SETUP
+#line 468 "lex.l"
+{ add_ifclause('E'); }
+       YY_BREAK
+case 291:
+YY_RULE_SETUP
+#line 469 "lex.l"
+{ add_ifclause('N'); }
+       YY_BREAK
+case 292:
+#line 471 "lex.l"
+case 293:
+YY_RULE_SETUP
+#line 471 "lex.l"
+{ addnumstr_ifclause(yytext); }
+       YY_BREAK
+case 294:
+YY_RULE_SETUP
+#line 472 "lex.l"
+{
+                               char * macname;
+                               int parens;
+                               int m;
+
+                               for (parens = m = 0; m < yyleng; m++) {
+                                       if (yytext[m] == '(') {
+                                               parens++;
+                                       } else if (yytext[m] == ')') {
+                                               parens--;
+                                       }
+                               }
+                               if (parens != 0) {
+                                       yyerror("unmatched parentheses around target of 'defined'");
+                               }
+                               macname = yytext + 7 + strspn(yytext + 7, "( \t\n");
+                               strtok(macname, " \t\n)");
+                               add_ifclause(is_defined(macname, YES) ? 'T' : 'F');
+                       }
+       YY_BREAK
+case 295:
+YY_RULE_SETUP
+#line 492 "lex.l"
+{
+                                       if (is_defined(yytext, YES) != 0) {
+                                               call_macro(yytext);
+                                       }
+                                       else {
+                                               addnumstr_ifclause("0");
+                                       }
+                               }
+       YY_BREAK
+case 296:
+YY_RULE_SETUP
+#line 500 "lex.l"
+;
+       YY_BREAK
+case 297:
+YY_RULE_SETUP
+#line 501 "lex.l"
+{
+                               yyerror("Missing 'then' for 'if' clause");
+                               BEGIN 0;
+                       }
+       YY_BREAK
+case 298:
+YY_RULE_SETUP
+#line 505 "lex.l"
+{
+                               bad_input("'if' clause");
+                               /* User forgetting or misspelling 'then' can
+                                * quickly cause hundreds of errors,
+                                * so bail out if we suspect that.
+                                * The actual number of errors to bail out on
+                                * is arbitrary. */
+                               if (++If_errs > 20) {
+                                       ufatal("Too many errors in 'if' clause. Maybe missing 'then'?");
+                               }
+                       }
+       YY_BREAK
+case 299:
+YY_RULE_SETUP
+#line 517 "lex.l"
+define_macro(yytext + 7);
+       YY_BREAK
+case 300:
+YY_RULE_SETUP
+#line 519 "lex.l"
+undef_macro(yytext + 6);
+       YY_BREAK
+case 301:
+YY_RULE_SETUP
+#line 521 "lex.l"
+{
+                                       int result;
+
+                                       /* do ifdef or ifndef as appropriate */
+                                       if (yytext[2] == 'n') {
+                                               result = ! is_defined(yytext + 7
+                                                       + strspn(yytext + 7, " \t"), NO);
+                                       }
+                                       else {
+                                               result = is_defined(yytext + 6
+                                                       + strspn(yytext + 6, " \t"), NO);
+                                       }
+
+                                       if (result) {
+                                               /* do stuff till else or endif */
+                                               If_count++;
+                                       }
+                                       else {
+                                               /* skip ifdef-ed part */
+                                               if (skip2else() == YES) {
+                                                       /* found an else */
+                                                       If_count++;
+                                               }
+                                               /* if found an endif instead,
+                                                * we just continue */
+                                       }
+                               }
+       YY_BREAK
+case 302:
+YY_RULE_SETUP
+#line 549 "lex.l"
+{
+                                       if (If_count < 1) {
+                                               yyerror("else without ifdef");
+                                       }
+                                       else {
+                                               If_count--;
+                                               if (skip2else() == YES) {
+                                                       yyerror("else without ifdef");
+                                               }
+                                       }
+                               }
+       YY_BREAK
+case 303:
+YY_RULE_SETUP
+#line 561 "lex.l"
+{
+                                       if (If_count < 1) {
+                                               yyerror("endif without ifdef");
+                                       }
+                                       else {
+                                               If_count--;
+                                       }
+                               }
+       YY_BREAK
+case 304:
+YY_RULE_SETUP
+#line 570 "lex.l"
+call_macro(yytext);
+       YY_BREAK
+case 305:
+YY_RULE_SETUP
+#line 571 "lex.l"
+{
+                               if (isspace(yytext[1]) ||
+                                               isspace(yytext[yyleng-2])) {
+                                       yyerror("spaces not allowed inside ` ` marks");
+                               }
+                               else {
+                                       /* We only need the leading ` to tell
+                                        * it is a quoted macro parm,
+                                        * and it's easier to deal with later
+                                        * if there is no trailing `
+                                        * so strip off the trailing. */
+                                       yytext[yyleng - 1] = '\0';
+                                       call_macro(yytext);
+                               }
+                       }
+       YY_BREAK
+case 306:
+YY_RULE_SETUP
+#line 587 "lex.l"
+{ yylval.intval = strlen(yytext); return(T_TICKS); }
+       YY_BREAK
+case 307:
+YY_RULE_SETUP
+#line 589 "lex.l"
+{
+                       /* ignore backslashed newlines;
+                        * allow white space after backslash */
+                       ignore();
+               }
+       YY_BREAK
+case 308:
+YY_RULE_SETUP
+#line 595 "lex.l"
+{
+                               /* in case we get control-Z from DOS */
+                               ignore();
+                       }
+       YY_BREAK
+case 309:
+YY_RULE_SETUP
+#line 600 "lex.l"
+{
+                               /* ignore extra white space */
+                               ignore();
+                       }
+       YY_BREAK
+case 310:
+YY_RULE_SETUP
+#line 604 "lex.l"
+{
+                       bad_input("input");
+               }
+       YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(IF_CLAUSE):
+case YY_STATE_EOF(STRING):
+#line 608 "lex.l"
+{
+                       /* In case user used an editor or other tool to
+                        * create the input file which may leave the final
+                        * line without a newline, add a newline to the
+                        * input. If there was already a newline, an extra
+                        * one should never hurt. Adding it can prevent
+                        * cryptic message about error at token '' */
+                       if (Eof_newline == 0) {
+                               Eof_newline = yy_scan_string("\n");
+                       }
+                       else {
+                               yy_delete_buffer(Eof_newline);
+                               return(0);
+                       }
+               }
+       YY_BREAK
+case 311:
+YY_RULE_SETUP
+#line 625 "lex.l"
+ECHO;
+       YY_BREAK
+
+       case YY_END_OF_BUFFER:
+               {
+               /* Amount of text matched not including the EOB char. */
+               int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+               /* Undo the effects of YY_DO_BEFORE_ACTION. */
+               *yy_cp = yy_hold_char;
+               YY_RESTORE_YY_MORE_OFFSET
+
+               if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+                       {
+                       /* We're scanning a new file or input source.  It's
+                        * possible that this happened because the user
+                        * just pointed yyin at a new source and called
+                        * yylex().  If so, then we have to assure
+                        * consistency between yy_current_buffer and our
+                        * globals.  Here is the right place to do so, because
+                        * this is the first action (other than possibly a
+                        * back-up) that will match for the new input source.
+                        */
+                       yy_n_chars = yy_current_buffer->yy_n_chars;
+                       yy_current_buffer->yy_input_file = yyin;
+                       yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+                       }
+
+               /* Note that here we test for yy_c_buf_p "<=" to the position
+                * of the first EOB in the buffer, since yy_c_buf_p will
+                * already have been incremented past the NUL character
+                * (since all states make transitions on EOB to the
+                * end-of-buffer state).  Contrast this with the test
+                * in input().
+                */
+               if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+                       { /* This was really a NUL. */
+                       yy_state_type yy_next_state;
+
+                       yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+                       yy_current_state = yy_get_previous_state();
+
+                       /* Okay, we're now positioned to make the NUL
+                        * transition.  We couldn't have
+                        * yy_get_previous_state() go ahead and do it
+                        * for us because it doesn't know how to deal
+                        * with the possibility of jamming (and we don't
+                        * want to build jamming into it because then it
+                        * will run more slowly).
+                        */
+
+                       yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+                       yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+                       if ( yy_next_state )
+                               {
+                               /* Consume the NUL. */
+                               yy_cp = ++yy_c_buf_p;
+                               yy_current_state = yy_next_state;
+                               goto yy_match;
+                               }
+
+                       else
+                               {
+                               yy_cp = yy_c_buf_p;
+                               goto yy_find_action;
+                               }
+                       }
+
+               else switch ( yy_get_next_buffer() )
+                       {
+                       case EOB_ACT_END_OF_FILE:
+                               {
+                               yy_did_buffer_switch_on_eof = 0;
+
+                               if ( yywrap() )
+                                       {
+                                       /* Note: because we've taken care in
+                                        * yy_get_next_buffer() to have set up
+                                        * yytext, we can now set up
+                                        * yy_c_buf_p so that if some total
+                                        * hoser (like flex itself) wants to
+                                        * call the scanner after we return the
+                                        * YY_NULL, it'll still work - another
+                                        * YY_NULL will get returned.
+                                        */
+                                       yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+                                       yy_act = YY_STATE_EOF(YY_START);
+                                       goto do_action;
+                                       }
+
+                               else
+                                       {
+                                       if ( ! yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+                                       }
+                               break;
+                               }
+
+                       case EOB_ACT_CONTINUE_SCAN:
+                               yy_c_buf_p =
+                                       yytext_ptr + yy_amount_of_matched_text;
+
+                               yy_current_state = yy_get_previous_state();
+
+                               yy_cp = yy_c_buf_p;
+                               yy_bp = yytext_ptr + YY_MORE_ADJ;
+                               goto yy_match;
+
+                       case EOB_ACT_LAST_MATCH:
+                               yy_c_buf_p =
+                               &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+                               yy_current_state = yy_get_previous_state();
+
+                               yy_cp = yy_c_buf_p;
+                               yy_bp = yytext_ptr + YY_MORE_ADJ;
+                               goto yy_find_action;
+                       }
+               break;
+               }
+
+       default:
+               YY_FATAL_ERROR(
+                       "fatal flex scanner internal error--no action found" );
+       } /* end of action switch */
+               } /* end of scanning one token */
+       } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *     EOB_ACT_LAST_MATCH -
+ *     EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *     EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+       {
+       register char *dest = yy_current_buffer->yy_ch_buf;
+       register char *source = yytext_ptr;
+       register int number_to_move, i;
+       int ret_val;
+
+       if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+               YY_FATAL_ERROR(
+               "fatal flex scanner internal error--end of buffer missed" );
+
+       if ( yy_current_buffer->yy_fill_buffer == 0 )
+               { /* Don't try to fill the buffer, so this is an EOF. */
+               if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+                       {
+                       /* We matched a single character, the EOB, so
+                        * treat this as a final EOF.
+                        */
+                       return EOB_ACT_END_OF_FILE;
+                       }
+
+               else
+                       {
+                       /* We matched some text prior to the EOB, first
+                        * process it.
+                        */
+                       return EOB_ACT_LAST_MATCH;
+                       }
+               }
+
+       /* Try to read more data. */
+
+       /* First move last chars to start of buffer. */
+       number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+       for ( i = 0; i < number_to_move; ++i )
+               *(dest++) = *(source++);
+
+       if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+               /* don't do the read, it's not guaranteed to return an EOF,
+                * just force an EOF
+                */
+               yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+       else
+               {
+               int num_to_read =
+                       yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+               while ( num_to_read <= 0 )
+                       { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+                       YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+                       /* just a shorter name for the current buffer */
+                       YY_BUFFER_STATE b = yy_current_buffer;
+
+                       int yy_c_buf_p_offset =
+                               (int) (yy_c_buf_p - b->yy_ch_buf);
+
+                       if ( b->yy_is_our_buffer )
+                               {
+                               int new_size = b->yy_buf_size * 2;
+
+                               if ( new_size <= 0 )
+                                       b->yy_buf_size += b->yy_buf_size / 8;
+                               else
+                                       b->yy_buf_size *= 2;
+
+                               b->yy_ch_buf = (char *)
+                                       /* Include room in for 2 EOB chars. */
+                                       yy_flex_realloc( (void *) b->yy_ch_buf,
+                                                        b->yy_buf_size + 2 );
+                               }
+                       else
+                               /* Can't grow it, we don't own it. */
+                               b->yy_ch_buf = 0;
+
+                       if ( ! b->yy_ch_buf )
+                               YY_FATAL_ERROR(
+                               "fatal error - scanner input buffer overflow" );
+
+                       yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+                       num_to_read = yy_current_buffer->yy_buf_size -
+                                               number_to_move - 1;
+#endif
+                       }
+
+               if ( num_to_read > YY_READ_BUF_SIZE )
+                       num_to_read = YY_READ_BUF_SIZE;
+
+               /* Read in more data. */
+               YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+                       yy_n_chars, num_to_read );
+
+               yy_current_buffer->yy_n_chars = yy_n_chars;
+               }
+
+       if ( yy_n_chars == 0 )
+               {
+               if ( number_to_move == YY_MORE_ADJ )
+                       {
+                       ret_val = EOB_ACT_END_OF_FILE;
+                       yyrestart( yyin );
+                       }
+
+               else
+                       {
+                       ret_val = EOB_ACT_LAST_MATCH;
+                       yy_current_buffer->yy_buffer_status =
+                               YY_BUFFER_EOF_PENDING;
+                       }
+               }
+
+       else
+               ret_val = EOB_ACT_CONTINUE_SCAN;
+
+       yy_n_chars += number_to_move;
+       yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+       yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+       yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+       return ret_val;
+       }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+       {
+       register yy_state_type yy_current_state;
+       register char *yy_cp;
+
+       yy_current_state = yy_start;
+
+       for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+               {
+               register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+               if ( yy_accept[yy_current_state] )
+                       {
+                       yy_last_accepting_state = yy_current_state;
+                       yy_last_accepting_cpos = yy_cp;
+                       }
+               while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                       {
+                       yy_current_state = (int) yy_def[yy_current_state];
+                       if ( yy_current_state >= 1176 )
+                               yy_c = yy_meta[(unsigned int) yy_c];
+                       }
+               yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+               }
+
+       return yy_current_state;
+       }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *     next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+       {
+       register int yy_is_jam;
+       register char *yy_cp = yy_c_buf_p;
+
+       register YY_CHAR yy_c = 1;
+       if ( yy_accept[yy_current_state] )
+               {
+               yy_last_accepting_state = yy_current_state;
+               yy_last_accepting_cpos = yy_cp;
+               }
+       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+               {
+               yy_current_state = (int) yy_def[yy_current_state];
+               if ( yy_current_state >= 1176 )
+                       yy_c = yy_meta[(unsigned int) yy_c];
+               }
+       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+       yy_is_jam = (yy_current_state == 1175);
+
+       return yy_is_jam ? 0 : yy_current_state;
+       }
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+       {
+       register char *yy_cp = yy_c_buf_p;
+
+       /* undo effects of setting up yytext */
+       *yy_cp = yy_hold_char;
+
+       if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+               { /* need to shift things up to make room */
+               /* +2 for EOB chars. */
+               register int number_to_move = yy_n_chars + 2;
+               register char *dest = &yy_current_buffer->yy_ch_buf[
+                                       yy_current_buffer->yy_buf_size + 2];
+               register char *source =
+                               &yy_current_buffer->yy_ch_buf[number_to_move];
+
+               while ( source > yy_current_buffer->yy_ch_buf )
+                       *--dest = *--source;
+
+               yy_cp += (int) (dest - source);
+               yy_bp += (int) (dest - source);
+               yy_current_buffer->yy_n_chars =
+                       yy_n_chars = yy_current_buffer->yy_buf_size;
+
+               if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+                       YY_FATAL_ERROR( "flex scanner push-back overflow" );
+               }
+
+       *--yy_cp = (char) c;
+
+
+       yytext_ptr = yy_bp;
+       yy_hold_char = *yy_cp;
+       yy_c_buf_p = yy_cp;
+       }
+#endif /* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+       {
+       int c;
+
+       *yy_c_buf_p = yy_hold_char;
+
+       if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+               {
+               /* yy_c_buf_p now points to the character we want to return.
+                * If this occurs *before* the EOB characters, then it's a
+                * valid NUL; if not, then we've hit the end of the buffer.
+                */
+               if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+                       /* This was really a NUL. */
+                       *yy_c_buf_p = '\0';
+
+               else
+                       { /* need more input */
+                       int offset = yy_c_buf_p - yytext_ptr;
+                       ++yy_c_buf_p;
+
+                       switch ( yy_get_next_buffer() )
+                               {
+                               case EOB_ACT_LAST_MATCH:
+                                       /* This happens because yy_g_n_b()
+                                        * sees that we've accumulated a
+                                        * token and flags that we need to
+                                        * try matching the token before
+                                        * proceeding.  But for input(),
+                                        * there's no matching to consider.
+                                        * So convert the EOB_ACT_LAST_MATCH
+                                        * to EOB_ACT_END_OF_FILE.
+                                        */
+
+                                       /* Reset buffer status. */
+                                       yyrestart( yyin );
+
+                                       /* fall through */
+
+                               case EOB_ACT_END_OF_FILE:
+                                       {
+                                       if ( yywrap() )
+                                               return EOF;
+
+                                       if ( ! yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+#ifdef __cplusplus
+                                       return yyinput();
+#else
+                                       return input();
+#endif
+                                       }
+
+                               case EOB_ACT_CONTINUE_SCAN:
+                                       yy_c_buf_p = yytext_ptr + offset;
+                                       break;
+                               }
+                       }
+               }
+
+       c = *(unsigned char *) yy_c_buf_p;      /* cast for 8-bit char's */
+       *yy_c_buf_p = '\0';     /* preserve yytext */
+       yy_hold_char = *++yy_c_buf_p;
+
+
+       return c;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+       {
+       if ( ! yy_current_buffer )
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+       yy_init_buffer( yy_current_buffer, input_file );
+       yy_load_buffer_state();
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+       {
+       if ( yy_current_buffer == new_buffer )
+               return;
+
+       if ( yy_current_buffer )
+               {
+               /* Flush out information for old buffer. */
+               *yy_c_buf_p = yy_hold_char;
+               yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+               yy_current_buffer->yy_n_chars = yy_n_chars;
+               }
+
+       yy_current_buffer = new_buffer;
+       yy_load_buffer_state();
+
+       /* We don't actually know whether we did this switch during
+        * EOF (yywrap()) processing, but the only time this flag
+        * is looked at is after yywrap() is called, so it's safe
+        * to go ahead and always set it.
+        */
+       yy_did_buffer_switch_on_eof = 1;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+       {
+       yy_n_chars = yy_current_buffer->yy_n_chars;
+       yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+       yyin = yy_current_buffer->yy_input_file;
+       yy_hold_char = *yy_c_buf_p;
+       }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+       {
+       YY_BUFFER_STATE b;
+
+       b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+       b->yy_buf_size = size;
+
+       /* yy_ch_buf has to be 2 characters longer than the size given because
+        * we need to put in 2 end-of-buffer characters.
+        */
+       b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+       if ( ! b->yy_ch_buf )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+       b->yy_is_our_buffer = 1;
+
+       yy_init_buffer( b, file );
+
+       return b;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+       {
+       if ( ! b )
+               return;
+
+       if ( b == yy_current_buffer )
+               yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+       if ( b->yy_is_our_buffer )
+               yy_flex_free( (void *) b->yy_ch_buf );
+
+       yy_flex_free( (void *) b );
+       }
+
+
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+       {
+       yy_flush_buffer( b );
+
+       b->yy_input_file = file;
+       b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+       b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+       b->yy_is_interactive = 0;
+#else
+       b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+       {
+       if ( ! b )
+               return;
+
+       b->yy_n_chars = 0;
+
+       /* We always need two end-of-buffer characters.  The first causes
+        * a transition to the end-of-buffer state.  The second causes
+        * a jam in that state.
+        */
+       b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+       b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+       b->yy_buf_pos = &b->yy_ch_buf[0];
+
+       b->yy_at_bol = 1;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       if ( b == yy_current_buffer )
+               yy_load_buffer_state();
+       }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+       {
+       YY_BUFFER_STATE b;
+
+       if ( size < 2 ||
+            base[size-2] != YY_END_OF_BUFFER_CHAR ||
+            base[size-1] != YY_END_OF_BUFFER_CHAR )
+               /* They forgot to leave room for the EOB's. */
+               return 0;
+
+       b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+       b->yy_buf_size = size - 2;      /* "- 2" to take care of EOB's */
+       b->yy_buf_pos = b->yy_ch_buf = base;
+       b->yy_is_our_buffer = 0;
+       b->yy_input_file = 0;
+       b->yy_n_chars = b->yy_buf_size;
+       b->yy_is_interactive = 0;
+       b->yy_at_bol = 1;
+       b->yy_fill_buffer = 0;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       yy_switch_to_buffer( b );
+
+       return b;
+       }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+       {
+       int len;
+       for ( len = 0; yy_str[len]; ++len )
+               ;
+
+       return yy_scan_bytes( yy_str, len );
+       }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+       {
+       YY_BUFFER_STATE b;
+       char *buf;
+       yy_size_t n;
+       int i;
+
+       /* Get memory for full buffer, including space for trailing EOB's. */
+       n = len + 2;
+       buf = (char *) yy_flex_alloc( n );
+       if ( ! buf )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+       for ( i = 0; i < len; ++i )
+               buf[i] = bytes[i];
+
+       buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+       b = yy_scan_buffer( buf, n );
+       if ( ! b )
+               YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+       /* It's okay to grow etc. this buffer, and we should throw it
+        * away when we're done.
+        */
+       b->yy_is_our_buffer = 1;
+
+       return b;
+       }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+       {
+       if ( yy_start_stack_ptr >= yy_start_stack_depth )
+               {
+               yy_size_t new_size;
+
+               yy_start_stack_depth += YY_START_STACK_INCR;
+               new_size = yy_start_stack_depth * sizeof( int );
+
+               if ( ! yy_start_stack )
+                       yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+               else
+                       yy_start_stack = (int *) yy_flex_realloc(
+                                       (void *) yy_start_stack, new_size );
+
+               if ( ! yy_start_stack )
+                       YY_FATAL_ERROR(
+                       "out of memory expanding start-condition stack" );
+               }
+
+       yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+       BEGIN(new_state);
+       }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+       {
+       if ( --yy_start_stack_ptr < 0 )
+               YY_FATAL_ERROR( "start-condition stack underflow" );
+
+       BEGIN(yy_start_stack[yy_start_stack_ptr]);
+       }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+       {
+       return yy_start_stack[yy_start_stack_ptr - 1];
+       }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+       {
+       (void) fprintf( stderr, "%s\n", msg );
+       exit( YY_EXIT_FAILURE );
+       }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+               yytext[yyleng] = yy_hold_char; \
+               yy_c_buf_p = yytext + n; \
+               yy_hold_char = *yy_c_buf_p; \
+               *yy_c_buf_p = '\0'; \
+               yyleng = n; \
+               } \
+       while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+       {
+       register int i;
+       for ( i = 0; i < n; ++i )
+               s1[i] = s2[i];
+       }
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+       {
+       register int n;
+       for ( n = 0; s[n]; ++n )
+               ;
+
+       return n;
+       }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+       {
+       return (void *) malloc( size );
+       }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+       {
+       /* The cast to (char *) in the following accommodates both
+        * implementations that use char* generic pointers, and those
+        * that use void* generic pointers.  It works with the latter
+        * because both ANSI C and C++ allow castless assignment from
+        * any pointer type to void*, and deal with argument conversions
+        * as though doing an assignment.
+        */
+       return (void *) realloc( (char *) ptr, size );
+       }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+       {
+       free( ptr );
+       }
+
+#if YY_MAIN
+int main()
+       {
+       yylex();
+       return 0;
+       }
+#endif
+#line 625 "lex.l"
+
+\f
+
+/* comments go to end of line. This can be done with a simple
+ * lex pattern, but when taken with all the other patterns, lex blows
+ * up because of too many right contexts. So we do this special case
+ * with this function.
+ */
+
+static void
+to_eol()
+
+{
+       while ((yytext[yyleng] = input()) != '\n' && yytext[yyleng] != 0 &&
+                                       yytext[yyleng] != EOF) {
+               if (++yyleng >= YYLMAX) {
+                       l_ufatal(Curr_filename, yylineno, "input line too long");
+               }
+               if (yytext[yyleng-1] == '\r') {
+                       /* If the \r is by itself, treat like a newline */
+                       char c;
+                       if ((c = input()) == '\n') {
+                               yytext[--yyleng] = '\n';
+                               break;
+                       }
+                       else if (c != 0) {
+                               unput(c);
+                       }
+               }
+       }
+
+       if (yytext[yyleng] ==  0 || yytext[yyleng] == EOF) {
+               return;
+       }
+       else {
+               if (yyleng > 0 && yytext[yyleng - 1] == '\\') {
+                       /* if backslashed newline, replace with real newline
+                        * and continue */
+                       yytext[--yyleng] = '\n';
+                       to_eol();
+               }
+               /* handle DOS style backslashed \r\n */
+               else if (yyleng > 1 && yytext[yyleng - 1] == '\r'
+                                               && yytext[yyleng - 2] == '\\') {
+                       yytext[yyleng - 2] = '\r';
+                       yytext[--yyleng] = '\n';
+                       to_eol();
+               }
+
+               /* put newline back onto input stream */
+               unput('\n');
+       }
+
+       yytext[yyleng] = '\0';
+
+       if (Preproc == YES && Ppcomments == YES) {
+               printf("%s", yytext);
+       }
+}
+\f
+
+/* Save macro text in specified file.
+ * @ is used to mark end of macro definition.
+ * Returns YES if there appeared to be any references to
+ * macro parameters to be quoted.
+ * (See the comment above the QS_ #defines in macros.c for more details.) */
+
+int
+save_macro(file)
+
+FILE *file;    /* put macro text into this file */
+
+{
+       int c;                          /* character read from macro */
+       int num_backslashes = 0;
+       int has_quoted_parameters = NO;
+
+
+       while ((c = input()) != 0 && c != EOF) {
+               if (c == '@') {
+                       /* if had a backslash before it, use real @ */
+                       if (num_backslashes == 1) {
+                               putc(c, file);
+                               num_backslashes = 0;
+                       }
+                       else {  
+                               /* reached end of macro definition */
+                               return(has_quoted_parameters);
+                       }
+               }
+               else {
+                       if (c == '\\') {
+                               num_backslashes++;
+                               if (num_backslashes == 2) {
+                                       putc(c, file);
+                                       num_backslashes = 0;
+                               }
+                       }
+                       else {
+                               if (num_backslashes == 1) {
+                                       putc('\\', file);
+                               }
+                               putc(c, file);
+                               num_backslashes = 0;
+                               if (c == '`') {
+                                       has_quoted_parameters = YES;
+                               }
+                       }
+               }
+       }
+
+       yyerror("unterminated macro");
+       return(has_quoted_parameters);
+}
+\f
+
+/* collect the parameter names on the definition of a macro with parameters */
+
+void
+get_parameters(macname)
+
+char *macname;         /* name of macro being defined */
+
+{
+       while (get_a_param(macname) == YES) {
+               ;
+       }
+}
+
+static int
+get_a_param(macname)
+
+char *macname;
+
+{
+       int c;          /* input character */
+       int index;      /* into name buffer */
+
+
+       /* skip leading white space */
+       skipwhite();
+
+       /* collect macro-like parameter names (upper case, digits, or
+        * underscore, starting with upper case), delimited by comma
+        * and ended by close parenthesis. */
+       while ((c = input()) != '\0' && c != EOF) {
+               if (isupper(c)) {
+                       yytext[0] = c;
+                       index = 1;
+                       while ((c = input()) != '\0' && c != EOF) {
+                               if (isupper(c) || isdigit(c) || c == '_') {
+                                       yytext[index++] = c;
+                               }
+                               else  {
+                                       /* found end of parameter name */
+                                       unput(c);
+                                       yytext[index] = '\0';
+                                       add_parameter(macname, yytext);
+
+                                       /* skip white space */
+                                       skipwhite();
+
+                                       /* next better be , or ) */
+                                       if ((c = input()) != ',' && c != ')') {
+                                               l_yyerror(Curr_filename, yylineno,
+                                                       "unexpected character '%c' in parameter list for macro %s",
+                                                       c, macname);
+                                               return(NO);
+                                       }
+                                       if (c == ')') {
+                                               /* return to input so we can
+                                                * read on next call to know
+                                                * we are at end of list */
+                                               unput(c);
+                                       }
+                                       return(YES);
+                               }
+                       }
+               }
+               else if (c == ')') {
+                       /* end of parameter list */
+                       return(NO);
+               }
+               else {
+                       l_yyerror(Curr_filename, yylineno,
+                               "illegal macro parameter name starting at character '%c'", c);
+                       return(NO);
+               }
+       }
+       yyerror("unexpected end-of-file in macro parameter list");
+       return(NO);
+}
+\f
+
+/* Read input, skipping any white space. White space is space, tab, return,
+ * backslashed return, newline, or backslashed newline.
+ * Backslashed anything else will leave the backslash in the input
+ * without the thing that followed it.
+ */
+
+static void
+skipwhite()
+
+{
+       int c;
+
+       while ((c = input()) != '\0' && c != EOF) {
+               if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
+                       continue;
+               }
+
+               if (c == '\\') {
+                       if ((c = input()) == '\n' || c == '\r' ) {
+                               /* backslashed newline/return is white space */
+                               continue;
+                       }
+                       else {
+                               unput('\\');
+                               return;
+                       }
+               }
+               /* non-space. Stuff back into input and return */
+               unput(c);
+               return;
+       }
+}
+
+\f
+
+/* collect arguments to a call to a macro with parameters */
+
+int
+get_mac_arguments(macname, num_args)
+
+char *macname;         /* name of the macro, to use in error messages */
+int num_args;          /* number of arguments expected */
+
+{
+       int c;          /* input character */
+       char *argbuff;  /* for storing argument */
+       int n;          /* number of arguments collected so far */
+
+
+       /* first skip any white space before the opening parenthesis */
+       skipwhite();
+
+       /* next thing better be open parenthesis */
+       if ((c = input()) != '(') {
+
+               l_yyerror(Curr_filename, yylineno,
+                       "macro %s has parameters, but has no '(' on call",
+                       macname);
+
+               /* Trying to parse anything more in this file might be
+                * almost hopeless. But we'll try just skipping to end of
+                * the line and returning failure and hope for the best. */
+               while (((c = input()) != '\0') && (c != EOF) &&
+                                               (c != '\n') && (c != '\r')) {
+                       ;
+               }
+               return(NO);
+       }
+
+       /* init to no argument collected. Space will be malloc-ed when needed */
+       argbuff = (char *) 0;
+       n = 0;
+
+       /* Now collect arguments. Read and process input
+        * one character at a time */
+       while ((c = input()) != '\0' && c != EOF) {
+               switch (c) {
+               case '\\':
+                       /* something that has been escaped with a backslash.
+                        * Get the next character and do appropriate escape. */
+                       switch (c = input()) {
+                       default:
+                               /* some unexpected backslashed thing */
+                               l_warning(Curr_filename, yylineno,
+                                       "dubious escape \\%c in argument %d of macro %s",
+                                       c, n+1, macname);
+                               /* fall through to use the literal, to be
+                                * sort of consistent with how C handles
+                                * such dubious escapes */
+                               /*FALLTHRU*/
+
+                       case ',':       /* would normally mean end of argument */
+                       case ')':       /* would normally mean end of argument list */
+                       case '\\':      /* user wants a real backslash */
+                               /* escaped to allow literal, so copy the
+                                * character without backslash to buffer */
+                               argbuff = add2argbuff(argbuff, c);
+                               break;
+
+                       case '\n':
+                               /* user wanted to put a newline in the input
+                                * to make it look better, but doesn't really
+                                * want a newline here in the argument text,
+                                * so just skip over this character */
+                               break;
+
+                       case '\r':
+                               /* If by itself, treat like newline.
+                                * If immediately followed by a newline,
+                                * treat the pair like newline.
+                                */
+                               if ((c = input()) != '\n') {
+                                       /* Followed by something other than
+                                        * newline, so push back into input.
+                                        */
+                                       if (c != EOF) {
+                                               unput(c);
+                                       }
+                               }
+                               break;
+                       case '\0':
+                               l_yyerror(Curr_filename, yylineno,
+                                       "unexpected end of file in macro %s argument %d",
+                                       macname, n + 1);
+                               return(NO);
+                       }
+                       break;
+
+               case ',':
+                       /* This marks the end of an argument.
+                        * Process this argument, then reset for next one */
+                       if (++n <= num_args) {
+                               set_parm_value(macname, argbuff, n);
+                       }
+                       else {
+                               /* discard this one. It's extra. But wait
+                                * to print error until we find the ),
+                                * so if they have lots of extras we only
+                                * print one message */
+                               if (argbuff != (char *) 0) {
+                                       FREE(argbuff);
+                               }
+                       }
+
+                       /* reset for next argument */
+                       argbuff = (char *) 0;
+                       break;
+
+               case ')':
+                       /* this marks end of arguments. Save the last one
+                        * collected and signal success */
+                       if (++n == num_args) {
+                               /* good. got exactly the right number of
+                                * arguments. Save the last one and
+                                * declare victory */
+                               set_parm_value(macname, argbuff, n);
+                               return(YES);
+                       }
+                       else {
+                               l_yyerror(Curr_filename, yylineno,
+                                       "too %s arguments to macro %s (expected %d, got %d)",
+                                       ((n < num_args) ? "few" : "many"),
+                                       macname, num_args, n);
+                       }
+                       return(NO);
+
+               default:
+                       /* ordinary character. Save it away */
+                       argbuff = add2argbuff(argbuff, c);
+                       break;
+               }
+       }
+
+       l_yyerror(Curr_filename, yylineno, "unexpected end of file in call to %s macro",
+               macname);
+       return(NO);
+}
+\f
+
+/* skip input until find an else or endif. If find else, return YES, if find
+ * endif or end of file, return NO */
+/* It probably would be possible to get lex to do this pattern matching with
+ * appropriate start conditions, but it seems like too much trouble to figure
+ * that out. Just need to look for 2 simple patterns, so do simple state
+ * machine */
+
+typedef enum { STATE_NONE, STATE_E, STATE_EL, STATE_ELS, STATE_EN,
+               STATE_END, STATE_ENDI, STATE_I, STATE_IF, STATE_IFD,
+               STATE_IFDE } STATE;
+
+static int
+skip2else()
+
+{
+       int c;                          /* char read from input */
+       STATE state = STATE_NONE;
+       int escaped;            /* true if got odd number of backslashes */
+       int saved_ppcomments;   /* saved value of Ppcomments */
+
+
+       /* When skipping stuff in if/else, we don't want anything to come
+        * out when using -E -C. Since this function can call to_eol(),
+        * we have to convince it -C isn't on even if it is. */
+       saved_ppcomments = Ppcomments;
+       Ppcomments = NO;
+
+       /* read characters. Based on current character and state, go into
+        * new state if appropriate. */
+       while ((c = input()) != 0 && c != EOF) {
+
+               switch (c) {
+
+               case 'e':
+                       if (state == STATE_ELS) {
+                               YY_FLUSH_BUFFER;
+                               Ppcomments = saved_ppcomments;
+                               return(YES);
+                       }
+                       else if (state == STATE_IFD) {
+                               state = STATE_IFDE;
+                       }
+                       else {
+                               state = STATE_E;
+                       }
+                       break;
+
+               case 'l':
+                       state = (state == STATE_E ? STATE_EL : STATE_NONE);
+                       break;
+
+               case 's':
+                       state = (state == STATE_EL ? STATE_ELS : STATE_NONE);
+                       break;
+
+               case 'n':
+                       if (state == STATE_E) {
+                               state = STATE_EN;
+                       }
+                       else if (state == STATE_IF) {
+                               /* for ifndef. Treat this like ifdef. There is
+                                * a tiny bug here in that user could input
+                                * ifnnndef and we would interpret that as
+                                * ifndef. However, since if we're in this
+                                * function, we are skipping stuff that is
+                                * ifdef-ed out, who cares if we miss some
+                                * off-the-wall syntax error? */
+                               ;
+                       }
+                       else {
+                               state = STATE_NONE;
+                       }
+                       break;
+
+               case 'd':
+                       if (state == STATE_EN) {
+                               state = STATE_END;
+                       }
+                       else if (state == STATE_IF) {
+                               state = STATE_IFD;
+                       }
+                       else {
+                               state = STATE_NONE;
+                       }
+                       break;
+
+               case 'i':
+                       state = (state == STATE_END ? STATE_ENDI : STATE_I);
+                       break;
+
+               case 'f':
+                       if (state == STATE_ENDI) {
+                               YY_FLUSH_BUFFER;
+                               Ppcomments = saved_ppcomments;
+                               return(NO);
+                       }
+                       else if (state == STATE_I) {
+                               state = STATE_IF;
+                       }
+                       else if (state == STATE_IFDE) {
+                               if (skip2else() == YES) {
+                                       if (skip2else() == YES) {
+                                               yyerror("else without ifdef");
+                                       }
+                               }
+                       }
+                       else {
+                               state = STATE_NONE;
+                       }
+                       break;
+
+               case '/':
+                       if ((c = input()) == '/') {
+                               /* Skip past comments, in case they happen to
+                                * contain 'else' or 'endif'
+                                * that could confuse us. */
+                               to_eol();
+                       }
+                       else if (c != 0 && c != EOF) {
+                               unput(c);
+                       }
+                       state = STATE_NONE;
+                       break;
+
+               case '"':
+                       /* Skip strings, in case they happen to contain
+                        * 'else' or 'endif' that could confuse us. */
+                       escaped = 0;
+                       while ((c = input()) != 0 && c != EOF) {
+                               if (c == '"' && ! escaped) {
+                                       break;
+                               }
+                               if (c == '\\') {
+                                       escaped ^= 1;
+                               }
+                               else {
+                                       escaped = 0;
+                               }
+                       }
+                       state = STATE_NONE;
+                       break;
+               default:
+                       if (state == STATE_IF) {
+                               /* skip to else or endif */
+                               if (skip2else() == YES) {
+                                       /* if was an else, need to continue
+                                        * to the endif */
+                                       if (skip2else() == YES) {
+                                               yyerror("else without ifdef");
+                                       }
+                               }
+                       }
+                       state = STATE_NONE;
+                       break;
+               }
+       }
+
+       /* end of file */
+       yyerror("unexpected end-of-file: missing endif");
+       return(NO);
+}
+\f
+
+/* at the very end, verify all if, ifdef, and ifndef clauses are closed */
+
+void
+chk_ifdefs()
+
+{
+       if (If_count != 0) {
+               yyerror("missing endif");
+       }
+}
+\f
+
+/* check if there is an odd number of backslashes starting before the final
+ * double quote. If so, return YES--the last backslash applies to the double
+ * quote. Otherwise return NO, because the backslash was itself backslashed
+ * which means user wants to end string with a backslash */
+
+static int
+oddbs()
+
+{
+       int i;
+       int bscount = 0;        /* count of backslashes */
+
+       for (i = yyleng - 2; i >= 0; i--) {
+               if (yytext[i] == '\\') {
+                       bscount++;
+               }
+               else {
+                       break;
+               }
+       }
+       return ((bscount & 1) ? YES: NO);
+}
+\f
+
+/* Flex has the (documented) limitation that you can't change the value
+ * of yyleng in the same rule action as you use yymore. So when there is
+ * an escaped double quote mark inside a string, we can't remove it and
+ * also use yymore in the same rule. So we collect the whole string,
+ * including their embedded quote marks and their backslashes,
+ * then call this function which moves the characters back to get rid of
+ * the backslashes, and adjusts yyleng appropriately.
+ */
+
+static void
+embedquotes()
+
+{
+       int i;
+       int moveback;
+
+       if (Escapedquotes < 1) {
+               /* No escaped quote found, so nothing to do here */
+               return;
+       }
+
+       moveback = 0;
+       for (i = 1; i < yyleng; i++) {
+               /* if there is a quote inside the string,
+                * it must have been escaped */
+               if (yytext[i] == '"' && yytext[i-1] == '\\' && i < yyleng - 1) {
+                       moveback++;
+               }
+               /* If we have come across one or more embedded quotes,
+                * move bytes to the left one position for each quote,
+                * which gets rid of the backslashes. */
+               if (moveback > 0) {
+                       yytext[i-moveback] = yytext[i];
+               }
+       }
+       yytext[i-moveback] = '\0';
+       yyleng -= Escapedquotes;
+       Escapedquotes = 0;
+               
+}
+\f
+
+/* Mapping of Latin-1 non-ASCII characters to their Mup names. If Mup
+ * doesn't support the value, or the value is undefined in Latin-1,
+ * value in this table is 0. */
+static char *latin1_to_mup_name[] = {
+       /* 128 */       0,
+       /* 129 */       0,
+       /* 130 */       0,
+       /* 131 */       0,
+       /* 132 */       0,
+       /* 133 */       0,
+       /* 134 */       0,
+       /* 135 */       0,
+       /* 136 */       0,
+       /* 137 */       0,
+       /* 138 */       0,
+       /* 139 */       0,
+       /* 140 */       0,
+       /* 141 */       0,
+       /* 142 */       0,
+       /* 143 */       0,
+       /* 144 */       0,
+       /* 145 */       0,
+       /* 146 */       0,
+       /* 147 */       0,
+       /* 148 */       0,
+       /* 149 */       0,
+       /* 150 */       0,
+       /* 151 */       0,
+       /* 152 */       0,
+       /* 153 */       0,
+       /* 154 */       0,
+       /* 155 */       0,
+       /* 156 */       0,
+       /* 157 */       0,
+       /* 158 */       0,
+       /* 159 */       0,
+       /* 160 */       0,
+       /* 161 */       "exclamdown",
+       /* 162 */       0,
+       /* 163 */       "sterling",
+       /* 164 */       0,
+       /* 165 */       "yen",
+       /* 166 */       0,
+       /* 167 */       0,
+       /* 168 */       "dieresis",
+       /* 169 */       "copyright",
+       /* 170 */       "ordfeminine",
+       /* 171 */       "<<",
+       /* 172 */       0,
+       /* 173 */       "emdash",
+       /* 174 */       0,
+       /* 175 */       "macron",
+       /* 176 */       "ring",
+       /* 177 */       0,
+       /* 178 */       0,
+       /* 179 */       0,
+       /* 180 */       "acute",
+       /* 181 */       0,
+       /* 182 */       0,
+       /* 183 */       0,
+       /* 184 */       "cedilla",
+       /* 185 */       0,
+       /* 186 */       0,
+       /* 187 */       ">>",
+       /* 188 */       0,
+       /* 189 */       0,
+       /* 190 */       0,
+       /* 191 */       "questiondown",
+       /* 192 */       "A`",
+       /* 193 */       "A'",
+       /* 194 */       "A^",
+       /* 195 */       "A~",
+       /* 196 */       "A:",
+       /* 197 */       "Ao",
+       /* 198 */       "AE",
+       /* 199 */       "C,",
+       /* 200 */       "E`",
+       /* 201 */       "E'",
+       /* 202 */       "E^",
+       /* 203 */       "E:",
+       /* 204 */       "I`",
+       /* 205 */       "I'",
+       /* 206 */       "I^",
+       /* 207 */       "I:",
+       /* 208 */       0,
+       /* 209 */       0,
+       /* 210 */       "N~",
+       /* 211 */       "O`",
+       /* 212 */       "O'",
+       /* 213 */       "O^",
+       /* 214 */       "O~",
+       /* 215 */       "O:",
+       /* 216 */       "U`",
+       /* 217 */       "U'",
+       /* 218 */       "U^",
+       /* 219 */       "U:",
+       /* 220 */       0,
+       /* 221 */       0,
+       /* 222 */       0,
+       /* 223 */       0,
+       /* 224 */       "a`",
+       /* 225 */       "a'",
+       /* 226 */       "a^",
+       /* 227 */       "a~",
+       /* 228 */       "a:",
+       /* 229 */       "ao",
+       /* 230 */       "ae",
+       /* 231 */       "c,",
+       /* 232 */       "e`",
+       /* 233 */       "e'",
+       /* 234 */       "e^",
+       /* 235 */       "e:",
+       /* 236 */       "i`",
+       /* 237 */       "i'",
+       /* 238 */       "i^",
+       /* 239 */       "i:",
+       /* 240 */       0,
+       /* 241 */       "n~",
+       /* 242 */       "o`",
+       /* 243 */       "o'",
+       /* 244 */       "o^",
+       /* 245 */       "o~",
+       /* 246 */       "o:",
+       /* 247 */       0,
+       /* 248 */       "o/",
+       /* 249 */       "u`",
+       /* 250 */       "u'",
+       /* 251 */       "u^",
+       /* 252 */       "u:",
+       /* 253 */       0,
+       /* 254 */       0,
+       /* 255 */       "y:"
+};
+
+/* This function goes through the string currently in yytext, and if it finds
+ * any non-ASCII characters that can be transformed into the non-ASCII
+ * characters that Mup supports through the \(....) escape mechanism,
+ * it replaces them with the appropriate escape strings.
+ * This functionality probably logically belongs in fix_string(),
+ * but for historical reasons, that function is not allowed
+ * to increase the length of a string,
+ * so it's easier to do this step separately.
+ */
+
+static void
+xpand_non_ascii()
+{
+       int index;                      /* walk through yytext */
+       int start;                      /* index of first non-ascii */
+       int value;                      /* value of a character */
+       char *replacement;              /* Mup's name for the non_ascii */
+       static char *tmp_buff = 0;      /* for expanded version */
+       int tmp_index;                  /* index into tmp_buff */
+
+       if (Raw_string == YES) {
+               /* Collecting a string for something like raw PostScript,
+                * that shouldn't be converted. */
+               return;
+       }
+
+       /* see if any non-ascii */
+       for (index = 0; index < yyleng; index++) {
+               if (yytext[index] & 0x80) {
+                       break;
+               }
+       }
+
+       if (index == yyleng) {
+               /* no non-ascii in current string, so leave it as is */
+               return;
+       }
+
+       /* If we don't have a buffer yet, allocate it. If an input file
+        * has no non-ascii in it at all, we'll never get here, and no
+        * memory will be wasted on a buffer we don't need. If we do get
+        * here, chances are there will be lots more non-ascii, so we
+        * keep the buffer around, rather than constantly doing malloc/free. */
+       if (tmp_buff == 0) {
+               MALLOCA(char, tmp_buff, YYLMAX);
+       }
+
+       /* only need to rewrite the part of the string
+        * beyond the first non-ascii, so remember where we are now */
+       start = index;
+
+       /* walk through, converting non-ascii to their Mup names */
+       for (tmp_index = 0; index < yyleng; index++) {
+
+               if (yytext[index] & 0x80) {
+                       /* Look up replacement. The replacement table
+                        * only contains entries for 128-255,
+                        * so adjust the value of the non-ascii character
+                        * to get the appropriate array offset. */
+                       value = ((int)(yytext[index])) & 0xff;
+                       replacement = latin1_to_mup_name[value - 128];
+
+                       if (replacement == (char *) 0) {
+                               /* Apparently user is able to input a
+                                * character that Mup doesn't support... */
+                               l_yyerror(Curr_filename, yylineno,
+                                       "unsupported non-ASCII character (0x%x) in string",
+                                       yytext[index] & 0xff);
+                       }
+                       else {
+                               (void) sprintf(tmp_buff + tmp_index, "\\(%s)",
+                                                               replacement);
+                               tmp_index += strlen(replacement) + 3;
+                       }
+               }
+               else {
+                       /* normal ASCII character; copy as is */
+                       tmp_buff[tmp_index++] = yytext[index];
+               }
+       }
+
+       /* Now we can copy the expanded string back into yytext and update
+        * yyleng so that all later code will think the user typed in the
+        * expanded version themselves. */
+       (void) strncpy(yytext + start, tmp_buff, tmp_index);
+       yyleng = start + tmp_index;
+       yytext[yyleng] = '\0';
+}
+\f
+
+/* push a character back into input. This allows another C file to
+ * access the unput macro */
+
+void
+pushback(c)
+
+int c;
+
+{
+       unput(c);
+}
+\f
+
+/* this function will do nothing unless the "preprocessor only" flag is on,
+ * in which case it will print the current token
+ */
+
+static void
+ignore()
+
+{
+       if (Preproc == YES) {
+               printf("%s", yytext);
+       }
+}
+\f
+
+/* When collecting raw PostScript, we don't want to convert non-ASCII to
+ * Mup escapes. These functions turn the raw processing on and off. */
+
+void
+begin_raw()
+{
+       Raw_string = YES;
+}
+
+void
+end_raw()
+{
+       Raw_string = NO;
+}
+\f
+
+/* Create a new flex buffer for the given input file and switch to it */
+
+void
+new_lexbuff(file)
+
+FILE * file;
+
+{
+       struct Lexbuffer *newbuff;
+
+       if (Lexlist == 0) {
+               MALLOC(Lexbuffer, newbuff, 1);
+               newbuff->next = 0;
+               newbuff->buff = YY_CURRENT_BUFFER;
+               Lexlist = newbuff;
+       }
+
+       MALLOC(Lexbuffer, newbuff, 1);
+       newbuff->next = Lexlist;
+       Lexlist = newbuff;
+       newbuff->buff = yy_create_buffer(file, YY_BUF_SIZE);
+       yy_switch_to_buffer(newbuff->buff);
+}
+
+/* Switch back to previous flex buffer on the stack */
+
+void
+del_lexbuff()
+
+{
+       struct Lexbuffer *nextbuff;
+
+       if (Lexlist == 0) {
+               pfatal("attempt to pop from empty lex buffer stack");
+       }
+       nextbuff = Lexlist->next;
+       yy_delete_buffer(Lexlist->buff);
+       FREE(Lexlist);
+       Lexlist = nextbuff;
+       yy_switch_to_buffer(nextbuff->buff);
+}
+\f
+
+/* The contents of an "if clause" is stored in compressed form in
+ * Ifclause_buff, and eventually passed to a mini-parser. This function
+ * add tokens to the buffer. Compressed format:
+ *     input           compressed token
+ *    -------------------------------------
+ *     (               (
+ *     )               )
+ *     !               !
+ *     ~               ~
+ *     *               *
+ *     /               /
+ *     %               %
+ *     +               +
+ *     -               -
+ *     <<              l
+ *     >>              r
+ *     <               <
+ *     >               >
+ *     <=              L
+ *     >=              G
+ *     ==              E
+ *     !=              N
+ *     &               &
+ *     ^               ^
+ *     |               |
+ *     &&              a
+ *     ||              o
+ *     ?               ?
+ *     :               :
+ *     defined(X)      T or F depending on whether X is defined or not
+ *      literal number # followed by 4 bytes in MSB order
+ *      macro name     # followed by macro's value as 4 bytes in MSB order
+ */
+
+static void
+add_ifclause(token)
+
+int token;
+
+{
+       if (If_length >= sizeof(Ifclause_buff)) {
+               ufatal("Sorry, 'if' clause is too complex");
+       }
+       Ifclause_buff[If_length++] = (unsigned char) (token & 0xff);
+}
+
+/* We store numbers in the if-clause compressed form as '#' followed by
+ * 4 bytes in MSB order.
+ */
+
+
+static void
+addnum_ifclause(value)
+
+int value;
+
+{
+       int shift;
+
+       add_ifclause('#');
+       for (shift = 24; shift >= 0; shift -= 8) {
+               add_ifclause((value >> shift) & 0xff);
+       }
+}
+
+
+/* Add number in ASCII. Convert to value and add */
+
+static void
+addnumstr_ifclause(numtoken)
+
+char *numtoken;
+
+{
+       int value;
+       char *end_p;
+
+#ifdef ERANGE
+       errno = 0;
+#endif
+       value = strtol(numtoken, &end_p, 0);
+       if (*end_p != '\0') {
+               /* Lexer shouldn't allow unparsable number,
+                * so if strtol didn't get to end, must be too big */
+               yyerror("bad number (probably out of range)");
+       }
+#ifdef ERANGE
+       /* Additional range check assuming strtol sets this properly
+        * on all systems. */
+       else if (errno == ERANGE) {
+               yyerror("number is out of range");
+       }
+#endif
+
+       addnum_ifclause(value);
+}
+\f
+
+/* Give error message for invalid input character, as actual character
+ * if printable, otherwise as hex value. */
+
+static void
+bad_input(where)
+
+char *where;           /* describes where the bad input was found */
+
+{
+       if (isgraph(yytext[0])) {
+               l_yyerror(Curr_filename, yylineno,
+                       "invalid character in %s: '%c'",
+                       where, yytext[0]);
+       }
+       else {
+               l_yyerror(Curr_filename, yylineno,
+                       "invalid character in %s: 0x%x",
+                       where, (int) yytext[0]);
+       }
+}
diff --git a/mup/mup/locvar.c b/mup/mup/locvar.c
new file mode 100644 (file)
index 0000000..7979307
--- /dev/null
@@ -0,0 +1,2359 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004 by Arkkra Enterprises */
+/* All rights reserved */
+
+/*
+There are 3 classes of location variables:
+
+       A. Those associated with a specific staff of a specific score.
+       This includes those for GRPSYLs and NOTES.
+
+       B. Those associated with a specific score. These are for bars.
+
+       C. Those associated with the current page. These are the builtin
+       variables such as _win and _page, or absolute coordinates.
+
+Type B variables, associated with bars, are extra strange. The y of a bar
+in not particularly useful. If the bar line happens to wind up at the end
+of a score, special consideration applies, because the right side of the
+bar is effectively at the beginning of the next score after the clefsig.
+So here are the rules:
+
+1. If a bar does not occur at the end of a score, the location variable
+associated with it, if any, is handled normally.
+
+2. If a bar does fall on the end of a score, if the x coordinate derived from
+a location variable associated with that bar in
+an INPCOORD, after offsetting, comes out to be either left of the x of
+the bar, or equal to the x of the bar, it will be handled normally.
+
+3. If a bar falls on the end of a score, and
+if the x coordinate derived from an INPCOORD, after offsetting, comes out
+to be right of the x of the bar,
+the x coordinate will be recalculated using the pseudo
+bar at the beginning of the following score,
+and if the y coordinate of the same INPCOORD is also associated
+with the same bar coordinate, it will also be recalculated from the pseudo bar.
+
+4. If rule 3 would normally apply, but there is no following score, rule 3
+will be ignored, and the coordinate will be used as is.
+
+A PRHEAD contains only a single location variable, so it should always
+be taken just as is.
+
+Lines and curves are more exciting, since they can have multiple
+coordinates, and thus may need to be split into 2 or more pieces
+across scores and/or pages. Lines are a degenerate case of curves,
+so if we can deal with curves, we've got it made.
+
+For drawing a specific curve, here are the rules:
+
+1. If any coordinate is associated with a staff that is invisible, the entire
+curve will be ignored.
+
+2. Type C variables are always used as is, never themselves causing splitting.
+Taking any adjacent pair of points in a curve, if either of them is of type C,
+the line segment between those 2 points will not be split.
+
+3. If all variables of type A and B are on the same score of the same page,
+then the curve can be printed as is, with no splitting needed.
+
+4. If the x and y components of a single INPCOORD are associated with
+different scores, this will be an error condition.
+
+5. If the x and y components of a single INPCOORD are associated with
+different staffs, but the same score, the point will be treated as if
+it were associated with the staff associated with the y coordinate.
+
+6. If 2 adjacent points of a curve are associated with different
+scores, the line segment must be split. The number of segments that will
+need to be generated will be equal to the number of FEEDs between
+the coordinates plus one. 
+
+7. Splitting will only be done to forward scores. In other words, if the
+coordinates of a curve would require splitting part of the curve onto a
+preceeding score, that will be an error. This is to keep things simpler,
+since I can't think of any times this restriction would cause a problem.
+
+8. If a segment needs to be split, the first piece will extend in the
+x direction from the first point to 0.1 inch left of the right edge of the
+score associated with the first point.
+However, if the starting x is already at the right edge of the score, a line of length 0.1 inches will be drawn instead.
+The last piece of the split line segment will extend in
+the x direction from the pseudo bar of the clefsig.
+
+8a. If there are additional scores
+between the one associated with the beginning point and the one associated
+with the endpoint, for each intervening score a line will be drawn with
+its x coordinates from the pseudo bar to the right margin.
+
+9. To calculate the y coordinates of each piece of a split line segment,
+there are several cases. First the easy case, where the y coordinates of
+the beginning and ending point are both associated with the same staff.
+Conceptionally, the scores are lined up on a single line without score
+feeds. The slope of the line is then calculated. The y coordinates of
+the derived points are then calculated using this slope. Thus, for example,
+if the ending y coordinate would be A inches from of the beginning y coordinate
+in the x direction (if they were on the same score),
+and the line segment is split into 2 segments, with the first having
+a length in the x direction of B and the second having a length in the x
+direction of C, the y coordinate of the end of the first segment would be
+y[begin] + (A/(B+C)) * B, and the y coordinate of the beginning of the second
+piece would be y[end] - (A/(B+C)) * C.
+
+10. If the y coordinates of the 2 points are associated with different staffs.
+the slope is calculated based on the distance of the endpoints from their
+respective staffs. Then for each segment, the slope and endpoints are adjusted
+based on the ratio of the distance between the two staffs on the current score
+relative to the widest distance.
+
+11. For purposes of determining y coordinates, the y and n values of a bar
+are considered to be associated with the top visible score, and the s value
+is considered to be associated with the bottom visible score.
+Then rules 9 and 10 above are applied as for with type A coordinates.
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+static int Total_pages = 1;            /* how many pages of output */
+
+/* if lines must be added for intervening scores, save info about them */
+struct SEGINFO {
+       struct MAINLL *mll_p;   /* FEED where line segment must go */
+       double xlength;         /* x length prior to current score */
+       struct SEGINFO *next;   /* linked list */
+};
+struct SEGINFO *Seginfo_p;
+
+static void gather_coord_info P((void));
+static void save_coord_info P((struct COORD_INFO *coord_info_p,
+               int coordtype, int page, int score, int staff,
+               struct MAINLL *mll_feed_p, int vis));
+static void coord_staff P((struct STAFF *staff_p, int page,
+               int score, struct MAINLL *mll_feed_p));
+static void split_lines_and_curves P((void));
+static void chkline P((struct MAINLL *mll_p));
+static void coordcheck P((struct COORD_INFO *x_info_p,
+               struct COORD_INFO *y_info_p, char *fname, int lineno));
+static void add_segment P((struct SEGINFO *seginfo_p, double slope,
+               double y_offset, int staffno1, int linetype));
+static double find_effXlength P((double seg1xlen, double seg2xlen,
+               struct COORD_INFO *x1info_p, struct COORD_INFO *x2info_p,
+               int save_feed_info));
+static void svfeed P((struct MAINLL *mll_feed_p, double xlength));
+static int eff_staff P((struct COORD_INFO *yinfo_p));
+static double getYstaff P((struct MAINLL *mll_p, int staffno));
+static void chkcurve P((struct MAINLL *mll_p));
+static int bulgedir P((struct CURVE *curve_p, int index, char *inputfile,
+               int inputlineno));
+static int cmpcoords P((struct CURVE *curve_p, int p1, int p2));
+static int abs2rel P((int vtype));
+static void add_crv_seg P((struct SEGINFO *seginfo_p, double slope,
+               double y_offset, int staffno1, int curvetype, int bulge,
+               char *filename, int lineno));
+static int is_invis P((struct COORD_INFO *cinfo_p));
+static int is_builtin P((struct COORD_INFO *cinfo_p));
+static void move2correct_page P((void));
+static void move_it P((struct MAINLL *m_p, struct MAINLL *im_p, int page));
+static void move2pseudo P((void));
+static void do_pseudo P((struct INPCOORD *inpc_p, struct MAINLL *mll_p));
+static void fix_inpcoords P((struct MAINLL *mll_p));
+static void adj_coord P((struct INPCOORD *coord_p, struct MAINLL *mll_p,
+               struct INPCOORD *prev_coord_p));
+static void calc_bulge P((struct CURVE *curve_p, char *fname, int lineno,
+               int is_split, struct MAINLL *mll_p));
+\f
+
+/* during parse phase, a table of coordinates associated with location
+ * variables was built. After all the positioning has been done, we need
+ * to go through the main list and stuff off of it checking each coordinate.
+ * If the coordinate is pointed to by something else, we'll need to
+ * save some info about it. Then we have to go through the main list
+ * again and for each line and curve, see whether it needs to be split
+ * into pieces. If so, add LINE or CURVE structs at appropriate places.
+ */
+
+
+void
+fix_locvars()
+
+{
+       /* first get info about all coordinates with loc variables */
+       gather_coord_info();
+
+       /* move things to pseudo-bar if necessary */
+       move2pseudo();
+
+       /* split any lines and curves that need to be split */
+       split_lines_and_curves();
+
+       /* move anything that is on the wrong page */
+       move2correct_page();
+}
+\f
+
+/* go through everything looking for coordinates. For each one found, if
+ * there is a location tag pointing at it, save info about what the coord
+ * is associated with (bar, note, or group), what page, score and
+ * staff it's on, etc. */
+
+static void
+gather_coord_info()
+
+{
+       struct MAINLL *mll_p;           /* to walk through list */
+       short page = 1;                 /* which page we're on */
+       short score = 0;                /* which staff on current page */
+       struct MAINLL *mll_feed_p;      /* FEED info for current score */
+       struct COORD_INFO *coord_info_p;
+       struct COORD_INFO *last_bar_coord_info_p;       /* info about the
+                                        * most recent bar line, in case we
+                                        * need to attach information about
+                                        * the pseudo bar at the beginning
+                                        * of the following score */
+
+
+       debug(32, "gather_coord_info");
+
+       initstructs();
+       last_bar_coord_info_p = (struct COORD_INFO *) 0;
+       /* We know that because of how the main list is set up, we will never
+        * actually access mll_feed_p without setting it first, but compilers
+        * aren't smart enough to know that, and some picky compilers warn
+        * that mll_feed_p could be used without being set, so shut them up.
+        */
+       mll_feed_p = (struct MAINLL *) 0;
+
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->next) {
+               switch (mll_p->str) {
+
+               case S_FEED:
+                       /* keep track of which page and score we're on */
+                       if (mll_p->u.feed_p->pagefeed == YES) {
+                               page++;
+                               score = 1;
+                               Total_pages++;
+                       }
+                       else {
+                               score++;
+                       }
+                       if (IS_CLEFSIG_FEED(mll_p)) {
+                               mll_feed_p = mll_p;
+                       }
+                       break;
+
+               case S_BAR:
+                       /* if bar is pointed to, save info about it */
+                       if ((coord_info_p = find_coord(mll_p->u.bar_p->c))
+                                               != (struct COORD_INFO *) 0) {
+
+                               save_coord_info(coord_info_p, CT_BAR,
+                                                       page, score, 0,
+                                                       mll_feed_p, YES);
+                               last_bar_coord_info_p = coord_info_p;
+                       }
+
+                       else {
+                               /* no reference to this bar, so no need to
+                                * attach pseudo bar info */
+                               last_bar_coord_info_p = (struct COORD_INFO *) 0;
+                       }
+                       break;
+
+               case S_CLEFSIG:
+                       if (mll_p->u.clefsig_p->bar_p != (struct BAR *) 0) {
+                               if (last_bar_coord_info_p != (struct COORD_INFO *) 0) {
+                                       /* point bar at end of previous score
+                                        * to the  pseudo bar on this score */
+                                       last_bar_coord_info_p->pseudo_bar_p
+                                               = mll_p->u.clefsig_p->bar_p;
+                               }
+
+                               /* always save info, because a split curve may
+                                * need to refer to it */
+                               add_coord(mll_p->u.clefsig_p->bar_p->c, CT_BAR);
+                               coord_info_p = find_coord(mll_p->u.clefsig_p->bar_p->c);
+                               save_coord_info(coord_info_p, CT_BAR,
+                                       page, score, 0, mll_feed_p, YES);
+                       }
+                       break;
+
+               case S_STAFF:
+                       /* will have to get info for both GRPSYLs and NOTES. */
+                       coord_staff(mll_p->u.staff_p, page, score, mll_feed_p);
+                       break;
+
+               case S_SSV:
+                       /* keep track of VISIBLE status */
+                       asgnssv(mll_p->u.ssv_p);
+                       break;
+
+               default:
+                       /* nothing else is of interest at this point */
+                       break;
+               }
+       }
+}
+\f
+
+/* fill in the COORD_INFO table with information about a coordinate.  */
+
+static void
+save_coord_info(coord_info_p, coordtype, page, score, staff, mll_feed_p, vis)
+
+struct COORD_INFO *coord_info_p;/* where to add -- assumed
+                                * to be non-NULL */
+int coordtype;                 /* CT_BAR, CT_NOTE, etc */
+int page;
+int score;
+int staff;
+struct MAINLL *mll_feed_p;     /* MAINLL containing FEED
+                                * associated with score */
+int vis;                       /* YES if visible */
+
+{
+       if (coord_info_p == (struct COORD_INFO *) 0) {
+               pfatal("invalid coordinate information");
+       }
+
+       /* make sure this phase matches parse phase */
+       if ((coord_info_p->flags & coordtype) == 0) {
+               pfatal("coordinate type mismatch");
+       }
+
+       /* save relevant info */
+       coord_info_p->page = (short) page;
+       coord_info_p->scorenum = (short) score;
+       coord_info_p->staffno = (short) staff;
+       coord_info_p->mll_feed_p = mll_feed_p;
+       if (vis == NO) {
+               coord_info_p->flags |= CT_INVISIBLE;
+       }
+}
+\f
+
+/* given a STAFF struct, save relevant info about all the GRPSYL
+ * and NOTE coordinates */
+
+static void
+coord_staff(staff_p, page, score, mll_feed_p)
+
+struct STAFF *staff_p;         /* get info from here */
+int page;
+int score;
+struct MAINLL *mll_feed_p;     /* FEED associated with this score */
+
+{
+       struct GRPSYL *gs_p;
+       struct COORD_INFO *coord_info_p;
+       int vis;                /* YES if staff is visible */
+       register int n;         /* to walk through NOTE lists */
+       register int v;         /* walk through voices/verses */
+
+
+       /* do for each voice */
+       for (v = 0; v < MAXVOICES; v++) {
+
+               vis = vvpath(staff_p->staffno, v + 1, VISIBLE)->visible;
+               /* for each GRPSYL in the list */
+               for (gs_p = staff_p->groups_p[v]; gs_p != (struct GRPSYL *) 0;
+                               gs_p = gs_p->next) {
+
+                       /* check its coordinate */
+                       if ((coord_info_p = find_coord(gs_p->c))
+                                       != (struct COORD_INFO *) 0) {
+                               save_coord_info(coord_info_p, CT_GRPSYL,
+                                               page, score, gs_p->staffno,
+                                               mll_feed_p, vis);
+                       }
+
+                       /* if has notes, check each note coordinate */
+                       for (n = 0; n < gs_p->nnotes; n++) {
+
+                               if ((coord_info_p = find_coord(gs_p->notelist[n].c))
+                                               != (struct COORD_INFO *) 0) {
+
+                                       save_coord_info(coord_info_p, CT_NOTE,
+                                                       page, score,
+                                                       gs_p->staffno,
+                                                       mll_feed_p, vis);
+                               }
+                       }
+               }
+       }
+}
+\f
+
+/* go down main list. For any lines and curves, see if they need to be
+ * split */
+
+static void
+split_lines_and_curves()
+
+{
+       struct MAINLL *mll_p;           /* walk through main list */
+
+
+       debug(16, "split_lines_and_curves");
+
+       initstructs();
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->next) {
+
+               switch(mll_p->str) {
+
+               case S_LINE:
+                       fix_inpcoords(mll_p);
+                       chkline(mll_p);
+                       break;
+
+               case S_CURVE:
+                       fix_inpcoords(mll_p);
+                       chkcurve(mll_p);
+                       break;
+
+               case S_SSV:
+                       asgnssv(mll_p->u.ssv_p);
+                       break;
+
+               default:
+                       /* ignore everything else */
+                       break;
+               }
+       }
+}
+\f
+
+/* check whether a LINE needs to be split. If so, split it */
+
+static void
+chkline(mll_p)
+
+struct MAINLL *mll_p;  /* points to LINE */
+
+{
+       struct COORD_INFO *x1info_p, *y1info_p; /* info about coordinates
+                               * referenced for the beginning of the line */
+       struct COORD_INFO *x2info_p, *y2info_p; /* same for end of line */
+       struct LINE *line_p;                    /* the line being processed */
+       struct MAINLL *new_mll_p;               /* new main list struct to add
+                                                * if line has to be split */
+       struct LINE *end_line_p;                /* new LINE struct to hang off
+                                                * of new_mll_p if the line
+                                                * has to be split */
+       double offset;
+       struct MAINLL *mll_clefsig_p;           /* clefsig before a continued
+                                                * line segment */
+       struct MAINLL *m_p;                     /* for finding BAR */
+       char *fname;                            /* file name for messages */
+       int lineno;                             /* line # for messages */
+       double seg1xlen, seg2xlen;              /* lengths of split segments */
+       double effective_x_len;                 /* effective horizontal
+                                                * distance of line, adding
+                                                * the split segments */
+       double slope;                           /* of effective line */
+       int p1staff, p2staff;                   /* effective staff associated
+                                                 * with y coord of line ends */
+       struct SEGINFO *seg_p;                  /* walk through segment list */
+       struct SEGINFO *to_free_p;              /* which is to be freed */
+
+
+       /* if we added this line internally, it's already split, so no
+        * more to check on it */
+       if (mll_p->inputlineno <= 0) {
+               return;
+       }
+
+       Seginfo_p = (struct SEGINFO *) 0;
+
+       /* get relevant info about each referenced coordinate */
+       line_p = mll_p->u.line_p;
+       x1info_p = find_coord(line_p->start.hor_p);
+       y1info_p = find_coord(line_p->start.vert_p);
+       x2info_p = find_coord(line_p->end.hor_p);
+       y2info_p = find_coord(line_p->end.vert_p);
+
+       if (x1info_p == (struct COORD_INFO *) 0
+                               || y1info_p == (struct COORD_INFO *) 0
+                               || x2info_p == (struct COORD_INFO *) 0
+                               || y2info_p == (struct COORD_INFO *) 0) {
+               /* must be an absolute coordinate */
+               return;
+       }
+
+       fname = mll_p->inputfile;
+       lineno = mll_p->inputlineno;
+
+       /* rule 1: if any invisible, ignore */
+       if ( is_invis(x1info_p) || is_invis(y1info_p) || is_invis(x2info_p)
+                                               || is_invis(y2info_p) ) {
+               /* not to be printed, so remove from main list */
+               unlinkMAINLL(mll_p);
+               /* don't free the space, since this way the function that
+                * called us can still do mll_p->next to get to the next
+                * item in list.  The space will never get reclaimed, but
+                * this case will be hit so rarely anyway, who cares
+                * about a few dead bytes? */
+               return;
+       }
+
+       /* rule 2:
+        * if there are any references to a builtin variable (like _cur)
+        * then there will be no split */
+       if ( is_builtin(x1info_p) || is_builtin(y1info_p)
+                       || is_builtin(x2info_p) || is_builtin(y2info_p) ) {
+               return;
+       }
+
+       /* rule 3:
+        * if all references are on same page and score, no split needed */
+       if ( (x1info_p->scorenum == y1info_p->scorenum)
+                       && (x1info_p->scorenum == x2info_p->scorenum)
+                       && (x1info_p->scorenum == y2info_p->scorenum)
+                       && (x1info_p->page == y1info_p->page)
+                       && (x1info_p->page == x2info_p->page)
+                       && (x1info_p->page == y2info_p->page) ) {
+               return;
+       }
+
+       /* rule 4:
+        * If x and y of a single INPCOORD are associated with different
+        * scores, we give up. (coordcheck ufatals if x and y are on
+        * different scores.)
+        */
+       coordcheck(x1info_p, y1info_p, fname, lineno);
+       coordcheck(x2info_p, y2info_p, fname, lineno);
+
+       /* rule 5:
+        * if x and y are associated with different staffs,
+        * make effective staff that of the y coordinate. */
+       /* figure out which staff the beginning is associated with */
+       p1staff = eff_staff(y1info_p);
+
+       /* figure out which staff end of line is associated with */
+       p2staff = eff_staff(y2info_p);
+
+       /* rule 6:
+        * Arrrgh! The line will have to be split. No specific code to do
+        * for this rule...the mere fact that we are here indicates rule 6
+        * has been satisfied */
+
+       /* rule 7:
+        *  Make sure x2 is not behind x1. */
+       if (x2info_p->page < x1info_p->page ||
+                       (x2info_p->page == x1info_p->page &&
+                       x2info_p->scorenum < x1info_p->scorenum)) {
+               l_ufatal(fname, lineno,
+                               "can't draw line backwards to previous score");
+       }
+
+       /* So... there will have to be at least 1 more LINE struct
+        * (more if the end is more than 1 score away) */
+       new_mll_p = newMAINLLstruct(S_LINE, -1);
+       new_mll_p->inputfile = mll_p->inputfile;
+       end_line_p = new_mll_p->u.line_p;
+       end_line_p->linetype = (short) line_p->linetype;
+
+       /* the new LINE will have its end equal to what the original LINE had */
+       end_line_p->end = line_p->end;
+
+       /* Start out with end of first segment the same as its
+        * start. Later, we'll add appropriate x and y offsets. */
+       line_p->end = line_p->start;
+
+       /* start out with last segment's beginning the same as its end.
+        * In a bit, we'll adjust the x and y appropriately. */
+       end_line_p->start = end_line_p->end;
+
+       /* rule 8:
+        * finding the x's of the new pieces isn't too bad... */
+
+       /* the end x of the first segment is just like the beginning x,
+        * but offset to the east far enough to
+        * reach the end of the score. */
+       seg1xlen = PGWIDTH - eff_rightmargin(mll_p) - inpc_x( &(line_p->start),
+                                       fname, lineno );
+
+       /* handle bizarre case of beginning being too far right to deal
+        * with properly */
+       if (seg1xlen < 0.1) {
+               seg1xlen = 0.1;
+       }
+       /* convert inches to stepsizes, which is how offset are stored */
+       line_p->end.hsteps += seg1xlen / STEPSIZE;
+
+       /* the begin x of the last segment is at the pseudo-bar */
+       /* The relevant clefsig should be immediately after the FEED
+        * associated with y2 */
+       mll_clefsig_p = y2info_p->mll_feed_p->next;
+       if (mll_clefsig_p->str != S_CLEFSIG) {
+               pfatal("missing clefsig info after newscore");
+       }
+
+       /* fill in x of beginning of final segment based on the pseudo-bar */
+       end_line_p->start.hor_p = mll_clefsig_p->u.clefsig_p->bar_p->c;
+       end_line_p->start.htype = AX;
+       end_line_p->start.hsteps = 0.0;
+       end_line_p->start.counts = 0.0;
+
+       /* effective distance in x direction will be the sum of the lengths of
+        * the first and last line segments and any intervening. We already
+        * know the length of the first segment and and now
+        * determine the lengths of the last segment. */
+       seg1xlen = inpc_x( &(line_p->end), fname, lineno)
+                       - inpc_x( &(line_p->start), fname, lineno);
+       seg2xlen = inpc_x( &(end_line_p->end), fname, lineno)
+                       - inpc_x( &(end_line_p->start), fname, lineno);
+
+       /* rule 8a */
+       /* check for intervening scores and find the effective length in
+        * the X direction. */
+       effective_x_len = find_effXlength(seg1xlen, seg2xlen, x1info_p,
+                                                       x2info_p, YES);
+
+       /* now find y values */
+
+       /* figure out the first segment y relative to the effective staff */
+       for (m_p = x1info_p->mll_feed_p; m_p != (struct MAINLL *) 0;
+                                                       m_p = m_p->next) {
+               if (m_p->str == S_STAFF &&
+                               m_p->u.staff_p->staffno == p1staff) {
+                       break;
+               }
+       }
+       offset = inpc_y( &(line_p->start), fname, lineno)
+                       - m_p->u.staff_p->c[AY];
+
+       /* rule 9:
+        * First we tackle the easy (relatively speaking) case of both
+        * coordinates being associated with the same staff. */
+       if (p1staff == p2staff) {
+
+               /* calculate y values based on slope */
+               slope = ((end_line_p->end.vert_p[RY]
+                               + end_line_p->end.vsteps * STEPSIZE) -
+                               (line_p->start.vert_p[RY]
+                               + line_p->start.vsteps * STEPSIZE))
+                               / effective_x_len;
+
+               /* use the slope to the end y of the first segment and
+                * begin y of the last segment, converted to stepsizes */
+               line_p->end.vsteps += (slope * seg1xlen) / STEPSIZE;
+               end_line_p->start.vsteps -= (slope * seg2xlen) / STEPSIZE;
+
+               /* if need more than 2 line segments
+                * do the rest of them */
+               for (seg_p = Seginfo_p; seg_p != (struct SEGINFO *) 0;  ) {
+
+                       add_segment(seg_p, slope, offset, p1staff,
+                                                       line_p->linetype);
+
+                       /* move on the next segment in list, if any. First
+                        * remember current one so we can free it, then move
+                        * to next, then free the one we just finished with */
+                       to_free_p = seg_p;
+                       seg_p = seg_p->next;
+                       FREE(to_free_p);
+               }
+       }
+
+       else {
+               /* ends are associated with different staffs */
+               double y1, y2;
+
+               /* find two slopes, one for the beginning line segment, one
+                * for the end. For each, base the slope on the distance
+                * between the two effective staffs, adjusted by the
+                * appropriate offset from those staffs. */
+               y1 = end_line_p->end.vert_p[RY]
+                               + end_line_p->end.vsteps * STEPSIZE;
+               y2 = line_p->start.vert_p[RY]
+                               + line_p->start.vsteps * STEPSIZE;
+               slope = ( (getYstaff(y1info_p->mll_feed_p, p2staff) + y1) -
+                       (getYstaff(y1info_p->mll_feed_p, p1staff) + y2) )
+                       / effective_x_len;
+               line_p->end.vsteps += (slope * seg1xlen) / STEPSIZE;
+
+               slope = ( (getYstaff(y2info_p->mll_feed_p, p2staff) + y1) -
+                       (getYstaff(y2info_p->mll_feed_p, p1staff) + y2) )
+                       / effective_x_len;
+               end_line_p->start.vsteps -= (slope * seg2xlen) / STEPSIZE;
+
+               /* if need more than 2 line segments
+                * do the rest of them */
+               for (seg_p = Seginfo_p; seg_p != (struct SEGINFO *) 0;  ) {
+
+                       slope = ( (getYstaff(seg_p->mll_p, p2staff) + y1) -
+                               (getYstaff(seg_p->mll_p, p1staff) + y2) )
+                               / effective_x_len;
+
+                       add_segment(seg_p, slope, offset, p1staff,
+                                                       line_p->linetype);
+
+                       /* move on the next segment in list, if any. First
+                        * remember current one so we can free it, then move
+                        * to next, then free the one we just finished with */
+                       to_free_p = seg_p;
+                       seg_p = seg_p->next;
+                       FREE(to_free_p);
+               }
+       }
+
+       /* link end_line_p into proper place in main list */
+       /* this will be right before the first BAR after the FEED associated
+        * with y2 */
+       for (m_p = mll_clefsig_p->next; m_p->str != S_BAR; m_p = m_p->next) {
+               ;
+       }
+       insertMAINLL(new_mll_p, m_p->prev);
+}
+\f
+
+/* check if location variables associated with an x and y point to at least
+ * the same score on the same page. If not, give up */
+
+static void
+coordcheck(x_info_p, y_info_p, fname, lineno)
+
+struct COORD_INFO *x_info_p;
+struct COORD_INFO *y_info_p;
+char *fname;
+int lineno;
+
+{
+       if (x_info_p == (struct COORD_INFO *) 0 ||
+                               y_info_p == (struct COORD_INFO *) 0) {
+               pfatal("coordinate not in table\n");
+       }
+
+       if ( (x_info_p->flags & CT_BUILTIN) || (y_info_p->flags & CT_BUILTIN)) {
+               /* if any reference to builtin tag, leave as is */
+               return;
+       }
+
+       if ( (x_info_p->scorenum != y_info_p->scorenum)
+                       || (x_info_p->page != y_info_p->page) ) {
+               l_ufatal(fname, lineno,
+                       "x and y cannot be associated with different scores");
+       }
+}
+\f
+
+/* given info about a coord, return its effective staff. This is the staff
+ * associated with the info if any, otherwise the top visible staff */
+
+static int
+eff_staff(yinfo_p)
+
+struct COORD_INFO *yinfo_p;
+
+{
+       int staff;
+
+
+       if (yinfo_p->staffno != 0) {
+               staff = yinfo_p->staffno;
+       }
+       else {
+               /* use top visible staff as effective staff */
+               for (staff = 1; staff <= Score.staffs; staff++) {
+                       if (svpath(staff, VISIBLE)->visible == YES) {
+                               break;
+                       }
+               }
+       }
+       return(staff);
+}
+\f
+
+/* find the total effective length of a line or curve, accounting for all
+ * intervening scores. For each intermediate score, if the save_feed_info
+ * flag is set, save away information for use in adding
+ * a line or curve for that score */
+
+static double
+find_effXlength(seg1xlen, seg2xlen, x1info_p, x2info_p, save_feed_info)
+
+double seg1xlen;       /* length of first part */
+double seg2xlen;       /* length of last part */
+struct COORD_INFO *x1info_p;   /* info about beginning point */
+struct COORD_INFO *x2info_p;   /* info about last point */
+int save_feed_info;    /* if YES, do svfeed() call, otherwise not */
+
+{
+       double effective_x_len;
+       struct MAINLL *m_p;     /* to search main list */
+
+
+       /* start out with length of first segment */
+       effective_x_len = seg1xlen;
+
+       /* check if there might be one or more intervening scores. If the
+        * end point is on the next page, there might be. If both are on
+        * the same page, with the first having a scorenum greater than
+        * the first one plus one, then there is an intervening score
+        * for sure. */
+       if (x2info_p->page > x1info_p->page ||
+                       (x2info_p->page == x1info_p->page &&
+                       x2info_p->scorenum > x1info_p->scorenum + 1)) {
+               /* search forward in main list. Every time we find
+                * a matching newscore that isn't the one associated with
+                * the last segment, save info to be able to
+                * add an intervening line. Also add the length of that line
+                * to the effective x length. */
+               for (m_p = x1info_p->mll_feed_p->next;
+                               m_p != (struct MAINLL *) 0; m_p = m_p->next) {
+                       if (IS_CLEFSIG_FEED(m_p)) {
+                               if (m_p == x2info_p->mll_feed_p) {
+                                       /* hurray! We found the score with
+                                        * the last line segment. No more to
+                                        * add */
+                                       break;
+                               }
+                               else {
+                                       /* need to add another line segment */
+                                       if (m_p->next != (struct MAINLL *) 0 &&
+                                               m_p->next->str == S_CLEFSIG &&
+                                               m_p->next->u.clefsig_p->bar_p
+                                               != (struct BAR *) 0) {
+                                          if (save_feed_info == YES) {
+                                               svfeed(m_p, effective_x_len);
+                                          }
+                                          effective_x_len += PGWIDTH
+                                             - eff_rightmargin(m_p) -
+                                             m_p->next->u.clefsig_p->bar_p->c[AX];
+                                       }
+                                       else {
+                                               pfatal("error in main list while splitting lines");
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /* add in length of final segment */
+       effective_x_len += seg2xlen;
+
+       return(effective_x_len);
+}
+\f
+
+/* allocate SEGINFO and fill it in  */
+
+static void
+svfeed(mll_feed_p, xlength)
+
+struct MAINLL *mll_feed_p;
+double xlength;
+
+{
+       struct SEGINFO *new_p;
+
+
+       MALLOC(SEGINFO, new_p, 1);
+       new_p->mll_p = mll_feed_p;
+       new_p->xlength = xlength;
+
+       /* link onto list */
+       new_p->next = Seginfo_p;
+       Seginfo_p = new_p;
+}
+\f
+
+/* add LINE for intervening scores */
+
+static void
+add_segment(seginfo_p, slope, y_offset, staffno1, linetype)
+
+struct SEGINFO *seginfo_p;
+double slope;
+double y_offset;       /* offset from staff of beginning point */
+int staffno1;  /* staff associated with y of beginning */
+int linetype;
+
+{
+       struct MAINLL *m_p;             /* index through main list */
+       struct MAINLL *new_mll_p;       /* points to new LINE */
+       struct LINE *new_line_p;        /* LINE connected to new_mll_p */
+       double xleng;                   /* distance to end in x direction */
+
+
+       /* create a new LINE */
+       new_mll_p = newMAINLLstruct(S_LINE, -1);
+       new_line_p = new_mll_p->u.line_p;
+       new_line_p->linetype = linetype;
+
+       /* x coords of the line are at the pseudobar and the rightmargin. We
+        * get to the right margin by adding the correct number of stepsizes
+        * from the pseudobar */
+       new_line_p->start.hor_p = seginfo_p->mll_p->next->u.clefsig_p->bar_p->c;
+       new_line_p->start.htype = AX;
+       new_line_p->start.hsteps = 0.0;
+       new_line_p->start.counts = 0.0;
+       new_line_p->end.hor_p = new_line_p->start.hor_p;
+       new_line_p->end.htype = AX;
+       xleng = PGWIDTH - eff_rightmargin(seginfo_p->mll_p)
+                                        - new_line_p->start.hor_p[AX];
+       new_line_p->end.hsteps = xleng / STEPSIZE;
+       new_line_p->end.counts = 0.0;
+
+       /* find staff coord info */
+       for (m_p = seginfo_p->mll_p; m_p != (struct MAINLL *) 0;
+                                                       m_p = m_p->next) {
+               if (m_p->str == S_STAFF && m_p->u.staff_p->staffno == staffno1) {
+                       break;
+               }
+       }
+       /* y coords are determined from the slope */
+       new_line_p->start.vert_p = m_p->u.staff_p->c;
+       new_line_p->start.vtype = AY;
+       new_line_p->start.vsteps = (y_offset + (slope * seginfo_p->xlength))
+                                                       / STEPSIZE;
+       new_line_p->end.vert_p = m_p->u.staff_p->c;
+       new_line_p->end.vtype = AY;
+       new_line_p->end.vsteps = (y_offset +
+                       (slope * (xleng + seginfo_p->xlength))) / STEPSIZE;
+
+       /* link into proper place in main list */
+       /* this will be right before the first BAR after the FEED */
+       for (m_p = seginfo_p->mll_p->next; m_p != (struct MAINLL *) 0;
+                                               m_p = m_p->next) {
+               if (m_p->str == S_BAR) {
+                       break;
+               }
+       }
+
+       if (m_p == (struct MAINLL *) 0) {
+               pfatal("couldn't find bar while adding line segment");
+       }
+
+       insertMAINLL(new_mll_p, m_p->prev);
+}
+\f
+
+/* given a MAINLL and a staff number, return the absolute Y of the staff
+ * searching forward from the MAINLL */
+
+static double
+getYstaff(mll_p, staffno)
+
+struct MAINLL *mll_p;
+int staffno;
+
+{
+       for (    ; mll_p != (struct MAINLL *) 0; mll_p = mll_p->next) {
+               if (mll_p->str == S_STAFF) {
+                       if (mll_p->u.staff_p->staffno == staffno) {
+                               return(mll_p->u.staff_p->c[AY]);
+                       }
+               }
+       }
+       pfatal("couldn't find Y of staff");
+       /*NOTREACHED*/
+       return(0.0);
+}
+\f
+
+/* check whether a CURVE needs to be split. If so, split it */
+
+static void
+chkcurve(mll_p)
+
+struct MAINLL *mll_p;  /* points to CURVE */
+
+{
+       struct CURVE *curve_p;
+       struct COORD_INFO *x1info_p, *y1info_p, *x2info_p, *y2info_p;
+       int bulge;              /* 1 for UP or -1 for DOWN */
+       register int n;
+       int j;
+       int curscore, curpage;  /* current score and page */
+       int is_split = NO;
+       int p1staff, p2staff;   /* staff associate with each endpoint */
+       struct MAINLL *new_mll_p;       /* place for 2nd part of split curve */
+       struct MAINLL *m_p;             /* to find place in list to insert */
+       struct CURVE *new_crv_p;        /* points for second part */
+       int ncoord1, ncoord2;   /* number of coords in each piece */
+       int add1, add2;         /* 1 if need to add another point to the
+                                * first of second piece of the curve,
+                                * 0 if not */
+       float offset;
+       struct MAINLL *mll_clefsig_p;   /* clefsig for score where part of
+                                        * a curve goes */
+       double seg1xlen, seg2xlen;      /* length of begin and end parts */
+       double effective_x_len;         /* total length in X direction */
+       double slope;                   /* of line */
+       int index1, index2;             /* into coordlist array */
+       char *fname;
+       int lineno;
+       struct SEGINFO *seg_p, *to_free_p;      /* to deal with curves for
+                                        * intermediate scores */
+       double addedx;          /* x of endpoint that we added */
+       double userx;           /* x of nearest user-defined point */
+       double y1, y2;
+
+
+       curve_p = mll_p->u.curve_p;
+       fname = mll_p->inputfile;
+       lineno = mll_p->inputlineno;
+       curscore = curpage = -1;
+
+       Seginfo_p = (struct SEGINFO *) 0;
+
+       for (n = 0; n < curve_p->ncoord; n++) {
+
+               x1info_p = find_coord( curve_p->coordlist[n].hor_p);
+               y1info_p = find_coord( curve_p->coordlist[n].vert_p);
+
+               if (x1info_p == (struct COORD_INFO *) 0 ||
+                               y1info_p == (struct COORD_INFO *) 0) {
+                       /* must be an absolute coordinate */
+                       continue;
+               }
+
+               /* rule 1: if any coordinate on the list
+                * is associated with something
+                * invisible, ignore the whole curve. */
+               if ( is_invis(x1info_p) || is_invis(y1info_p) ) {
+
+                       /* as with lines, unlink so we don't print, but
+                        * don't free, so that calling function can still
+                        * follow the ->next pointer */
+                       unlinkMAINLL(mll_p);
+                       return;
+               }
+
+               /* rule 4. Check that x and y are on same score */
+               coordcheck(x1info_p, y1info_p, fname, lineno);
+
+               /* rule 3 checking. See if all on same score/page */
+               if (curpage == -1) {
+                       curscore = x1info_p->scorenum;
+                       curpage = x1info_p->page;
+               }
+               else {
+                       if (curscore != x1info_p->scorenum ||
+                                       curpage != x1info_p->page) {
+                               is_split = YES;
+                       }
+               }
+       }
+
+       /* If this curve was specified using bulge parameters, go calculate
+        * the intermediate points */
+       if (curve_p->nbulge > 0) {
+               calc_bulge(curve_p, fname, lineno, is_split, mll_p);
+               /* some INPCOORDs might well point off the page, so fix those */
+               fix_inpcoords(mll_p);
+       }
+
+       /* finish rule 3 checking. If all were on same score, we are done */
+       if (is_split == NO) {
+               return;
+       }
+
+       /* go through curve points a pair at a time */
+       for (n = 0; n < curve_p->ncoord - 1; n++) {
+               x1info_p = find_coord( curve_p->coordlist[n].hor_p);
+               y1info_p = find_coord( curve_p->coordlist[n].vert_p);
+               x2info_p = find_coord( curve_p->coordlist[n + 1].hor_p);
+               y2info_p = find_coord( curve_p->coordlist[n + 1].vert_p);
+
+               if (x1info_p == (struct COORD_INFO *) 0
+                               || y1info_p == (struct COORD_INFO *) 0
+                               || x2info_p == (struct COORD_INFO *) 0
+                               || y2info_p == (struct COORD_INFO *) 0) {
+                       /* absolute coordinate */
+                       continue;
+               }
+
+               /* rule 2. If any builtin variable used,
+                * no split of this segment */
+               if ( is_builtin(x1info_p) || is_builtin(y1info_p) ||
+                               is_builtin(x2info_p) || is_builtin(y2info_p) ) {
+                       continue;
+               }
+
+               /* rule 6. If both ends of segment are on same page/score
+                * no split of this segment */
+               if ( (x1info_p->scorenum == y1info_p->scorenum)
+                               && (x1info_p->scorenum == x2info_p->scorenum)
+                               && (x1info_p->scorenum == y2info_p->scorenum)
+                               && (x1info_p->page == y1info_p->page)
+                               && (x1info_p->page == x2info_p->page)
+                               && (x1info_p->page == y2info_p->page) ) {
+                       continue;
+               }
+
+               /* rule 7. Only split to forward score */
+               if (x2info_p->page < x1info_p->page ||
+                               (x2info_p->page == x1info_p->page &&
+                               x2info_p->scorenum < x1info_p->scorenum)) {
+                       l_ufatal(mll_p->inputfile, mll_p->inputlineno,
+                               "can't draw curve backwards to previous score");
+               }
+
+               /* if we're here, segment must be split */
+
+               /* figure out if curve generally bulges up or down */
+               bulge = bulgedir(curve_p, n, mll_p->inputfile,
+                                                       mll_p->inputlineno);
+
+               /* get effective staffs */
+               p1staff = eff_staff(y1info_p);
+               p2staff = eff_staff(y2info_p);
+
+               /* set up first part of split curve. It will have as many
+                * coords as we have so far, unless that is only 2, in which
+                * case we have to add another, because a curve must have at
+                * least three points */
+               if (n == 0) {
+                       ncoord1 = 3;
+                       add1 = 1;
+               }
+               else {
+                       ncoord1 = n + 2;
+                       add1 = 0;
+               }
+               /* similarly, the second portion has as many points as are
+                * left, or a minimum of 3 */
+               if (curve_p->ncoord - n == 2) {
+                       ncoord2 = 3;
+                       add2 = 1;
+               }
+               else {
+                       ncoord2 = curve_p->ncoord - n;
+                       add2 = 0;
+               }
+
+               /* Split off the second part into a separate curve */
+               new_mll_p = newMAINLLstruct(S_CURVE, mll_p->inputlineno);
+               new_mll_p->inputfile = mll_p->inputfile;
+               new_crv_p = new_mll_p->u.curve_p;
+               new_crv_p->curvetype = curve_p->curvetype;
+               new_crv_p->ncoord = (short) ncoord2;
+               MALLOC (INPCOORD, new_crv_p->coordlist, ncoord2);
+
+               /* copy second part into second curve. Copy backwards from
+                * the end, but don't fill in the first point of it, because
+                * we still need to calculate that */
+               for (ncoord2--, j = curve_p->ncoord - 1; ncoord2 > 0 + add2;
+                                                       ncoord2--, j--) {
+                       new_crv_p->coordlist[ncoord2] = curve_p->coordlist[j];
+               }
+
+               /* realloc space for first part of curve, with just the
+                * points needed */
+               REALLOC(INPCOORD, curve_p->coordlist, ncoord1);
+               curve_p->ncoord = (short) ncoord1;
+
+               /* find new endpoints for the split ends */
+
+               /* the end x of the first segment is just like the beginning x,
+                * but offset to the east far enough to
+                * reach the end of the score. */
+               curve_p->coordlist[ncoord1 - 1] = curve_p->coordlist[0];
+               offset = PGWIDTH - eff_rightmargin(mll_p)
+                               - inpc_x( &(curve_p->coordlist[0]),
+                               fname, lineno );
+
+               /* handle bizarre case of beginning being too far right to deal
+                * with properly */
+               if (offset < 0.1) {
+                       offset = 0.1;
+               }
+               /* convert inches to stepsizes,
+                * which is how offset are stored */
+               curve_p->coordlist[ncoord1 - 1].hsteps
+                                               += offset / STEPSIZE;
+
+               /* the begin x of the last segment is at the pseudo-bar */
+               /* The relevant clefsig should be immediately after the FEED
+                * associated with y2 */
+               mll_clefsig_p = y2info_p->mll_feed_p->next;
+               if (mll_clefsig_p->str != S_CLEFSIG) {
+                       pfatal("missing clefsig info after newscore");
+               }
+
+
+               /* fill in x of beginning of final part based
+                * on the pseudo-bar */
+               new_crv_p->coordlist[0].hor_p
+                               = mll_clefsig_p->u.clefsig_p->bar_p->c;
+               new_crv_p->coordlist[0].htype = AX;
+               new_crv_p->coordlist[0].hsteps = 0.0;
+               new_crv_p->coordlist[0].counts = 0.0;
+
+               /* If the first user defined point on the subsequent score
+                * is extremely close to the pseudo-bar where we want to
+                * start this segment, or worse yet, is west of it
+                * (because they specified a negative offset that makes the
+                * curve bend back into the preceeding measure),
+                * we move the beginning point that we added,
+                * to make it 0.1 inch west of the user's point.
+                * This is not the same remedial action as we take later for
+                * the somewhat similar case at the end of the preceeding score.
+                * The argument for this lack of symmetry is that when
+                * carrying out from the end of a score, we don't want to
+                * spill out into the margin--it's better to end the curve
+                * a tiny bit too early. On the other hand, at the beginning
+                * of a score, there is probably some room in the
+                * clef/key/time area to allow starting somewhat earlier
+                * than the pseudo-bar and still look okay.
+                * Also, if the user did do some crazy curve that would
+                * bend back into the preceeding measure, it's just too
+                * hard to try to do anything about that on the preceeding
+                * score, but we can make it bend back prior to the
+                * pseudobar, which can sort of honor what they asked for.
+                */
+               addedx = inpc_x( &(new_crv_p->coordlist[0]), fname, lineno );
+               userx = inpc_x( &(new_crv_p->coordlist[1+add2]), fname, lineno );
+               if (userx - addedx < 0.1) {
+                       new_crv_p->coordlist[0].hsteps =
+                                       (-0.1 + (userx - addedx)) / STEPSIZE;
+               }
+
+               /* use the last user defined point (the one immediately
+                * before the one or two points we just added to the
+                * first part) as a reference point */
+               index1 = (add1 ? 0 : curve_p->ncoord - 2);
+               /* similarly, use first user-defined point of last part */
+               index2 = (add2 ? 2 : 1);
+
+               /* find y values for split ends  */
+
+               /* copy vertical info from nearest point, will adjust vsteps
+                * later as needed based on slope */
+               curve_p->coordlist[ncoord1 - 1].vert_p =
+                               curve_p->coordlist[index1].vert_p;
+               curve_p->coordlist[ncoord1 - 1].vtype =
+                               curve_p->coordlist[index1].vtype;
+               curve_p->coordlist[ncoord1 - 1].vsteps =
+                               curve_p->coordlist[index1].vsteps;
+               new_crv_p->coordlist[0].vert_p =
+                               new_crv_p->coordlist[index2].vert_p;
+               new_crv_p->coordlist[0].vtype =
+                               new_crv_p->coordlist[index2].vtype;
+               new_crv_p->coordlist[0].vsteps =
+                               new_crv_p->coordlist[index2].vsteps;
+
+               /* first need to find effective length in X direction for
+                * determining slope */
+               seg1xlen = offset;
+               seg2xlen = inpc_x( &(new_crv_p->coordlist[index2]), fname, lineno)
+                       - inpc_x( &(new_crv_p->coordlist[0]), fname, lineno);
+               effective_x_len = find_effXlength(seg1xlen, seg2xlen, x1info_p,
+                                               x2info_p, YES);
+
+               /* figure out the first part's y relative
+                * to the effective staff */
+               for (m_p = x1info_p->mll_feed_p; m_p != (struct MAINLL *) 0;
+                                                       m_p = m_p->next) {
+                       if (m_p->str == S_STAFF &&
+                                       m_p->u.staff_p->staffno == p1staff) {
+                               break;
+                       }
+               }
+               offset = inpc_y( &(curve_p->coordlist[index1]),
+                               fname, lineno) - m_p->u.staff_p->c[AY];
+
+               /* find two slopes, one for the beginning line segment,
+                * one for the end. For each, base the slope
+                * on the distance between the two effective staffs,
+                * adjusted by the appropriate offset
+                * from those staffs. */
+               y1 = new_crv_p->coordlist[index2].vert_p[RY] +
+                               new_crv_p->coordlist[index2].vsteps * STEPSIZE;
+               y2 = curve_p->coordlist[index1].vert_p[RY]
+                               + curve_p->coordlist[index1].vsteps * STEPSIZE;
+               slope = ((getYstaff(y1info_p->mll_feed_p, p2staff) + y1)
+                           - (getYstaff(y1info_p->mll_feed_p, p1staff) + y2))
+                           / effective_x_len;
+               curve_p->coordlist[ncoord1 - 1].vsteps
+                                       += (slope * seg1xlen) / STEPSIZE;
+
+               slope = ((getYstaff(y2info_p->mll_feed_p, p2staff) + y1) -
+                               (getYstaff(y2info_p->mll_feed_p, p1staff) + y2))
+                               / effective_x_len;
+                               new_crv_p->coordlist[0].vsteps
+                                       -= (slope * seg2xlen) / STEPSIZE;
+
+               /* if need more than 2 curve segments
+                * do the rest of them */
+               for (seg_p = Seginfo_p; seg_p != (struct SEGINFO *) 0;  ) {
+
+                       slope = ((getYstaff(seg_p->mll_p, p2staff) + y1)
+                                   - (getYstaff(seg_p->mll_p, p1staff) + y2))
+                                   / effective_x_len;
+
+                       add_crv_seg(seg_p, slope, offset, p1staff,
+                               curve_p->curvetype, bulge, fname, lineno);
+
+                       /* move on the next segment in list, if any.
+                        * First remember current one so we can free it,
+                        * then move to next, then free the one
+                        * we just finished with */
+                       to_free_p = seg_p;
+                       seg_p = seg_p->next;
+                       FREE(to_free_p);
+               }
+
+               /* If there was a user-defined point extremely close to
+                * where we did the split (which is moderately likely,
+                * since they may well specific a point at a bar line),
+                * or even worse, if the one we added somehow came out
+                * to the left of the user-defined point,
+                * the curve could end up looking very strange since it
+                * contains a very tiny segment. So in that case we discard
+                * the extra point we added as the end of the split place,
+                * and just use the user-defined point.
+                */
+               addedx = inpc_x( &(curve_p->coordlist[ncoord1 - 1]), fname, lineno);
+               userx = inpc_x( &(curve_p->coordlist[ncoord1 - 2]), fname, lineno);
+               if (add1 == 0 && (fabs(addedx - userx) < 0.1 || userx > addedx)) {
+                       if (ncoord1 == 3) {
+                               /* If discarding a point would get us down
+                                * to only two points, we'll discard the
+                                * user's point, by marking that we need to
+                                * fill in an extra point in the middle
+                                * (at subscript [1]). The ending point we added
+                                * at [2] is so close that no one should
+                                * notice. */
+                               add1 = 1;
+                       }
+                       else {
+                               /* We already had more than 3 points,
+                                * so we'll just ignore the extra one we
+                                * added. The previous user-defined point
+                                * is close enough to where it should end.
+                                * It isn't worth the trouble to reclaim
+                                * the extra array element; just let it leak.
+                                */
+                               ncoord1--;
+                               curve_p->ncoord = ncoord1;
+                       }
+               }
+
+               /* if first part of curve ended up with only a single segment,
+                * need to add another point in the middle to make the
+                * required minimum of 3 points for a curve. So copy the
+                * first point, adjust the x to be halfway between the first
+                * and last point, and adjust the y to be halfway between the
+                * the y's of the endpoint, offset by a little bit to get
+                * a bend in the curve. */
+               if (add1 == 1) {
+                       curve_p->coordlist[1] = curve_p->coordlist[0];
+                       curve_p->coordlist[1].hsteps =
+                                       (curve_p->coordlist[0].hsteps
+                                       + curve_p->coordlist[2].hsteps) / 2.0;
+                       curve_p->coordlist[1].counts =
+                                       (curve_p->coordlist[0].counts
+                                       + curve_p->coordlist[2].counts) / 2.0;
+                       /* the square root is to make the amount of bulge
+                        * proportional to the x length, 1 stepsize for a
+                        * piece 1 inch long, less for shorter pieces,
+                        * more for longer pieces */
+                       curve_p->coordlist[1].vsteps =
+                                       (curve_p->coordlist[0].vsteps
+                                       + curve_p->coordlist[2].vsteps) / 2.0
+                                       + (bulge * sqrt(seg1xlen * Score.scale_factor));
+               }
+
+               /* similarly for the ending part of curve */
+               if (add2 == 1) {
+                       new_crv_p->coordlist[1] = new_crv_p->coordlist[0];
+                       new_crv_p->coordlist[1].hsteps =
+                                       (seg2xlen / 2.0) / STEPSIZE;
+                       new_crv_p->coordlist[1].counts = 0.0;
+                       /* the square root is to make the amount of bulge
+                        * proportional to the x length, 1 stepsize for a
+                        * piece 1 inch long, less for shorter pieces,
+                        * more for longer pieces */
+                       new_crv_p->coordlist[1].vsteps =
+                                       (new_crv_p->coordlist[0].vsteps
+                                       + new_crv_p->coordlist[2].vsteps) / 2.0
+                                       + (bulge * sqrt(seg2xlen * Score.scale_factor));
+               }
+
+
+               /* link new_mll_p into proper place in main list */
+               /* this will be right before the first BAR after
+                * the FEED associated with y2 */
+               for (m_p = mll_clefsig_p->next; m_p->str != S_BAR;
+                                                       m_p = m_p->next) {
+                       ;
+               }
+               insertMAINLL(new_mll_p, m_p->prev);
+
+               /* If the rest of the curve requires further splitting,
+                * we do that now, then break out of this loop */
+               chkcurve(new_mll_p);
+               break;
+       }
+}
+\f
+
+/* try to determine whether a user-defined curve generally bulged upward
+ * or downward and return 1 for up or -1 for down as appropriate.
+ * If intermediate points
+ * seem to be mainly higher than the endpoints it is probably up, if they
+ * tend to be below the endpoints, it is probably down. */
+
+static int
+bulgedir(curve_p, index, inputfile, inputlineno)
+
+struct CURVE *curve_p;
+int index;             /* check bulge dir between this point in array and
+                        * the next one */
+char *inputfile;       /* where curve was defined */
+int inputlineno;
+
+{
+       int retval = 0;
+
+       
+       if (index == 0 || index == curve_p->ncoord - 2) {
+               /* if checking an end of the curve, we use the two end
+                * segments to guess the direction */
+               retval += cmpcoords(curve_p, 0, 1);
+               retval += cmpcoords(curve_p, curve_p->ncoord - 1,
+                                       curve_p->ncoord - 2);
+               /* if more than 3 points in curve, we can use the adjacent
+                * segment on the one side where there is an adjacent segment
+                * as another reference point */
+               if (curve_p->ncoord > 3) {
+                       if (index == 0) {
+                               retval += cmpcoords(curve_p, 1, 2);
+                       }
+                       else {
+                               retval += cmpcoords(curve_p,
+                                               curve_p->ncoord - 2,
+                                               curve_p->ncoord - 3);
+                       }
+               }
+       }
+       else {
+               /* for a segment in the middle, use the segments on
+                * either side for reference */
+               retval += cmpcoords(curve_p, index - 1, index);
+               retval += cmpcoords(curve_p, index + 2, index + 1);
+               /* if that was inconclusive, try using the endpoints */
+               if (retval == 0) {
+                       retval += cmpcoords(curve_p, 0, 1);
+                       retval += cmpcoords(curve_p, curve_p->ncoord - 1,
+                                       curve_p->ncoord - 2);
+               }
+       }
+
+       if (retval == 0) {
+               /**** eventually try more drastic measures to try to deduce
+                *** the direction??? It's debatable about whether this should
+                * be a ufatal or pfatal. The program should be smart enough
+                * to figure out the direction, but probably can't be that
+                * smart for just any arbitrary curve shape
+                * the user tries to throw at it, and
+                * user can probably always manage to get what they want by
+                * specifying enough points, so make ufatal. */
+               l_ufatal(inputfile, inputlineno,
+                       "can't determine curve bend direction; try specifying more points");
+       }
+       return (retval > 0 ? 1 : -1);
+}
+\f
+
+/* return 1 if point p1 appears to be below point p2. Return -1 if p1 appears
+ * to be above point p2. Return 0 if can't tell */
+
+static int
+cmpcoords(curve_p, p1, p2)
+
+struct CURVE *curve_p;
+int p1;
+int p2;
+
+{
+       struct COORD_INFO *y1info_p, *y2info_p;
+       int staff1, staff2;
+       double y1, y2;
+
+
+       /* check the two points */
+       y1info_p = find_coord(curve_p->coordlist[p1].vert_p);
+       y2info_p = find_coord(curve_p->coordlist[p2].vert_p);
+
+       if ((y1info_p == (struct COORD_INFO *) 0)
+                               || (y2info_p == (struct COORD_INFO *) 0)) {
+               pfatal("couldn't find coord info in cmpcoords");
+       }
+
+       /* if on same score, can compare the absolute Y values */
+       if (y1info_p->mll_feed_p == y2info_p->mll_feed_p) {
+               y1 = inpc_y( &(curve_p->coordlist[p1]), (char *) 0, -1);
+               y2 = inpc_y( &(curve_p->coordlist[p2]), (char *) 0, -1);
+               if (y1 < y2) {
+                       return(1);
+               }
+               else if (y2 < y1) {
+                       return(-1);
+               }
+       }
+       else {
+               /* weren't on same score. See if associated with same staff.
+                * If so, we can compare the relative Y values. If associated
+                * with different staffs, if second point is with lower staff
+                * it probably bulges downward. */
+               staff1 = eff_staff(y1info_p);
+               staff2 = eff_staff(y2info_p);
+               if (staff1 == staff2) {
+                       y1 = curve_p->coordlist[p1].vert_p
+                               [abs2rel(curve_p->coordlist[p1].vtype)]
+                               + (curve_p->coordlist[p1].vsteps * STEPSIZE
+                               * svpath(staff1, STAFFSCALE)->staffscale);
+                       y2 = curve_p->coordlist[p2].vert_p
+                               [abs2rel(curve_p->coordlist[p2].vtype)]
+                               + (curve_p->coordlist[p2].vsteps * STEPSIZE
+                               * svpath(staff2, STAFFSCALE)->staffscale);
+                       if (y1 < y2) {
+                               return(1);
+                       }
+                       else if (y2 < y1) {
+                               return(-1);
+                       }
+               }
+               else if (staff1 < staff2) {
+                       /* first point higher, bends down */
+                       return(-1);
+               }
+               else {
+                       return(1);
+               }
+       }
+       return(0);
+}
+\f
+
+/* given a coord type of AY, AN, or AS, return its relative coord type,
+ * that is RY, RN, or RS respectively */
+
+static int
+abs2rel(vtype)
+
+int vtype;     /* AY, AN, or AS */
+
+{
+       switch(vtype) {
+       case AY:
+               return(RY);
+       case AN:
+               return(RN);
+       case AS:
+               return(RS);
+       default:
+               pfatal("illegal coordinate type in abs2rel");
+       }
+       /*NOTREACHED*/
+       return(0);
+}
+\f
+
+/* add CURVE for intervening scores */
+
+static void
+add_crv_seg(seginfo_p, slope, y_offset, staffno1, curvetype, bulge, filename, lineno)
+
+struct SEGINFO *seginfo_p;
+double slope;
+double y_offset;       /* offset from staff of beginning point */
+int staffno1;  /* staff associated with y of beginning */
+int curvetype;
+int bulge;     /* 1 for bulge up, -1 for bulge down */
+char *filename;        /* where original curve was defined */
+int lineno;    /* where original curve was defined */
+
+{
+       struct MAINLL *m_p;             /* index through main list */
+       struct MAINLL *new_mll_p;       /* points to new LINE */
+       struct CURVE *new_crv_p;        /* CURVE connected to new_mll_p */
+       double xleng;                   /* distance to end in x direction */
+
+
+       /* create a new CURVE */
+       new_mll_p = newMAINLLstruct(S_CURVE, lineno);
+       new_mll_p->inputfile = filename;
+       new_crv_p = new_mll_p->u.curve_p;
+       new_crv_p->curvetype = (short) curvetype;
+       new_crv_p->ncoord = 3;
+       MALLOC (INPCOORD, new_crv_p->coordlist, 3);
+
+       /* x coords of the curve ends are at the pseudobar and the rightmargin.
+        * The middle point, appropriately enough, is in the middle. We
+        * get to the right margin by adding the correct number of stepsizes
+        * from the pseudobar */
+       new_crv_p->coordlist[0].hor_p = seginfo_p->mll_p->next->u.clefsig_p->bar_p->c;
+       new_crv_p->coordlist[0].htype = AX;
+       new_crv_p->coordlist[0].hsteps = 0.0;
+       new_crv_p->coordlist[0].counts = 0.0;
+       new_crv_p->coordlist[2].hor_p = new_crv_p->coordlist[0].hor_p;
+       new_crv_p->coordlist[2].htype = AX;
+       xleng = PGWIDTH - eff_rightmargin(seginfo_p->mll_p)
+                                       - new_crv_p->coordlist[0].hor_p[AX];
+       new_crv_p->coordlist[2].hsteps = xleng / STEPSIZE;
+       new_crv_p->coordlist[2].counts = 0.0;
+       new_crv_p->coordlist[1].hor_p = new_crv_p->coordlist[0].hor_p;
+       new_crv_p->coordlist[1].htype = AX;
+       new_crv_p->coordlist[1].hsteps = (xleng / 2.0) / STEPSIZE;
+       new_crv_p->coordlist[1].counts = 0.0;
+
+       /* find staff coord info */
+       for (m_p = seginfo_p->mll_p; m_p != (struct MAINLL *) 0;
+                                                       m_p = m_p->next) {
+               if (m_p->str == S_STAFF && m_p->u.staff_p->staffno == staffno1) {
+                       break;
+               }
+       }
+       /* y coords are determined from the slope. Offset the endpoint by 1
+        * STEPSIZE and the middle point by 1 STEPSIZE in the opposite
+        * direction to get a little bulge */
+       new_crv_p->coordlist[0].vert_p = m_p->u.staff_p->c;
+       new_crv_p->coordlist[0].vtype = AY;
+       new_crv_p->coordlist[0].vsteps = (y_offset - (bulge * STEPSIZE)
+                               + (slope * seginfo_p->xlength)) / STEPSIZE;
+       new_crv_p->coordlist[2].vert_p = m_p->u.staff_p->c;
+       new_crv_p->coordlist[2].vtype = AY;
+       new_crv_p->coordlist[2].vsteps = (y_offset - (bulge * STEPSIZE) +
+                       (slope * (xleng + seginfo_p->xlength))) / STEPSIZE;
+
+       /* add middle point, bulging by 2 stepsizes */
+       new_crv_p->coordlist[1].vert_p = m_p->u.staff_p->c;
+       new_crv_p->coordlist[1].vtype = AY;
+       new_crv_p->coordlist[1].vsteps = (y_offset + (bulge * STEPSIZE) +
+               (slope * (seginfo_p->xlength + (xleng / 2.0))))
+               / STEPSIZE;
+
+       /* link into proper place in main list */
+       /* this will be right before the first BAR after the FEED */
+       for (m_p = seginfo_p->mll_p->next; m_p != (struct MAINLL *) 0;
+                                                       m_p = m_p->next) {
+               if (m_p->str == S_BAR) {
+                       break;
+               }
+       }
+
+       if (m_p == (struct MAINLL *) 0) {
+               pfatal("couldn't find bar when adding curve segment");
+       }
+
+       insertMAINLL(new_mll_p, m_p->prev);
+}
+\f
+
+/* return YES if given coordinate is invisible */
+
+static int
+is_invis(cinfo_p)
+
+struct COORD_INFO *cinfo_p;
+
+{
+       /* It is invisible if explictly marked as such, or if
+        * it is not a builtin, but never had its page set differently
+        * than the initial default of zero. */
+       if ((cinfo_p->flags & CT_INVISIBLE) ||
+                       (cinfo_p->page == 0 && is_builtin(cinfo_p) == NO)) {
+               return(YES);
+       }
+       else {
+               return(NO);
+       }
+}
+\f
+
+/* return YES if given coordinate is a builtin location variable */
+
+static int
+is_builtin(cinfo_p)
+
+struct COORD_INFO *cinfo_p;
+
+{
+       return((cinfo_p->flags & CT_BUILTIN) ? YES : NO); 
+}
+\f
+
+/* go through list and see if any variables were defined on one page and
+ * used on another. If so, move them. */
+
+static void
+move2correct_page()
+
+{
+       int page = 1;                           /* current page */
+       struct MAINLL *m_p;                     /* index through main list */
+       struct MAINLL **insertp_p;              /* where, on each page, to
+                                                * insert items moved from
+                                                * other pages */
+       struct COORD_INFO *info_p, *info1_p;    /* to see what page the item
+                                                * is supposed to be on */
+       struct PRINTDATA *pr_p;                 /* index through print list */
+       struct PRINTDATA **pr_del_p_p;          /* where to delete item from
+                                                * list when moving */
+       struct MAINLL *next_p;                  /* which to check next */
+       int xabs, yabs;                         /* YES if x or y is absolute or
+                                                * builtin-relative coord */
+
+
+       /* allocate array for saving where to insert things to be moved.
+        * There is no page 0, so leave extra element for that */
+       CALLOC(MAINLL *, insertp_p, Total_pages + 1);
+
+
+       for (m_p = Mainllhc_p; m_p != (struct MAINLL *) 0; ) {
+
+               /* save what will be the next to check, in case the current
+                * one gets moved */
+               next_p = m_p->next;
+
+               switch(m_p->str) {
+
+               case S_BAR:
+                       if (insertp_p[page] == (struct MAINLL *) 0) {
+                               /* find first bar on that page and save the
+                                * main list struct right before that. That
+                                * is where we will move anything that has to
+                                * be moved to this page */
+                               insertp_p[page] = m_p->prev;
+                       }
+                       break;
+
+               case S_FEED:
+                       if (m_p->u.feed_p->pagefeed == YES) {
+                               page++;
+                       }
+                       break;
+
+               case S_LINE:
+                       /* only check user defined lines */
+                       if (m_p->inputlineno != -1) {
+                               info_p = find_coord(m_p->u.line_p->start.hor_p);
+                               if (info_p != (struct COORD_INFO *) 0 &&
+                                               info_p->page != page &&
+                                               info_p->flags != CT_BUILTIN) {
+                                       move_it(m_p, insertp_p[info_p->page],
+                                                       info_p->page);
+                               }
+                       }
+                       break;
+
+               case S_CURVE:
+                       /* only check user defined curves */
+                       if (m_p->inputlineno != -1) {
+                               info_p = find_coord(m_p->u.curve_p->
+                                                       coordlist[0].hor_p);
+                               if (info_p != (struct COORD_INFO *) 0 &&
+                                               info_p->page != page &&
+                                               info_p->flags != CT_BUILTIN) {
+                                       move_it(m_p, insertp_p[info_p->page],
+                                                       info_p->page);
+                               }
+                       }
+                       break;
+
+               case S_PRHEAD:
+                       for (pr_p = m_p->u.prhead_p->printdata_p, pr_del_p_p =
+                                               &(m_p->u.prhead_p->printdata_p);
+                                               pr_p != (struct PRINTDATA *) 0;
+                                               pr_del_p_p = &(pr_p->next)) {
+
+                               /* find out about x and y portions */
+                               info_p = find_coord(pr_p->location.hor_p);
+                               info1_p = find_coord(pr_p->location.vert_p);
+
+                               /* figure out if x and y are absolute or
+                                * associated with builtins */
+                               xabs = yabs = NO;
+                               if (info_p == (struct COORD_INFO *) 0) {
+                                       xabs = YES;
+                               }
+                               else if (info_p->flags & CT_BUILTIN) {
+                                       xabs = YES;
+                               }
+                               if (info1_p == (struct COORD_INFO *) 0) {
+                                       yabs = YES;
+                               }
+                               else if (info1_p->flags & CT_BUILTIN) {
+                                       yabs = YES;
+                               }
+                               /* if both x and y are absolute coordinates,
+                                * don't move it */
+                               if ((xabs == YES) && (yabs == YES)) {
+                                       pr_p = pr_p->next;
+                                       continue;
+                               }
+
+                               /* if both x and y are not absolute, make sure
+                                * they are associated with same staff */
+                               if ((xabs == NO) && (yabs == NO)) {
+                                       coordcheck(info_p, info1_p,
+                                                       pr_p->inputfile,
+                                                       pr_p->inputlineno);
+                               }
+
+                               /* normally we'll check for moving based on x.
+                                * (most of the time x and y will be on the same
+                                * page, so we can use either.) However, if
+                                * x happens to be the one that is absolute,
+                                * use y instead */
+                               if ((xabs == YES) && (yabs == NO)) {
+                                       info_p = info1_p;
+                               }
+
+                               if (info_p->page != page ) {
+                                       struct MAINLL *new_mll_p;
+                                       struct PRINTDATA *save_p;
+
+                                       /* moving a PRINTDATA is harder than
+                                        * moving a line or curve, because,
+                                        * there could be a list, so we have
+                                        * surgically remove this one from the
+                                        * list and graft onto a new PRHEAD */
+                                       new_mll_p = newMAINLLstruct(S_PRHEAD,
+                                               m_p->u.prhead_p->printdata_p->
+                                               inputlineno);
+                                       new_mll_p->inputfile = m_p->u.prhead_p->                                                        printdata_p->inputfile;
+                                       new_mll_p->u.prhead_p->printdata_p
+                                                       = pr_p;
+
+                                       /* save link for continuing for loop */
+                                       save_p = pr_p->next;
+
+                                       /* patch up linked list */
+                                       *pr_del_p_p = pr_p->next;
+                                       pr_p->next = (struct PRINTDATA *) 0;
+
+                                       /* If there is a page to move it to,
+                                        * move it there. If page is zero,
+                                        * it must be associated with something
+                                        * invisible, so discard it. */
+                                       if (info_p->page != 0) {
+                                               /* move to correct page */
+                                               if (insertp_p[info_p->page] ==
+                                                                       0) {
+                                                       l_ufatal(pr_p->inputfile,
+                                                               pr_p->inputlineno,
+                                                               "forward reference to location tag");
+                                               }
+                                               insertMAINLL(new_mll_p,
+                                                       insertp_p[info_p->page]); 
+                                       }
+                                       else {
+                                               FREE(new_mll_p);
+                                       }
+
+                                       /* prepare for next time through loop */
+                                       pr_p = save_p;
+                               }
+                               else {
+                                       pr_p = pr_p->next;
+                               }
+                       }
+
+                       /* if all moved, can discard */
+                       if (m_p->u.prhead_p->printdata_p
+                                               == (struct PRINTDATA *) 0) {
+                               unlinkMAINLL(m_p);
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+
+               m_p = next_p;
+       }
+       FREE(insertp_p);
+}
+\f
+
+/* move given MAINLL to specified place */
+
+static void
+move_it(m_p, im_p, page)
+
+struct MAINLL *m_p;    /* move this */
+struct MAINLL *im_p;   /* insert here */
+int page;              /* if page 0, move to oblivion */
+
+{
+       unlinkMAINLL(m_p);
+       if (page == 0) {
+               /* must be invisible, so discard it */
+               FREE(m_p);
+               return;
+       }
+       if (im_p == (struct MAINLL *) 0) {
+               l_ufatal(m_p->inputfile, m_p->inputlineno,
+                               "forward reference to location tag");
+       }
+       insertMAINLL(m_p, im_p);
+}
+\f
+
+/* Go through main list.
+ * If there are any INPCOORDs that have a hor_p of a bar, and have a positive
+ * x offset, and that bar is at the end of a score and thus has a pseudo-bar
+ * on the following score, move the hor_p to point to the pseudo-bar instead.
+ * If the y of the same INPCOORD also pointed to the same bar before, move it
+ * as well, otherwise leave it as is. */
+
+static void
+move2pseudo()
+
+{
+       struct MAINLL *m_p;     /* walk through main list */
+       struct PRINTDATA *pr_p; /* walk through list of print commands */
+       int n;                  /* index through curve coordinates */
+
+
+       /* go through main list */
+       for (m_p = Mainllhc_p; m_p != (struct MAINLL *) 0; m_p = m_p->next) {
+
+               if (m_p->str == S_LINE) {
+                       /* handle start and end points of line */
+                       do_pseudo( &(m_p->u.line_p->start), m_p );
+                       do_pseudo( &(m_p->u.line_p->end), m_p );
+               }
+
+               else if (m_p->str == S_CURVE) {
+                       /* do each point of curve */
+                       for (n = m_p->u.curve_p->ncoord - 1; n >= 0; n--) {
+                               do_pseudo( &(m_p->u.curve_p->coordlist[n]), m_p);
+                       }
+               }
+
+               else if (m_p->str == S_PRHEAD) {
+                       /* do each print command */
+                       for (pr_p = m_p->u.prhead_p->printdata_p;
+                                       pr_p != (struct PRINTDATA *) 0;
+                                       pr_p = pr_p->next) {
+                               do_pseudo( &(pr_p->location), m_p );
+                       }
+               }
+       }
+}
+\f
+
+/* given an INPCOORD, if it has a hor_p of a bar, and has a positive
+ * x offset, and that bar is at the end of a score and thus has a pseudo-bar
+ * on the following score, move the hor_p to point to the pseudo-bar instead.
+ * If the y of the same INPCOORD also pointed to the same bar before, move it
+ * as well, otherwise leave it as is. */
+
+static void
+do_pseudo(inpc_p, mll_p)
+
+struct INPCOORD *inpc_p;
+struct MAINLL *mll_p;
+
+{
+       struct COORD_INFO *info_p;
+
+
+       if ((info_p = find_coord(inpc_p->hor_p)) == (struct COORD_INFO *) 0) {
+               /* probably an absolute coordinate */
+               return;
+       }
+
+       /* if x is associated with a bar... */
+       if (info_p->flags & CT_BAR) {
+               /* and that bar has an associated pseudo bar... */
+               if (info_p->pseudo_bar_p != (struct BAR *) 0) {
+                       /* and the x value after adding offsets is into
+                        * the right margin area... */
+                       if (inpc_x(inpc_p, (char *) 0, -1)
+                                       > PGWIDTH - eff_rightmargin(mll_p)) {
+                               /* if y of INPCOORD was also associated with
+                                * the same bar, move it to pseudo-bar */
+                               if (inpc_p->hor_p == inpc_p->vert_p) {
+                                       inpc_p->vert_p = info_p->pseudo_bar_p->c;
+                               }
+                               /* move x to pseudo-bar */
+                               inpc_p->hor_p = info_p->pseudo_bar_p->c;
+                       }
+               }
+       }
+}
+\f
+
+/* Given a line or curve, fix any INPCOORD that end up off the margin */
+
+static void
+fix_inpcoords(mll_p)
+
+struct MAINLL *mll_p;
+
+{
+       int n;          /* index through curve points */
+
+
+       if (mll_p->str == S_CURVE) {
+               for (n = 0; n < mll_p->u.curve_p->ncoord; n++) {
+                       adj_coord( & (mll_p->u.curve_p->coordlist[n]), mll_p,
+                               ((n > 0) ? &(mll_p->u.curve_p->coordlist[n-1])
+                               : (struct INPCOORD *) 0) );
+               }
+       }
+       else if (mll_p->str == S_LINE) {
+               adj_coord( &(mll_p->u.line_p->start), mll_p,
+                               (struct INPCOORD *) 0);
+               adj_coord( &(mll_p->u.line_p->end), mll_p,
+                               &(mll_p->u.line_p->start) );
+       }
+}
+\f
+
+/* If x of INPCOORD ends up off the page, change the INPCOORD
+ * to be on the following score, using that score's pseudo-bar
+ * as the reference. */
+
+static void
+adj_coord(coord_p, mll_p, prev_coord_p)
+
+struct INPCOORD *coord_p;      /* what to potentially adjust */
+struct MAINLL *mll_p;  /* points to the line or curve containing coord_p */
+struct INPCOORD *prev_coord_p; /* previous coord if any, else NULL */
+
+{
+       struct MAINLL *m_p;             /* for finding thing in main list */
+       float x, y;
+       float prev_x, prev_y;           /* location of prev_coord_p */
+       struct INPCOORD temp_coord;     /* reference if prev_coord_p is NULL */
+       float right_margin_x;           /* PGWIDTH - eff_rightmargin */
+       float staff_y = 0.0;
+       struct COORD_INFO *xinfo_p, *yinfo_p;   /* for finding which staff,
+                                        * clefsig, etc is associated with
+                                        * the point */
+       struct BAR *bar_p;              /* pseudo-bar */
+       int staffno;
+
+
+       /* don't bother with invisible points. */
+       if (prev_coord_p != (struct INPCOORD *) 0) {
+               xinfo_p = find_coord(prev_coord_p->hor_p);
+               yinfo_p = find_coord(prev_coord_p->vert_p);
+               if (xinfo_p == (struct COORD_INFO *) 0
+                               || yinfo_p == (struct COORD_INFO *) 0) {
+                       return;
+               }
+
+               if (is_invis(xinfo_p) == YES || is_invis(yinfo_p) == YES) {
+                       /* things with invisible points are ignored */
+                       return;
+               }
+       }
+
+       xinfo_p = find_coord(coord_p->hor_p);
+       yinfo_p = find_coord(coord_p->vert_p);
+       if (xinfo_p == (struct COORD_INFO *) 0
+                               || yinfo_p == (struct COORD_INFO *) 0) {
+               return;
+       }
+
+       if (is_invis(xinfo_p) == YES || is_invis(yinfo_p) == YES) {
+               return;
+       }
+
+       x = inpc_x(coord_p, (char *) 0, -1);
+       y = inpc_y(coord_p, mll_p->inputfile, mll_p->inputlineno);
+       prev_x = prev_y = 0.0;  /* avoid bogus "used before set" warning */
+
+       /* Check for points being too close together. If user specifies the
+        * same point for both endpoints of a line, or something like that,
+        * PostScript might get asked to divide by zero. */
+       if (prev_coord_p != (struct INPCOORD *) 0) {
+               prev_x = inpc_x(prev_coord_p, mll_p->inputfile, mll_p->inputlineno);
+               prev_y = inpc_y(prev_coord_p, mll_p->inputfile, mll_p->inputlineno);
+
+               if ( (fabs(x - prev_x) < .0001) && (fabs(y - prev_y) < .0001)) {
+                       l_ufatal(mll_p->inputfile, mll_p->inputlineno,
+                               "points too close together");
+               }
+       }
+       
+       /* Find the x value and see if it is off the right of the page.
+        * Pretend we don't know the file/lineno, because that way if it is
+        * off the page, no error message will be printed, which is what we
+        * want, since we hope to be able to patch things up so it isn't
+        * off the page anymore. */
+       if (x < PGWIDTH) {
+               /* this one is okay as is */
+               return;
+       }
+
+       /* Get the staff associated with the y */
+       staffno = eff_staff(yinfo_p);
+
+       /* Find the pseudo bar of the next score and the y of the staff */
+       for (m_p = xinfo_p->mll_feed_p->next; m_p != (struct MAINLL *) 0;
+                                               m_p = m_p->next) {
+
+               if (m_p->str == S_STAFF && m_p->u.staff_p->staffno == staffno) {
+                       staff_y = m_p->u.staff_p->c[AY];
+               }
+
+               if (IS_CLEFSIG_FEED(m_p)) {
+                       /* pseudo-bar will be in CLEFSIG right after this */
+                       break;
+               }
+       }
+       if (m_p == (struct MAINLL *) 0) {
+               /* no future score. Give up trying to fix this one */
+               return;
+       }
+
+       /* Use the pseudo-bar as reference */
+       bar_p = m_p->next->u.clefsig_p->bar_p;
+
+       /* If there was a previous point, we will use that as a reference
+        * point, otherwise make a temporary point that is the same
+        * as the current point but with no x or y offset. */
+       if (prev_coord_p == (struct INPCOORD *) 0) {
+               temp_coord = *coord_p;
+               temp_coord.hsteps = 0.0;
+               temp_coord.counts = 0.0;
+               temp_coord.vsteps = 0.0;
+               prev_coord_p = &temp_coord;
+               prev_x = inpc_x(prev_coord_p, mll_p->inputfile, mll_p->inputlineno);
+               prev_y = inpc_y(prev_coord_p, mll_p->inputfile, mll_p->inputlineno);
+       }
+
+       /* Use the pseudo-bar for y */
+       coord_p->vert_p = bar_p->c;
+       coord_p->vtype = AY;
+
+       /* Pretend to draw a line from reference point to the current point,
+        * and calculate, using similar triangles, what the y would be
+        * where that line would hit the right margin. */
+       right_margin_x = PGWIDTH - eff_rightmargin(m_p);
+       y = prev_y + ((y - prev_y) * (right_margin_x - prev_x)) / (x - prev_x);
+       /* Now adjust to be relative to the staff's y */
+       y = y - staff_y;
+
+       /* on the following score, where we are moving the INPCOORD,
+        * find the y of the appropriate staff */
+       for (m_p = m_p->next; m_p != (struct MAINLL *) 0; m_p = m_p->next) {
+               if (m_p->str == S_STAFF && m_p->u.staff_p->staffno == staffno) {
+                       /* The new y for the INPCOORD is the staff's y offset
+                        * from the score's y, plus the relative offset
+                        * found above. */
+                       y += m_p->u.staff_p->c[AY] - bar_p->c[AY];
+                       break;
+               }
+               if (m_p->str == S_BAR) {
+                       l_ufatal(mll_p->inputfile, mll_p->inputlineno,
+                               "curve is associated with staff %d, which does not exists", staffno);
+               }
+       }
+
+       coord_p->vsteps = y / (STEPSIZE * svpath(staffno, STAFFSCALE)->staffscale);
+
+       /* change the INPCOORD x to point to the pseudo-bar's coord array */
+       coord_p->hor_p = bar_p->c;
+       coord_p->htype = AX;
+       coord_p->counts = 0.0;
+       /* x offset will be the excess that sticks beyond the right edge
+        * of the score */
+       coord_p->hsteps = (x - right_margin_x)
+                       / (STEPSIZE * svpath(staffno, STAFFSCALE)->staffscale);
+
+       /* If the original was really, really far off the page, even the
+        * moved version may still be off the page, so try again. Eventually
+        * either we should get within the current score or run off the end
+        * of the song and have to give up. */
+       adj_coord(coord_p, mll_p, prev_coord_p);
+}
+\f
+
+/* For manual curves that use "bulge" values, figure out the intermediate
+ * points for curves, and put them in the coordlist, getting rid of the
+ * bulgelist.
+ */
+
+static void
+calc_bulge(curve_p, fname, lineno, is_split, mll_p)
+
+struct CURVE *curve_p; /* curve defined using bulge */
+char *fname;
+int lineno;
+int is_split;  /* YES if goes across at least one FEED */
+struct MAINLL *mll_p;  /* for finding effective margin */
+
+{
+       double x1, y1;                  /* start point location */
+       double x2, y2;                  /* end point location */
+       double xlen, ylen;              /* distances between endpoints */
+       double seg1xlen, seg2xlen;      /* lengths of parts of curve on
+                                        * first and last score when split */
+       double sintheta, costheta;      /* for rotation */
+       double length;                  /* between endpoints */
+       double segX, segY;              /* distance to intermediate point */
+       int p1staff, p2staff;           /* staff associated with each point */
+       struct INPCOORD *coordlist_p;   /* the new calculated curve */
+       int n;                          /* index through bulge points */
+       int nbulge;                     /* how many bulge points specified */
+       double staffscale;
+       struct COORD_INFO *x1info_p, *y1info_p; /* to get staff info, etc */
+       struct COORD_INFO *x2info_p, *y2info_p;
+
+
+       nbulge = curve_p->nbulge;
+
+       /* The calculated curve will have the 2 endpoints plus nbulge
+        * intermediate points */
+       MALLOC (INPCOORD, coordlist_p, 2 + nbulge);
+
+       /* The endpoints just get copied. All the inner points will
+        * be calculated relative to the first, so for now we copy all of
+        * the INPCOORD data from the first point into them, then later
+        * we will overwrite the offset values appropriately. */
+       for (n = 0; n < nbulge + 1; n++) {
+               coordlist_p[n] = curve_p->coordlist[0];
+       }
+       coordlist_p[nbulge + 1] = curve_p->coordlist[1];
+
+       /* Find relevant information about the endpoints */
+       x1 = inpc_x( &(curve_p->coordlist[0]), fname, lineno);
+       y1 = inpc_y( &(curve_p->coordlist[0]), fname, lineno);
+       x2 = inpc_x( &(curve_p->coordlist[1]), fname, lineno);
+       y2 = inpc_y( &(curve_p->coordlist[1]), fname, lineno);
+       
+       x1info_p = find_coord( curve_p->coordlist[0].hor_p);
+       y1info_p = find_coord( curve_p->coordlist[0].vert_p);
+       x2info_p = find_coord( curve_p->coordlist[1].hor_p);
+       y2info_p = find_coord( curve_p->coordlist[1].vert_p);
+
+       /* If all coordinates associated with staffs having the same
+        * staffscale value, then use that, otherwise use score value
+        */
+       if ((staffscale = svpath(x1info_p->staffno, STAFFSCALE)->staffscale) !=
+                       svpath(y1info_p->staffno, STAFFSCALE)->staffscale
+                       || staffscale !=
+                       svpath(x2info_p->staffno, STAFFSCALE)->staffscale
+                       || staffscale !=
+                       svpath(y2info_p->staffno, STAFFSCALE)->staffscale) {
+               staffscale = Score.staffscale;
+       }
+
+       /* Find the length of the line segment
+        * that would go straight between the two endpoints. To do this,
+        * we get the x and y distances to use with Pythagorean theorem */
+       if (is_split == NO) {
+               /* if all on same score, easier to find a and y */
+               xlen = (x2 - x1);
+               ylen = (y2 - y1);
+       }
+       else {
+               /* Split curves take more work. First find x length
+                * on the score containing the first part of the curve */
+               seg1xlen = PGWIDTH - eff_rightmargin(mll_p) -
+                       inpc_x( &(curve_p->coordlist[0]), fname, lineno );
+
+               /* Find the x length of the score containing the last past.
+                * To do this, have to find the pseudo-bar inside the
+                * appropriate CLEFSIG, which should be on the main list
+                * immediately following the FEED
+                * of the score containing the ending x coordinate. */
+               seg2xlen = inpc_x( &(curve_p->coordlist[1]), fname, lineno) -
+                       x2info_p->mll_feed_p->next->u.clefsig_p->bar_p->c[AX];
+
+               /* Finally, add in the x lengths of any intervening scores */
+               xlen = find_effXlength(seg1xlen, seg2xlen,
+                                               x1info_p, x2info_p, NO);
+
+               /* Now we need the distance in the y direction. First, the
+                * easy case, when both endpoints are associated with the
+                * same staff */
+               p1staff = eff_staff(y1info_p);
+               p2staff = eff_staff(y2info_p);
+               if (p1staff == p2staff) {
+                       /* y length is the relative Y of the INPCOORD
+                        * of the final point, offset by its vsteps, minus
+                        * the similar value of the beginning point. */
+                       ylen = (curve_p->coordlist[1].vert_p
+                               [abs2rel(curve_p->coordlist[1].vtype)]
+                               + curve_p->coordlist[1].vsteps
+                               * STEPSIZE * staffscale)
+                               - (curve_p->coordlist[0].vert_p
+                               [abs2rel(curve_p->coordlist[0].vtype)]
+                               + curve_p->coordlist[0].vsteps
+                               * STEPSIZE * staffscale);
+               }
+               else {
+                       /* The endpoints are associated with different staffs.
+                        * The y distance between these two staffs may vary
+                        * from score to score, so to get things really
+                        * accurate, we'd have to adjust the y proportionally
+                        * on each intervening score, which may require adding
+                        * lots of intermediate points and lots of complicated
+                        * calculations which may or may not look much better
+                        * than doing something more simple. So just do
+                        * something fairly simple: Find the distance between
+                        * each endpoint's y and its staff's y, and subtract
+                        * those two distances to get an approximate ylen.
+                        * As long as the distance between the two staffs is
+                        * somewhat similar on both scores,
+                        * which is likely to be the case,
+                        * the results should be pretty good. */
+                       ylen = (y1info_p->mll_feed_p->next->u.clefsig_p->bar_p->c[AY] - y1) -
+                               (y2info_p->mll_feed_p->next->u.clefsig_p->bar_p->c[AY] - y2);
+               }
+       }
+
+       /* Find distance between the endpoints */
+       length = sqrt( SQUARED(xlen) + SQUARED(ylen) );
+
+       /* Guard again divide by zero */
+       if (length < 0.0001) {
+               l_ufatal(fname, lineno, "curve endpoints too close together");
+       }
+
+       /* We find the intermediate points as if the line were horizontal,
+        * then rotate it, so need the sine and cosine for rotation.
+        */
+       sintheta = ylen / length;
+       costheta = xlen / length;
+
+       /* Calculate the position of each inner point.  */
+       for (n = 1; n <= nbulge; n++) {
+               /* horizontal offset is based on a fraction of the length
+                * between endpoints: 1/2 if there is one bulge value,
+                * 1/3 and 2/3 if there are two values, etc, so use
+                * n/(nbulge + 1) to get the unrotated x lengths.
+                * Use the bulge value (which is already in stepsizes)
+                * for the unrotated y length.
+                * Then to do the rotation, use
+                * x' = x costheta - y sintheta
+                * y' = y costheta + x sintheta
+                */
+               segX = (length * ((double) n / (double)(nbulge + 1)))
+                                               / (STEPSIZE * staffscale);
+               segY = curve_p->bulgelist[n-1];
+               coordlist_p[n].hsteps += (segX * costheta) - (segY * sintheta);
+               coordlist_p[n].vsteps += (segY * costheta) + (segX * sintheta);
+       }
+
+       /* free the old coord list, which just had the endpoints */
+       FREE(curve_p->coordlist);
+
+       /* replace the old coordlist with the newly calculated one */
+       curve_p->coordlist = coordlist_p;
+       curve_p->ncoord = 2 + nbulge;
+
+       /* don't need bulgelist anymore, since it has been converted to
+        * regular curve. */
+       FREE(curve_p->bulgelist);
+       curve_p->bulgelist = 0;
+       curve_p->nbulge = 0;
+}
diff --git a/mup/mup/lyrics.c b/mup/mup/lyrics.c
new file mode 100644 (file)
index 0000000..badeec4
--- /dev/null
@@ -0,0 +1,1266 @@
+
+/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions called by the parse phase to deal with lyrics */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+/* information about a measure-worth of lyrics */
+struct LYRINFO {
+       short   place;          /* PL_ABOVE, etc */
+       short   vno;            /* verse number */
+       struct  GRPSYL  *gs_p;  /* the lyrics themselves */
+       struct LYRINFO  *next;  /* for linked list of other verses on the
+                                * same staff */
+};
+
+/* current font/size for each staff/verse/place combination */
+struct LYRFONTSIZE {
+       short   staffno;
+       short   verse;
+       char    place;                  /* PL_ABOVE, etc */
+       char    font;
+       char    size;
+       char    all;                    /* YES if "above all" or "below all".
+                                        * In that case, the staffno is
+                                        * irrelevant */
+       struct LYRFONTSIZE *next;       /* linked list */
+};
+
+/* we keep the font/size info independently for each staff/verse/place combo
+ * and carry it forward from measure to measure. Info is stored here */
+struct LYRFONTSIZE *Lyrfontsizeinfo_p [MAXSTAFFS + 1];
+
+/* for each staff, keep a list of all the GRPSYL lyric lists that will be
+ * associated with that staff. */
+static struct LYRINFO *Lyr_tbl[MAXSTAFFS + 1];
+
+/* need to keep a list of all verse numbers ever used, for setting Maxverses */
+static struct RANGELIST *Above_vnumbers_used;
+static struct RANGELIST *Below_vnumbers_used;
+static struct RANGELIST *Between_vnumbers_used;
+
+/* for auto-numbering verses, keep track of the last verse number used
+ * for each staff/place */
+static short Prev_verse_num[MAXSTAFFS+1][NUM_PLACE];
+
+/* static function declarations */
+static void free_lyrinfo P((struct LYRINFO *lyrinfo_p));
+static void assoc_lyr2staff P((int staffno, int verse, struct GRPSYL *gs_p,
+               char *lyrstring, int all, int place));
+static struct LYRFONTSIZE *getlyrfontsize P((int staffno, int verse,
+               int place, int all));
+static void updlyrfontsize P((struct LYRFONTSIZE *lyrfontsize_p,
+               int font, int size));
+static char *next_syl P((char **sylstring_p, int *font_p, int *size_p,
+                       short *position_p, int staffno));
+static void do_sylwidth P((char *lyrstring, float *wid_b4_syl_p,
+               float *wid_real_syl_p, float *wid_after_syl_p,
+               int compensating));
+static void count_verses P((struct RANGELIST *used_p));
+static void vno_used P((int vno));
+\f
+
+/* given a range of verses, save the range for later use */
+
+void
+lyr_verse(begin, end)
+
+int begin;     /* first verse in range */
+int end;       /* last verse number in range */
+
+{
+       /* error check */
+       /* Note that -1 is a special value meaning "one more than previous."
+        * Zero is also special, meaning "centered," but that doesn't
+        * get handled by this function, since that doesn't need the error
+        * checks that are done here, since the parser guarantees good values.
+        * If a zero does get passed in, the user must have explicitly
+        * specified it, which is a user error.
+        */
+       if (begin < 1 && begin != -1) {
+               yyerror("verse number must be >= 1");
+               return;
+       }
+
+       if (end < begin) {
+               yyerror("end of verse range smaller than beginning");
+               return;
+       }
+
+       save_vno_range(begin, end);
+}
+\f
+
+/* once all the information about a measure-worth of lyrics has been
+ * gathered, process it. Break up the lyrics string into syllables and
+ * store them in the appropriate GRPSYL structs. Then clone the list as
+ * many times as necessary for each staff/verse, and associate with
+ * appropriate staffs.
+ */
+
+void
+proc_lyrics(grpsyl_p, lyrstring)
+
+struct GRPSYL *grpsyl_p;       /* list of GRPSYLs with time values */
+char *lyrstring;               /* string containing the lyrics */
+
+{
+       struct RANGELIST *slist_p;      /* walk through list of staffs */
+       struct RANGELIST *vlist_p;      /* walk through list of verses */
+       int staffno;
+       int verse;
+       int place;
+
+
+       if (grpsyl_p == (struct GRPSYL *) 0 || lyrstring == (char *) 0) {
+               return;
+       }
+
+       debug(2, "proc_lyrics file=%s lineno=%d", grpsyl_p->inputfile,
+                       grpsyl_p->inputlineno);
+
+       /* for each staff and verse being defined, clone the GRPSYL
+        * list and associate with appropriate staff */
+       /* do each appropriate staff */
+       for (slist_p = Staffrange_p; slist_p !=  (struct RANGELIST *) 0;
+                               slist_p = slist_p->next) {
+               place = (slist_p->place == PL_UNKNOWN ? PL_BELOW : slist_p->place);
+               for (staffno = slist_p->begin; staffno <= slist_p->end;
+                                                       staffno++) {
+
+                       /* do each appropriate verse */
+                       for (vlist_p = Vnorange_p;
+                                       vlist_p != (struct RANGELIST *) 0;
+                                       vlist_p = vlist_p->next) {
+
+                               for (verse = vlist_p->begin;
+                                                       verse <= vlist_p->end;
+                                                       verse++) {
+
+                                       /* -1 means one more than previous */
+                                       if (verse == -1) {
+               
+                                               verse = Prev_verse_num[staffno][place] + 1;
+                                       }
+                                       Prev_verse_num[staffno][place] = verse;
+                                       /* connect to proper staff */
+                                       assoc_lyr2staff(staffno, verse,
+                                                       grpsyl_p, lyrstring,
+                                                       slist_p->all, place);
+
+                                       /* mark that we've use this verse # */
+                                       vno_used(verse);
+                               }
+                       }
+               }
+       }
+
+       /* free the vno rangelist.  Don't free the staff info yet, because
+        * there may be more verses */
+       free_vnorange();
+
+       /* the lyrics string has been broken into syllables. Don't need
+        * the original string anymore */
+       FREE(lyrstring);
+}
+\f
+
+/* connect a list of syllable to specified STAFF */
+
+static void
+assoc_lyr2staff(staffno, verse, gs_p, lyrstring, all, place)
+
+int staffno;           /* which staff lyrics belong to */
+int verse;             /* verse number of lyrics */
+struct GRPSYL *gs_p;   /* list of GRPSYLs with time information */
+char *lyrstring;       /* string of lyrics syllables in this measure/verse */
+int all;               /* YES if associated with "all" */
+int place;             /* PL_*   */
+
+{
+       struct LYRINFO *new_p;                  /* to store info about
+                                                * current staff/verse lyrics */
+       struct LYRINFO *lyrinfo_p;              /* used when searching for
+                                                * where to insert this verse */
+       struct LYRINFO **insert_place_p_p;      /* address of where to add
+                                                * lyric info when doing
+                                                * insertion sort */
+       char *lyr_copy;                         /* copy of lyrics */
+       int font;
+       int size;
+       struct LYRFONTSIZE *lyrfontsize_p;      /* info about font/size for
+                                                * current staff/verse/place */
+
+
+       debug(4, "assoc_lyr2staff file=%s lineno=%d staffno=%d, verse=%d, all=%d, place=%d",
+                       gs_p->inputfile, gs_p->inputlineno, staffno, verse,
+                       all, place);
+
+       if (staffno > Score.staffs) {
+               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                       "can't have lyrics for staff %d when there aren't that many staffs",
+                       staffno);
+               return;
+       }
+
+       /* make a copy of the grpsyl list for this staff/verse */
+       gs_p = clone_gs_list(gs_p, NO);
+
+       /* allocate space to save info, and fill it in */
+       CALLOC(LYRINFO, new_p, 1);
+       new_p->vno = (short) verse;
+       new_p->place = place;
+       new_p->gs_p = gs_p;
+
+       /* insertion sort into list of lyrics for this staff */
+       for (insert_place_p_p = & (Lyr_tbl[staffno]);
+                       *insert_place_p_p != (struct LYRINFO *) 0;
+                       insert_place_p_p = & ((*insert_place_p_p)->next) ) {
+
+               lyrinfo_p = (*insert_place_p_p);
+
+               if ( lyrinfo_p->vno > verse) {
+                       /* need to insert new one right before this one */
+                       break;
+               }
+
+               if ( (lyrinfo_p->vno == verse)
+                                       && (lyrinfo_p->place == new_p->place)) {
+                       l_yyerror(Curr_filename, yylineno,
+                                       "verse %d, staff %d multiply defined",
+                                       verse, staffno);
+                       return;
+               }
+       }
+       new_p->next = *insert_place_p_p;
+       *insert_place_p_p = new_p;
+
+       /* we need to set font/size on a per-staff basis. That means we
+        * have to make a temporary copy for each instance and get the
+        * syllables each time */
+       lyrfontsize_p = getlyrfontsize(staffno, verse, Place, all);
+       font = lyrfontsize_p->font;
+       size = lyrfontsize_p->size;
+
+       lyr_copy = lyrstring = copy_string(lyrstring + 2, font, size);
+
+       /* get into internal format */
+       fix_string(lyrstring, font, size, Curr_filename, yylineno);
+
+       /* skip past the font/size */
+       lyrstring += 2;
+
+       /* fill in vno, staffno, and syllables */
+       for (   ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+
+               gs_p->staffno = (short) staffno;
+               gs_p->vno = (short) verse;
+
+               /* if this GRPSYL is a space, don't fill in a syllable */
+               if (gs_p->grpcont == GC_SPACE) {
+                       continue;
+               }
+
+               /* otherwise, find the next syllable, and store it in
+                * the GRPSYL */
+               gs_p->syl = next_syl(&lyrstring, &font, &size,
+                                               &(gs_p->sylposition), staffno);
+       }
+
+       /* keep track of font/size at end of measure in case we have more
+        * lyrics in this same staff/verse/place on a later measure */
+       updlyrfontsize(lyrfontsize_p, font, size);
+
+       /* skip over any trailing white space */
+       while (*lyrstring == ' ' || *lyrstring == '\t') {
+               lyrstring++;
+       }
+
+       if (*lyrstring != '\0') {
+               yyerror("too many syllables in string");
+       }
+
+       /* the copy has been broken into syllables. Free the copy */
+       FREE(lyr_copy);
+}
+\f
+
+/* given a staffno, verse, and place, return (via pointer to struct of info)
+ * the font and size that should be used */
+
+static struct LYRFONTSIZE *
+getlyrfontsize(staffno, verse, place, all)
+
+int staffno;
+int verse;
+int place;
+int all;       /* YES if associated with "all" */
+
+{
+       struct LYRFONTSIZE *lfs_p;      /* walk through linked list */
+
+
+       /* if this staff/verse/place is on the list, use the values stored
+        * there. */
+       for (lfs_p = Lyrfontsizeinfo_p [staffno];
+                                       lfs_p != (struct LYRFONTSIZE *) 0;
+                                       lfs_p = lfs_p->next) {
+
+               if (lfs_p->staffno == staffno && lfs_p->verse == verse
+                               && lfs_p->place == place && lfs_p->all == all) {
+                       return(lfs_p);
+               }
+       }
+
+       /* wasn't on list yet. Add to list, using default values from SSV */
+       MALLOC(LYRFONTSIZE, lfs_p, 1);
+       lfs_p->staffno = (short) staffno;
+       lfs_p->verse = (short) verse;
+       lfs_p->place = (char) place;
+       lfs_p->all = (char) all;
+       if (all == YES) {
+               lfs_p->font = (char) (Score.lyricsfamily + Score.lyricsfont);
+               lfs_p->size = (char) Score.lyricssize;
+       }
+       else {
+               lfs_p->font = svpath(staffno, LYRICSFAMILY)->lyricsfamily
+                               + svpath(staffno, LYRICSFONT)->lyricsfont;
+               lfs_p->size = svpath(staffno, LYRICSFONT)->lyricssize;
+       }
+       lfs_p->next = Lyrfontsizeinfo_p [ staffno ];
+       Lyrfontsizeinfo_p [ staffno ] = lfs_p;
+
+       return(lfs_p);
+}
+\f
+
+/* update values of font/size for a given LYRFONTSIZE struct */
+
+static void
+updlyrfontsize(lyrfontsize_p, font, size)
+
+struct LYRFONTSIZE *lyrfontsize_p;
+int font;
+int size;
+
+{
+       lyrfontsize_p->font = (char) font;
+       lyrfontsize_p->size = (char) size;
+}
+\f
+
+/* when user sets lyricsfont via an SSV, that overrides whatever fonts are
+ * currently in effect, so change them. */
+
+void
+setlyrfont(staffno, font)
+
+int staffno;
+int font;
+
+{
+       int s;                          /* index through staffs */
+       struct LYRFONTSIZE *lfs_p;      /* info about font/size */
+
+
+       if (Context == C_SCORE) {
+               Context = C_STAFF;
+               /* reset all staffs */
+               for (s = 1; s <= Score.staffs; s++) {
+                       setlyrfont(s, font);
+               }
+               Context = C_SCORE;
+       }
+       else {
+               /* set all place/verse combinations of given staff */
+               for (lfs_p = Lyrfontsizeinfo_p [staffno];
+                                       lfs_p != (struct LYRFONTSIZE *) 0;
+                                       lfs_p = lfs_p->next) {
+                       lfs_p->font = (lfs_p->all == YES ? Score.lyricsfamily
+                               + Score.lyricsfont
+                               : svpath(staffno, LYRICSFAMILY)->lyricsfamily
+                               + font);
+               }
+       }
+}
+\f
+
+/* when user sets lyricsize via an SSV, that overrides whatever fonts are
+ * currently in effect, so change them. */
+
+void
+setlyrsize(staffno, size)
+
+int staffno;
+int size;
+
+{
+       int s;                          /* index through staffs */
+       struct LYRFONTSIZE *lfs_p;      /* font/size info */
+
+
+       if (Context == C_SCORE) {
+               /* reset all staffs */
+               Context = C_STAFF;
+               for (s = 1; s <= Score.staffs; s++) {
+                       setlyrsize(s, size);
+               }
+               Context = C_SCORE;
+       }
+       else {
+               /* set all place/verse combinations of given staff */
+               for (lfs_p = Lyrfontsizeinfo_p [staffno];
+                                       lfs_p != (struct LYRFONTSIZE *) 0;
+                                       lfs_p = lfs_p->next) {
+                       lfs_p->size = (char) (lfs_p->all == YES
+                                       ? Score.lyricssize : size);
+               }
+       }
+}
+\f
+
+/* This function is called when an entire measure has been collected, to
+ * take care of all the lyrics.
+ * For each staff, allocate the proper number of elements for the syls_p
+ * list and fill them in.
+ * Then free all the LYRINFO structs and clean out the Lyr_tbl.
+ */
+
+void
+attach_lyrics2staffs(mll_staffs_p)
+
+struct MAINLL *mll_staffs_p;   /* the list of staffs to attch to */
+
+{
+       struct STAFF *staff_p;          /* the staff we are currently dealing
+                                        * with */
+       int verses;                     /* how many verses for staff */
+       struct LYRINFO *lyrinfo_p;      /* where lyrics info is stored */
+
+
+       debug(4, "attach_lyrics2staffs");
+
+       /* do each staff */
+       for (   ; mll_staffs_p != (struct MAINLL *) 0;
+                                       mll_staffs_p = mll_staffs_p->next) {
+
+               if (mll_staffs_p->str != S_STAFF) {
+                       /* must have gotten to end of staffs; done */
+                       break;
+               }
+
+               /* need staff pointer a lot. Get shorter name for it */
+               staff_p = mll_staffs_p->u.staff_p;
+
+               /* count up how many verses there are associated with this
+                * staff */
+               for ( verses = 0, lyrinfo_p = Lyr_tbl[staff_p->staffno];
+                                       lyrinfo_p != (struct LYRINFO *) 0;
+                                       lyrinfo_p = lyrinfo_p->next) {
+                       verses++;
+               }
+
+               /* if no verses, nothing to do */
+               if (verses == 0) {
+                       continue;
+               }
+
+               /* alloc space for the appropriate number of verses */
+               MALLOC(GRPSYL *, staff_p->syls_p, verses);
+               if ((staff_p->sylplace = (short *) malloc
+                               (sizeof(short) * verses)) == (short *) 0) {
+                       l_no_mem(__FILE__, __LINE__);
+               }
+               staff_p->nsyllists = (short) verses;
+
+               /* now attach the GRPSYLs and set the places for each */
+               for (verses = 0, lyrinfo_p = Lyr_tbl[staff_p->staffno];
+                                       lyrinfo_p != (struct LYRINFO *) 0;
+                                       lyrinfo_p = lyrinfo_p->next, verses++) {
+
+                       staff_p->syls_p[verses] = lyrinfo_p->gs_p;
+                       staff_p->sylplace[verses] = lyrinfo_p->place;
+               }
+
+               free_lyrinfo(Lyr_tbl[staff_p->staffno]);
+               Lyr_tbl[staff_p->staffno] = (struct LYRINFO *) 0;
+       }
+}
+\f
+
+/* recursively free list of LYRINFO structs */
+
+static void
+free_lyrinfo(lyrinfo_p)
+
+struct LYRINFO *lyrinfo_p;     /* the list to free */
+
+{
+       if (lyrinfo_p == (struct LYRINFO *) 0) {
+               return;
+       }
+
+       free_lyrinfo(lyrinfo_p->next);
+       FREE(lyrinfo_p);
+}
+\f
+
+/* At each bar line, reset previous verse number for auto-verse-numbering */
+
+void
+lyr_new_bar()
+{
+       int staff_index;
+       int place_index;
+
+       for (staff_index = 1; staff_index <= MAXSTAFFS; staff_index++) {
+               for (place_index = 0; place_index < NUM_PLACE; place_index++) {
+                       Prev_verse_num[staff_index][place_index] = 0;
+               }
+       }
+}
+
+\f
+
+/* in several places we need to copy part of a lyric from one string to
+ * another while keeping track of the font and size changes along the way.
+ * Doing this with a function gets hard to think about because you'd
+ * have to pass around a bunch of pointers to pointers and keep all the
+ * levels of indirection straight, so I opted for a macro.
+ * destbuff is the char array into which to copy. destindex is the subscript
+ * into that array. src_p is a char * from which to copy. delimiter is the
+ * character at which to stop copying. fnt_p and sz_p are pointer to font
+ * and size which need to be updated if the font or size change.
+ */
+#define COPY_LYR(destbuff, destindex, src_p, delimiter, fnt_p, sz_p) \
+       for (   ; *src_p != '\0' && *src_p != delimiter; src_p++) { \
+               destbuff[destindex++] = *src_p; \
+                                               \
+               switch ( (unsigned) *src_p & 0xff) { \
+               case STR_FONT: \
+                       *fnt_p = *++src_p; \
+                       destbuff[destindex++] = *src_p; \
+                       break; \
+               case STR_SIZE: \
+                       *sz_p = *++src_p; \
+                       destbuff[destindex++] = *src_p; \
+                       break; \
+               case STR_MUS_CHAR: \
+                       destbuff[destindex++] = *++src_p; \
+                       destbuff[destindex++] = *++src_p; \
+                       break; \
+               case STR_BACKSPACE: \
+                       destbuff[destindex++] = *++src_p; \
+                       break; \
+               default: \
+                       break; \
+               } \
+       }
+\f
+
+
+/* break a string of lyrics into individual syllables. The following
+ * characters are special:
+ *     <space>         marks end of syllable
+ *     <tab>           same as space
+ *     -               end of syllable
+ *     _               end of syllable
+ *     '<'             beginning of non-lyric item
+ *     '>'             end of non-lyric item
+ */
+/* Each syllable will be returned as a string of the form:
+ *     <font> <size> [<STR_PRE> pre-item <STR_PRE_END>] syllable [<STR_PST> post-item <STR_PST_END>]
+ * where
+ *     <font> is a 1-byte font identifier, FONT_TR, FONT_TI etc
+ *     <size> is a 1-byte size, in points
+ *     if there is non-lyrics stuff to be put before the lyric syllable, it
+ *             will be surrounded by <STR_PRE> and <STR_PRE_END> characters.
+ *             It may contain other commands for font changes, etc.
+ *             This field is optional. If present it may be of arbitrary
+ *             length, including zero length
+ *             If this text is to be used for syllable
+ *             placement, the header will be <STR_U_PRE> instead
+ *     The syllable follows. It may contain any of the commands found in
+ *             any other string. It can be of zero length.
+ *     Optionally, there may there something to print after the syllable
+ *             that isn't part of the syllable. If there is such a thing,
+ *             it will be surrounded by <STR_PST> and <STR_PST_END> characters.
+ *             If this text is to be used for syllable placement, the
+ *             header will be <STR_U_PST> instead.
+ *     Any of the fields can be of zero length, but at least one of them
+ *             must be of non-zero length for each syllable to be sensible.
+ * This function should be called after the string has been transformed
+ * to internal format, with font/size changes stored as commands.
+ * If a syllable starts with a positioning value, that is updated.
+ */
+
+static char *
+next_syl(sylstring_p, font_p, size_p, position_p, staffno)
+
+char **sylstring_p;    /* address of pointer to current spot in lyric string
+                        * of syllables. At entry, its contents should be
+                        * the address of the first character of the syllable
+                        * to be returned. On return, its contents will be
+                        * updated to point to the first character of the
+                        * following syllable, to be ready for the next call
+                        * to this function.
+                        */
+int *font_p;           /* pointer to current font value, will be updated
+                        * with new font if it changes. */
+int *size_p;           /* pointer to current size value; will be updated
+                        * with new size if it changes */
+short *position_p;     /* pointer to sylposition field, will be updated
+                        * with the user-specified position value, if
+                        * they specified one, otherwise will be left as is. */
+int staffno;           /* which staff this syllable is for */
+
+{
+       char *p;                /* pointer into lyrics string */
+       int done;               /* boolean to keep track of if we are done */
+       int font, size;         /* original font and size */
+       int i;                  /* index into sylbuff */
+       char sylbuff[BUFSIZ];   /* temporary storage for a syllable */
+
+
+       /* initialize */
+       sylbuff[0] = '\0';
+       i = 0;
+       font = *font_p;
+       size = *size_p;
+
+       /* skip any leading white space */
+       for (p = *sylstring_p; *p != '\0'; p++) {
+               if (*p != ' ') {
+                       break;
+               }
+       }
+
+       /* see if we have a non-lyrics before the lyric */
+       if ( *p == '<') {
+
+               /* we do have a non-lyric. Put in the header, and copy up
+                * to the '>', keeping track of any font/size changes
+                * along the way */
+               if (*(p+1) == '^') {
+                       sylbuff[i++] = (char) STR_U_PRE;
+                       p++;
+               }
+               else {
+                       sylbuff[i++] = (char) STR_PRE;
+               }
+               p++;
+               COPY_LYR(sylbuff, i, p, '>', font_p, size_p);
+
+               /* add in the > marker */
+               sylbuff[i++] = (char) STR_PRE_END;
+               if (*p == '\0') {
+                       yyerror("missing '>' in lyric");
+               }
+               else {
+                       p++;
+               }
+       }
+
+       /* see if user gave a position value */
+       if (*p == '|') {
+               /* use default value from parameter */
+               *position_p = svpath(staffno, SYLPOSITION)->sylposition;
+               p++;
+       }
+       else if ( isdigit(*p) ||
+                       ( (*p == '-' || *p == '+') && isdigit(*(p+1)) ) ) {
+               char *after_num_p;
+               int value;
+
+               /* if there is a pipe after the number, it's a position */
+               value = strtol(p, &after_num_p, 10);
+               if ( *after_num_p == '|') {
+                       *position_p = value;
+                       p = after_num_p + 1;
+               }
+       }
+
+       /* now collect the lyric syllable itself */
+       for ( done = NO; *p != '\0' && i < BUFSIZ; p++) {
+
+               switch ( (unsigned) *p & 0xff) {
+
+               case ' ':
+               case '\t':
+                       /* definitely end of this lyric syllable */
+                       done = YES;
+                       break;
+
+
+               case '~':
+                       /* two syllables joined into one. Replace the ~
+                        * by a space */
+                       sylbuff[i++] = ' ';
+                       p++;
+                       break;
+
+               case '-':
+               case '_':
+                       /* end of syllable */
+                       /* need to peek ahead to check for non-lyric following */
+                       sylbuff[i++] = *p++;
+                       if ( *p != '<') {
+                               done = YES;
+                               break;
+                       }
+                       /*FALLTHRU*/
+
+               case '<':
+                       if (*(p+1) == '^') {
+                               sylbuff[i++] = (char) STR_U_PST;
+                               p++;
+                       }
+                       else {
+                               sylbuff[i++] = (char) STR_PST;
+                       }
+                       p++;
+                       COPY_LYR(sylbuff, i, p, '>', font_p, size_p);
+
+                       sylbuff[i++] = (char) STR_PST_END;
+                       p++;
+                       /* A ~ joins this syllable with the next to make
+                        * them effectively one, but anything else ends
+                        * the syllable. But copy - or _ if they are there */
+                       if ( *p != '~') {
+                               if (*p == '-' || *p == '_') {
+                                       sylbuff[i++] = *p++;
+                               }
+                               done = YES;
+                       }
+                       break;
+
+               case STR_FONT:
+                       sylbuff[i++] = *p++;
+                       *font_p = *p;
+#ifdef EXTCHAR
+                       if (*font_p >= FONT_XTR) {
+                               sylbuff[i++] = *p++;
+                       }
+#endif
+                       break;
+
+               case STR_SIZE:
+                       sylbuff[i++] = *p++;
+                       *size_p = *p;
+                       break;
+
+               case STR_BACKSPACE:
+                       sylbuff[i++] = *p++;
+                       break;
+
+               case STR_MUS_CHAR:
+                       sylbuff[i++] = *p++;
+                       sylbuff[i++] = *p++;
+                       break;
+
+               case STR_BOX:
+                       yyerror("boxed text not allowed in lyrics");
+                       break;
+
+               case STR_BOX_END:
+                       break;
+
+               case STR_CIR:
+                       yyerror("circled text not allowed in lyrics");
+                       break;
+
+               case STR_CIR_END:
+                       break;
+
+               case STR_PILE:
+                       yyerror("\\: not allowed in lyric syllable");
+                       break;
+
+               case STR_C_ALIGN:
+               case STR_L_ALIGN:
+                       yyerror("alignment not allowed in lyric syllable");
+                       break;
+
+               default:
+                       break;
+               }
+
+               if (done == NO) {
+                       sylbuff[i++] = *p;
+               }
+               else {
+                       break;
+               }
+       }
+
+       sylbuff[i] = '\0';
+
+       if (i == 0) {
+               yyerror("too few syllables in string");
+       }
+
+       /* prepare for next call to this function */
+       *sylstring_p = p;
+
+       /* return a copy of the extracted syllable */
+       return(copy_string(sylbuff, font, size));
+}
+\f
+
+/* given a syllable string, return the width (in inches) of the non-lyric
+ * parts and of the actual syllable */
+
+void
+sylwidth(lyrstring, wid_b4_syl_p, wid_real_syl_p, wid_after_syl_p)
+
+char *lyrstring;
+float *wid_b4_syl_p;   /* width of leading non-lyrics will be put here */
+float *wid_real_syl_p; /* width of actual syllable will be put here */
+float *wid_after_syl_p;        /* width of trailing non-lyric will be put here */
+
+{
+       do_sylwidth(lyrstring, wid_b4_syl_p, wid_real_syl_p, wid_after_syl_p,
+                                                       NO);
+}
+\f
+
+/* find width of syllable and <...> things. When called in placement phase
+ * we count the <^...> and don't count <...>. When called in print phase
+ * we do the opposite to compensate.
+ */
+
+static void
+do_sylwidth(lyrstring, wid_b4_syl_p, wid_real_syl_p, wid_after_syl_p,
+               compensating)
+
+char *lyrstring;
+float *wid_b4_syl_p;   /* width of leading non-lyrics will be put here */
+float *wid_real_syl_p; /* width of actual syllable will be put here */
+float *wid_after_syl_p;        /* width of trailing non-lyric will be put here */
+int compensating;      /* YES if being called from print phrase when we
+                        * have to compensate for the fact that <...> may
+                        * not have been used in placement. */
+
+{
+       int pre_counts = NO;    /* if pre width should be included */
+       int post_counts = NO;   /* if post width should be included */
+       int had_post = NO;      /* if had post <...> */
+       float w1 = 0.0;         /* width of pre */
+       float w2 = 0.0;         /* width of pre + syllable */
+       float w3;               /* width of entire string */
+       char *p;
+       char save;              /* temp storage */
+       
+
+       if (lyrstring == (char *) 0) {
+               *wid_b4_syl_p = *wid_real_syl_p = *wid_after_syl_p = 0.0;
+               return;
+       }
+
+       for (p = lyrstring; *p != '\0'; p++) {
+               switch ( (unsigned) *p & 0xff) {
+               case STR_PRE:
+                       if (compensating == YES) {
+                               pre_counts = YES;
+                       }
+                       break;
+               case STR_U_PRE:
+                       if (compensating == NO) {
+                               pre_counts = YES;
+                       }
+                       break;
+               case STR_PRE_END:
+                       /* get width of string so far. Temporarily shorten
+                        * string to this point and get its length. This
+                        * will be the length of the preceeding <...> */
+                       *p = '\0';
+                       w1 = strwidth(lyrstring);
+                       *p = (char) STR_PRE_END;
+                       break;
+               case STR_U_PST:
+                       /* get width of string so far. Temporarily shorten
+                        * string to this point and get its length. This
+                        * will be the length of the syllable and its
+                        * preceeding <...> */
+                       if (compensating == NO) {
+                               post_counts = YES;
+                       }
+                       save = *p;
+                       *p = '\0';
+                       w2 = strwidth(lyrstring);
+                       *p = save;
+                       had_post = YES;
+                       break;
+               case STR_PST:
+                       if (compensating == YES) {
+                               post_counts = YES;
+                       }
+                       save = *p;
+                       *p = '\0';
+                       w2 = strwidth(lyrstring);
+                       *p = save;
+                       had_post = YES;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       /* get length of entire string */
+       w3 =  strwidth(lyrstring);
+
+       /* if there wasn't a post <...> we didn't yet get the width of
+        * the syllable plus preceeding <...> */
+       if (had_post == NO) {
+               w2 = w3;
+       }
+
+       /* now calculate and return the widths */
+       *wid_b4_syl_p = (pre_counts == YES ? w1 : 0.0);
+       *wid_real_syl_p = w2 - w1;
+       *wid_after_syl_p = (post_counts == YES ? w3 - w2 : 0.0);
+}
+\f
+
+/* during placement phase, <...> things were used or not used as appropriate
+ * for setting placement. During print phrase, we do the opposite to
+ * compensate, and update the group east and west boundaries as necessary */
+void
+lyr_compensate(gs_p)
+
+struct GRPSYL *gs_p;
+
+{
+       float pre_wid, syl_wid, post_wid;
+
+       do_sylwidth(gs_p->syl, &pre_wid, &syl_wid, &post_wid, YES);
+       gs_p->c[AW] -= pre_wid;
+       gs_p->c[AE] += post_wid;
+}
+\f
+
+/* every time a verse number is used, see whether we've already had that
+ * verse number before. if not, add it to the list of verse numbers used. */
+/* We could keep each range of defined verses in a RANGELIST, so that,
+ * for example, 1-3 could be keep in a single struct. However, trying to
+ * coalese the list could get very hairy, so do the simple-minded way of
+ * saving each unique verse number in its own struct. We could also
+ * insertion sort the list, but rarely will there be more than a couple
+ * verses, and inserting into a singly linked list takes a slight amount
+ * of work, so be very lazy and just search the whole list each time and
+ * insert at beginning if need to add to list. */
+
+static void
+vno_used(vno)
+
+int vno;       /* the verse number to check */
+
+{
+       struct RANGELIST *v_p;  /* to walk through list of verse nums used */
+       struct RANGELIST **list_p_p;    /* which list to check */
+
+
+       switch (Place) {
+       case PL_ABOVE:
+               list_p_p = &Above_vnumbers_used;
+               break;
+       case PL_BETWEEN:
+               list_p_p = &Between_vnumbers_used;
+               break;
+       case PL_BELOW:
+       case PL_UNKNOWN:
+               list_p_p = &Below_vnumbers_used;
+               break;
+       default:
+               pfatal("illegal place in vno_used");
+               /*NOTREACHED*/
+               return;
+       }
+
+       /* see if this verse is already on the list */
+       for (v_p = *list_p_p; v_p != (struct RANGELIST *) 0; v_p = v_p->next) {
+               if (v_p->begin == vno) {
+                       /* already had this verse before */
+                       return;
+               }
+       }
+
+       /* must not have seen this verse number before, so add it */
+       CALLOC(RANGELIST, v_p, 1);
+       v_p->begin = (short) vno;
+       /* ->end is not used in this list */
+       v_p->next = *list_p_p;
+       *list_p_p = v_p;
+}
+\f
+
+/* when parsing is complete, we can find out how many unique verse numbers
+ * there were in the input */
+
+void
+set_maxverses()
+{
+       debug(4, "set_maxverses");
+
+       count_verses(Above_vnumbers_used);
+       count_verses(Below_vnumbers_used);
+       count_verses(Between_vnumbers_used);
+}
+
+/* recursively walk down list of verse numbers used. Count them up and
+ * free them while unwinding */
+
+static void
+count_verses(used_p)
+
+struct RANGELIST *used_p;
+
+{
+       if (used_p == (struct RANGELIST *) 0) {
+               return;
+       }
+
+       count_verses(used_p->next);
+       Maxverses++;
+       FREE(used_p);
+}
+\f
+
+/* Return pointer to the SSV that contains the default timeunit information
+ * for verses being defined. Make sure if there are multiple staffs
+ * being defined, they all have the same default timeunit. If there is only
+ * one voice on the staff, use that for default. If there are 2 voices, if the
+ * place is PL_ABOVE use voice 1, otherwise use voice 2. */
+
+struct SSV *
+get_lyr_dflt_timeunit_ssv()
+
+{
+       struct RANGELIST *staffrange_p; /* to index through list of staffs */
+       struct SSV *ssv_p;              /* containing relevent timeunit */
+       struct SSV *ref_ssv_p;          /* to ensure consistency */
+       RATIONAL timeunit;              /* timeunit for current staff */
+       RATIONAL reference_timeunit;    /* the timeunit found on previous
+                                        * staff, for comparison to make sure
+                                        * they are the same */
+       int staff;
+
+
+       reference_timeunit = Zero;
+       /* if all else fails, use Score value */
+       ssv_p = ref_ssv_p = &Score;
+
+       /* go down the list of staffs, get timeunit for each */
+       for (staffrange_p = Staffrange_p;
+                                       staffrange_p != (struct RANGELIST *) 0;
+                                       staffrange_p = staffrange_p->next) {
+
+               for (staff = staffrange_p->begin; staff <= staffrange_p->end;
+                                               staff++) {
+
+                       /* get appropriate default timeunit value */
+                       if (svpath(staff, VSCHEME)->vscheme == V_1 ||
+                                               Place == PL_ABOVE) {
+                               ssv_p = vvpath(staff, 1, TIMEUNIT);
+                       }
+                       else {
+                               ssv_p = vvpath(staff, 2, TIMEUNIT);
+                       }
+                       timeunit = ssv_p->timeunit;
+
+                       /* check for consistency */
+                       if ( NE(reference_timeunit, Zero) ) {
+                               if ( NE(timeunit, reference_timeunit) ||
+                                               timelists_equal(
+                                               ssv_p->timelist_p,
+                                               ref_ssv_p->timelist_p) == NO) {
+                                       /*  have a mis-match. Give error message,
+                                        * and return the first timeunit we got.
+                                        * No reason to check any more, because
+                                        * all that may happen is that we'll
+                                        * print lots more error messages for
+                                        * the same problem. */
+                                       yyerror("timeunit value must be the same for all lyric staffs being defined on the same input line");
+                                       return(ssv_p);
+                               }
+                       }
+                       else {
+                               /* first time through. Now we have a timeunit
+                                * to use for default */
+                               reference_timeunit = timeunit;
+                               ref_ssv_p = ssv_p;
+                       }
+               }
+       }
+
+       /* Used to pfatal if couldn't find default value. However, that can
+        * happen if user specifies an invalid staff number, so that isn't
+        * a program bug, but a user error. The user error would already have
+        * been flagged, so no reason to complain at all here */
+
+       return(ssv_p);
+}
+\f
+
+/* user wants us to derive the lyrics time values from corresponding music
+ * time values. Find the proper list of GRPSYLs to copy time values from,
+ * and make a copy of that list, with field set properly for lyrics. */
+
+struct GRPSYL *
+derive_lyrtime()
+
+{
+       struct MAINLL *mll_p;           /* to find STAFF to derive from */
+       struct GRPSYL *new_list_p;      /* the list of derived time values */
+       struct GRPSYL *gs_p;            /* to walk through new_list_p */
+       struct GRPSYL *ref_gs_p;        /* to walk through the reference list--
+                                        * the list we are deriving from */
+       int staff, voice;               /* which list of GRPSYLs to clone */
+
+
+       /* If there are no staffs associated with these lyrics, then nothing
+        * to do here. We should have already printed an error elsewhere */
+       if (Staffrange_p == (struct RANGELIST *) 0) {
+               return (struct GRPSYL *) 0;
+       }
+
+       /* find the proper music GRPSYL from which to derive time values */
+       staff = leadstaff();
+       for (mll_p = Mainlltc_p; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->prev) {
+
+               /* if back up all the way to a bar, user hasn't defined the
+                * right staff's music input yet */
+               if (mll_p->str == S_BAR) {
+                       /* pretend we fell off top of list and break out.
+                        * That way we only need one copy of error message code */
+                       mll_p = (struct MAINLL *) 0;
+                       break;
+               }
+               if (mll_p->str == S_STAFF && mll_p->u.staff_p->staffno == staff) {
+                       /* found the right staff data */
+                       break;
+               }
+       }
+
+       if (mll_p == (struct MAINLL *) 0) {
+               l_yyerror(Curr_filename, yylineno,
+                       "can't derive lyrics time values: staff %d music not defined yet", staff);
+               return (struct GRPSYL *) 0;
+       }
+
+       /* usually use voice 1 of first staff specified. Only exceptions
+        * are if voice 1 is invisible or nonexistent or if explicitly below,
+        * and there is a visible voice 2, in which case voice 2 is used */
+       voice = 0;
+       if ((vvpath(staff, 1, VISIBLE)->visible == NO ||
+                       mll_p->u.staff_p->groups_p[0] == (struct GRPSYL *) 0
+                       || Place == PL_BELOW)
+                       && mll_p->u.staff_p->groups_p[1] != (struct GRPSYL *) 0
+                       && vvpath(staff, 2, VISIBLE)->visible == YES) {
+               voice = 1;
+       }
+       /* One more exception. If both voices are invisible, but we would
+        * have used voice 2 if it was visible, use voice 2. Otherwise
+        * if times would normally be derived from voice 2, but the
+        * whole staff is invisible, we could derive the wrong values. */
+       if (vvpath(staff, 1, VISIBLE)->visible == NO &&
+                       vvpath(staff, 2, VISIBLE)->visible == NO &&
+                       mll_p->u.staff_p->groups_p[1] != (struct GRPSYL *) 0 &&
+                       Place == PL_BELOW) {
+               voice = 1;
+       }
+
+       if (mll_p->u.staff_p->groups_p[voice] == (struct GRPSYL *) 0) {
+               l_yyerror(Curr_filename, yylineno,
+                       "can't derive lyrics time values: staff %d voice %d music not defined yet", staff, voice + 1);
+               return (struct GRPSYL *) 0;
+       }
+
+       new_list_p = clone_gs_list(mll_p->u.staff_p->groups_p[voice], NO);
+
+       /* grace notes don't count in the time derivation, so remove
+        * them from the cloned list */
+       for (gs_p = new_list_p; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+               if (gs_p->grpvalue == GV_ZERO) {
+                       struct GRPSYL *to_free_p;
+                       to_free_p = gs_p;
+                       if (gs_p->prev == 0) {
+                               new_list_p = gs_p->next;
+                       }
+                       else {
+                               gs_p->prev->next = gs_p->next;
+                       }
+                       /* Note that there should always be a 'next' after
+                        * a grace note, so this 'if' shouldn't really be
+                        * necessary, but it is here as defensive code. */
+                       if (gs_p->next != 0) {
+                               gs_p->next->prev = gs_p->prev;
+                       }
+                       FREE(to_free_p);
+               }
+       }
+
+       /* go through cloned list, changing type to lyrics and changing rests
+        * in the music to spaces for the lyrics. Also deal with ties and slurs,
+        * since notes that are tied or slurred to will be treated like a
+        * space, since there is probably only a single syllable wanted. */
+       for (gs_p = new_list_p, ref_gs_p = mll_p->u.staff_p->groups_p[voice];
+                       gs_p != (struct GRPSYL *) 0;
+                       gs_p = gs_p->next, ref_gs_p = ref_gs_p->next) {
+               /* Skip graces in reference list. (There aren't any in
+                * the new list since we removed them above.) */
+               while (ref_gs_p->grpvalue == GV_ZERO) {
+                       ref_gs_p = ref_gs_p->next;
+                       if (ref_gs_p == 0) {
+                               /* should be impossible to get here */
+                               pfatal("unexpected null ref_gs_p in derive_lyrtime");
+                       }
+               }
+
+               gs_p->grpsyl = GS_SYLLABLE;
+               if (ref_gs_p->grpcont == GC_REST) {
+                       gs_p->grpcont = GC_SPACE;
+               }
+               else if (ref_gs_p->grpcont == GC_NOTES && ref_gs_p->nnotes > 0) {
+                       /* if the top note of the chord is tied or slurred,
+                        * or the entire chord is tied,
+                        * make the following lyrics GRPSYL, if any, a space. */
+                       if ((ref_gs_p->notelist[0].tie == YES ||
+                                       ref_gs_p->tie == YES ||
+                                       ref_gs_p->notelist[0].nslurto > 0) &&
+                                       gs_p->next != (struct GRPSYL *) 0) {
+                               gs_p->next->grpcont = GC_SPACE;
+                       }
+               }
+       }
+
+       /* One more detail: if the first note was tied-to or slurred-to from
+        * the previous measure, we have to change that to a space. To do that,
+        * we call prevgrpsyl, but it expects the staffno and vno to be filled
+        * in on the GRPSYL passed to it, and we're so early in parsing that
+        * that hasn't happened yet. So first have to patch that up. Later on,
+        * all the GRPSYLs will get the staffno and vno filled in, but it won't
+        * hurt anything that we've already done this one here; they will
+        * just be overwritten with the same values. */
+       ref_gs_p = mll_p->u.staff_p->groups_p[voice];
+       ref_gs_p->staffno = mll_p->u.staff_p->staffno;
+       ref_gs_p->vno = voice + 1;
+       if ((gs_p = prevgrpsyl(ref_gs_p, &mll_p)) != (struct GRPSYL *) 0) {
+               if (gs_p->grpcont == GC_NOTES && gs_p->nnotes > 0) {
+                       if (gs_p->notelist[0].tie == YES ||
+                                       gs_p->tie == YES ||
+                                       gs_p->notelist[0].nslurto > 0) {
+                               new_list_p->grpcont = GC_SPACE;
+                       }
+               }
+       }
+
+       return (new_list_p);
+}
+
diff --git a/mup/mup/macros.c b/mup/mup/macros.c
new file mode 100644 (file)
index 0000000..d6d6f63
--- /dev/null
@@ -0,0 +1,1322 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2004, 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions to support Mup macros */
+
+/* When a macro is defined, its text is copied to a file. When a macro is
+ * invoked, information about the current input file is pushed on a stack,
+ * and the macro text is read from the macro file. This file also has the
+ * code to handle include files. They are handled similarly. Info about the
+ * current file is pushed on a stack, and text is read from the included
+ * file. */
+
+#include <string.h>
+#include <fcntl.h>
+#include "globals.h"
+
+#ifdef VMS
+#define unlink delete
+#endif
+
+/* size of macro name hash table. should be prime, big enough to not have too
+ * many collisions, small enough to not use too much memory. */
+#define MTSIZE (79)
+
+/* how many bytes to allocate at a time when collecting macro arguments */
+#define MAC_ARG_SZ     (512)
+
+/* We may need just a plain copy of the text passed as a macro parameter,
+ * or a quoted copy, or both. These flags say which we need.
+ * This is currently only actually implemented in a limited form:
+ * we always generate an unquoted copy, and if there is any chance any
+ * parameter in a macro will be needed in quoted form, we make quoted
+ * copies of all parameters for that macro. This is because to really
+ * figure out unequivicably which we need would be complicated enough
+ * that we'd probably wind up spending more than we'd save,
+ * so just doing this half-hearted optimization seems like the best tradeoff.
+ */
+#define QS_UNQUOTED    (0x1)
+#define QS_QUOTED      (0x2)
+
+/* information about a macro parameter */
+struct MAC_PARAM {
+       char    *param_name;    /* name of the parameter */
+       int     quote_style;    /* bitmap of QS_* values */
+       struct MAC_PARAM *next; /* for linked list */
+};
+
+/* info about a macro */
+struct MACRO {
+       char    *macname;       /* name of macro */
+       char    *filename;      /* file in which macro was defined */   
+       int     lineno;         /* line in file where macro definition began */
+       int     lineoffset;     /* how many lines we are into macro */
+       long    offset;         /* offset in macro temporary file where the
+                                * text of the macro is stored for later use */
+       long    quoted_offset;  /* offset into macro temp file where the
+                                * quoted version is stored, if any.
+                                * Only used on macro parameters. */
+       struct MACRO    *next;  /* for hash collision list */
+       int     recursion;      /* incremented each time the macro is called,
+                                * and decremented on completion. If this gets
+                                * above 1 we are in trouble and ufatal */
+       int     num_params;     /* how many parameters */
+       struct  MAC_PARAM *parameters_p;        /* list of macro parameter
+                                * names. Null if this macro doesn't
+                                * have parameters */
+};
+
+/* macro information hash table */
+static struct MACRO *Mactable[MTSIZE];
+
+/* temporary file for saving text of macros. Need separate handles for reading
+ * and writing */
+static FILE *Mactmp_read = (FILE *) 0;
+static FILE *Mactmp_write = (FILE *) 0;
+#ifdef UNIX_LIKE_FILES
+static char Macfile[] = "mupmacXXXXXX";                /* name of temp file */
+#else
+/* As last resort, we use a temp file name of 11 character length,
+ * so make sure we have enough room for that. Usually L_tmpnam is
+ * already longer than that, but better safe than core dump.
+ */
+#if L_tmpnam < 12
+#undef L_tmpnam
+#define L_tmpnam 12
+#endif
+static char Macfile[L_tmpnam];         /* name of temp file */
+#endif
+
+/* Some OSs require us to open files in binary mode. Most implementations
+ * of fopen these days accept the 'b' suffix, even when they don't care
+ * about it, but to be safe, we only add on systems that appear to have
+ * binary mode defined. */
+#ifdef O_BINARY
+static char *Read_mode = "rb";
+#ifndef UNIX_LIKE_FILES
+static char *Write_mode = "wb";
+static char *Append_mode = "ab";
+#endif
+#else
+static char *Read_mode = "r";
+#ifndef UNIX_LIKE_FILES
+static char *Write_mode = "w";
+static char *Append_mode = "a";
+#endif
+#endif
+
+/* maximum number of files on file stack */
+#ifndef FOPEN_MAX
+#ifdef _NFILE
+#define FOPEN_MAX      _NFILE
+#else
+#define FOPEN_MAX      (20)
+#endif
+#endif
+/* The -5 is to account for stdin, stdout, stderr, and the 2 tmp file handles.
+ * The +20 is to allow for nested macros. They can take 2 stack slots per call
+ * since argument expansion also uses a slot, but they don't take extra
+ * file descriptors, since all the macros are kept in one file. */
+#define MAXFSTK        (FOPEN_MAX - 5 + 20)
+
+
+struct FILESTACK {
+       FILE    *file;
+       char    *filename;
+       long    fileoffset;             /* fseek position in file */
+       int     lineno;                 /* where we are in the file */
+       struct MACRO    *mac_p;         /* if pushing because of a macro call,
+                                        * this will point to info about the
+                                        * macro, otherwise 0. */
+};
+
+static struct FILESTACK Filestack[MAXFSTK];
+
+static int Fstkptr = -1;               /* stack pointer for Filestack */
+static char quote_designator[] = "`";
+
+extern int unlink();                   /* to remove temp file */
+extern char *tmpnam();         /* generate temp file name */
+
+/* static function declarations */
+static void pushfile P((FILE *file, char *filename, int lineno,
+               struct MACRO *mac_p));
+static char *path_combiner P((char *prefix));
+static int is_absolute_path P((char *filename));
+static struct MACRO *findMacro P((char *macname));
+static int hashmac P(( char *macname));
+static struct MACRO *setup_macro P((char *macname));
+static void free_parameters P((struct MAC_PARAM *param_p, char *macname,
+               int values_only));
+static char *dupstring P((char *string));
+static char *mkmacparm_name P((char *macname, char *param_name));
+static struct MACRO *resolve_mac_name P((char *macname));
+static int has_quote_designator P((char *macname));
+
+
+\f
+
+/* add macro name to hash table and arrange to save its text in temp file */
+
+void
+define_macro(macname)
+
+char *macname;         /* name of macro to be defined */
+
+{
+       int has_params = NO;
+       char *mac_name;         /* copy of macro name, because what gets
+                                * passed in can get overwritten by parameter
+                                * names */
+       struct MACRO *mac_p;
+       struct MAC_PARAM *parm_p;
+
+       debug (4, "define_macro macname=%s\n", macname);
+
+       /* there might be some leading white space in front of macro name,
+        * if so, ignore that */
+       while (*macname == ' ' || *macname == '\t') {
+               macname++;
+       }
+
+       /* if ends with a ( this macro has parameters */
+       if (macname[strlen(macname) - 1] == '(') {
+               /* this is a macro with parameters */
+               macname[strlen(macname) - 1] = '\0';
+               has_params = YES;
+       }
+
+       mac_p = setup_macro(macname);
+       mac_name = mac_p->macname;
+
+       if (has_params == YES) {
+               get_parameters(mac_name);
+       }
+
+       /* copy the macro text to the macro temp file */
+       if (save_macro(Mactmp_write) == YES) {
+               /* There may have been a reference to a parameter to be
+                * quoted. So remind ourseleves to create quoted copies
+                * of parameters when this macro is called later.
+                * This is a half-hearted optimization:
+                * we will sometimes create extra copies unnecessarily,
+                * but much of the time we will get the benefit of a
+                * full optimization with only a fraction of the work. */
+               for (parm_p = mac_p->parameters_p;
+                                       parm_p != (struct MAC_PARAM *) 0;
+                                       parm_p = parm_p->next) {
+                       parm_p->quote_style |= QS_QUOTED;
+               }
+       }
+               
+
+       /* terminate the macro with a NULL, so that when lex hits it when
+        * the macro is called, it will think it hit EOF */
+       putc('\0', Mactmp_write);
+
+       /* make sure macro has really been written and not still buffered */
+       (void) fflush(Mactmp_write);
+
+#ifndef UNIX_LIKE_FILES
+       /* on non-unix system, multiple opens on the same file may not work,
+        * so open and close each time */
+       fclose(Mactmp_write);
+#endif
+}
+\f
+
+/* save macro info in hash table and make sure macro temporary file is
+ * set up and ready to use */
+
+static struct MACRO *
+setup_macro(macname)
+
+char *macname;         /* name of macro being defined */
+
+{
+       struct MACRO *mac_p;    /* info about current macro */
+       int h;                  /* hash number */
+       static int have_mac_file = NO;
+#ifdef UNIX_LIKE_FILES
+       int filedesc;           /* of tmp file for storing macros */
+#endif
+
+
+       /* if macro has not been defined before, add to hash table */
+       if ((mac_p = findMacro(macname)) == (struct MACRO *) 0) {
+
+               MALLOC(MACRO, mac_p, 1);
+               h = hashmac(macname);
+               mac_p->next = Mactable[h];
+               Mactable[h] = mac_p;
+
+               mac_p->macname = dupstring(macname);
+               mac_p->num_params = 0;
+               mac_p->parameters_p = (struct MAC_PARAM *) 0;
+               mac_p->recursion = 0;
+       }
+       else {
+               l_warning(Curr_filename, yylineno,
+                                       "macro '%s' redefined", macname);
+               free_parameters(mac_p->parameters_p, macname, NO);
+               mac_p->parameters_p = (struct MAC_PARAM *) 0;
+               mac_p->num_params = 0;
+       }
+
+       /* save current filename and line number so they can be used to give
+        * useful error messages when the macro is called */
+       if (Fstkptr >= 0 && Filestack[Fstkptr].mac_p != (struct MACRO *) 0) {
+               /* if current expanding a macro, get file/line info relative
+                * to the macro */
+               mac_p->filename = Filestack[Fstkptr].mac_p->filename;
+               mac_p->lineno = Filestack[Fstkptr].mac_p->lineno +
+                               Filestack[Fstkptr].mac_p->lineoffset;
+       }
+       else {
+               mac_p->filename = Curr_filename;
+               mac_p->lineno = yylineno;
+       }
+
+       /* if we don't yet have a temp file to store macro info, open one */
+       if (have_mac_file == NO) {
+               /* We need separate read/write file pointers in case of defining
+                * one macro inside another, so can't easily use tmpfile().
+                * The most straightforward way to do this is to use tmpnam.
+                * But recent versions of gcc complain loudly that tmpnam
+                * is dangerous--you should use mkstemp instead. While it's
+                * true tmpnam could have problems under certain conditions,
+                * Mup's use of it hardly qualifies as "dangerous." Yes,
+                * perhaps if you tried really hard by running lots and
+                * lots of instances of Mup simultaneously, and they all
+                * used macros, maybe you could get one of them to fail once
+                * in a while. But some systems may not support mkstemp,
+                * since it's more from BSD than System V, and it's unclear
+                * how it ought to function on a system that has DOS-style
+                * (8.3 character) filenames if you gave it a longer string
+                * than would be a legal file name.
+                * And, interestingly, the Solaris manual pages say
+                * that you should NOT use mkstemp, in direct conflict with
+                * gcc's opinion. They say to use tmpfile, which we can't do
+                * because that just gives a single file pointer for writing,
+                * but we want one for writing and one for reading.
+                * So it's very unclear what to do. For unix-ish systems
+                * we'll go with mkstemp, and for others use tmpnam.
+                * We get a temp file name, open it twice, once for writing,
+                * once for reading, then remove the file. This will make it a
+                * hidden file that will disappear when the 2 file pointers
+                * are closed.
+                */
+#ifdef UNIX_LIKE_FILES
+               if ((filedesc = mkstemp(Macfile)) < 0) {
+                       ufatal("can't create temporary file for macro storage (possibly you don't have write permissions on directory/file?)");
+               }
+               if ((Mactmp_write = fdopen(filedesc, "w")) == (FILE *) 0) {
+                       pfatal("can't fdopen temporary file for macro storage");
+               }
+               if ((Mactmp_read = fopen(Macfile, "r")) == (FILE *) 0) {
+                       pfatal("can't open temporary file for reading macro");
+               }
+
+               /* arrange for file to vanish */
+               (void) unlink(Macfile);
+#else
+               /* On non-UNIX systems, unlinking an open file may not have
+                * the desired effect, and some systems don't properly
+                * handle both a read and write FILE * on the same file.
+                * So for those we just create it here and have to open
+                * and close the file each time. */
+               (void) tmpnam(Macfile);
+               if ((Mactmp_write = fopen(Macfile, Write_mode)) == (FILE *) 0) {
+                       /* If tmpnam isn't implemented or fails,
+                        * try a hard-coded temp name and hope
+                        * for the best... */
+                       (void) strcpy(Macfile, "MupMacF.tmp");
+                       if ((Mactmp_write = fopen(Macfile, Write_mode))
+                                                       == (FILE *) 0) {
+                               ufatal("can't open temporary file for macro storage (possibly you don't have write permissions on directory/file?)");
+                       }
+               }
+#endif
+               have_mac_file = YES;
+       }
+#ifndef UNIX_LIKE_FILES
+       else {
+               if ((Mactmp_write = fopen(Macfile, Append_mode)) == (FILE *) 0) {
+                       pfatal("can't open temporary file for macro storage (maybe out of memory?)");
+               }
+       }
+#endif
+       /* make sure we're at the end. Now that we have separate read/write
+        * file pointers, this should be unnecessary. However, on one non-UNIX
+        * system is seemed the opening for append didn't really work,
+        * requiring this fseek to actually go to the end. And in a previous
+        * variation of this code, this fseek was needed for the UNIX way too.
+        * In any case, it doesn't hurt to be sure we are where we want to be. */
+       if (fseek(Mactmp_write, 0L, SEEK_END) != 0) {
+               pfatal("fseek failed in setup_macro");
+       }
+
+       /* keep track of where this macro will begin in the temp file */
+       mac_p->offset = ftell(Mactmp_write);
+
+       return(mac_p);
+}
+\f
+
+#ifndef UNIX_LIKE_FILES
+/* on non-unix systems, unlinking an open file may produce undesired results,
+ * so clean up the macro temp file after parsing is done. Unfortunately,
+ * this leave a higher possibility of leaving an orphan temp file. */
+
+void
+mac_cleanup()
+
+{
+       if (Macfile[0] != '\0') {
+               unlink(Macfile);
+       }
+       Macfile[0] =  '\0';
+}
+#endif
+\f
+
+/* look up macro name in hash table and return info about it, or null if
+ * not defined */
+
+static struct MACRO *
+findMacro(macname)
+
+char *macname;         /* which macro to look up */
+
+{
+       struct MACRO *mac_p;    /* pointer to info about macro */
+
+
+       /* search hash table and collision chain off the table for match
+        * of macro name */
+       for (mac_p = Mactable[ hashmac(macname) ]; mac_p != (struct MACRO *) 0;
+                                               mac_p = mac_p->next) {
+
+               if (strcmp(mac_p->macname, macname) == 0) {
+                       /* found it! */
+                       return(mac_p);
+               }
+       }
+
+       /* macro not defined */
+       return( (struct MACRO *) 0);
+}
+\f
+
+/* remove a macro definition. We just remove its entry from the hash table.
+ * Its text will still remain in the macro temp file, because it seems like
+ * too much trouble to do storage management on a temp file. */
+/* Note that if asked to undef a macro that isn't defined, it silently
+ * does nothing. */
+
+void
+undef_macro(macname)
+
+char *macname;         /* which macro to undefine */
+
+{
+       struct MACRO *mac_p;    /* to walk though list of info about macros */
+       struct MACRO **mac_p_p; /* to keep track of delete place */
+
+
+       /* there might be some leading white space in front of macro name,
+        * if so, ignore that */
+       while (*macname == ' ' || *macname == '\t') {
+               macname++;
+       }
+
+       /* keep track of where to delete from linked list */
+       for (mac_p_p = &(Mactable[ hashmac(macname) ]);
+                                       *mac_p_p != (struct MACRO *) 0;
+                                       mac_p_p = &((*mac_p_p)->next)) {
+               mac_p = *mac_p_p;
+               if (strcmp(mac_p->macname, macname) == 0) {
+                       
+                       /* found it--delete this entry from list */
+                       *mac_p_p = mac_p->next;
+                       FREE(mac_p->macname);
+                       free_parameters(mac_p->parameters_p, macname, NO);
+                       FREE(mac_p);
+                       return;
+               }
+       }
+}
+\f
+
+/* generate hash number from macro name */
+
+static int
+hashmac(macname)
+
+char *macname;
+
+{
+       int h;
+
+       /* add up characters of name and take sum modulo hash table size */
+       for (h = 0; *macname != '\0'; macname++) {
+               h += *macname;
+       }
+       return(h % MTSIZE);
+}
+\f
+
+/* when macro is called, arrange to read its text from macro file */
+
+void
+call_macro(macname)
+
+char *macname;         /* which macro to call */
+
+{
+       struct MACRO *mac_p;    /* info about the macro */
+
+
+       debug(4, "call_macro macname=%s\n", macname);
+
+       if ((mac_p = resolve_mac_name(macname)) == (struct MACRO *) 0) {
+               l_yyerror(Curr_filename, yylineno,
+                               "macro '%s' not defined", macname);
+               return;
+       }
+
+       
+       /* if macro has parameter,  remove any previous arguments
+        * and gather the arguments for this call */
+       if (mac_p->parameters_p != (struct MAC_PARAM *) 0) {
+               free_parameters(mac_p->parameters_p, macname, YES);
+               if (get_mac_arguments(macname, mac_p->num_params) == NO) {
+                       /* something was wrong with argument. Don't bother
+                        * trying to expand, because we'll probably just
+                        * just lots more error messages */
+                       return;
+               }
+       }
+
+#ifndef UNIX_LIKE_FILES
+       if ((Mactmp_read = fopen(Macfile, Read_mode)) == (FILE *) 0) {
+               pfatal("can't open macro file for reading (maybe out of memory?)");
+       }
+#endif
+
+       /* save old yyin value and make macro definition the input */
+       pushfile(Mactmp_read, mac_p->filename, mac_p->lineno, mac_p);
+       
+       /* go to where macro definition begins */
+       if (fseek(Mactmp_read, (has_quote_designator(macname)
+                       ? mac_p->quoted_offset : mac_p->offset),
+                       SEEK_SET) != 0) {
+               pfatal("fseek failed in call_macro");
+       }
+}
+\f
+
+/* save info about current yyin and set yyin to specified file */
+
+static void
+pushfile(file, filename, lineno, mac_p)
+
+FILE *file;            /* replace current file with this file */
+char *filename;                /* name of new file to use */
+int lineno;            /* current linenumber in new file */
+struct MACRO *mac_p;   /* if switching to macro temp file because of a
+                        * macro call, this is information about macro.
+                        * Otherwise, it will be null. */
+
+{
+       debug(4, "pushfile file=%s", filename);
+
+       /* do error checks */
+       if (++Fstkptr >= MAXFSTK) {
+               l_ufatal(filename, lineno,
+                       "too many nested files or macros (%d levels maximum)\n",
+                       MAXFSTK);
+       }
+       
+       if (mac_p != (struct MACRO *) 0) {
+               if ( ++(mac_p->recursion) != 1) {
+                       l_ufatal(Curr_filename, yylineno,
+                               "macro '%s' called recursively",
+                               mac_p->macname);
+               }
+       }
+
+       /* save current info */
+       Filestack[Fstkptr].file = yyin;
+       Filestack[Fstkptr].fileoffset = ftell(yyin);
+       Filestack[Fstkptr].filename = Curr_filename;
+       Filestack[Fstkptr].lineno = yylineno;
+       Filestack[Fstkptr].mac_p = mac_p;
+
+       /* arrange to use the new file */
+       new_lexbuff(file);
+
+       /* if we are now expanding a macro, we don't change the input line
+        * number.  If doing an include, then we do. */
+       if (Filestack[Fstkptr].mac_p == (struct MACRO *) 0) {
+               yylineno = lineno;
+               Curr_filename = filename;
+       }
+       else {
+               Filestack[Fstkptr].mac_p->lineoffset = 0;
+       }
+}
+\f
+
+/* if there are any files on the Filestack, go back to the previous one
+ * on the stack. Return 1 if something was popped, 0 if stack was empty */
+
+int
+popfile()
+
+{
+       debug(4, "popfile");
+
+       /* if nothing on file stack, nothing to do  except return 0 */
+       if (Fstkptr < 0) {
+               return(0);
+       }
+
+       if (Filestack[Fstkptr].mac_p != (struct MACRO *) 0) {
+               /* returning from macro call */
+               Filestack[Fstkptr].mac_p->recursion = 0;
+#ifndef UNIX_LIKE_FILES
+               (void) fclose(yyin);
+#endif
+       }
+       else {
+               /* this is an include rather than a macro file, so close it */
+               (void) fclose(yyin);
+       }
+
+       /* set things back to the previous file */
+       yyin = Filestack[Fstkptr].file;
+       Curr_filename = Filestack[Fstkptr].filename;
+       if (Filestack[Fstkptr].fileoffset >= 0) {
+               if (fseek(yyin, Filestack[Fstkptr].fileoffset, SEEK_SET) != 0) {
+                       pfatal("fseek failed in popfile");
+               }
+       }
+       yylineno = Filestack[Fstkptr].lineno;
+
+       /* go back to previous file */
+       del_lexbuff();
+
+       /* decrement stackpointer */
+       Fstkptr--;
+
+       return(1);
+}
+\f
+
+/* return 1 if we are NOT currently expanding a macro, 0 if we are.
+ * This backwards logic is used because when we ARE doing a macro, we
+ * should NOT muck with yylineno, and vice versa. If in a macro, adjust
+ * the line offset within the macro by the specified amount. */
+
+int
+not_in_mac(inc_dec)
+
+int inc_dec;   /* how much to increment/decrement the in-macro line offset */
+{
+       if (Fstkptr >= 0 && Filestack[Fstkptr].mac_p != (struct MACRO *) 0) {
+               /* we are in a macro */
+               Filestack[Fstkptr].mac_p->lineoffset += inc_dec;
+               return(0);
+       }
+       else {
+               return(1);
+       }
+}
+\f
+
+/* if an error occurs while expanding a macro, give additional help */
+
+void
+mac_error()
+
+{
+       struct MACRO *mac_p;
+
+       if (Fstkptr >= 0 && (mac_p = Filestack[Fstkptr].mac_p)
+                                               != (struct MACRO *) 0) {
+               (void) fprintf(stderr, "note: previous error found while expanding macro %s'%s' from %s: line %d:\n",
+                               (strchr(mac_p->macname, '(') ? "parameter " : ""),
+                               mac_p->macname,
+                               mac_p->filename,
+                               mac_p->lineno + mac_p->lineoffset);
+               print_offending_line(mac_p->filename, mac_p->lineno + mac_p->lineoffset);
+       }
+}
+\f
+
+/* process an included file */
+
+void
+includefile(fname)
+
+char *fname;   /* name of file to include */
+
+{
+       FILE *file;             /* the included file */
+       char *fnamecopy;
+
+
+       /* attempt to open file. Give message if fail */
+       /* Note that if we find the file somewhere up the MUPPATH
+        * rather than directly, fname will be updated to contain the
+        * actual path of the file we are using, so we can tell that
+        * to the user. That way if they have several files by the same
+        * name but in different directories, and we're picking up a different
+        * one than they had intended, we can give them a clue of what's
+        * going on... */
+       if ((file = find_file(&fname)) == (FILE *) 0) {
+
+               l_ufatal(Curr_filename, yylineno,
+                               "can't open include file '%s'", fname);
+       }
+
+       /* need to make copy of file name */
+       fnamecopy = dupstring(fname);
+
+       /* arrange to connect yyin to the included file, save info, etc */
+       pushfile(file, fnamecopy, 1, (struct MACRO *) 0);
+}
+\f
+
+/* Find a file to be included. First look using file name as is.
+ * If not found, check if is absolute path name, and if so, give up.
+ * Otherwise, try prepending each component of $MUPPATH in turn,
+ * and trying that as a path. If a file is found, return that.
+ * If we reach the end of the list, give up. 
+ * Giving up means returning 0. If we find it somewhere up the MUPPATH
+ * rather than directly, update filename to point to the actual path used.
+ */
+
+FILE *
+find_file(filename_p)
+
+char **filename_p;
+
+{
+       char *filename;
+       FILE *file;
+       char *fullpath;
+       char *combiner;                 /* what goes between path components */
+       char *muppath;                  /* value of $MUPPATH */
+       char *prefix;                   /* component of $MUPPATH,
+                                        * to prepend to filename */
+       char *path_separator = "\0";    /* between components in $MUPPATH */
+
+
+       /* first try name just as it is. */
+       filename = *filename_p;
+       if ((file = fopen(filename, Read_mode)) != (FILE *) 0) {
+               return(file);
+       }
+
+       /* If it's an absolute path, we have to give up */
+       if (is_absolute_path(filename)) {
+               return ((FILE *) 0);
+       }
+
+       /* See if user set a $MUPPATH for where to look for includes */
+       if ((muppath = getenv("MUPPATH")) != (char *) 0) {
+
+#ifdef UNIX_LIKE_PATH_RULES
+               path_separator = ":";
+#endif
+#ifdef DOS_LIKE_PATH_RULES
+               path_separator = ";";
+#endif
+               if (*path_separator == '\0') {
+                       /* If user went to the trouble of setting $MUPPATH,
+                        * they probably think it will work, so we better
+                        * let them know it doesn't. Hopefully they will
+                        * tell us what path rules their operating system
+                        * uses, so we support it in the next release. */
+                       warning("MUPPATH facility not implemented for this operating system");
+                       return (FILE *) 0;
+               }
+
+               /* walk through $MUPPATH */
+               for (prefix = strtok(muppath, path_separator);
+                               prefix != (char *) 0;
+                               prefix = strtok(0, path_separator)) {
+       
+                       combiner = path_combiner(prefix);
+
+                       /* get enough space for the full name */
+                       MALLOCA(char, fullpath, strlen(filename) +
+                               strlen(prefix) + 1 + strlen(combiner));
+
+                       /* create full path */
+                       sprintf(fullpath, "%s%s%s", prefix, combiner, filename);
+
+                       /* See if this file exists */
+                       debug(4, "checking '%s' for include, using MUPPATH",
+                                       fullpath);
+                       if ((file = fopen(fullpath, Read_mode)) != (FILE *) 0) {
+                               *filename_p = fullpath;
+                               return(file);
+                       }
+
+                       /* no file here, no need to save this path */
+                       FREE(fullpath);
+               }
+       }
+
+       return (FILE *) 0;
+}
+\f
+
+/* return true if given filename is an absolute path name */
+
+static int
+is_absolute_path(filename)
+
+char *filename;
+
+{
+
+#ifdef UNIX_LIKE_PATH_RULES
+       /* For Unix, a pathname is absolute if it starts with a slash */
+       return (*filename == '/');
+#endif
+
+#ifdef DOS_LIKE_PATH_RULES
+       /* If second character is a colon, then absolute */
+       if (*filename != '\0' && *(filename + 1) == ':') {
+               return(1);
+       }
+       else {
+               return(0);
+       }
+#endif
+
+#if ! defined(UNIX_LIKE_PATH_RULES) && ! defined(DOS_LIKE_PATH_RULES)
+       /* Not implemented for this operating system. We'll pretend
+        * it's not, which will make it fall through and fail later. */
+       return(0);
+#endif
+}
+\f
+
+/* What to use to glue together a prefix and relative path to get a
+ * full path. */
+
+static char *
+path_combiner(prefix)
+
+char *prefix;
+
+{
+
+#ifdef UNIX_LIKE_PATH_RULES
+       /* Unix separator is slash. If there was already a slash at the
+        * end of the prefix, no problem: multiples slashes are like one */
+       return ("/");
+#endif
+
+#ifdef DOS_LIKE_PATH_RULES
+       /* Use backslash, unless prefix ended with slash or backslash,
+        * in which case we don't need anything. */
+       char last_ch;
+       last_ch = prefix[strlen(prefix) - 1];
+       return ((last_ch == '\\' || last_ch == '/') ? "" : "\\");
+#endif
+
+#if ! defined(UNIX_LIKE_PATH_RULES) && ! defined(DOS_LIKE_PATH_RULES)
+       /* Shouldn't be here. Unimplemented for this operating system */
+       return ("");
+#endif
+}
+\f
+
+/* return YES if macro is currently defined, NO if it isn't */
+
+int
+is_defined(macname, paramtoo)
+
+char *macname;
+int paramtoo;  /* if YES, also look for macro parameter by this name,
+                * otherwise just macro */
+
+{
+       if (paramtoo) {
+               return(resolve_mac_name(macname) == 0 ? NO : YES);
+       }
+       else {
+               return(findMacro(macname) == 0 ? NO : YES);
+       }
+}
+\f
+
+/* when the -D option is used on the command line, save the macro definition. */
+
+void
+cmdline_macro(macdef)
+
+char *macdef;  /* MACRO=definition */
+
+{
+       char *def;
+
+
+       /* separate out the macro name */
+       if (*macdef == '_') {
+               if (Mupmate == YES) {
+                       l_yyerror(0, -1, "Run > Set Options > Define Macros: macro name cannot start with underscore.");
+               }
+               else {
+                       l_yyerror(0, -1, "argument for %cD is invalid: macro name cannot start with underscore", Optch);
+               }
+               return;
+       }
+       for (def = macdef; *def != '\0'; def++) {
+               if ( ! isupper(*def) && ! isdigit(*def) && *def != '_') {
+                       break;
+               }
+       }
+
+       /* make sure has form XXX=definition */
+       if (def == macdef) {
+               if (Mupmate == YES) {
+                       l_yyerror(0, -1, "Run > Set Options > Define Macros: macro name only allowed to contain upper case letters, numbers and underscores.");
+               }
+               else {
+                       l_yyerror(0, -1, "argument for %cD is missing or wrong format", Optch);
+               }
+               return;
+       }
+
+       if (*def == '=') {
+               *def++ = '\0';
+       }
+       else if (*def != '\0') {
+               if (Mupmate == YES) {
+                       l_yyerror(0, -1, "Run > Set Options > Define Macros: macro name is invalid or missing '=' on macro definition.");
+               }
+               else {
+                       l_yyerror(0, -1, "argument for %cD had invalid name or missing '=' on macro definition", Optch);
+               }
+               return;
+       }
+
+       Curr_filename = "Command line argument";
+       (void) setup_macro(macdef);
+
+       /* copy the macro to the macro temp file */
+       do {
+               putc(*def, Mactmp_write);
+       } while ( *def++ != '\0');
+       (void) fflush(Mactmp_write);
+#ifndef UNIX_LIKE_FILES
+       fclose(Mactmp_write);
+#endif
+}
+\f
+
+/* recursively free a list of macro parameters */
+
+static void
+free_parameters(param_p, macname, values_only)
+
+struct MAC_PARAM *param_p;     /* what to free */
+char *macname;                 /* name of macro having this parameter */
+int values_only;               /* if YES, just get rid of current
+                                * argument values, otherwise dispose of
+                                * the entire parameters list */
+
+{
+       char *mp_name;          /* internal name of macro parameter */
+
+
+       if (param_p == (struct MAC_PARAM *) 0) {
+               /* end of list */
+               return;
+       }
+
+       /* recurse */
+       free_parameters(param_p->next, macname, values_only);
+
+       /* need to undef the internal name */
+       mp_name = mkmacparm_name(macname, param_p->param_name);
+       undef_macro(mp_name);
+       FREE(mp_name);
+
+       if (values_only == NO) {
+
+               /* release space */
+               if (param_p->param_name != (char *) 0) {
+                       FREE(param_p->param_name);
+               }
+               FREE(param_p);
+       }
+}
+\f
+
+/* given a macro name and a parameter name, add the parameter name to the
+ * list of parameters for the macro */
+
+void
+add_parameter(macname, param_name)
+
+char *macname;
+char *param_name;              /* name of parameter to add */
+
+{
+       struct MACRO *macinfo_p;        /* which macro to add to */
+       struct MAC_PARAM *new_p;        /* new parameter */
+       struct MAC_PARAM *param_p;      /* to walk through parameter list */
+
+
+       /* get space to store info about the parameter */
+       MALLOC(MAC_PARAM, new_p, 1);
+
+       /* get the macro information to know where to attach */
+       if ((macinfo_p = findMacro(macname)) == (struct MACRO *) 0) {
+               pfatal("add_parameter unable to find macro %s", macname);
+       }
+
+       /* if this is first parameter, link directly to macro, otherwise
+        * to the end of the parameter linked list */
+       if (macinfo_p->parameters_p == (struct MAC_PARAM *) 0) {
+               macinfo_p->parameters_p = new_p;
+       }
+       else {
+               /* walk down current parameter list */
+               for (param_p = macinfo_p->parameters_p;
+                               param_p != (struct MAC_PARAM *) 0;
+                               param_p = param_p->next) {
+
+                       /* check for duplicate name */
+                       if (strcmp(param_name, param_p->param_name) == 0) {
+                               l_yyerror(Curr_filename, yylineno,
+                                       "duplicate parameter name %s for macro %s",
+                                       param_name, macname);
+                       }
+
+                       /* link onto end of list */
+                       if (param_p->next == (struct MAC_PARAM *) 0) {
+                               param_p->next = new_p;
+                               break;
+                       }
+               }
+       }
+
+       /* fill in the info */
+       new_p->param_name = dupstring(param_name);
+       /* assume non-quoted for now */
+       new_p->quote_style = QS_UNQUOTED;
+       new_p->next = (struct MAC_PARAM *) 0;
+
+       (macinfo_p->num_params)++;
+}
+\f
+
+/* given a string to duplicate, allocate space for a copy and return pointer
+ * to the copy. Caller is responsible for freeing if it needs to be freed */
+
+static char *
+dupstring(string)
+
+char *string;  /* what to duplicate */
+
+{
+       char *newstr;   /* the duplicate */
+
+       /* get space and copy the old to new */
+       MALLOCA(char, newstr, strlen(string) + 1);
+       (void) strcpy(newstr, string);
+
+       return(newstr);
+}
+\f
+
+/* save the value of a macro argument by making a macro out of it */
+
+void
+set_parm_value(macname, argbuff, argnum)
+
+char *macname; /* name of macro */
+char *argbuff; /* value of argument */
+int argnum;    /* which argument. 1 for the first, 2 for second, etc */
+
+{
+       static struct MAC_PARAM *param_p;       /* keep track of current
+                        * parameter. The first time we are called for a
+                        * given macro, we look up the macro and get its
+                        * first parameter. After that, we just follow
+                        * the linked list of parameters */
+       struct MACRO *mac_p;    /* info about macro */
+       struct MACRO *argmac_p; /* info about the parameter */
+       char *mp_name;  /* pointer to malloc-ed space containing internal
+                        * name of MACRO(PARAMETER) */
+       char *p;        /* to copy value to macro temp file */
+
+       if (argnum == 1) {
+               /* this is the first argument, so we have to look up the
+                * macro */
+               if ((mac_p = findMacro(macname)) == (struct MACRO *) 0) {
+                       pfatal("set_parm_value can't find macro");
+               }
+
+               /* point to head of parameters list */
+               param_p = mac_p->parameters_p;
+       }
+       else {
+               /* just advance to the next parameter */
+               if (param_p != (struct MAC_PARAM *) 0) {
+                       param_p = param_p->next;
+               }
+               if (param_p == (struct MAC_PARAM *) 0) {
+                       /* no next parameter. Error msg is printed elsewhere,
+                        * so just clean up and return */
+                       FREE(argbuff);
+                       return;
+               }
+       }
+
+       /* if argbuff is null, there is no argument, which really means the
+        * argument is the null string. */
+       if (argbuff == (char *) 0) {
+               argbuff = dupstring("");
+       }
+
+       /* now associate the value with the parameter */
+       mp_name = mkmacparm_name(macname, param_p->param_name);
+       argmac_p = setup_macro(mp_name);
+
+       /* copy the macro to the macro temp file */
+       if (param_p->quote_style & QS_UNQUOTED) {
+               fprintf(Mactmp_write, "%s", argbuff);
+               putc('\0', Mactmp_write);
+       }
+
+       if (param_p->quote_style & QS_QUOTED) {
+               short in_string;        /* are we within double quotes? */
+               short escaped;          /* did we just see a backslash? */
+
+               /* Remember where we are stashing this quoted copy */
+               argmac_p->quoted_offset = ftell(Mactmp_write);
+
+               /* Add the initial quote */
+               putc('"', Mactmp_write);
+
+               /* Have to copy a character at a time, because we
+                * need to backslash any embedded quotes. This follows
+                * rules like the ANSI C preprocessor, except we only have
+                * to worry about strings, not character constants, because
+                * Mup doesn't have character constants. Also, we don't
+                * squeeze not-in-string white space runs to a single space,
+                * because this keeps the code simpler and there's no
+                * particular benefit in squeezing, other than perhaps
+                * saving a few bytes in the macro temp file. This code
+                * is similar to the gcc implementation of cpp. */
+               in_string = escaped = NO;
+               for (p = argbuff; *p != '\0'; p++) {
+                       if (escaped == YES) {
+                               escaped = NO;
+                       }
+                       else {
+                               if (*p == '\\') {
+                                       escaped = YES;
+                               }
+                               if (in_string == YES) {
+                                       if (*p == '"') {
+                                               /* reached end of string */
+                                               in_string = NO;
+                                       }
+                               }
+                               else if (*p == '"') {
+                                       /* starting a string */
+                                       in_string = YES;
+                               }
+                       }
+
+                       /* Escape quotes always; escape backslashes
+                        * when they are inside strings. */
+                       if (*p == '"' || (in_string == YES && *p == '\\')) {
+                               putc('\\', Mactmp_write);
+                       }
+                       putc(*p, Mactmp_write);
+               }
+
+               /* Add the final quote */
+               putc('"', Mactmp_write);
+               putc('\0', Mactmp_write);
+       }
+       (void) fflush(Mactmp_write);
+#ifndef UNIX_LIKE_FILES
+       fclose(Mactmp_write);
+#endif
+
+       /* temp space no longer needed */
+       FREE(mp_name);
+       FREE(argbuff);
+}
+\f
+
+/* make an internal macro name for a macro parameter name. The internal
+ * name is MACRO(PARAMETER). Space for name is malloc-ed, caller must free */
+
+static char *
+mkmacparm_name(macname, param_name)
+
+char *macname;
+char *param_name;
+
+{
+       char *internal_name;
+
+       /* add 3 for the 2 parentheses and the null */
+       MALLOCA(char, internal_name,
+                       strlen(macname) + strlen(param_name) + 3);
+
+       (void) sprintf(internal_name, "%s(%s)", macname, param_name);
+       return(internal_name);
+}
+\f
+
+/* add a character to the current macro argument buffer. */
+
+char *
+add2argbuff(argbuff, c)
+
+char *argbuff;         /* the argument buffer so far */
+int c;                 /* a character to add to the buffer */
+
+{
+       static int offset;      /* where in argbuff to put character */
+       static int length;      /* how many characters we have allocated */
+
+
+       if (argbuff == (char *) 0) {
+               /* first time we were called, so malloc some space */
+               MALLOCA(char, argbuff, MAC_ARG_SZ);
+               offset = 0;
+               length = MAC_ARG_SZ;
+       }
+       else if (offset == length - 1) {
+               /* need more space */
+               length += MAC_ARG_SZ;
+               REALLOCA(char, argbuff, length);
+       }
+
+       /* put character in the buffer and null terminate it */
+       argbuff[offset++] = (char) c;
+       argbuff[offset] = '\0';
+
+       return(argbuff);
+}
+\f
+
+/* given a macro name that might be either a macro parameter or a regular
+ * macro, return pointer to the proper MACRO struct. We do this by
+ * searching up the stack of macros being expanded. If the name matches
+ * that of a macro parameter, use that, otherwise treat as a normal macro.
+ * Return null if can't resolve */
+
+static struct MACRO *
+resolve_mac_name(macname)
+
+char *macname;
+
+{
+       struct MACRO *mac_p;    /* macro that matches the macname */
+       int i;                  /* index through file stack */
+       char *mp_name;          /* macro parameter internal name */
+       int quoted;             /* if has quote designator */
+       char *basename;         /* macname not counting quote designator */
+
+
+       if ((quoted = has_quote_designator(macname)) == YES) {
+               basename = macname + strlen(quote_designator);
+       }
+       else {
+               basename = macname;
+       } 
+               
+       /* first go up the stack of macro calls, seeing if the macro
+        * name matches the parameter name of any macro. If so, that's
+        * the correct macro to use. Failing that, we look for the macro
+        * name just as is. If that fails too, we have to admit defeat
+        * and return null. */
+       for (i = 0; i <= Fstkptr; i++) {
+               if (Filestack[i].mac_p != (struct MACRO *) 0) {
+                       /* we are expanding a macro. See if that macro
+                        * has a parameter by the name we are trying to
+                        * resolve. If so, that's what we want */
+                       mp_name = mkmacparm_name(Filestack[i].mac_p->macname,
+                                       basename);
+                       mac_p = findMacro(mp_name);
+                       FREE(mp_name);
+                       if (mac_p != 0) {
+                               /* Eureka! We found it */
+                               return(mac_p);
+                       }
+               }
+       }
+
+       /* well, guess it wasn't a macro parameter. Try treating as
+        * just an ordinary macro name */
+       /* Not allowed to be a special quoted macro; you can only do that
+        * to a macro parameter */
+       if (quoted == YES) {
+               l_yyerror(Curr_filename, yylineno,
+                       "cannot use '%s' on a macro, only on a macro parameter",
+                       quote_designator);
+               return ((struct MACRO *) 0);
+       }
+
+       return(findMacro(macname));
+}
+\f
+
+/* Return YES if macro name reference includes designator denoting
+ * it is to be quoted (like usage of # in ANSI C preprocessor) */
+
+static int
+has_quote_designator(macname)
+
+char *macname;
+
+{
+       return (strncmp(macname, quote_designator, strlen(quote_designator))
+                                                       == 0 ? YES : NO );
+}
+\f
+
+/* For "preprocessor" option, similar to the C compiler option to
+ * just run the macro preprocessor, instead of the usual yacc-generated
+ * yyparse(), we have this function that simply writes tokens out.
+ */
+
+void
+preproc()
+{
+       while (yylex() != 0) {
+               /* In strings, the backslashes before any embedded quotes
+                * will have been swallowed, so we have to recreate them. */
+               if (yytext[0] == '"') {
+                       char *t;
+                       putchar('"');
+                       for (t = yytext + 1; *t != '\0'; t++) {
+                               if (*t == '"' && *(t+1) != '\0') {
+                                       putchar('\\');
+                               }
+                               putchar(*t);
+                       }
+               }
+               else {
+                       printf("%s", yytext);
+               }
+       }
+}
diff --git a/mup/mup/main.c b/mup/mup/main.c
new file mode 100644 (file)
index 0000000..77ca530
--- /dev/null
@@ -0,0 +1,1441 @@
+static char Copyright[] =
+       "Copyright (c) 1995-2006 by Arkkra Enterprises.\nAll rights reserved.\n";
+
+/* main for "Mup" music publication program */
+
+/*
+ *             Command line arguments 
+ * -cN Combine strings of N measures of rest into multirests (N > 1)
+ * -C          Include comments in macro-processed output (with -E)
+ * -dn   turns on debug level n
+ *             1 = yydebug
+ *             2 = parse phase high level trace
+ *             4 = parse phase low level trace
+ *             8 = reserved
+ *             16 = placement phase high level trace
+ *             32 = placement phase low level trace
+ *             64 = reserved
+ *             128 = print contents of main linked list
+ *             256 = print phase high level trace
+ *             512 = print phase low level trace
+ *     This is a bitmap, so multiple levels can be on at once
+ * -DMACRO[=def] define a macro
+ * -e errfile  write error output into errfile instead of stderr
+ * -E          just do macro expansion
+ * -f file     write output to file instead of stdout
+ * -F          write output to file, deriving the name
+ * -m midifile  generate MIDI output into specified file instead of the
+ *             usual PostScript output to stdout.
+ * -M          create MIDI file, deriving the file name
+ * -olist      print only pages given in list
+ * -pN         start numbering pages at N instead of from 1
+ * -r          print registration form
+ * -slist      print only the staffs in list
+ * -v          print verion number and exit
+ * -xN,M       extract just measures N through M.
+ *     Negative values are relative to the end of the song.
+ *     The comma and second number are optional.
+ *
+ * Expects zero or more input files. If no file specified, reads stdin
+ *
+ * Exit code is 0 on success, or the number of errors found, up to 254,
+ * or 255 for internal error.
+ */
+
+
+#ifdef __WATCOMC__
+#include <io.h>
+#endif
+#ifdef Mac_BBEdit
+#include <Files.h>
+#include <Folders.h>
+#include <MupInterface.h>
+#define main _mup      /* rename entry point to _mup */
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include "defines.h"
+#include "globals.h"
+
+
+/* List of valid command line options and their explanations */
+struct Options {
+       char    option_letter;
+       char    *argument;      /* describes the arg if any, or "" if none */
+       char    *explanation;
+} Option_list[] = {
+       { 'c', " N",            "combine N or more measures of rests into multirests" },
+       { 'C',  "",             "include comments in macro preprocessor output" },
+       { 'd', " N",            "turn on debug level N" },
+       { 'D', " MACRO[=macro_def]", "define macro" },
+       { 'e', " errfile",      "write error messages to errfile" },
+       { 'E', "",              "run macro preprocessor only" },
+       { 'f', " outfile",      "write output to outfile" },
+       { 'F', "",              "write output to file with derived name" },
+       { 'm', " midifile",     "generate MIDI output file" },
+       { 'M', "",              "generate MIDI output file, derive file name" },
+       { 'o', " pagelist",     "only print pages in pagelist" },
+       { 'p', " N",            "start numbering pages at N" },
+       { 'r', "",              "print shareware REGISTRATION form" },
+       { 's', " stafflist",    "print only staffs in stafflist" },
+       { 'v', "",              "print version number" },
+       { 'x', " N[,M]",        "extract measures N through M" }
+};
+
+
+#ifndef _UNISTD_H
+/* to process command line args */
+extern int getopt P((int argc, char * const *argv, const char *optstr));
+extern int optind;     /* set by getopt to point to current cmd line argument */
+extern char *optarg;   /* set by getopt */
+extern char *getenv();
+#endif
+extern FILE *yyout;    /* lex could try to write error output here */
+
+static char **Arglist;         /* global pointer to argv */
+static int Num_args;           /* global copy of argc */
+static char Version[] = "5.3"; /* Mup version number */
+static int Got_e_option = NO;  /* was there a -e option on the command line? */
+
+/* The different kinds of things that can be argument to -o option.
+ * If no -o option, then it will be PG_ALL, "odd" and "even" will
+ * map to PG_ODD and PG_EVEN, and a list of page numbers or ranges to PG_LIST.
+ */
+static int Pglist_type;
+#define PG_LIST                0
+#define PG_ODD         1
+#define PG_EVEN                2
+#define PG_ALL         3
+
+#ifdef O_BINARY
+static char * Read_mode = "rb";
+#else
+static char * Read_mode = "r";
+#endif
+
+/* If there is a list of pages to print using -o, the values are stored
+ * in a list of RANGELIST structs. This points to that list. The "all" field
+ * of the struct is unused.
+ */
+static struct RANGELIST *Page_range;
+
+static void usage P((char **argv));    /* print usage message and exit */
+static int ignore_option P((int opt));
+static void notice P((void));
+static void first_msg P((char *pname));
+static void setvflag P((char *fname));
+static void registration P((void));
+static char *derive_file_name P((char *suffix));
+static int get_first_page P((int pagenum));
+static void set_pagelist P((char *pagelist, int startpage));
+static void prune_page_range P((int start_page));
+static void vis_staffs P((char *stafflist));
+
+
+\f
+
+int
+main(argc, argv)
+
+int argc;
+char **argv;
+
+{
+       int a;                  /* for command line args */
+       char *midifilename = (char *) 0;
+       int combine = NORESTCOMBINE;    /* number of measures to combine into
+                                * multirests with -c option */
+       int derive_out_name = NO;       /* YES is -F option is specified */
+       char *vis_stafflist = (char *) 0;       /* -s list of visible staffs */
+       int pagenum;
+       char *pagelist = 0;
+       int start = 1, end = -1;        /* Arguments to -x option */
+       int has_x_arg = NO;
+       int outfile_args = 0;   /* we only allow one instance of [fFmM] options */
+       int n, i;
+       int num_options;
+       char *getopt_string;
+
+
+
+       notice();
+       first_msg(argv[0]);
+       /* must init head shapes table before first call to initstructs */
+       init_symtbl();
+
+       /* set initial page number to "not set" */
+       pagenum = MINFIRSTPAGE - 1;
+       initstructs();
+
+       /* If run via mupmate, user may not understand error messages   
+        * about things like -c or -p, so we give different messages. */
+       Mupmate = (getenv("MUPMATE") == 0 ? NO : YES);
+
+       /* process command line arguments */
+       /* create getopt string */
+       num_options = NUMELEM(Option_list);
+       /* allow for worst case of all requiring colon */
+       MALLOCA(char, getopt_string, 2 * num_options + 1);
+       for (n = i = 0; n < num_options; n++) {
+               if (ignore_option( (int) Option_list[n].option_letter) == YES) {
+                       continue;
+               }
+               getopt_string[i] = Option_list[n].option_letter;
+               if (Option_list[n].argument[0] != '\0') {
+                       getopt_string[++i] = ':';
+               }
+               i++;
+       }
+       getopt_string[i] = '\0';
+
+       while ((a = getopt(argc, argv, getopt_string)) != EOF) {
+
+               switch (a) {
+
+               case 'c':
+                       combine = atoi(optarg);
+                       if (combine < MINRESTCOMBINE || combine > MAXRESTCOMBINE) {
+                               if (Mupmate == YES) {
+                                       /* Should be impossible to get here,
+                                        * since mupmate refuses to accept
+                                        * out of range values. */
+                                       l_yyerror(0, -1, "Run > Set Options > Min measures to combine: value must be between %d and %d.",
+                                               MINRESTCOMBINE, MAXRESTCOMBINE);
+                               }
+                               else {
+                                       l_yyerror(0, -1, "argument for %cc (number of measures to combine) must be between %d and %d",
+                                               Optch, MINRESTCOMBINE, MAXRESTCOMBINE);
+                               }
+                       }
+                       break;
+
+               case 'C':
+                       Ppcomments = YES;
+                       break;
+
+               case 'd':
+                       Debuglevel = (int) strtol(optarg, (char **) 0, 0);
+                       break;
+
+               case 'e':
+                       if (freopen(optarg, "w", stderr) == (FILE *) 0) {
+                               cant_open(optarg);
+                       }
+                       Got_e_option = YES;
+                       break;
+
+               case 'E':
+                       Preproc = YES;
+                       break;
+
+               case 'f':
+                       Outfilename = optarg;
+                       outfile_args++;
+                       break;
+
+               case 'F':
+                       derive_out_name = YES;
+                       outfile_args++;
+                       break;
+
+               case 'D':
+                       cmdline_macro(optarg);
+                       break;
+
+               case 'm':
+                       midifilename = optarg;
+                       /* FALLTHRU */
+               case 'M':
+                       Doing_MIDI = YES;
+                       /* define "built-in" MIDI macro */
+                       cmdline_macro("MIDI");
+                       outfile_args++;
+                       break;
+
+               case 'o':
+                       pagelist = optarg;
+                       break;
+
+               case 'p':
+                       pagenum = atoi(optarg);
+                       if (pagenum < MINFIRSTPAGE || pagenum > MAXFIRSTPAGE) {
+                               if (Mupmate == YES) {
+                                       /* Should be impossible to get here,
+                                        * since mupmate refuses to accept
+                                        * out of range values. */
+                                       l_yyerror(0, -1, "Run > Set Options > First Page: value must be between %d and %d.",
+                                               MINFIRSTPAGE, MAXFIRSTPAGE);
+                               }
+                               else {
+                                       l_yyerror(0, -1, "argument for %cp (first page) must be between %d and %d",
+                                               Optch, MINFIRSTPAGE, MAXFIRSTPAGE);
+                               }
+                       }
+                       break;
+
+               case 'r':
+                       registration();
+                       exit(0);
+                       /*NOTREACHED*/
+                       break;
+
+               case 's':
+                       vis_stafflist = optarg;
+                       break;
+
+               case 'v':
+                       /* if got "-e errfile -v" then we want to put the
+                        * opening notice into the errfile. This can allow
+                        * another program to execute "mup -e errfile -v"
+                        * and then use the contents of errfile as the
+                        * text for an "About Mup" informational block.
+                        */
+                       if (Got_e_option == YES) {
+                               notice();
+                       }
+
+                       (void) fprintf(stderr,"Version %s\n", Version);
+                       exit(0);
+                       /*NOTREACHED*/
+                       break;
+
+               case 'x':
+                       chk_x_arg(optarg, &start, &end);
+                       has_x_arg = YES;
+                       break;
+
+               default:
+                       usage(argv);
+                       break;
+               }
+       }
+
+       if (Ppcomments == YES && Preproc == NO) {
+               warning("-C only valid with -E; ignored");
+       }
+
+       if (outfile_args > 1) {
+               (void) fprintf(stderr, "Only one output file option (-f, -F, -m, -M) can be specified\n");
+               exit(1);
+       }
+
+       /* turn on yacc debug flag if appropriate */
+       if (Debuglevel & 1) {
+               yydebug = 1;
+               ifdebug = 1;
+       }
+
+       /* save info about arguments so yywrap can open additional input files
+        * if necessary */
+       Arglist = argv;
+       Num_args = argc;
+       yyin = stdin;
+       yyout = stderr;
+
+       /* if file argument, open that, else use stdin */
+       if (optind <= argc - 1) {
+               (void) yywrap();
+       }
+       else {
+#ifdef Mac_BBEdit
+               Curr_filename  = _mup_input_filename;
+#else
+               Curr_filename = "stdin";
+#if defined(unix) || defined(__WATCOM__)
+               /* Sometimes people forget to give a file name,
+                * then wonder why Mup is "hanging," so let user
+                * know it isn't hanging... it's waiting for them
+                * to type something. But only if input is a terminal,
+                * and stderr is a terminal--if stdin is a pipe,
+                * user probably doesn't need a reminder. */
+               if (isatty(0) && isatty(2)) {
+                       fprintf(stderr, "No input file specified; reading standard input.\n\n");
+               }
+#endif
+#endif
+       }
+
+       /* initialize for parser */
+       raterrfuncp = doraterr;
+       initstructs();
+       vis_staffs(vis_stafflist);
+       reset_ped_state();
+
+       /* parse the input */
+       if (Preproc == YES) {
+               preproc();
+       }
+       else {
+               (void) yyparse();
+       }
+#ifndef UNIX_LIKE_FILES
+       mac_cleanup();
+#endif
+
+
+       /* do final checks and cleanup of input data */
+       /* check for missing endif */
+       chk_ifdefs();   
+       if (Preproc == YES) {
+               error_exit();
+       }
+
+       /* find height of headers and footers */
+       /* Note: this has to be called when we are at the *end* of the main
+        * list with all SSVs applied, so that we know the margin settings */
+       calc_block_heights();
+       /* make sure there is a final barline */
+       check4barline_at_end();
+       /* make sure we go to new score if visibility changes */
+       chk_vis_feed();
+
+       /* derive tabnote staff data for tablature staffs. But if there
+        * have been errors found, don't bother, because we may have
+        * some incomplete/inconsistent data that tab2tabnote doesn't
+        * know how to deal with cleanly. */
+       if (Errorcount == 0) {
+               tab2tabnote();
+       }
+
+       /* do -c option or restcombine parameter */
+       combine_rests(combine);
+
+       /* make sure there aren't til clauses past end of song */
+       chk4dangling_til_clauses("the end of the song");
+
+       /* count how many verses */
+       set_maxverses();
+
+       /* process ties */
+       tie();
+
+       /* Verify that -o argument (and maybe -p or firstpage parameter)
+        * is valid. If not, this will ufatal. */
+       pagenum = get_first_page(pagenum);
+       set_pagelist(pagelist, pagenum);
+
+       /* Do -x (extract) option if needed. But if there were errors before,
+        * skip this, because there could be empty measures and such,
+        * that could confuse it, and we're going to give up soon anyway. */
+       if (has_x_arg == YES && Errorcount == 0) {
+               extract(start, end);
+       }
+
+       debug(2, "finished with parsing, Errorcount is %d", Errorcount);
+
+       if (Errorcount > 0) {
+               (void) fprintf(stderr, "\nstopping due to previous error%s\n",
+                                               Errorcount ? "s" : "");
+               error_exit();
+       }
+
+       /* do the placement phase */
+
+       /* initialize the Staffscale and related variables to default values */
+       initstructs();
+       set_staffscale(0);
+
+       /* transpose */
+       transgroups();
+
+       /* set up ties that carry into next measure */
+       tie_carry();
+
+       /* line up chords */
+       makechords();
+
+       /* place notes relative to staff and set stem direction */
+       setnotes();     
+       /* find relative horizontal position of notes */
+       setgrps();
+       /* set coordinates of rests and syllables */
+       restsyl();
+
+       /* generate MIDI file if appropriate. We wait until here to
+        * do MIDI, so that chord widths have been established, so midi
+        * code can more easily figure out how to crunch all-space chords */
+       if (Doing_MIDI == YES) {
+               if (midifilename == (char *) 0) {
+                       /* -M option, so we have to derive the name */
+                       midifilename = derive_file_name(".mid");
+               }
+               gen_midi(midifilename);
+               exit(0);
+       }
+
+       /* figure out absolute horizontal locations */
+       abshorz();
+       /* find lengths of beams, angles of beams, etc */
+       beamstem();
+       /* set up mussym, octave, rom, bold, pedal, etc */
+       stuff();
+
+       /* find vertical coordinates relative to staff */
+       relvert();
+       /* set absolute vertical coordinates */
+       absvert();
+
+       /* split lines and curves */
+       fix_locvars();  
+
+       print_mainll();
+
+       if (derive_out_name == YES) {
+               Outfilename = derive_file_name(".ps");
+       }
+       if (*Outfilename != '\0') {
+               if (freopen(Outfilename, "w", stdout) == (FILE *) 0) {
+                       cant_open(Outfilename);
+                       exit(1);
+               }
+       }
+
+       /* output PostScript for printing */
+       prune_page_range(pagenum);
+       do {
+               Pagenum = (short) pagenum;
+               print_music();
+       } while (Page_range != (struct RANGELIST *) 0);
+       trailer();
+
+       /* if we get to here, all is okay. If there was a problem,
+        * we would have exited where the problem occurred */
+       return(0);
+}
+\f
+
+/* print copyright notice */
+
+static void
+notice()
+
+{
+       if (getenv("MUPQUIET") == (char *) 0 || Got_e_option == YES) {
+               fprintf(stderr, "Mup - Music Publisher   Version %s\n", Version);
+               fprintf(stderr, Copyright);
+       }
+}
+\f
+
+/* print registration form */
+
+static void
+registration()
+{
+       printf("Mup is SHAREWARE.  You can try out a copy for free, but if you decide\n");
+       printf("to keep and use it, you must register by filling out the form below\n");
+       printf("and sending the form and cash, check, or money order to:\n");
+       printf("                Arkkra Enterprises\n");
+       printf("                P. O. Box 315\n");
+       printf("                Warrenville, IL  60555    USA\n");
+       printf("\nName______________________________________________________________\n\n");
+       printf("Address___________________________________________________________\n\n");
+       printf("City_____________________________ State/Province__________________\n\n");
+       printf("Zip code/Postal code_____________________ Country_________________\n\n");
+       printf("Email address (please print clearly)______________________________\n\n");
+       printf("How did you find out about Mup?___________________________________\n\n");
+       printf("__________________________________________________________________\n\n");
+       printf("___Linux  ___ Windows/MS-DOS  ___Mac  ___Other____________________\n\n");
+       printf("Would you like to join the Mup users mailing list? ___ Yes  ___ No\n\n");
+       printf("___ Mup Version %s Registrations.........................$29 each\n", Version);
+       printf("\t\t\t(Illinois residents, add $2.18 sales tax)\n");
+       printf("(For credit card payment, see http://www.arkkra.com/doc/credtcrd.html)\n");
+}
+\f
+
+/* print usage message and exit */
+
+static void
+usage(argv)
+
+char **argv;
+
+{
+       int num_options;        /* how many options */
+       int n;
+       char *whitespace;       /* for lining things up */
+       int white_length;       /* strlen(whitespace) */
+       int length;             /* of an argument item */
+       char *extra_options;    /* parent process can ask us to print more */
+
+
+       /* print the usage summary */
+       fprintf(stderr, "usage: %s ", argv[0]);
+       num_options = NUMELEM(Option_list);
+       for (n = 0; n < num_options; n++) {
+               if (ignore_option( (int) Option_list[n].option_letter) == YES) {
+                       /* ignore this option */
+                       continue;
+               }
+               fprintf(stderr, "[%c%c%s] ", Optch,
+                       Option_list[n].option_letter, Option_list[n].argument);
+       }
+       fprintf(stderr, "[file...]\n");
+
+       /* We'll add as much of this whitespace string to each argument
+        * item as needed to line the explanations up nicely. */
+       whitespace = "                  ";
+       white_length = strlen(whitespace);
+
+       /* print the explanations of each option */
+       for (n = 0; n < num_options; n++) {
+
+               if (ignore_option( (int) Option_list[n].option_letter) == YES) {
+                       continue;
+               }
+
+               fprintf(stderr, "   %c%c%s", Optch,
+                       Option_list[n].option_letter, Option_list[n].argument);
+
+               /* add enough white space to line things up */
+               if ((length = strlen(Option_list[n].argument)) < white_length) {
+                       fprintf(stderr, whitespace + length);
+               }
+
+               fprintf(stderr, " %s\n", Option_list[n].explanation);
+       }
+       /* If calling program tells us to add some options to the list,
+        * print those out too. */
+       if ((extra_options = getenv("MUPADDOP")) != (char *) 0) {
+               fprintf(stderr, "%s", extra_options);
+       }
+
+       exit(1);
+}
+\f
+
+/* If Mup is being called by some other program, like mupdisp,
+ * such that some of Mup's options should be disallowed, it
+ * should set $MUPDELOP to the list of options to be deleted
+ * from the list of valid options. This function will say, for the
+ * given option, whether it should be disallowed. */
+
+static int
+ignore_option(opt)
+
+int opt;       /* an option letter */
+
+{
+       static char *del_options = 0;   /* which options to delete from list */
+
+       /* the first time we are called, get the list, if any */
+       if (del_options == (char *) 0) {
+               if ((del_options = getenv("MUPDELOP")) == (char *) 0) {
+                       del_options = "";
+               }
+       }
+
+       return ((strchr(del_options, opt) != (char *) 0) ? YES : NO);
+}
+\f
+
+/* print message to display first time program is executed if appropriate.
+ * If a particular magic file exists, we know
+ * (or at least assume) the user has already seen the
+ * message about Mup being shareware. If not, we print the message and
+ * exit.  For unix, the magic file is called .mup and must be either in the
+ * current directory or in $HOME. For DOS, it is called mup.ok and must be
+ * either in the current directory or in the directory where mup.exe was
+ * executed, as indicated by argv[0]. */
+
+#ifndef MAGIC_FILE_NAME
+#define MAGIC_FILE_NAME (char *) 0
+#endif
+
+int check = 100, *Check_p = &check;
+
+static void
+first_msg(pname)
+
+char *pname;           /* argv[0] */
+
+{
+       char *fname;            /* name of magic file */
+       char *home;             /* $HOME (unix) or where mup is located (DOS) */
+       char *path = (char *) 0;/*  home/fname */
+
+
+       fname = MAGIC_FILE_NAME;
+       
+       if (fname == (char *) 0) {
+               fprintf(stderr, "\tMup is shareware.  You may try it out for free, but if you\n");
+               fprintf(stderr, "\tdecide to keep it, you must pay a registration fee of $29.\n");
+               fprintf(stderr, "\tThis copy of Mup was compiled for an unrecognized Operating System\n");
+               fprintf(stderr, "\tor compiler. If you have a UNIX-like operating system,\n");
+               fprintf(stderr, "\tyou can try compiling with -Dunix, or if you have as MS-DOS-like\n");
+               fprintf(stderr, "\tOperating system, you can try compiling with -D__DOS__\n");
+               fprintf(stderr, "\tIf that still doesn't work, to suppress this message,\n");
+               fprintf(stderr, "\tand start using Mup, modify defines.h to define MAGIC_FILE_NAME\n");
+               fprintf(stderr, "\tto a name that is appropriate for your operating system.\n");
+               fprintf(stderr, "\tBy doing so, you acknowledge that you have read\n");
+               fprintf(stderr, "\tthe Mup license and agree to its terms,\n");
+               fprintf(stderr, "\tand agree that if you decide to continue to use Mup\n");
+               fprintf(stderr, "\tafter trying it out, you will pay the registration fee.\n");
+               fprintf(stderr, "\tAfter changing MAGIC_FILE_NAME or any other related #defines\n");
+               fprintf(stderr, "\tthat you might need, and recompiling, execute\n");
+               fprintf(stderr, "\t\tmup -r\n\tto get a registration form. If you let us know about any changes\n");
+               fprintf(stderr, "\tyou need to make to support your OS, we will consider\n");
+               fprintf(stderr, "\tincorporating those changes in a future Mup release.\n");
+               exit(1);
+       }
+
+       /* if magic file exists in current directory,
+        * indicating user has already seen the message, return */
+#ifndef Mac_BBEdit
+       if (access(fname, 0) == 0) {
+               setvflag(fname);
+               if (Vflag == YES) {
+                       return;
+               }
+               else {
+                       check = 100;
+               }
+       }
+#endif
+
+#ifdef MAGIC_FILE_HOME
+       /* construct pathname to magic file if it is in $HOME */
+       if ((home = getenv("HOME")) != (char *) 0) {
+               MALLOCA(char, path, strlen(home)+ strlen(fname) + 2);
+#ifdef VMS
+               (void) sprintf(path, "%s%s", home, fname);
+#else
+               (void) sprintf(path, "%s/%s", home, fname);
+#endif
+       }
+#else
+#ifdef __DOS__
+       /* construct pathname to magic file if it is in the directory where
+        * mup.exe came from */
+       if ((home = strrchr(pname, '\\')) != (char *) 0) {
+               int baselength;         /* strlen up through last \  */
+
+               baselength = home - pname + 1;
+               MALLOCA(char, path, baselength + strlen(fname) + 1);
+               /* copy pname up to last backslash */
+               strncpy(path, pname, baselength);
+               /* add magic file name */
+               strcpy(path + baselength, fname);
+       }
+#endif
+#endif
+#ifdef Mac_BBEdit
+#pragma unused(pname)
+       /* check for file in Preferences folder inside System folder */
+       path = 0;
+       home = 0;
+       {
+               short vRefNum;
+               long dirID;
+               FSSpec fsSpec;
+               
+               if (FindFolder(kOnSystemDisk, kPreferencesFolderType, false, &vRefNum, &dirID) == noErr)
+                       /* preferences folder exists */
+                       if (FSMakeFSSpec(vRefNum, dirID, (StringPtr) MupRegFileName, &fsSpec) == noErr) {       /* file exists */
+                               short old_vRefNum;
+                               long old_dirID;
+                               if (HGetVol((StringPtr) 0, &old_vRefNum, &old_dirID) != noErr) return;
+                               if (HSetVol((StringPtr) 0, vRefNum, dirID) != noErr) return;
+                               setvflag(fname);
+                               HSetVol((StringPtr) 0, old_vRefNum, old_dirID);
+                               return;
+                       }
+       }
+#else
+       /* check for file in $HOME or where mup.exe came from */
+       if (path != (char *) 0 && access(path, 0) == 0) {
+               setvflag(path);
+               return;
+       }
+#endif
+
+       /* print shareware message and exit */
+       fprintf(stderr, "\n\tMup is shareware.  You may try it out for free, but if you\n");
+       fprintf(stderr, "\tdecide to keep it, you must pay a registration fee of $29.\n");
+       fprintf(stderr, "\n\tTo use Mup, first create a file called %s\n", fname);
+#ifdef Mac_BBEdit
+       fprintf(stderr, "\tin the Preferences folder inside the system folder");
+#else
+       fprintf(stderr, "\tin the current directory");
+#endif
+       if (path == (char *) 0) {
+               fprintf(stderr, ".\n");
+       }
+       else {
+               fprintf(stderr, " or at %s\n", path);
+       }
+       fprintf(stderr, "\t(It can be zero length.  It just has to exist.)\n");
+       fprintf(stderr, "\tBy creating this file, you acknowledge that you have read\n");
+       fprintf(stderr, "\tthe Mup license and agree to its terms, and agree that\n");
+       fprintf(stderr, "\tif you decide to continue to use Mup after trying it out,\n\tyou will pay the registration fee.\n");
+#ifdef Mac_BBEdit
+       fprintf(stderr, "\n\tAfter creating this file, select\n\t'Registration' from the Mup dialog box\n\tto get a registration form.\n\n");
+#else
+       fprintf(stderr, "\n\tAfter creating this file, execute\n\t\tmup %cr\n\tto get a registration form.\n\n", Optch);
+#endif
+       exit(0);
+}
+\f
+
+static void
+setvflag(fname)
+char *fname;
+{
+       int f;
+       char buff[48];
+       int sum = 0;
+       int hash = 0x45;
+       int n = 16;
+       int i;
+
+       if ((f = open(fname, O_RDONLY, 0)) > 0) {
+               if (read(f, buff, n) == n) {
+                       for (i = 0; i < n; i++) {
+                               sum += buff[i];
+                               hash ^= (buff[i] ^ sum);
+                               check ^= (buff[i] << (1 + (i & 3)));
+                       }
+                       Vflag = (((sum == 02703) && (hash == 02146)) ? YES : NO);
+               }
+       }
+       (void) close(f);
+}
+\f
+
+/* make our own yywrap rather than use the one in the lex library.
+ * In case user specifies more than one file, open
+ * each in turn, and return control to lex */
+
+int
+yywrap()
+
+{
+       int leng = 0;   /* Length of file name. Initialization done solely
+                        * to avoid bogus "used before set" warning. */
+
+       /* return from any macros or includes */
+       if (popfile() == 1) {
+               return(0);
+       }
+
+       /* if user specified more files, open the next one */
+       for (  ; optind < Num_args; optind++) {
+               if (yyin != NULL) {
+                       (void) fclose(yyin);
+               }
+               errno = 0;
+               if ((yyin = fopen(Arglist[optind], Read_mode)) != NULL) {
+                       Curr_filename = Arglist[optind++];
+                       yylineno = 1;
+                       return(0);
+               }
+               /* If name doesn't already end with .mup or .MUP and the open
+                * failed because the file didn't exist, try the name with
+                * .mup appended. */
+               else if (
+#ifdef ENOENT
+                               errno == ENOENT &&
+#endif
+                               ( ((leng = strlen(Arglist[optind])) < 5) ||
+                               (strcmp(Arglist[optind] + leng - 4, ".mup") != 0 &&
+                               strcmp(Arglist[optind] + leng - 4, ".MUP") != 0
+                               )) ) {
+                       MALLOCA(char, Curr_filename, leng + 5);
+                       sprintf(Curr_filename, "%s.mup", Arglist[optind]);
+                       if ((yyin = fopen(Curr_filename, Read_mode)) != NULL) {
+                               yylineno = 1;
+                               optind++;
+                               return(0);
+                       }
+                       /* try upper case suffix before giving up */
+                       sprintf(Curr_filename, "%s.MUP", Arglist[optind]);
+                       if ((yyin = fopen(Curr_filename, Read_mode)) != NULL) {
+                               yylineno = 1;
+                               optind++;
+                               return(0);
+                       }
+                       FREE(Curr_filename);
+               }
+               cant_open(Arglist[optind]);
+       }
+
+       return(1);
+}
+\f
+
+/* If user used -M or -F option, we need to derive the output file name.
+ * Use the last input file name, strip off the trailing .mup if it is there,
+ * add the suffix, and return the derived name.
+ */
+
+static char *
+derive_file_name(suffix)
+
+char *suffix;          /* ".mid" or ".ps" */
+
+{
+       int length;             /* of Curr_filename */
+       char *file_name;        /* the name we derive */
+       char *suffix_location;  /* where the suffix will go */
+
+
+       length = strlen(Curr_filename);
+       MALLOCA(char, file_name, length + strlen(suffix) + 1);
+
+       /* start with the original Mup input file name */
+       strcpy(file_name, Curr_filename);
+
+       /* see if we need to strip off a .mup */
+       if (length > 3) {
+               /* find where the .mup would start if it is there */
+               suffix_location = file_name + length - 4;
+
+               /* If user used upper case, so will we */
+               if (strcmp(suffix_location, ".MUP") == 0) {
+                       if (strcmp(suffix, ".mid") == 0) {
+                               suffix = ".MID";
+                       }
+                       else if (strcmp(suffix, ".ps") == 0) {
+                               suffix = ".PS";
+                       }
+                       else {
+                               pfatal("derive_file_name() called with unknown suffix '%s'", suffix);
+                       }
+               }
+               else if (strcmp(suffix_location, ".mup") != 0) {
+                       /* no .mup to strip off; just add to the end */
+                       suffix_location = file_name + length;
+               }
+       }
+       else {
+               suffix_location = file_name + length;
+       }
+
+       /* append the suffix and return the derived name */
+       strcpy(suffix_location, suffix);
+       return(file_name);
+}
+\f
+
+/* Determine the first page number. If user used -p option, use that,
+ * otherwise get from first_page parameter, else use 1. */
+
+static int
+get_first_page(pagenum)
+
+int pagenum;           /* from -p option */
+
+{
+       struct MAINLL *m_p;
+
+       /* if there wasn't a -p value, figure out what to use for first page */
+       if (pagenum < MINFIRSTPAGE) {
+               /* default to page 1 */
+               pagenum = 1;
+
+               /* look for last setting of firstpage parameter before
+                * any STAFFs */
+               initstructs();
+               for (m_p = Mainllhc_p; m_p != 0; m_p = m_p->next) {
+                       if (m_p->str == S_SSV) {
+                               if (m_p->u.ssv_p->used[FIRSTPAGE] == YES) {
+                                       pagenum = m_p->u.ssv_p->firstpage;
+                               }
+                       }
+                       else if (m_p->str == S_STAFF) {
+                               break;
+                       }
+               }
+       }
+       return(pagenum);
+}
+\f
+
+/* Parse the argument to -o, if there is a -o option specified, and
+ * save the info away for later use. Gives error if argument is invalid.
+ */
+
+static void
+set_pagelist(pagelist, startpage)
+
+char *pagelist;
+int startpage; /* from -p option */
+
+{
+       if (pagelist == (char *) 0) {
+               /* no -o option, print all pages */
+               Pglist_type = PG_ALL;
+       }
+
+       else if (strcmp(pagelist, "odd") == 0) {
+               Pglist_type = PG_ODD;
+       }
+
+       else if (strcmp(pagelist, "even") == 0) {
+               Pglist_type = PG_EVEN;
+       }
+
+       else {
+               struct RANGELIST *new_range;
+               struct RANGELIST **linkpoint_p_p;/* tail of Page_range list,
+                                                * for linking to the end
+                                                * of the list */
+               char *p, *beyondnum;            /* for parsing the numbers */
+               short lower, upper;             /* page number range */
+
+
+               Pglist_type = PG_LIST;
+
+               /* Parse the argument to -o and save the ranges */
+               /* first set up where to link onto tail of list */
+               linkpoint_p_p = &Page_range;
+
+               /* walk through the -o argument */
+               for (p = pagelist; *p != '\0';   ) {
+
+                       /* skip any leading white space */
+                       while (isspace(*p)) {
+                               p++;
+                       }
+
+                       /* get page number (which may or may not be the
+                        * start of a range of numbers) */
+                       lower = (short) strtol(p, &beyondnum, 10);
+                       if (beyondnum == p || lower <= 0 || lower < startpage) {
+                               /* bad number from user, jump to error out */
+                               break;
+                       }
+
+                       p = beyondnum;
+                       /* skip any white space */
+                       while (isspace(*p)) {
+                               p++;
+                       }
+
+                       if (*p == '-') {
+                               /* there is a range of page numbers. Get the
+                                * upper limit of the range */
+                               upper = (short) strtol(++p, &beyondnum, 10);
+                               if (beyondnum == p || upper <= 0
+                                                       || upper < lower) {
+                                       /* bad value from user */
+                                       break;
+                               }
+                               p = beyondnum;
+                               while (isspace(*p)) {
+                                       p++;
+                               }
+                               if (*p == ',') {
+                                       p++;
+                               }
+                               else if (*p != '\0') {
+                                       break;
+                               }
+                       }
+                       else if (*p == ',') {
+                               /* not a range, so treat like range of n-n */
+                               upper = lower;
+                               p++;
+                       }
+                       else if (*p == '\0') {
+                               upper = lower;
+                       }
+                       else {
+                               /* something other than dash, comma, or end of
+                                * string, which is a user error */
+                               break;
+                       }
+
+                       /* save info about this page range */
+                       MALLOC(RANGELIST, new_range, 1);
+                       new_range->begin = lower;
+                       new_range->end = upper;
+                       new_range->next = (struct RANGELIST *) 0;
+
+                       /* link onto tail of list */
+                       *linkpoint_p_p = new_range;
+                       linkpoint_p_p = &(new_range->next);
+               }
+
+               /* if jumped out of loop without finishing parsing, user
+                * gave us something we didn't understand */
+               if (*p != '\0') {
+                       if (Mupmate == YES) {
+                               l_yyerror(0, -1, "Run > Set Options > Pages to display: value is invalid.");
+                       }
+                       else {
+                               l_yyerror(0, -1, "argument for -o (list of pages to display) is invalid");
+                       }
+               }
+       }
+}
+\f
+
+/* Calculate the page number for the final page and put it in Last_pagenum.
+ * If there is a -o list, make sure all the
+ * pages listed on the -o list are less than that. If they aren't remove them
+ * from the list. Without this step, Mup could go into a loop trying to print
+ * a page that doesn't exist. */
+
+static void
+prune_page_range(start_page)
+
+int start_page;                /* number given to the first page via the -p option
+                        * or via the firstpage parameter */
+
+{
+       struct MAINLL *mll_p;   /* to count page feeds */
+       struct RANGELIST **range_p_p;
+       int pruned;             /* if we removed anything from list */
+
+       /* find the largest page number */
+       Last_pagenum = start_page;
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0; mll_p = mll_p->next) {
+               if (mll_p->str == S_FEED && mll_p->u.feed_p->pagefeed == YES) {
+                       Last_pagenum++;
+               }
+       }
+
+       /* If there are extra pages for gridsatend, add those on */
+       if (Atend_info.separate_page == YES) {
+               int grids_per_page;
+
+               grids_per_page = Atend_info.grids_per_row *
+                               Atend_info.rows_per_page;
+               /* round up */
+               Last_pagenum += (Atend_info.grids_used + grids_per_page - 1)
+                                               / grids_per_page;
+       }
+
+
+       if (Pglist_type != PG_LIST) {
+               return;
+       }
+
+       /* see if any items in Page_range are bigger
+        * than the biggest page number */
+       pruned = NO;
+       for (range_p_p = &Page_range; *range_p_p != (struct RANGELIST *) 0;
+                                       range_p_p = &((*range_p_p)->next) ) {
+               if ((*range_p_p)->begin > Last_pagenum) {
+                       /* need to get rid of this entire entry, because none
+                        * of the pages listed actually exist */
+                       pruned = YES;
+                       if ((*range_p_p = (*range_p_p)->next)
+                                               == (struct RANGELIST *) 0) {
+                               /* last one on the list */
+                               break;
+                       }
+               }
+               else if ((*range_p_p)->end > Last_pagenum) {
+                       /* just need to shorten this range */
+                       (*range_p_p)->end = Last_pagenum;
+                       pruned = YES;
+               }
+       }
+
+       if (pruned == YES) {
+               l_warning( (char *) 0, -1, "-o list included one or more pages that don't exist");
+       }
+}
+\f
+
+/* given a page number, return YES if that page should be printed now, NO
+ * if not. If user gave a list of pages to print using -o, we print the page
+ * only if it is the very first thing on the list. If there is a smaller
+ * number further on in the list, we'll do that page later on another pass.
+ * The print phase has to keep making multiple passes until the list is
+ * empty. This allows user to print things out in random order, which may
+ * be useful especially for 2-on-1 printing, where for example, you may
+ * want a 4-page "booklet", printing page 4 then page 1 on one side and
+ * pages 2 and 3 on the other side.
+ */
+
+int
+onpagelist(pagenum)
+
+int pagenum;
+
+{
+       struct RANGELIST *old_range;    /* to keep track of item to free */
+
+       switch (Pglist_type) {
+
+       case PG_ALL:
+               return(YES);
+
+       case PG_ODD:
+               return (pagenum & 1) == 1 ? YES : NO;
+
+       case PG_EVEN:
+               return (pagenum & 1) == 0 ? YES : NO;
+
+       default:
+               if (Page_range == (struct RANGELIST *) 0) {
+                       /* ran off the end of list, so no more to print */
+                       return(NO);
+               }
+
+               if (Page_range->begin == pagenum) {
+                       /* is first on list so we will print it.
+                        * But first, fix up the list. If we've used up all of
+                        * the current range, free it and point to the next. */
+                       (Page_range->begin)++;
+                       if (Page_range->begin > Page_range->end) {
+                               old_range = Page_range;
+                               Page_range = Page_range->next;
+                               FREE(old_range);
+                       }
+                       return(YES);
+               }
+               break;
+       }
+       return(NO);
+}
+\f
+
+/* return YES if we were doing a page list (-o option) but have now handled
+ * all of the pages */
+
+int
+last_page()
+{
+       if (Pglist_type == PG_LIST) {
+               return ((Page_range == 0) ? YES : NO);
+       }
+       else {
+               return ((Pagenum == Last_pagenum) ? YES : NO);
+       }
+}
+\f
+
+/* handle the argument to -s (list of staffs to make visible). For each
+ * visible staff, make an SSV marking it visible */
+
+static void
+vis_staffs(stafflist)
+
+char *stafflist;
+{
+       int s;                          /* staff index */
+       int v;                          /* voice index */
+       long start, end;                /* staff range */
+
+
+       if (stafflist == (char *) 0) {
+               /* user didn't use -s, so set to all visible */
+               for (s = 1; s <= MAXSTAFFS; s++) {
+                       Staff_vis[s] = YES;
+                       for (v = 1; v <= MAXVOICES; v++) {
+                               Voice_vis[s][v] = YES;
+                       }
+               }
+               return;
+       }
+
+       /* init to all invisible */
+       for (s = 1; s <= MAXSTAFFS; s++) {
+               Staff_vis[s] = NO;
+               for (v = 1; v <= MAXVOICES; v++) {
+                       Voice_vis[s][v] = NO;
+               }
+       }
+
+       for (  ; *stafflist != '\0';   ) {
+               /* get first staff number in list. Will error check below */
+               start = strtol(stafflist, &stafflist, 10);
+
+               if (*stafflist == '-') {
+                       /* we have a range. Get end of range */
+                       end = strtol(stafflist + 1, &stafflist, 10);
+               }
+               else {
+                       /* single number, use end same as start */
+                       end = start;
+               }
+
+               /* error check */
+               if (start < 1 || start > MAXSTAFFS || end < 1 ||
+                                       end > MAXSTAFFS || end < start) {
+                       if (Mupmate == YES) {
+                               l_yyerror(0, -1, "Run > Set Options > Staffs to display/play: value is invalid.");
+                       }
+                       else {
+                               l_yyerror(0, -1, "invalid argument for %cs option (staffs to make visible)", Optch);
+                       }
+                       return;
+               }
+
+               /* see if there is a voice qualifier */
+               if (*stafflist == 'v') {
+                       stafflist++;
+                       switch (*stafflist) {
+                       case '1':
+                               v = 1;
+                               break;
+                       case '2':
+                               v = 2;
+                               break;
+                       case '3':
+                               v = 3;
+                               break;
+                       default:
+                               if (Mupmate == YES) {
+                                       l_yyerror(0, -1, "Run > Set Options > Staffs to display/play: voice qualifier must be 1, 2, or 3.");
+                               }
+                               else {
+                                       l_yyerror(0, -1, "voice qualifier for -s option must be 1, 2, or 3");
+                               }
+                               return;
+                       }
+                       stafflist++;
+                       if (*stafflist != '\0' && *stafflist != ',') {
+                               if (Mupmate == YES) {
+                                       l_yyerror(0, -1, "Run > Set Options > Staffs to display/play: invalid voice qualifier. (Maybe missing comma?)");
+                               }
+                               else {
+                                       l_yyerror(0, -1, "invalid voice qualifier for -s option (missing comma?)");
+                               }
+                               return;
+                       }
+               }
+               else {
+                       /* no voice qualifier */
+                       v = 0;
+               }
+
+               /* mark all staffs in range as visible */
+               for (  ; start <= end; start++) {
+                       Staff_vis[start] = YES;
+                       if (v != 0) {
+                               Voice_vis[start][v] = YES;
+                       }
+                       else {
+                               /* no voice qualifier, so all voices are visible */
+                               int vn;
+                               for (vn = 1; vn <= MAXVOICES; vn++) {
+                                       Voice_vis[start][vn] = YES;
+                               }
+                       }
+               }
+
+               /* if comma for another range, skip past it */
+               if (*stafflist == ',') {
+                       stafflist++;
+               }
+       }
+}
+\f
+
+#ifdef NEED_GETOPT
+/* for non-unix or other systems that don't have a getopt() function,
+ * define one here. This is NOT a general purpose implementation of getopt(),
+ * but something good enough to work with Mup */
+
+int optind = 1;
+char *optarg;
+static int argoffset;
+int opttype P((int option, char *optstring));
+
+#define NOARG 1
+#define WITHARG        2
+#define BADOPT  3
+
+int
+getopt(argc, argv, optstring)
+
+#ifdef __STDC__
+int argc;
+char * const *argv;
+const char *optstring;
+#else
+int argc;
+char **argv;
+char *optstring;
+#endif
+
+{
+       int option;
+
+
+       if (optind >= argc) {
+               return(EOF);
+       }
+
+       if (argoffset == 0) {
+#ifdef __DOS__
+               if (argv[optind][argoffset] == '-'
+                                       || argv[optind][argoffset] == '/') {
+#else
+               if (argv[optind][argoffset] == '-') {
+#endif
+                       argoffset = 1;
+               }
+               else {
+                       return(EOF);
+               }
+       }
+
+       /* determine if option is valid and if should have an argument */
+       option = argv[optind][argoffset] & 0x7f;
+       switch (opttype(option, (char *) optstring)) {
+       case NOARG:
+               /* valid option without argument. Keep track of where
+                * to look for next option */
+               if (argv[optind][++argoffset] == '\0') {
+                       optind++;
+                       argoffset = 0;
+               }
+               break;
+
+       case WITHARG:
+               /* valid option with argument. */
+               if (argv[optind][++argoffset] != '\0') {
+                       /* argument immediately follows in same argv */
+                       optarg = &(argv[optind][argoffset]);
+                       optind++;
+               }
+               else {
+                       /* white space. argument must be in next argv */
+                       optind++;
+                       if (optind >= argc) {
+                               fprintf(stderr, "missing argument to %c%c option\n", Optch, option);
+                               return('?');
+                       }
+                       optarg = &(argv[optind][0]);
+                       optind++;
+               }
+               argoffset = 0;
+               break;
+
+       default:
+               fprintf(stderr, "invalid option %c%c\n", Optch, option);
+               option = '?';
+       }
+       return(option);
+}
+
+
+/* look up option in optstring and return type of option */
+
+int
+opttype(option, optstring)
+
+int option;
+char *optstring;
+
+{
+       char *p;
+
+       for (p = optstring; *p != '\0'; ) {
+               if (*p++ == option) {
+                       return(*p == ':' ? WITHARG : NOARG);
+               }
+               if (*p == ':') {
+                       p++;
+               }
+       }
+       return(BADOPT);
+}
+
+#endif
diff --git a/mup/mup/mainlist.c b/mup/mup/mainlist.c
new file mode 100644 (file)
index 0000000..c3061c6
--- /dev/null
@@ -0,0 +1,170 @@
+
+/* Copyright (c) 1995, 2001, 2003 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions for manipulating the main list of structs, allocating,
+ * inserting and deleting. */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+
+
+/* allocate a new MAINLL struct and return a pointer to it */
+
+struct MAINLL *
+newMAINLLstruct(structtype, lineno)
+
+int structtype;                /* what kind to allocate: S_SSV, S_BAR, etc */
+int lineno;            /* input line number that caused this call */
+
+{
+       struct MAINLL *new_p;   /* the newly allocated struct */
+
+
+       debug(4, "newMAINLLstruct lineno=%d structtype=%d", lineno, structtype);
+
+       /* allocate the struct */
+       CALLOC(MAINLL, new_p, 1);
+
+       /* fill in the type to say which union member will be used */
+       new_p->str = (short) structtype;
+
+       /* initialize link pointers to point nowhere */
+       new_p->next = new_p->prev = (struct MAINLL *) 0;
+
+
+       /* now allocate and initialize the proper S_* struct */
+       switch (structtype) {
+
+       case S_SSV:
+               CALLOC(SSV, new_p->u.ssv_p, 1);
+               break;
+
+       case S_STAFF:
+               CALLOC(STAFF, new_p->u.staff_p, 1);
+               break;
+
+       case S_BAR:
+               CALLOC(BAR, new_p->u.bar_p, 1);
+               break;
+
+       case S_LINE:
+               CALLOC(LINE, new_p->u.line_p, 1);
+               break;
+
+       case S_CURVE:
+               CALLOC(CURVE, new_p->u.curve_p, 1);
+               break;
+
+       case S_PRHEAD:
+               CALLOC(PRHEAD, new_p->u.prhead_p, 1);
+               break;
+
+       case S_CHHEAD:
+               CALLOC(CHHEAD, new_p->u.chhead_p, 1);
+               break;
+
+       case S_FEED:
+               CALLOC(FEED, new_p->u.feed_p, 1);
+               /* negative value for margin means use score parameter */
+               new_p->u.feed_p->rightmargin = -1.0;
+               new_p->u.feed_p->leftmargin = -1.0;
+               break;
+
+       case S_BLOCKHEAD:
+               CALLOC(BLOCKHEAD, new_p->u.blockhead_p, 1);
+               break;
+
+       case S_CLEFSIG:
+               CALLOC(CLEFSIG, new_p->u.clefsig_p, 1);
+               break;
+
+       default:
+               pfatal("unknown structure type %d requested", structtype);
+               break;
+       }
+
+       /* remember the user's input file and line number,
+        * so in case we have to print an error message later,
+        * we know which line number to print */
+       new_p->inputlineno = (short) lineno;
+       new_p->inputfile = Curr_filename;
+
+       /* return the newly allocated struct */
+       return(new_p);
+}
+\f
+
+/* insert MAINLL struct into main list, after an arbitrary existing struct. */
+/* If where to insert is NULL, put at beginning of list */
+
+void
+insertMAINLL(info_p, where)
+
+struct MAINLL *info_p; /* what to insert */
+struct MAINLL *where;  /* put it right after this one in the list */
+
+{
+       if (info_p == where) {
+               /* Any bug that gets us here would cause an infinite loop */
+               pfatal("attempt to insert a MAINLL after itself");
+       }
+
+       /* if where is NULL, this means to insert at beginning of list */
+       if (where == (struct MAINLL *) 0) {
+               if (Mainllhc_p != (struct MAINLL *) 0) {
+                       Mainllhc_p->prev = info_p;
+               }
+               info_p->prev = (struct MAINLL *) 0;
+               info_p->next = Mainllhc_p;      
+               Mainllhc_p = info_p;
+       }
+
+       else {
+               /* standard linked list stuff --
+                * fix up the next and prev pointers */
+               info_p->next = where->next;
+               info_p->prev = where;
+               if (where->next != (struct MAINLL *) 0) {
+                       where->next->prev = info_p;
+               }
+               where->next = info_p;
+       }
+
+       /* if we just added to the very end of the list, need to adjust the
+        * tail pointer */
+       if ( (Mainlltc_p == (struct MAINLL *) 0) || (where == Mainlltc_p) ) {
+               Mainlltc_p = info_p;
+       }
+}
+\f
+
+/* unlink a MAINLL struct from the main list
+ * (probably for re-inserting elsewhere). The struct is not freed. */
+
+void
+unlinkMAINLL(which_p)
+
+struct MAINLL *which_p;        /* the one to unlink */
+
+{
+       if (which_p->prev != (struct MAINLL *) 0) {
+               which_p->prev->next = which_p->next;
+       }
+       if (which_p->next != (struct MAINLL *) 0) {
+               which_p->next->prev = which_p->prev;
+       }
+
+       /* if this happened to be the tail cell, need to fix up */
+       if (Mainlltc_p == which_p) {
+               Mainlltc_p = which_p->prev;
+       }
+
+       /* likewise for head cell */
+       if (Mainllhc_p == which_p) {
+               Mainllhc_p = which_p->next;
+       }
+}
diff --git a/mup/mup/map.c b/mup/mup/map.c
new file mode 100644 (file)
index 0000000..2ec577a
--- /dev/null
@@ -0,0 +1,1242 @@
+
+/* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* This file contains functions for mapping input to individual voices.
+ * The user can give a single line of input
+ * that gets expanded into several voices.
+ * There are two flavors of this:
+ * voice-at-a-time input and chord-at-a-time input.
+ * For the former, the GRPSYL list just gets cloned and altered as needed.
+ * For the latter, brand new GRPSYL lists are created
+ * by distributing individual notes from the user's input.
+ * For any given staff/voice, only one type of input can be used per measure.
+ * For chord-at-a-time, a given staff/voice can appear more than once
+ * within a single input line, but not on multiple input lines per measure.
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+/* mark whether we mapped user data, only mapped implicit spaces, or nothing */
+#define MAPPED_NOTHING (0)
+#define MAPPED_IMPLICIT        (1)
+#define MAPPED_EXPLICIT        (2)
+
+/* This struct tells how to map one note for chord-at-a-time input,
+ * i.e., which staff/voice combinations it should be mapped to.
+ * Each map item in input (semicolon-separated)
+ * gets saved in one of these. */
+struct NOTEMAP {
+       struct SVRANGELIST *svlist_p;   /* staffs/voices to map this note to */
+       struct NOTEMAP *next;           /* linked list */
+};
+
+/* This struct gives the mapping for a particular number of notes.
+ * The set of things inside a pair of brackets gets saved in one of these. */
+struct MAP {
+       int num_entries;                /* how many item in list */
+       struct NOTEMAP *notemap_p;      /* one entry for each note in chord */
+       struct MAP *next;               /* linked list */
+};
+
+/* This points to the list of maps, or to 0 if doing voice-at-a-time input */
+static struct MAP *Map_p;
+/* This points to where to add to the map list */
+static struct MAP **End_map_p_p = &Map_p;
+
+/* This is where to insert the next NOTEMAP */
+static struct NOTEMAP **Note_p_p;
+
+/* It is handy to be able to treat both input styles identically
+ * as much as possible. So for when input is voice-at-a-time, it can be handy
+ * to have a MAP that just points to Svrangelist_p. These two structs are
+ * used for that purpose. Since the value of Svrangelist_p changes
+ * at runtime, we have to set Sv_notemap->svlist_p each time
+ * before these are used. */
+static struct NOTEMAP Sv_notemap = {
+       (struct SVRANGELIST *) 0, (struct NOTEMAP *) 0
+};
+static struct MAP Voice_at_a_time_map = {
+       1, &Sv_notemap, (struct MAP *) 0
+};
+
+/* Keep track of which input style was used */
+static short Input_style[MAXSTAFFS][MAXVOICES];
+
+static int map_groups P((void));
+static void clean_map_data P((void));
+static void free_maps P((struct MAP *map_p));
+static void free_notemaps P((struct NOTEMAP *notemap_p));
+static struct NOTEMAP *find_notemap P((int num_notes));
+static void map1note P((struct GRPSYL *from_gs_p, int n, int staff, int voice,
+       short allocated[MAXSTAFFS][MAXVOICES]));
+static void do_link_groups P((void));
+static void link_a_grouplist P((int staffno, int vno, int copies));
+static void convert_rest_space P((struct GRPSYL *grpsyl_p, int staffno, int vno));
+static void conv_grpsyl P((struct GRPSYL *grpsyl_p, int staffno, int vno));
+static void mult_def P((int staff, int voice));
+\f
+
+/* Initialize Input_style to default of IS_VOICE_INPUT */
+
+void
+reset_input_style()
+
+{
+       int staff;
+       int voice;
+
+       for (staff = 0; staff < MAXSTAFFS; staff++) {
+               for (voice = 0; voice < MAXVOICES; voice++) {
+                       Input_style[staff][voice] = IS_VOICE_INPUT;
+               }
+       }
+}
+\f
+
+/* Return the current input style for a given staff/voice */
+
+int
+input_style(staff, voice)
+
+int staff;
+int voice;
+
+{
+       return(Input_style[staff-1][voice-1]);
+}
+\f
+
+/* This is called when a '[' is encountered in input, starting a new map */
+
+void
+begin_map()
+
+{
+       struct MAP *new_p;
+
+
+       /* allocate space for a new map */
+       CALLOC(MAP, new_p, 1);
+
+       /* Keep track of where to link on the first NOTEMAP */
+       Note_p_p = &(new_p->notemap_p);
+
+       /* Add to MAP list */
+       *End_map_p_p = new_p;
+
+       begin_sv_list();
+}
+\f
+
+/* Save one item of a map. Items are the semicolon-separated specifications. */
+
+void
+map_item()
+{
+       CALLOC(NOTEMAP, *Note_p_p, 1);
+
+       /* Save the current range */
+       (*Note_p_p)->svlist_p = Svrangelist_p;
+       ((*End_map_p_p)->num_entries)++;
+
+       /* prepare for another, if any */
+       Note_p_p = &( (*Note_p_p)->next);
+
+       begin_sv_list();
+       begin_range(PL_UNKNOWN);
+}
+\f
+
+/* At the end of a map specification, this function is called to save the
+ * info about the map for later use, and prepare for another map, if any.
+ */
+
+void
+end_map()
+
+{
+       /* prepare for another map, if any */
+       End_map_p_p = &( (*End_map_p_p)->next);
+
+       begin_range(Place);
+}
+\f
+
+/* Map chord-at-a-time input so it looks just like voice-at-a-time input.
+ * Return YES if current measure is chord-at-a-time, and thus
+ * mapping was done, NO if current measure is voice-at-a-time.
+ */
+
+static int
+map_groups()
+
+{
+       struct MAP *map_p;
+       /* Multiple notes in a chord might get mapped to a single staff/voice.
+        * In that case, after the first note for that staff/voice,
+        * we need to just add a note to the existing GRPSYL rather than
+        * allocating a new one. This keeps track of whether we have already
+        * allocated a GRPSYL for the current chord of a given staff/voice. */
+       short allocated[MAXSTAFFS][MAXVOICES];
+       /* This array tells us which staffs/voices we are mapping things to */
+       short used[MAXSTAFFS][MAXVOICES];
+       /* This array will have MAPPED_EXPLICIT
+        * in entries where we mapped actual user data.
+        * If we only mapped implicit spaces (MAPPED_IMPLICIT),
+        * we can treat things as if user didn't use the voice
+        * on this input line. */
+       short mapped_something[MAXSTAFFS][MAXVOICES];
+       /* This says if we've printed an error yet for multiply defined voice,
+        * to make sure we only print it once. */
+       short printed_mult_err[MAXSTAFFS][MAXVOICES];
+       /* This tells which numbers of notes we have maps for. */
+       short have_map[MAXHAND];
+       int s;                  /* staff number */
+       int v;                  /* voice number */
+       int n;                  /* note index */
+       struct NOTEMAP *notemap_p;      /* how to map notes to voices */
+       struct SVRANGELIST *svr_p;
+       struct RANGELIST *sr_p; /* range of staffs being defined */
+       struct RANGELIST *vr_p; /* range of vno's being defined */
+       struct GRPSYL *gs_p;
+       struct GRPSYL *g_p;
+       int errors;
+
+
+       if (Map_p == (struct MAP *) 0) {
+               /* not chord-at-a-time mapping, so nothing to do here */
+               return(NO);
+       }
+
+       /* remember current error count */
+       errors = Errorcount;
+
+       /* Initialize arrays. These will later tell us
+        * which GRPSYL lists we are mapping to, and whether we mapped
+        * any actual user input, or just implicit spaces. */
+       for (s = 0; s < Score.staffs; s++) {
+               for (v = 0; v < MAXVOICES; v++) {
+                       used[s][v] = NO;
+                       mapped_something[s][v] = MAPPED_NOTHING;
+                       printed_mult_err[s][v] = NO;
+               }
+       }
+       /* This tells for which numbers of notes we have maps */
+       for (n = 0; n < MAXHAND; n++) {
+               have_map[n] = NO;
+       }
+
+       /* Do some error checking on the MAP list */
+       for (map_p = Map_p; map_p != (struct MAP *) 0; map_p = map_p->next) {
+
+               if (have_map[map_p->num_entries] == YES) {
+                       l_yyerror(Curr_filename, yylineno,
+                               "more than one map for chords with %d notes",
+                               map_p->num_entries);
+                       continue;
+               }
+               else {
+                       have_map[map_p->num_entries] = YES;
+               }
+
+               for (notemap_p = map_p->notemap_p;
+                               notemap_p != (struct NOTEMAP *) 0;
+                               notemap_p = notemap_p->next) {
+                       for (svr_p = notemap_p->svlist_p;
+                                       svr_p != (struct SVRANGELIST *) 0;
+                                       svr_p = svr_p->next) {
+                           for (sr_p = svr_p->stafflist_p; sr_p != 0;
+                                                       sr_p = sr_p->next) {
+                               for (s = sr_p->begin; s <= sr_p->end; s++) {
+
+                                       if (s > Score.staffs) {
+                                               l_yyerror(Curr_filename,
+                                                       yylineno,
+                                                       "staff %d does not exist",
+                                                       s);
+                                               continue;
+                                       }
+
+                                       for (vr_p = svr_p->vnolist_p; vr_p != 0;
+                                                       vr_p = vr_p->next) {
+                                           for (v = vr_p->begin;
+                                                       v <= vr_p->end; v++) {
+
+                                               /* make sure voice exists */
+                                               if (v > 1 && svpath(s, VSCHEME)
+                                                       ->vscheme == V_1) {
+                                                  l_yyerror(Curr_filename,
+                                                       yylineno,
+                                                       "there is no voice %d on staff %d",
+                                                       v, s);
+                                               }
+                                               used[s-1][v-1] = YES;
+                                               Input_style[s-1][v-1]
+                                                       = IS_CHORD_INPUT;
+                                           }
+                                       }
+                               }
+                           }
+                       }
+               }
+       }
+
+       if (Errorcount > errors) {
+               clean_map_data();
+               return(YES);
+       }
+
+       /* process each chord in the GRPSYL list */
+       for (gs_p = Curr_gs_list_p; gs_p != (struct GRPSYL *) 0;
+                                                       gs_p = gs_p->next) {
+               /* initialize the allocation array for current chord */
+               for (s = 0; s < Score.staffs; s++) {
+                       for (v = 0; v < MAXVOICES; v++) {
+                               allocated[s][v] = NO;
+                       }
+               }
+
+               /* With voice-at-a-time input, we allow the first group
+                * to have no pitch specified iff it is on a 1-line staff.
+                * For chord-at-a-time, to allow that
+                * we would have to allow a mapping of zero notes,
+                * which doesn't make sense, or map an implicit note,
+                * which seems questionable at best.
+                * If there is a mixture of 1-line and not-1-line
+                * staffs being mapped, things get even more confusing.
+                * So we disallow implicit pitch on chord-at-at-time. */
+               if (gs_p->nnotes == 1 && gs_p->notelist[0].letter == PP_NO_PITCH) {
+                       l_yyerror(Curr_filename, yylineno, "no notes specified");
+                       notemap_p = (struct NOTEMAP *) 0;
+               }
+               else {
+                       /* Find the pattern matching the number of notes.
+                        * If none is found, this will return 0, and the 'for'
+                        * below will get skipped, and we'll add spaces */
+                       notemap_p = find_notemap(gs_p->nnotes);
+               }
+
+               /* Go through each note in the chord, and copy it
+                * to the appropriate staffs/voices */
+               for (n = 0; notemap_p != (struct NOTEMAP *) 0;
+                                       n++, notemap_p = notemap_p->next) {
+                       for (svr_p = notemap_p->svlist_p;
+                                       svr_p != (struct SVRANGELIST *) 0;
+                                       svr_p = svr_p->next) {
+                           for (sr_p = svr_p->stafflist_p; sr_p != 0;
+                                                       sr_p = sr_p->next) {
+                               for (s = sr_p->begin; s <= sr_p->end; s++) {
+                                   for (vr_p = svr_p->vnolist_p; vr_p != 0;
+                                                       vr_p = vr_p->next) {
+                                       for (v = vr_p->begin;
+                                                       v <= vr_p->end; v++) {
+                                               /* If we have not yet mapped
+                                                * anything from the current
+                                                * input line, yet there is
+                                                * something in the grpsyl
+                                                * list for this staff/voice,
+                                                * that means user must have
+                                                * already defined data for
+                                                * this staff/voice on some
+                                                * other input line, and thus
+                                                * is not allowed to map
+                                                * anything from the current
+                                                * line. */
+                                               if (mapped_something[s-1][v-1]
+                                                       == MAPPED_NOTHING
+                                                       && Staffmap_p[s]->u.staff_p->groups_p[v-1] != 0
+                                                       && printed_mult_err[s-1][v-1] == NO) {
+                                                   mult_def(s, v);
+                                                   printed_mult_err[s-1][v-1] = YES;
+                                                   continue;
+                                               }
+                                               map1note(gs_p, n, s, v,
+                                                               allocated);
+                                               mapped_something[s-1][v-1]
+                                                       = MAPPED_EXPLICIT;
+                                       }
+                                   }
+                               }
+                           }
+                       }
+               }
+
+               /* For any staff/voice that is being mapped to, but which
+                * didn't get anything mapped for this particular chord,
+                * add a space group. This could happen either because
+                * user specified several patterns and some patterns don't
+                * contain all the staffs/voices, which implies they want
+                * us to fill in spaces, or because there was an error in
+                * input. If there was an error, it's still nice to add the
+                * space, because it prevents extra error messages */
+               for (s = 1; s <= Score.staffs; s++) {
+                       for (v = 1; v <= MAXVOICES; v++) {
+                               /* If we haven't mapped anything to this
+                                * voice, but there is something there,
+                                * user must have defined it on an earlier
+                                * input line. In that case we should leave
+                                * it be, because either (1) user didn't
+                                * actually use any pattern that uses this
+                                * voice, or (2) they multiply defined the
+                                * voice, in which case the error is caught
+                                * elsewhere. In either case, their
+                                * earlier input should stand. */
+                               if (mapped_something[s-1][v-1] == MAPPED_NOTHING
+                                               && Staffmap_p[s]->u.staff_p->groups_p[v-1] != 0) {
+                                       continue;
+                               }
+
+                               if (used[s-1][v-1] == YES &&
+                                               allocated[s-1][v-1] == NO) {
+                                       map1note(gs_p, -1, s, v, allocated);
+                                       if (mapped_something[s-1][v-1] !=
+                                                       MAPPED_EXPLICIT) {
+                                               mapped_something[s-1][v-1]
+                                                       = MAPPED_IMPLICIT;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /* If this particular input line didn't actually use some of the
+        * patterns, some voices might not *really* have been used--we
+        * merely filled in implicit spaces for it. So we can undo that
+        * so user can specify the voice via voice-at-a-time if they want to.
+        * If they don't, the regular filling in of missing voices with
+        * implicit spaces will happen later. */
+       for (s = 0; s < Score.staffs; s++) {
+               for (v = 0; v < MAXVOICES; v++) {
+                       if (used[s][v] == YES &&
+                                       mapped_something[s][v] != MAPPED_EXPLICIT) {
+                               used[s][v] = NO;
+                               Input_style[s][v] = IS_VOICE_INPUT;
+
+                               /* If only implict, we free that up */
+                               if (mapped_something[s][v] == MAPPED_IMPLICIT) {
+                                       free_grpsyls(Staffmap_p[s+1]->u.staff_p->groups_p[v]);
+                                       Staffmap_p[s+1]->u.staff_p->groups_p[v] = 0;
+                               }
+                       }
+               }
+       }
+
+       /* Now we can go through and free up any wasted space */
+       for (s = 0; s < Score.staffs; s++) {
+               for (v = 0; v < MAXVOICES; v++) {
+                       if (used[s][v] == YES) {
+                               /* Rests and spaces get moved from
+                                * NOTE pseudo-pitches to GRPSYL */
+                               convert_rest_space(Staffmap_p[s+1]->u.
+                                               staff_p->groups_p[v], s+1, v+1);
+                               for (g_p = Staffmap_p[s+1]->u.staff_p->groups_p[v];
+                                               g_p != (struct GRPSYL *) 0;
+                                               g_p = g_p->next) {
+                                       resize_notelist(g_p);
+                               }
+                       }
+               }
+       }
+
+       clean_map_data();
+
+       /* Everything in the original GRPSYL list
+        * has been copied to other lists, so original can be freed */
+       free_grpsyls(gs_p);
+
+       return(YES);
+}
+\f
+
+/* map one note to one staff/voice */
+
+static void
+map1note(from_gs_p, n, staff, voice, allocated)
+
+struct GRPSYL *from_gs_p;      /* copy from here */
+int n;                         /* copy the nth note in from_gs_p, or if -1,
+                                * create a space group */
+int staff;
+int voice;
+short allocated[MAXSTAFFS][MAXVOICES]; /* tracks whether to allocate a new
+                                * GRPSYL; may be updated */
+
+{
+       struct GRPSYL *to_gs_p;         /* where to map note to */
+       struct GRPSYL **add_p_p;        /* where to add to_gs_p */
+       struct NOTE *from_note_p;
+       struct NOTE *to_note_p;
+       struct GRPSYL *prev;            /* value to set to_gs_p->prev to */
+
+
+       /* If original group is a grace group, we don't need to add a
+        * space group, since grace already take no time */
+       if (n == -1 && from_gs_p->grpvalue == GV_ZERO) {
+               return;
+       }
+
+       /* If this is the first note allocated to this staff/voice for
+        * current chord, have to allocate a GRPSYL for it. */
+       if (allocated [staff - 1] [voice - 1] == NO) {
+               to_gs_p = newGRPSYL(GS_GROUP);
+               copy_attributes(to_gs_p, from_gs_p);
+               /* by the time we get here, we've already gone past the
+                * newline, so the input line number is one too much */
+               to_gs_p->inputlineno--;
+
+               allocated [staff - 1] [voice - 1] = YES;
+
+               /* Add to end of list */
+               prev = (struct GRPSYL *) 0;
+               for (add_p_p = &(Staffmap_p[staff]->u.staff_p->groups_p[voice-1]);
+                                       *add_p_p != (struct GRPSYL *) 0;
+                                       add_p_p = &((*add_p_p)->next) ) {
+                       prev = *add_p_p;
+               }
+               to_gs_p->prev = prev;
+               *add_p_p = to_gs_p;
+
+               /* copy the other attributes */
+               to_gs_p->staffno = staff;
+               to_gs_p->vno = voice;
+               to_gs_p->basictime = from_gs_p->basictime;
+               to_gs_p->fulltime = from_gs_p->fulltime;
+               to_gs_p->dots = from_gs_p->dots;
+               to_gs_p->is_meas = from_gs_p->is_meas;
+               to_gs_p->tuploc = from_gs_p->tuploc;
+               to_gs_p->tupcont = from_gs_p->tupcont;
+               to_gs_p->tupside = from_gs_p->tupside;
+               to_gs_p->beamloc = from_gs_p->beamloc;
+               to_gs_p->breakbeam = from_gs_p->breakbeam;
+               to_gs_p->beamto = from_gs_p->beamto;
+               to_gs_p->printtup = from_gs_p->printtup;
+               to_gs_p->tie = from_gs_p->tie;
+               to_gs_p->inhibitprint = from_gs_p->inhibitprint;
+               to_gs_p->ho_usage = from_gs_p->ho_usage;
+               to_gs_p->ho_value = from_gs_p->ho_value;
+       }
+       else {
+               /* find the last group for this staff/voice */
+               for (to_gs_p = Staffmap_p[staff]->u.staff_p->groups_p[voice-1];
+                                       to_gs_p->next != (struct GRPSYL *) 0;
+                                       to_gs_p = to_gs_p->next) {
+                       ;
+               }
+       }
+
+       /* Special case: If n == -1, make this a space group */
+       if (n == -1) {
+               to_gs_p->grpcont = GC_SPACE;
+               /* some things don't make sense with space,
+                * so nullify the things that just apply to notes */
+               to_gs_p->grpvalue = GV_NORMAL;
+               to_gs_p->headshape = HS_UNKNOWN;
+               to_gs_p->grpsize = GS_NORMAL;
+               to_gs_p->stemdir = UNKNOWN;
+               to_gs_p->stemlen = STEMLEN_UNKNOWN;
+               to_gs_p->roll = NOITEM;
+               to_gs_p->beamloc = NOITEM;
+               to_gs_p->breakbeam = NO;
+               to_gs_p->beamto = CS_SAME;
+               to_gs_p->stemto = CS_SAME;
+               to_gs_p->slash_alt = 0;
+               return;
+       }
+
+       from_note_p = &(from_gs_p->notelist[n]);
+       if (Doing_tab_staff == YES) {
+               /* fret, nticks, and bendstring exist in from_note_p
+                * in an internal format, whereas add_note() needs them
+                * in something close to user input format,
+                * so we have to reconstruct
+                * what the user input must have been. */
+               add_note(to_gs_p, from_gs_p->notelist[n].letter,
+                       from_note_p->accidental,
+                       TMP_FRET(from_note_p),
+                       TMP_NTICKS(from_note_p),
+                       from_note_p->acc_has_paren,
+                       (HASBEND(from_gs_p->notelist[n])
+                         ? bend_string(from_note_p)
+                         : (char *) 0) );
+       }
+       else {
+               add_note(to_gs_p, from_gs_p->notelist[n].letter,
+                       from_note_p->accidental,
+                       from_note_p->octave,
+                       0,
+                       from_note_p->acc_has_paren,
+                       (char *) 0);
+       }
+
+       /* copy remaining note attributes: tie, slur, etc */
+       to_note_p = &(to_gs_p->notelist[to_gs_p->nnotes - 1]);
+       to_note_p->tie = from_note_p->tie;
+       to_note_p->tiestyle = from_note_p->tiestyle;
+       to_note_p->tiedir = from_note_p->tiedir;
+       to_note_p->nslurto = from_note_p->nslurto;
+       if (from_note_p->nslurto > 0) {
+               /* slurto lists cannot be safely shared, so make copy */
+               MALLOC(SLURTO, to_note_p->slurtolist, 
+                                       from_note_p->nslurto);
+               (void) memcpy(to_note_p->slurtolist,
+                                       from_note_p->slurtolist,
+                                       sizeof(struct SLURTO) *
+                                       from_note_p->nslurto);
+       }
+       else {
+               to_note_p->slurtolist = (struct SLURTO *) 0;
+       }
+       to_note_p->notesize = from_note_p->notesize;
+       to_note_p->note_has_paren = from_note_p->note_has_paren;
+       to_note_p->is_bend = from_note_p->is_bend;
+       to_note_p->smallbend = from_note_p->smallbend;
+}
+\f
+
+/* When done with temporary map data, clean everything up, to prepare
+ * for potentially getting another set of data */
+
+static void
+clean_map_data()
+
+{
+       /* free up the lists */
+       free_maps(Map_p);
+
+       /* reset pointers to be ready for more data */
+       Map_p = (struct MAP *) 0;
+       End_map_p_p = &Map_p;
+}
+\f
+
+/* free up the MAP list and everything hanging off of it */
+
+static void
+free_maps(map_p)
+
+struct MAP *map_p;
+
+{
+       if (map_p == (struct MAP *) 0) {
+               /* end recursion */
+               return;
+       }
+
+       /* free the list hanging off of this struct */
+       free_notemaps(map_p->notemap_p);
+
+       /* recurse */
+       free_maps(map_p->next);
+
+       /* free the passed-in struct */
+       FREE(map_p);
+}
+
+/* free up a NOTEMAP list and everything hanging off of it */
+
+static void
+free_notemaps(notemap_p)
+
+struct NOTEMAP *notemap_p;
+
+{
+       if (notemap_p == (struct NOTEMAP *) 0) {
+               return;
+       }
+
+       free_sv_list(notemap_p->svlist_p);
+       free_notemaps(notemap_p->next);
+       FREE(notemap_p);
+}
+\f
+
+/* Given a number of notes, find the NOTEMAP list for that many and return it.
+ * If not found, return 0. */
+
+static struct NOTEMAP *
+find_notemap(num_notes)
+
+int num_notes;
+
+{
+       struct MAP *m_p;
+
+       for (m_p = Map_p; m_p != (struct MAP *) 0; m_p = m_p->next) {
+               if (m_p->num_entries == num_notes) {
+                       return(m_p->notemap_p);
+               }
+       }
+       
+       l_yyerror(Curr_filename, yylineno,
+                       "there is no bracketed mapping for chords containing %d note%s", num_notes, num_notes == 1 ? "" : "s");
+       return ((struct NOTEMAP *) 0);
+}
+\f
+
+/* Once a measure-worth of data is gathered for one or more staffs/voices,
+ * link copies onto the appropriate STAFF structs */
+
+void
+link_groups()
+
+{
+       /* if haven't yet set up the STAFFs for this measure, do so now */
+       create_staffs();
+
+       /* if we are in this function, user specified some music data */
+       Got_some_data = YES;
+       Got_group = YES;
+
+       /* do error check--can't have notes and multirest in same measure */
+       if (Got_multirest == 1) {
+               report_mix_error();
+               return;
+       }
+
+       /* Do either chord-to-voice-mapping or standard voice mapping,
+        * as appropriate. */
+       if (map_groups() == NO) {
+               do_link_groups();
+       }
+
+       /* re-initialize for next measure */
+       Curr_gs_list_p = (struct GRPSYL *) 0;
+       free_rlists();
+}
+\f
+
+/* Go through Svrangelist, creating copies of the GRPSYL lists and
+ * linking them to the appropriate STAFFs. */
+
+static void
+do_link_groups()
+
+{
+       struct SVRANGELIST *svr_p;      /* list of ranges of staffs and vnos */
+       register int s;         /* staff index */
+       register int v;         /* voice index */
+       struct RANGELIST *sr_p; /* range of staffs being defined */
+       struct RANGELIST *vr_p; /* range of vno's being defined */
+       int copies = 0;         /* how many copies of grpsyl list made so far */
+
+
+       for (svr_p = Svrangelist_p; svr_p != (struct SVRANGELIST *) 0;
+                                               svr_p = svr_p->next) {
+
+               for (sr_p = svr_p->stafflist_p; sr_p != (struct RANGELIST *) 0;
+                                                       sr_p = sr_p->next) {
+
+                       for (s = sr_p->begin; s <= sr_p->end; s++) {
+
+                               for (vr_p = svr_p->vnolist_p;
+                                               vr_p != (struct RANGELIST *) 0;
+                                               vr_p = vr_p->next) {
+
+                                       for (v = vr_p->begin;
+                                                       v <= vr_p->end; v++) {
+                                               link_a_grouplist(s, v, copies++);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+\f
+
+/* connect list of GRPSYLs to a staff. If copies == 0, use the current
+ * grpsyl list, otherwise make a copy of it and use the copy */
+
+static void
+link_a_grouplist(staffno, vno, copies)
+
+int staffno;
+int vno;
+int copies;    /* if non-zero, need to make a copy */
+
+{
+       if (rangecheck(staffno, MINSTAFFS, Score.staffs, "staff number")
+                                       == NO) {
+               return;
+       }
+
+       if (rangecheck(vno, MINVOICES, MAXVOICES, "voice number") == NO) {
+               return;
+       }
+
+       if (Staffmap_p[staffno] == (struct MAINLL *) 0) {
+               return;
+       }
+
+       if (Staffmap_p[staffno]->u.staff_p == (struct STAFF *) 0) {
+               pfatal("null staff pointer while linking group list");
+       }
+
+       if (Staffmap_p[staffno]->u.staff_p->groups_p[vno-1]
+                       != (struct GRPSYL *) 0) {
+               mult_def(staffno, vno);
+               return;
+       }
+
+       /* the first time through, we can use the
+        * existing list. After that we need to
+        * make a clone of the list */
+       if (copies == 0) {
+               (Staffmap_p[staffno])->u.staff_p->groups_p[vno-1]
+                                       = Curr_gs_list_p;
+               convert_rest_space(Staffmap_p[staffno]->u.
+                                       staff_p->groups_p[vno-1], staffno, vno);
+       }
+       else {
+               (Staffmap_p[staffno])->u.staff_p->groups_p[vno-1]
+                                       = clone_gs_list(Curr_gs_list_p, YES);
+       }
+}
+\f
+
+/* With chord-at-a-time input style, it is legal to have
+ * a mixture of pitches, spaces, and rests. However, once
+ * everything has been distributed to individual voices, we need to check
+ * that there aren't still any mixtures, and convert the rest and
+ * space pseudo-notes into rest and space groups. Some error checks
+ * also get done that couldn't be done till after this conversion. */
+
+static void
+convert_rest_space(grpsyl_p, staffno, vno)
+
+struct GRPSYL *grpsyl_p;
+int staffno;
+int vno;
+
+{
+       for (   ; grpsyl_p != (struct GRPSYL *) 0; grpsyl_p = grpsyl_p->next) {
+               conv_grpsyl(grpsyl_p, staffno, vno);
+       }
+}
+\f
+
+/* Given a GRPSYL, convert all the rest and space
+ * pseudo notes to groups and do related error checking */
+
+static void
+conv_grpsyl(grpsyl_p, staffno, vno)
+
+struct GRPSYL *grpsyl_p;
+int staffno;
+int vno;
+
+{
+       int notes, rests, spaces, rpts;/* count how many of each in chord */
+       int n;                          /* index through notes */
+
+       /* Count how many notes, rests, and spaces in the group */
+       rests = spaces = notes = rpts = 0;
+       for (n = 0; n < grpsyl_p->nnotes; n++) {
+               if (grpsyl_p->notelist[n].letter == PP_REST) {
+                       rests++;
+               }
+               else if (grpsyl_p->notelist[n].letter == PP_SPACE) {
+                       spaces++;
+               }
+               else if (grpsyl_p->notelist[n].letter == PP_RPT) {
+                       rpts++;
+               }
+               else {
+                       notes++;
+               }
+       }
+
+       /* Group may not mix space, rest, rpt, and notes */
+       if (spaces > 0 && spaces != grpsyl_p->nnotes) {
+               l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                       "staff %d voice %d: mixture of space and non-space",
+                       staffno, vno);
+               return;
+       }
+       if (rests > 0 && rests != grpsyl_p->nnotes) {
+               l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                       "staff %d voice %d: mixture of rest and non-rest",
+                       staffno, vno);
+               return;
+       }
+       if (rpts > 0 && rpts != grpsyl_p->nnotes) {
+               l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                       "staff %d voice %d: mixture of rpt and non-rpt",
+                       staffno, vno);
+               return;
+       }
+
+       /* convert rest, space, and rpt pseudo-notes to groups */
+       if (notes < grpsyl_p->nnotes) {
+               if (rests > 0) {
+                       /* This is actually a rest group */
+                       grpsyl_p->grpcont = GC_REST;
+                       grpsyl_p->tie = NO;
+                       /* If entire group was marked cue, leave it that way.
+                        * Otherwise, if multiple rests map to this group,
+                        * grpsize should be the biggest of them.
+                        * So initialize to small size,
+                        * and if we find any normal size,
+                        * set to normal and jump out of the loop. */
+                       if (grpsyl_p->grpsize != GS_SMALL) {
+                               grpsyl_p->grpsize = GS_SMALL;
+                               for (n = 0; n < grpsyl_p->nnotes; n++) {
+                                       if (grpsyl_p->notelist[n].notesize == GS_NORMAL) {
+       
+                                               grpsyl_p->grpsize = GS_NORMAL;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               else if (spaces > 0) {
+                       /* This is actually a space group */
+                       grpsyl_p->grpcont = GC_SPACE;
+                       grpsyl_p->tie = NO;
+                       /* Uncompressibility was temporarily saved
+                        * in octave, so move it now. If multiple spaces
+                        * mapped to this group, if any of them are
+                        * uncompressible, make the group uncompressible. */
+                       for (n = 0; n < grpsyl_p->nnotes; n++) {
+                               if (grpsyl_p->notelist[n].octave == YES) {
+                                       grpsyl_p->uncompressible = YES;
+                                       break;
+                               }
+                       }
+               }
+               else if (rpts > 0) {
+                       /* This is actually a rpt. Internally, that is stored
+                        * as a note group with no notes (nnotes gets zeroed
+                        * a few lines down from here). This should 
+                        * already be notes but doesn't hurt to set again. */
+                       grpsyl_p->grpcont = GC_NOTES;
+               }
+               if (grpsyl_p->notelist[0].slurtolist != (struct SLURTO *) 0) {
+                       l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                                       "can't have slur on rest, space, or rpt");
+               }
+               free_notelist(grpsyl_p);
+               grpsyl_p->notelist = 0;
+               grpsyl_p->nnotes = 0;
+       }
+
+       if (grpsyl_p->grpcont == GC_NOTES) {
+               if (grpsyl_p->is_meas == YES && grpsyl_p->nnotes > 0) {
+                       l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                               "'m' can only be used with rest, space, or rpt, not notes");
+                       return;
+               }
+       }
+
+       /* grace can only apply to notes */
+       if (grpsyl_p->grpvalue == GV_ZERO && (grpsyl_p->grpcont != GC_NOTES ||
+                                       grpsyl_p->nnotes == 0)) {
+               l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
+                               "grace can only be used with notes");
+       }
+}
+\f
+
+/* If first group of a measure has no time value specified, we have to use
+ * the default. This is complicated by the fact that the user could be 
+ * defining mulitples staffs/voices at once. If they are, we need to make
+ * sure that all of them have the same default. */
+
+struct SSV *
+get_dflt_timeunit_ssv()
+
+{
+       struct MAP *map_p;              /* list of maps */
+       struct NOTEMAP *notemap_p;      /* list of notemaps per map */
+       struct SVRANGELIST *svr_p;      /* list of staff/voice ranges */
+       struct RANGELIST *sr_p;         /* list of staffs being defined */
+       struct RANGELIST *vr_p;         /* list of voices being defined */
+       int s;                          /* staff number */
+       int v;                          /* voice */
+       int got_one = NO;               /* YES if have found a dflt value */
+       RATIONAL this_timeunit;         /* value for current staff/voice */
+       RATIONAL dflt_timeunit;         /* the default time unit to use */
+       struct SSV *tu_ssv_p;           /* SSV containing relevent timeunit */
+       struct SSV *ref_ssv_p;          /* SSV we had checked on prev
+                                        * staff/voice being defined together */
+
+
+       /* If doing voice-at-a-time input, use the special MAP for that case,
+        * otherwise use the Map_p */
+       if (Map_p == (struct MAP *) 0) {
+               map_p = &Voice_at_a_time_map;
+               map_p->notemap_p->svlist_p = Svrangelist_p;
+       }
+       else {
+               map_p = Map_p;
+       }
+
+       /* score value is the ultimate default */
+       dflt_timeunit = Score.timeunit;
+       tu_ssv_p = ref_ssv_p = &Score;
+
+       /* check each map/notemap/svrangelist/svrange/staff/voice combination */
+       for (   ; map_p != (struct MAP *) 0; map_p = map_p->next) {
+           for (notemap_p = map_p->notemap_p;
+                               notemap_p != (struct NOTEMAP *) 0;
+                               notemap_p = notemap_p->next) {
+               for (svr_p = notemap_p->svlist_p;
+                                       svr_p != (struct SVRANGELIST *) 0;
+                                       svr_p = svr_p->next) {
+                   for (sr_p = svr_p->stafflist_p;
+                                               sr_p != (struct RANGELIST *) 0;
+                                               sr_p = sr_p->next) {
+                       for (s = sr_p->begin; s <= sr_p->end; s++) {
+                           for (vr_p = svr_p->vnolist_p;
+                                               vr_p != (struct RANGELIST *) 0;
+                                               vr_p = vr_p->next) {
+                               for (v = vr_p->begin; v <= vr_p->end; v++) {
+
+                                   /* find default timeunit for
+                                    * this staff/voice */
+                                   tu_ssv_p = vvpath(s, v, TIMEUNIT);
+                                   this_timeunit = tu_ssv_p->timeunit;
+
+                                   if (got_one == NO) {
+                                       /* now we have one to
+                                        * compare against */
+                                       dflt_timeunit = this_timeunit;
+                                       ref_ssv_p = tu_ssv_p;
+                                       got_one = YES;
+                                   }
+                                   else if ( NE(this_timeunit, dflt_timeunit)
+                                               || timelists_equal(
+                                               tu_ssv_p->timelist_p,
+                                               ref_ssv_p->timelist_p)
+                                               == NO) {
+                                       yyerror("timeunit value must be the same for all staffs being defined on the same input line");
+                                   }
+                               }
+                           }
+                       }
+                   }
+               }
+           }
+       }
+
+       return(tu_ssv_p);
+}
+\f
+
+/* Return YES if the given lists are equivalent, NO if they aren't. */
+
+int
+timelists_equal(list1_p, list2_p)
+
+struct TIMELIST *list1_p;
+struct TIMELIST *list2_p;
+
+{
+       for (   ; list1_p != 0 && list2_p != 0;
+                       list1_p = list1_p->next, list2_p = list2_p->next) {
+               if ( NE(list1_p->fulltime, list2_p->fulltime) ) {
+                       return(NO);
+               }
+       }
+       return((list1_p == 0 && list2_p == 0) ? YES : NO);
+}
+\f
+
+/* Return YES if the current staff range is for all tablature staffs.
+ * Return NO if not. If there are a mixture, this is an error, so print
+ * a message. It still returns NO in this case, so if the user wanted tab,
+ * they may get a lot of errors.  Oh well. After all, they did make an error.
+ */ 
+
+int
+is_tab_range()
+
+{
+       struct MAP *map_p;
+       struct NOTEMAP *notemap_p;
+       struct SVRANGELIST *svr_p;
+       struct RANGELIST *sr_p;
+       int s;                          /* staff number */
+       int found_tab_staff = NO;
+       int found_non_tab_staff = NO;
+
+       /* If doing voice-at-a-time input, use the special MAP for that case,
+        * otherwise use the Map_p */
+       if (Map_p == (struct MAP *) 0) {
+               map_p = &Voice_at_a_time_map;
+               map_p->notemap_p->svlist_p = Svrangelist_p;
+       }
+       else {
+               map_p = Map_p;
+       }
+
+       /* check each map/notemap/svrangelist/svrange/staff/voice combination */
+       for (   ; map_p != (struct MAP *) 0; map_p = map_p->next) {
+               for (notemap_p = map_p->notemap_p;
+                               notemap_p != (struct NOTEMAP *) 0;
+                               notemap_p = notemap_p->next) {
+                       for (svr_p = notemap_p->svlist_p;
+                                       svr_p != (struct SVRANGELIST *) 0;
+                                       svr_p = svr_p->next) {
+                               for (sr_p = svr_p->stafflist_p;
+                                               sr_p != (struct RANGELIST *) 0;
+                                               sr_p = sr_p->next) {
+                                       for (s = sr_p->begin; s <= sr_p->end; s++) {
+                                               if (is_tab_staff(s) == YES) {
+                                                       found_tab_staff = YES;
+                                               }
+                                               else {
+                                                       found_non_tab_staff = YES;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (found_tab_staff == YES && found_non_tab_staff == YES) {
+               yyerror("mixture of tab and non-tab staffs not allowed");
+       }
+
+       return(found_tab_staff);
+}
+\f
+
+/* When two notes in a chord are duplicates from chord-at-a-time input,
+ * we want to merge the notes, and get rid of the extra. This function will
+ * change the value of gs_p->nnotes and the size of the notelist array. */
+
+void
+merge_dup_notes(gs_p, n)
+
+struct GRPSYL *gs_p;   /* remove duplicate from here */
+int n;                 /* merge note n and n+1 into slot n, then remove
+                        * the note in slot n+1 by moving any remaining
+                        * notes down. */
+
+{
+       int i;
+       int sn, sn1;            /* slurto index */
+       struct NOTE *note_p, *extra_p;
+
+
+       /* get shorter names for what we will use a lot */
+       note_p = &(gs_p->notelist[n]);
+       extra_p = &(gs_p->notelist[n+1]);
+       /* Merge the data between the two as best we can.
+        * In general, if one has a "stronger" version of some attribute,
+        * go with that one. We check the second; if it is "stronger",
+        * force the result to that--if it was already set the same, fine--
+        * probably faster to just assign than check and maybe assign.
+        * If second wasn't stronger, go with whatever the first was. */
+
+       /* If one is normal, one small, override the small */
+       if (extra_p->notesize == GS_NORMAL) {
+               note_p->notesize = GS_NORMAL;
+       }
+
+       /* If either has a tie, do a tie */
+       if (extra_p->tie == YES) {
+               note_p->tie = YES;
+       }
+       /* Consider normal tie the strongest, then dashed, then dotted */
+       if (extra_p->tiestyle == L_NORMAL) {
+               note_p->tiestyle = L_NORMAL;
+       }
+       else if (extra_p->tiestyle == L_DASHED &&
+                       note_p->tiestyle != L_NORMAL) {
+               note_p->tiestyle = L_DASHED;
+       }
+       if ( (extra_p->tiedir == UP && note_p->tiedir == DOWN) ||
+                       (extra_p->tiedir == DOWN && note_p->tiedir == UP)) {
+               /* It would be nice to allow both up and down tie,
+                * especially since we can do that for slurs,
+                * but we only support one tie per note. */
+               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                       "duplicate notes with opposite tie direction not allowed");
+       }
+       else if (extra_p->tiedir != UNKNOWN) {
+               note_p->tiedir = extra_p->tiedir;
+       }
+
+
+       /* Parentheses around an accidental means "just in case you forgot..."
+        * which is weaker than no parentheses, so only use parentheses if
+        * both have it. */
+       if (extra_p->acc_has_paren == NO) {
+               note_p->acc_has_paren = NO;
+       }
+       /* Parentheses around a note generally means the note is optional.
+        * An optional merged with a non-optional, is non-optional. */
+       if (extra_p->note_has_paren == NO) {
+               note_p->note_has_paren = NO;
+       }
+
+       /* Sorry, we don't deal with incompatible bends */
+       if (note_p->is_bend != extra_p->is_bend ||
+                       extra_p->smallbend != note_p->smallbend) {
+               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                       "duplicate notes with bend mismatch not allowed");
+       }
+
+       /* Slurs... If duplicate between the two slurto lists, just leave
+        * the one, but use strongest slurstyle. If there is one in the
+        * NOTE to be deleted but not in the one to keep, move it. */
+       for (sn1 = 0; sn1 < extra_p->nslurto; sn1++) {
+               for (sn = 0; sn < note_p->nslurto; sn++) {
+                       if (note_p->slurtolist[sn].letter ==
+                                       extra_p->slurtolist[sn1].letter &&
+                                       note_p->slurtolist[sn].slurdir ==
+                                       extra_p->slurtolist[sn1].slurdir &&
+                                       note_p->slurtolist[sn].octave ==
+                                       extra_p->slurtolist[sn1].octave) {
+                               /* duplicate; just fix style if necessary */
+                               if (extra_p->slurtolist[sn1].slurstyle
+                                                               == L_NORMAL) {
+                                       note_p->slurtolist[sn].slurstyle
+                                                       = L_NORMAL;
+                               }
+                               else if (extra_p->slurtolist[sn1].slurstyle
+                                               == L_DASHED &&
+                                               note_p->slurtolist[sn].slurstyle
+                                               != L_NORMAL) {
+                                       note_p->slurtolist[sn].slurstyle
+                                                       = L_DASHED;
+                               }
+                               break;
+                       }
+               }
+               if (sn == note_p->nslurto) {
+                       /* wasn't on the list to keep, so add it */
+                       add_slurto(gs_p, extra_p->slurtolist[sn1].letter,
+                                       extra_p->slurtolist[sn1].octave,
+                                       sn,
+                                       extra_p->slurtolist[sn1].slurstyle);
+               }
+       }
+
+       /* Move things down in the notelist to remove the extra */
+       for (i = n + 1; i < gs_p->nnotes - 1; i++) {
+               gs_p->notelist[i] = gs_p->notelist[i+1];
+       }
+       (gs_p->nnotes)--;
+       REALLOC(NOTE, gs_p->notelist, gs_p->nnotes);
+}
+\f
+
+/* print error message for multiply defined voice */
+
+static void
+mult_def(staff, voice)
+
+int staff;
+int voice;
+
+{
+       l_yyerror(Curr_filename, yylineno,
+               "staff %d voice %d multiply defined (first defined on line %d)",
+               staff, voice,
+               Staffmap_p[staff]->u.staff_p->groups_p[voice-1]->inputlineno);
+}
diff --git a/mup/mup/midi.c b/mup/mup/midi.c
new file mode 100644 (file)
index 0000000..a425c37
--- /dev/null
@@ -0,0 +1,2804 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* generate a MIDI file from the Mup internal representation */
+
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef __WATCOMC__
+#include <io.h>
+#endif
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+/* Minimum and maximum number of quarter notes per minute.
+ * This should be ridiculously wide enough range and
+ * also prevents division by zero when calculating microsecs per quarter */
+#define MINQNPM                (10)
+#define MAXQNPM                (1000)
+
+/* Default value for microseconds per quarter note */
+#define DFLT_USEC_PER_QUARTER  (500000L)
+
+#define USEC_PER_MINUTE                (60L * 1000000)
+
+/* it is possible to get a legitimate rational overflow, and we don't really
+ * care about absolutely precise time, so when a rational gets bigger than
+ * MAXMIDI_RAT, throw away the lower bits and reduce */
+#define MAXMIDI_RAT    1000000L
+/* delta can get multiplied by MIDI_FACTOR. Need to make sure it can
+ * never overflow a signed long, or bad things can happen,
+ * so need smaller limit. */
+#define MAXDELTA_RAT   300000L
+
+/* This marks that we don't have to defer a sharp/flat. We have to defer
+ * them if a note is tied over a barline. The value has to be something
+ * outside the normal accidental range of -2 (double flat) to +2 (double sharp)
+ */
+#define NO_DEFERRED_ACC        (-100)
+
+/* save information about stuff for the current measure so that it can
+ * be applied at the proper time. */
+struct MIDISTUFF {
+       RATIONAL        time;           /* when to do the MIDI event */
+       struct STUFF    *stuff_p;       /* STUFF to do */
+       struct MIDISTUFF *next;         /* linked list */
+};
+
+/* if a roll spans multiple groups, save information about the other
+ * groups. The reason for saving it around rather than just walking down the
+ * gs_p chord list is that if the added groups have to go at the very
+ * beginning of the measure, the only way to find where to link them is to
+ * go back to the main list and search for the appropriate STAFF and follow
+ * one of the groups_p lists. Since we'll get around to visiting that STAFF
+ * eventually anyway, just save the info and do it when we get there. */
+struct MIDIROLL {
+       struct GRPSYL   *gs_p;          /* group roll applies to */
+       short           notesbefore;    /* how many notes duration of rest
+                                        * to add before this group's portion
+                                        * of the roll */
+       RATIONAL        duration;       /* duration of each note in roll */
+       struct MIDIROLL *link_p;        /* linked list  */
+};
+
+/* stuff is in floating point, but we keep track of time in RATIONAL. So
+ * when we need to convert, put in terms of 1/F2RFACTOR of a count */
+#define F2RFACTOR      ((UINT32B)(192L * 256L))
+
+/* Number of ticks in a whole note */
+#define MIDI_FACTOR    ((UINT32B)(4L * Division))
+
+/* default note on velocity */
+#define DFLT_VELOCITY  (64)
+
+/* the MIDI STUFF info for current measure/voice */
+static struct MIDISTUFF *Midistufflist_p;
+
+/* list of pending rolls to do */
+static struct MIDIROLL *Midirollinfo_p;
+
+/* tables for mapping voices to tracks and vice versa */
+static short Voice2track_map [MAXSTAFFS + 1] [MAXVOICES];
+static short Track2staff_map [MAXSTAFFS * MAXVOICES];
+static short Track2voice_map [MAXSTAFFS * MAXVOICES];
+
+static short Accidental_map[128];/* if a note has an implied accidental, either
+                                * due to the key signature or an accidental
+                                * earlier in the measure, this table tells
+                                * how to adjust the note. For example, if
+                                * we have a C, but are in the key of D, the
+                                * table entry for C would have a 1 to say to
+                                * add 1 because it should really be a C# */
+static short Deferred_acc[128];        /* If set to something other than
+                                * NO_DEFERRED_ACC, then once the current
+                                * tie on this note ends, we need to set the
+                                * Accidental_map entry to this value. */
+static short Tie_table[128];   /* YES if note number has a tie on it */
+
+/* keep track of all time to an absolute reference so that all tracks stay
+ * in sync, even though midi times are stored as delta times */
+static RATIONAL Absolute_time;
+static RATIONAL Sum_of_deltas;
+
+static int Status;     /* 0 if haven't yet written first MIDI status byte
+                        * for current track. Otherwise is the current MIDI
+                        * status byte. */
+
+static short Channel = 0;      /* MIDI channel, 0-15 */
+static char Onvelocity[MAXHAND];       /* note on velocity */
+static char Offvelocity[MAXHAND];      /* note off velocity */
+static short Time_specified_by_user = NO;      /* YES if user had a score SSV
+                                * setting the time before any music data */
+static short Key_specified_by_user = NO;       /* YES if user had a score SSV
+                                * setting the key before any music data */
+static int Division = DEFDIVISION;     /* clock ticks per quarter note */
+
+static UINT32B Usec_per_quarter_note = DFLT_USEC_PER_QUARTER;
+
+static short Pedbounce = NO;   /* if pedal bounce pending */
+
+/* local functions */
+static void repeats P((struct MAINLL **mll_p_p, int *doing_repeat_p,
+               struct MAINLL **repeat_start_p_p));
+static RATIONAL eff_meas_time P((struct MAINLL *mll_p));
+static void midi_header P((int mfile, int ntracks));
+static void track_header P((int mfile));
+static UINT32B write_midi_data P((int mfile, struct GRPSYL *gs_p));
+static void init_accidental_map P((int staffno));
+static void mark_accidental P((int pitch_offset, int acc));
+static UINT32B midi_multirest P((int mfile, struct STAFF *staff_p, int staffno,
+               int vno, int nummeas));
+static void init_tie_table P((void));
+static int xlate_note P((struct NOTE *note_p, char *fname, int lineno,
+               int *raw_notenum_p));
+static void prepmidi_stuff P((struct STAFF *staff_p, int vno, int all));
+static UINT32B do_midi_stuff P((RATIONAL timeval, int mfile, int all));
+static UINT32B midihex P((int mfile, char *str, char *fname, int lineno));
+static UINT32B midi_item P((struct STUFF *stuff_p, int mfile, int all));
+static UINT32B wr_meta P((int mfile, int evtype, char *str));
+static UINT32B all_midi P((int mfile));
+static void midi_adjust P((void));
+static void adjust_notes P((struct GRPSYL *gs_p, int staffno, int v,
+               struct MAINLL *mll_p));
+static void add_release P((struct GRPSYL *gs_p, RATIONAL release_adjust,
+               struct MAINLL *mll_p));
+static UINT32B pedswitch P((int nfile, int on));
+static void midi_roll P((struct GRPSYL *gs_p, struct GRPSYL **gslist_p_p));
+static RATIONAL roll_time P((RATIONAL grptime, int nnotes));
+static void do_mroll P((struct GRPSYL *gs_p, struct GRPSYL **gslist_p_p,
+               RATIONAL rolltime, int notesbefore));
+static void addrollgrp P((struct GRPSYL *gs_p, RATIONAL duration, int start,
+               int end, struct GRPSYL **link_p_p, struct GRPSYL *prev_p));
+static void savemidiroll P((struct GRPSYL *gs_p, int notesbefore,
+               RATIONAL duration));
+static struct MIDIROLL *getmidiroll P((struct GRPSYL *gs_p));
+static void fix_tempo P((int to_end));
+static void free_midistuff P((struct MIDISTUFF *ms_p));
+static void adj4squeeze P((RATIONAL timeval));
+\f
+
+/* generate a MIDI file. Assigns each staff/voice combo to a MIDI track.
+ * Write MIDI file header and first track with tempo, etc info. Then for
+ * each staff/voice, generate a MIDI track with all note on/off and
+ * whatever STUFF we know how to deal with. */
+
+void
+gen_midi(midifilename)
+
+char *midifilename;            /* put MIDI data in this file */
+
+{
+       struct MAINLL *mll_p;   /* to index through main list */
+       int i;
+       int track = 0;
+       int staff;
+       int vno;                /* voice index */
+       int mfile;              /* file descriptor for MIDI output file */
+       UINT32B track_size;     /* bytes in track */
+       UINT32B track_start;    /* offset in file where track begins */
+       int t;                  /* track index */
+       int doing_repeat;       /* YES or NO */
+       int got_data;           /* YES or NO, to deal with case where the
+                                * number of staffs/voices changes mid-stream */
+       struct MAINLL *repeat_start_p;  /* pointer to first measure of a
+                                        * repeated section, so we know where to
+                                        * jump back to when we hit the end of
+                                        * the repeat. */
+       struct STAFF *staff_p;  /* need to refer to STAFF a lot, so keep a
+                                * pointer to it. */
+       struct STAFF *last_staff_p = (struct STAFF *) 0;/* in case measure
+                                * was invisible or something,
+                                * this points to the most recent
+                                * staff for current loop */
+       struct GRPSYL *g_p;
+       int first;              /* YES/NO if processing first meas */
+
+
+       debug(256, "gen_midi");
+
+       /* first go through main list, and find out which staff/voice pairs
+        * are used, and assign each to a track. */
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
+                                       mll_p = mll_p->next) {
+
+               if (mll_p->str == S_STAFF) {
+                       staff = mll_p->u.staff_p->staffno;
+
+                       /* ignore tab staffs -- we use the notes on the
+                        * associated tabnote staff above it instead */
+                       if (is_tab_staff(staff) == YES) {
+                               continue;
+                       }
+
+                       for (vno = 0; vno < MAXVOICES; vno++) {
+
+                               if (mll_p->u.staff_p->groups_p[vno] ==
+                                               (struct GRPSYL *) 0) {
+                                       continue;
+                               }
+
+                               if (Voice2track_map [staff] [vno] == 0) {
+                                       /* haven't allocated this staffno/vno to
+                                        * a track yet, so do so now. */
+                                       Track2staff_map [track] = (short) staff;
+                                       Track2voice_map [track] = (short) vno;
+                                       Voice2track_map [staff] [vno] = ++track;
+                                       debug(512, "assigned staff %d voice %d to track %d",
+                                                       staff, vno + 1, track);
+                               }
+                       }
+               }
+       }
+
+       if (track == 0) {
+               ufatal("no note data found");
+       }
+
+       /* open the specified MIDI file */
+#ifdef O_BINARY
+       if ((mfile = open(midifilename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666))
+#else
+       if ((mfile = open(midifilename, O_WRONLY | O_CREAT | O_TRUNC, 0666))
+#endif
+                                                                       < 0) {
+               ufatal("can't open MIDI file '%s'", midifilename);
+       }
+
+       /* adjust grace notes to get a little time, etc */
+       midi_adjust();
+
+       /* squeeze out any all-space chords */
+       midi_squeeze();
+
+       /* the default Guitar tablature staff notes get transposed an octave,
+        * so do that if appropriate */
+       guitar_transpose();
+
+       /* generate MIDI file header */
+       initstructs();
+       Usec_per_quarter_note = DFLT_USEC_PER_QUARTER;
+       midi_header(mfile, track);
+
+       /* go through  the main list once for each staff/voice, generating a
+        * MIDI track for it. */
+       for (t = 0; t < track; t++)  {
+
+               /* initialize everything for this track */
+               initstructs();
+               init_tie_table();
+               track_start = lseek(mfile, 0L, SEEK_CUR);
+               track_header(mfile);
+               staff = Track2staff_map[t];
+               vno = Track2voice_map[t];
+               track_size = 0;
+               doing_repeat = NO;
+               repeat_start_p = Mainllhc_p;
+               got_data = NO;
+               Octave_adjust[staff] = 0;
+               Octave_bars[staff] = 0;
+               Octave_count[staff] = 0.0;
+               Channel = 0;
+               first = YES;
+               for (i = 0; i < MAXHAND; i++) {
+                       Onvelocity[i] = (char) DFLT_VELOCITY;
+                       Offvelocity[i] = (char) 0;
+               }
+
+               /* go through main list */
+               for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->next) {
+
+                       switch (mll_p->str) {
+
+                       case S_STAFF:
+                               /* There may be an implicit repeatstart at
+                                * the beginning of the piece, so we need
+                                * to save the current SSV state, in case
+                                * the user repeats back to this implicit
+                                * repeatstart. */
+                               if (first == YES) {
+                                       repeat_start_p = mll_p;
+                                       first = NO;
+                               }
+
+                               staff_p = mll_p->u.staff_p;
+                               /* check if this is for the staff we are
+                                * currently generating midi data for */
+                               if (staff_p->staffno == staff
+                                               && staff_p->groups_p[vno]
+                                               != (struct GRPSYL *) 0) {
+
+                                       /* treat invisible staffs as
+                                        * inaudible as well */
+                                       if (svpath(staff, VISIBLE) ->visible
+                                                               == NO) {
+                                               /* if next staff is a tab staff,
+                                                * and it is visible, then we
+                                                * want this staff to still be
+                                                * audible, otherwise skip */
+                                               if (staff >= Score.staffs ||
+                                                       ! is_tab_staff(staff+1)
+                                                       || svpath(staff+1, VISIBLE)->visible == NO) {
+                                                   /* convert notes to rests.
+                                                    * Can't just ignore,
+                                                    * because if we do, space
+                                                    * that has been squeezed
+                                                    * out isn't handled right,
+                                                    * and tracks can get out of
+                                                    * sync with each other */
+                                                   for (g_p = staff_p->groups_p[vno];
+                                                   g_p != (struct GRPSYL *) 0;
+                                                   g_p = g_p->next) {
+                                                       if (g_p->nnotes > 0) {
+                                                               g_p->grpcont
+                                                               = GC_REST;
+                                                       }
+                                                   }
+                                               }
+                                       }
+
+                                       /* found information for the track/voice
+                                        * we are currently generating */
+                                       got_data = YES;
+
+                                       /* check for multi-rest */
+                                       if (staff_p->groups_p[vno]->basictime
+                                                                       < -1) {
+                                               track_size += midi_multirest
+                                                       (mfile, staff_p,
+                                                       staff, vno,
+                                                       -(staff_p->groups_p[vno]
+                                                       ->basictime) );
+                                               break;
+                                       }
+
+                                       /* generate MIDI data */
+                                       /* Handle octave marks, but only first
+                                        * time through a repeat, or it will
+                                        * get transposed twice! */
+                                       if (doing_repeat == NO) {
+                                               octave_transpose(staff_p, mll_p,
+                                                               vno, YES);
+                                       }
+                                       init_accidental_map(staff);
+                                       prepmidi_stuff(staff_p, vno, NO);
+                                       track_size += write_midi_data(mfile,
+                                               staff_p->groups_p[vno]);
+                               }
+                               else if (staff_p->staffno == staff) {
+                                       /* Voice doesn't exist in this meas,
+                                        * so just keep track of the staff
+                                        * so when we hit the bar we can
+                                        * add the silence, and update any
+                                        * midi parameters and such. */
+                                       last_staff_p = staff_p;
+                               }
+                               break;
+
+                       case S_SSV:
+                               asgnssv(mll_p->u.ssv_p);
+
+                               /* update key signature for this track
+                                * if necessary. Note that score-wide
+                                * key signature changes will be written
+                                * out via all_midi(). */
+                               if (mll_p->u.ssv_p->context == C_STAFF &&
+                                               mll_p->u.ssv_p->staffno
+                                               == staff &&
+                                               (mll_p->u.ssv_p->used[SHARPS]
+                                               == YES ||
+                                               mll_p->u.ssv_p->used[TRANSPOSITION]
+                                               == YES ||
+                                               mll_p->u.ssv_p->used[ADDTRANSPOSITION]
+                                               == YES) ) {
+                                       track_size += midi_keysig(mfile,
+                                               eff_key(mll_p->u.ssv_p->staffno),
+                                               mll_p->u.ssv_p->is_minor);
+                               }
+                               break;
+
+                       case S_BAR:
+                               /* if this voice is defined somewhere in the
+                                * song, but not in this measure, need to add
+                                * virtual measure of rest. (This could happen
+                                * if user changed the number of staffs
+                                * and/or voices in mid-stream */
+                               if (got_data == NO && mll_p->inputlineno != -1) {
+                                       /* Arrange to do any midi things
+                                        * for this voice, even though it
+                                        * doesn't exist at the moment. */
+                                       if (last_staff_p != (struct STAFF *) 0) {
+                                               prepmidi_stuff(last_staff_p,
+                                                               vno, NO);
+                                       }
+                                       /* This will update the current
+                                        * absolute time to include the
+                                        * effective time for this measure. */
+                                       track_size += do_midi_stuff(
+                                                       eff_meas_time(mll_p),
+                                                       mfile, NO);
+                                       last_staff_p = (struct STAFF *) 0;
+                               }
+                               else {
+                                       got_data = NO;
+                               }
+
+                               /* handle repeats */
+                               repeats(&mll_p, &doing_repeat, &repeat_start_p);
+
+                               break;
+
+                       default:
+                               break;
+                       }
+
+                       if (mll_p == (struct MAINLL *) 0) {
+                               /* shouldn't happen, but repeats() can change
+                                * mll_p, and if it ever became null, we'd
+                                * try to take the ->next of it, which isn't
+                                * good, so take precautions */
+                               break;
+                       }
+               }
+
+               /* add end of track mark */
+               track_size += write(mfile, "\0\377/\0", 4);
+
+               /* now that we know the track size, fill it in */
+               fix_track_size(mfile, track_start, track_size);
+       }
+
+       (void) close(mfile);
+}
+\f
+
+/* given a bar, handle repeats at that bar line. First time we hit the end
+ * of a repeated section, go back to its beginning. Handles the case where
+ * the repeat end is at the end of an ending. */
+
+static void
+repeats (mll_p_p, doing_repeat_p, repeat_start_p_p)
+
+struct MAINLL **mll_p_p;       /* points to a BAR */
+int *doing_repeat_p;           /* return YES or NO via this pointer to
+                                * indicate whether now doing a repeat */
+struct MAINLL **repeat_start_p_p;      /* indicates where repeated section
+                                * begins. May be updated by this function if
+                                * we hit a repeat sign */
+
+{
+       struct MAINLL *m_p;
+
+       /* handle endings (simple case only). If we
+        * hit the beginning of an ending while doing second time through
+        * a repeated section, assume we should jump to the end
+        * of the repeat */
+       if ((*mll_p_p)->u.bar_p->endingloc == STARTITEM
+                                               && *doing_repeat_p == YES) {
+
+               for (*mll_p_p = (*mll_p_p)->next;
+                           *mll_p_p != (struct MAINLL *)0;
+                           *mll_p_p = (*mll_p_p)->next) {
+
+                       if ((*mll_p_p)->str == S_BAR &&
+                               ((*mll_p_p)->u.bar_p->bartype == REPEATEND ||
+                               (*mll_p_p)->u.bar_p->bartype == REPEATBOTH)) {
+                           break;
+                       }
+               }
+               *doing_repeat_p = NO;
+               *repeat_start_p_p = *mll_p_p;
+               return;
+       }
+
+
+       /* handle repeats. At beginning of a repeat,
+        * remember where it is. At end, if first time
+        * through, jump back. */
+       switch ((*mll_p_p)->u.bar_p->bartype) {
+
+       case REPEATSTART:
+               /* remember where repeat begins */
+               *repeat_start_p_p = *mll_p_p;
+               break;
+
+       case REPEATEND:
+       case REPEATBOTH:
+               if (*doing_repeat_p == YES) {
+                       /* 2nd time through */
+                       *doing_repeat_p = NO;
+                       *repeat_start_p_p = *mll_p_p;
+               }
+               else {
+                       /* first time through */
+                       *doing_repeat_p = YES;
+                       *mll_p_p = *repeat_start_p_p;
+                       /* set the SSV's back to what they were at the
+                        * beginning of the repeat. */
+                       initstructs();
+                       for (m_p = Mainllhc_p; m_p != *repeat_start_p_p;
+                                                       m_p = m_p->next) {
+                               if (m_p->str == S_SSV) {
+                                       asgnssv(m_p->u.ssv_p);
+                               }
+                       }
+               }
+               break;
+
+       default:
+               break;
+       }
+}
+\f
+
+/* Find the "effective" duration of a measure. Because of squeezing of
+ * space chords, a measure may be shorter than the time signature.
+ * Given a spot in the main list, this finds the first visible voice
+ * at or above that place, and counts up the time of the GRPSYLS in it,
+ * ignoring squeezed-out spaces.
+ */
+
+static RATIONAL
+eff_meas_time(mll_p)
+
+struct MAINLL *mll_p;
+
+{
+       RATIONAL eff_time;      /* calculated value to return */
+       struct GRPSYL *g_p;     /* to loop through groups */
+       int v = 0;              /* voice index. Initialization is just
+                                * to avoid bogus "used before set"
+                                 */
+
+       /* find top visible voice */
+       for (   ; mll_p != 0; mll_p = mll_p->prev) {
+               if (mll_p->str == S_STAFF && svpath(mll_p->u.staff_p->staffno,
+                                       VISIBLE)->visible == YES) {
+                       for (v = 0; v < MAXVOICES; v++) {
+                               if (vvpath(mll_p->u.staff_p->staffno, v+1,
+                                               VISIBLE)->visible == YES) {
+                                       break;
+                               }
+                       }
+                       if (v < MAXVOICES) {
+                               break;
+                       }
+               }
+       }
+       if (mll_p == 0) {
+               pfatal("eff_meas_time couldn't find a visible voice");
+       }
+
+       /* All up the time in this voice */
+       eff_time = Zero;
+       for (g_p = mll_p->u.staff_p->groups_p[v]; g_p != 0; g_p = g_p->next) {
+               if (g_p->grpvalue == GV_ZERO && g_p->grpcont == GC_SPACE) {
+                       /* squeezed out space, so doesn't count */
+                       continue;
+               }
+               eff_time = radd(eff_time, g_p->fulltime);
+       }
+       return(eff_time);
+}
+\f
+
+/* write MIDI header to file */
+
+static void 
+midi_header(mfile, ntracks)
+
+int mfile;     /* file descriptor to write to */
+int ntracks;   /* how many tracks are to be written */
+
+{
+       unsigned char buff[8];
+       UINT32B track1start;
+       UINT32B trklength;
+
+
+       debug(512, "midi_header");
+
+       trklength = write(mfile, "MThd\0\0\0\6\0", 9);
+
+       /* always use format 1 */
+       buff[0] = 1;
+
+       /* 2 bytes for number of tracks */
+       /* add 1 for the track giving time signature, etc */
+       buff[1] = (unsigned char) (ntracks + 1) >> 8;
+       buff[2] = (unsigned char) (ntracks + 1) & 0xff;
+
+       /* division field. */
+       buff[3] = (unsigned char) (Division >> 8);
+       buff[4] = (unsigned char) (Division & 0xff);
+       (void) write(mfile, buff, 5);
+
+       /* now do first track, which gives time and key signature info */
+       track1start = lseek(mfile, 0L, SEEK_CUR);
+       track_header(mfile);
+       trklength = 0;
+
+       /* if there is a header and the first item to print is centered,
+        * it's probably a title, so do it as a text event. */
+       if (Header.printdata_p != (struct PRINTDATA *) 0) {
+               if (Header.printdata_p->justifytype == J_CENTER &&
+                               Header.printdata_p->string != (char *) 0) {
+                       trklength += write_delta(mfile);
+                       buff[0] = 0xff;
+                       buff[1] = 0x01;
+                       trklength += write(mfile, buff, 2);
+                       trklength += midi_wrstring(mfile,
+                                       Header.printdata_p->string, YES);
+               }
+       }
+       /* do default time signature if necessary */
+       if (Time_specified_by_user == NO) {
+               trklength += midi_timesig(mfile);
+       }
+
+       /* do default key signature if necessary */
+       if (Key_specified_by_user == NO) {
+               trklength += midi_keysig(mfile, eff_key(0), Score.is_minor);
+       }
+
+       /* output usecs per quarter note */
+       trklength += write(mfile, "\0\377Q\3", 4);
+       buff[0] = (Usec_per_quarter_note >> 16) & 0xff;
+       buff[1] = (Usec_per_quarter_note >> 8) & 0xff;
+       buff[2] = Usec_per_quarter_note & 0xff;
+       trklength += write(mfile, buff, 3);
+
+       /* do everything else for track 1 */
+       trklength += all_midi(mfile);
+
+       /* end of track marker */
+       trklength += write(mfile, "\0\377/\0", 4);
+       fix_track_size(mfile, track1start, trklength);
+}
+\f
+
+/* write a MIDI track header */
+
+static void
+track_header(mfile)
+
+int mfile;     /* write track header to this file descriptor */
+
+{
+       debug(512, "track_header");
+
+       (void) write(mfile, "MTrk\0\0\0\0", 8);
+
+       /* reset time reference */
+       Absolute_time = Sum_of_deltas = Zero;
+
+       /* reset "running status" */
+       Status = 0;
+}
+\f
+
+/* write MIDI info. Return number of bytes written to mfile */
+
+static UINT32B
+write_midi_data(mfile, gs_p)
+
+int mfile;             /* write MIDI data to this file descriptor */
+struct GRPSYL *gs_p;   /* write info about these chords */
+
+{
+       UINT32B bytes = 0;      /* number of bytes written */
+       int n;                  /* walk through notes of chord */
+       unsigned char buff[4];  /* temp storage for MIDI data */
+       int notenum;            /* MIDI note number 0-127 */
+       int raw_notenum;        /* note numer not counting accidentals */
+       short newstatus;        /* running status */
+
+
+       /* go through each GRPSYL in the measure */
+       for (  ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+
+               /* do any MIDI stuffs that happen right on this beat. They
+                * should happen after notes have been turned off for previous
+                * chord but before the notes for the following chord */
+               bytes += do_midi_stuff(Zero, mfile, NO);
+
+               /* if rest or space, just keep track of time used. */
+               if ( gs_p->grpcont != GC_NOTES) {
+                       /* special case of all-space chord. It gets no time.
+                        * Just adjust pending MIDI events so they happen
+                        * at the right time */
+                       if (gs_p->grpcont == GC_SPACE && gs_p->grpvalue == GV_ZERO) {
+                               adj4squeeze(gs_p->fulltime);
+                               bytes += do_midi_stuff(Zero, mfile, NO);
+                       }
+                       else {
+                               bytes += do_midi_stuff(gs_p->fulltime, mfile, NO);
+                       }
+                       continue;
+               }
+
+               /* turn on each note in chord */
+               for (n = 0; n < gs_p->nnotes; n++) {
+
+                       notenum = xlate_note( &(gs_p->notelist[n]),
+                                       gs_p->inputfile, gs_p->inputlineno,
+                                       &raw_notenum);
+
+                       /* if this note is tied from previous, it is already
+                        * turned on, so just mark off that we've done the tie.
+                        */
+                       if (Tie_table[raw_notenum] == YES) {
+                               Tie_table[raw_notenum] = NO;
+                       }
+
+                       else {
+                               /* not tied from previous, so turn note on */
+                               bytes += write_delta(mfile);
+       
+                               /* first time through have to put the status.
+                                * After that we can use running status */
+                               newstatus = (0x90 | Channel) & 0xff;
+                               if (Status != newstatus) {
+                                       buff[0] = (unsigned char) newstatus;
+                                       (void) write(mfile, buff, 1);
+                                       Status = newstatus;
+                                       bytes++;
+                               }
+
+                               buff[0] = (unsigned char) notenum;
+                               buff[1] = (unsigned char) Onvelocity[n];
+                               (void) write(mfile, buff, 2);
+                               bytes += 2;
+                       }
+               }
+               
+               bytes += do_midi_stuff(gs_p->fulltime, mfile, NO);
+
+               /* now turn all the notes off, unless tied */
+               for (n = 0; n < gs_p->nnotes; n++) {
+
+                       notenum = xlate_note( &(gs_p->notelist[n]),
+                               gs_p->inputfile, gs_p->inputlineno,
+                               &raw_notenum);
+
+                       /* if this note is tied to next, mark that */
+                       if ( (gs_p->notelist[n].tie == YES) ||
+                                               (gs_p->tie == YES) ) {
+                               Tie_table[raw_notenum] = YES;
+                       }
+                       else {
+                               /* not tied to next, so turn off */
+                               bytes += write_delta(mfile);
+
+                               /* use note on with onvelocity 0 (which means
+                                * note off), unless user explicitly set an
+                                * off velocity */
+                               if (Offvelocity[n] != 0) {
+                                       newstatus = (0x80 | Channel) & 0xff;
+                               }
+                               else {
+                                       newstatus = (0x90 | Channel) & 0xff;
+                               }
+                               if (Status != newstatus) {
+                                       buff[0] = (unsigned char) newstatus;
+                                       (void) write(mfile, buff, 1);
+                                       Status = newstatus;
+                                       bytes++;
+                               }
+                               buff[0] = (unsigned char) notenum;
+                               buff[1] = (unsigned char) Offvelocity[n];
+                               (void) write(mfile, buff, 2);
+                               bytes += 2;
+
+                               /* If we had to defer the setting of
+                                * sharps/flats because of a tie into the
+                                * measure, do that now. */
+                               if (Deferred_acc[raw_notenum] != NO_DEFERRED_ACC) {
+                                       Accidental_map[raw_notenum] =
+                                               Deferred_acc[raw_notenum];
+                                       Deferred_acc[raw_notenum] = NO_DEFERRED_ACC;
+                               }
+                       }
+               }
+       }
+
+       /* do any midi events that happen at the end of the measure after
+        * the notes. */
+       bytes += do_midi_stuff(Zero, mfile, NO);
+
+       return(bytes);
+}
+\f
+
+/* write out delta value. Return number of bytes written */
+
+UINT32B
+write_delta(mfile)
+
+int mfile;     /* file descriptor of MIDI file */
+
+{
+       UINT32B idelta;         /* delta rounded to 32-bit integer */
+       RATIONAL delta;
+       RATIONAL rounded;       /* idelta converted back to RATIONAL */
+
+
+       /* avoid rational overflow, which can happen under certain
+        * circumstances with lots of grace, rolls, etc */
+       while (Absolute_time.n > MAXMIDI_RAT
+                               || Absolute_time.d > MAXMIDI_RAT) {
+               /* avoid rational divide by zero */
+               if (Absolute_time.d > 1) {
+                       Absolute_time.n >>= 1;
+                       Absolute_time.d >>= 1;
+                       rred ( &Absolute_time );
+               }
+               else {
+                       break;
+               }
+       }
+       while( Sum_of_deltas.n > MAXMIDI_RAT
+                               || Sum_of_deltas.d > MAXMIDI_RAT) {
+               if (Sum_of_deltas.d > 1) {
+                       Sum_of_deltas.n >>= 1;
+                       Sum_of_deltas.d >>= 1;
+                       rred ( &Sum_of_deltas );
+               }
+               else {
+                       break;
+               }
+       }
+
+       delta = rsub(Absolute_time, Sum_of_deltas);
+       if (LT(delta, Zero)) {
+               delta = Zero;
+       }
+
+       /* Multiply by factor to get delta value in MIDI clock ticks,
+        * then round off to UINT32B. Entire calculation must be done
+        * in floating point, then cast to UINT32B, otherwise overflow
+        * can occur, which really messes things up!! */
+       idelta = (UINT32B)((((double) MIDI_FACTOR * (double) delta.n)
+                                               / (double) delta.d) + 0.5);
+
+       /* now convert the rounded-off value back to a RATIONAL,
+        * and add it to the Sum_of_deltas, so we'll know exactly how far
+        * off we are the next time around and can compensate. */
+       rounded.n = idelta;
+       rounded.d = MIDI_FACTOR;
+       rred(&rounded);
+       /* certain combinations of division value, release values, and
+        * input could cause rounded to overflow and become negative.
+        * Because of all the other code added to try to avoid overflow,
+        * this should be extremely unlikely, but it's better to catch
+        * it and give an error than leave the user to wonder why the
+        * generated MIDI file says to hold a note for several days. */
+       if (LT(rounded, Zero)) {
+               pfatal("arithmetic overflow on MIDI delta calculation, input probably too complex\n  (hint: changing the 'release' parameter might help)");
+       }
+
+       Sum_of_deltas = radd(Sum_of_deltas, rounded);
+
+       return(wr_varlength(mfile, idelta));
+}
+\f
+
+/* given a NOTE, return the corresponding MIDI note number */
+
+static int
+xlate_note(note_p, fname, lineno, raw_notenum_p)
+
+struct NOTE *note_p;
+char *fname;   /* input file */
+int lineno;    /* input line number */
+int *raw_notenum_p;    /* return the note number without accidentals */
+
+{
+       int val;
+
+       switch (note_p->letter) {
+       case 'a':
+               val = 9;
+               break;
+       case 'b':
+               val = 11;
+               break;
+       case 'c':
+               val = 0;
+               break;
+       case 'd':
+               val = 2;
+               break;
+       case 'e':
+               val = 4;
+               break;
+       case 'f':
+               val = 5;
+               break;
+       case 'g':
+               val = 7;
+               break;
+       default:
+               pfatal("invalid note\n");
+               /*NOTREACHED*/
+               return(0);
+       }
+
+       /* adjust for octave */
+       val += 12 * (note_p->octave + 1);
+
+       /* If user overlaps octave marks inside a measure, which we don't
+        * catch, or if they transpose a note so many octaves that it is out
+        * of range (like transposing something down when it's already in
+        * octave 0) a note could end up out of range, so catch that here. */
+       if (note_p->octave < MINOCTAVE || note_p->octave > MAXOCTAVE ||
+                               val < 0 || val > 127) {
+               l_ufatal(fname, lineno, "note is out of range");
+       }
+
+
+       /* return the value not considering accidentals. This is needed to
+        * keep track of ties properly. */
+       *raw_notenum_p = val;
+
+       switch (note_p->accidental) {
+       case '#':
+               Accidental_map[val] = 1;
+               break;
+       case '&':
+               Accidental_map[val] = -1;
+               break;
+       case 'x':
+               Accidental_map[val] = 2;
+               break;
+       case 'B':
+               Accidental_map[val] = -2;
+               break;
+       case 'n':
+               Accidental_map[val] = 0;
+               break;
+       case '\0':
+               /* leave note as is */
+               break;
+       default:
+               pfatal("unknown accidental type '%c'", note_p->accidental);
+               break;
+       }
+
+       /* the top few notes in octave 9 are outside midi range */
+       if (val + Accidental_map[val] > 127) {
+               l_ufatal(fname, lineno, "note out of range");
+       }
+       return (val + Accidental_map[val]);
+}
+\f
+
+/* initialize map of accidentals, based on key signature. */
+
+static void
+init_accidental_map(staffno)
+
+int staffno;
+
+{
+       register int n;
+
+       /* first clear the map for all MIDI notes */
+       for (n = 0; n < 128; n++) {
+               /* If a note with any sort of accidental on it is currently
+                * tied, then we don't clear that note's accidental map,
+                * but mark that we will need to set the key signature
+                * value later, after the tie ends. Otherwise we set it
+                * immediately. */
+               if (Tie_table[n] == YES) {
+                       /* set to zero for now. Will set to something else
+                        * in mark_accidental later if appropriate. */
+                       Deferred_acc[n] = 0;
+               }
+               else {
+                       Accidental_map[n] = 0;
+                       Deferred_acc[n] = NO_DEFERRED_ACC;
+               }
+       }
+
+       /* now fill in the key signature items in all octaves */
+       switch (eff_key(staffno) ) {
+       case 7:
+               /* B# */
+               mark_accidental(11, 1);
+               /*FALLTHRU*/
+       case 6:
+               /* E# */
+               mark_accidental(4, 1);
+               /*FALLTHRU*/
+       case 5:
+               /* A# */
+               mark_accidental(9, 1);
+               /*FALLTHRU*/
+       case 4:
+               /* D# */
+               mark_accidental(2, 1);
+               /*FALLTHRU*/
+       case 3:
+               /* G# */
+               mark_accidental(7, 1);
+               /*FALLTHRU*/
+       case 2:
+               /* C# */
+               mark_accidental(0, 1);
+               /*FALLTHRU*/
+       case 1:
+               /* F# */
+               mark_accidental(5, 1);
+               break;
+       case 0:
+               break;
+       case -7:
+               /* F& */
+               mark_accidental(5, -1);
+               /*FALLTHRU*/
+       case -6:
+               /* C& */
+               mark_accidental(0, -1);
+               /*FALLTHRU*/
+       case -5:
+               /* G& */
+               mark_accidental(7, -1);
+               /*FALLTHRU*/
+       case -4:
+               /* D& */
+               mark_accidental(2, -1);
+               /*FALLTHRU*/
+       case -3:
+               /* A& */
+               mark_accidental(9, -1);
+               /*FALLTHRU*/
+       case -2:
+               /* E& */
+               mark_accidental(4, -1);
+               /*FALLTHRU*/
+       case -1:
+               /* B& */
+               mark_accidental(11, -1);
+               break;
+       default:
+               pfatal("unknown key signature");
+               break;
+       }
+}
+\f
+
+/* initialize table to say that no notes are tied */
+
+static void
+init_tie_table()
+
+{
+       register int i;
+
+
+       for (i = 0; i < 128; i++) {
+               Tie_table[i] = NO;
+       }
+}
+\f
+
+/* in each octave, mark the given note as having the given accidental, if not
+ * tied. If tied, mark to set it later. */
+
+static void
+mark_accidental(pitch_offset, acc)
+
+int pitch_offset;      /* 0 = C, 2 = D, 4 = E, 5 = F, 7 = G, 9 = A, 11 = B */
+int acc;               /* 1 = sharp, -1 = flat */
+
+{
+       register int n;
+
+       for (n = pitch_offset; n < 128; n += 12) {
+               if (Tie_table[n] == YES) {
+                       Deferred_acc[n] = (short) acc;
+               }
+               else {
+                       Accidental_map[n] = (short) acc;
+               }
+       }
+}
+\f
+
+/* handle a multi-rest. Adjust the absolute time reference value to account
+ * for the length of the multi-rest */
+
+static UINT32B
+midi_multirest(mfile, staff_p, staffno, vno, nummeas)
+
+int mfile;             /* MIDI file */
+struct STAFF *staff_p;
+int staffno;
+int vno;       /* voice number */
+int nummeas;   /* how many measure of rest */
+
+{
+       RATIONAL rat_nummeas;   /* number of measure as a rational */
+
+
+       if (staff_p != (struct STAFF *) 0) {
+               prepmidi_stuff(staff_p, vno, NO);
+       }
+
+       /* if truly a multirest and if octave were in progress,
+        * need to adjust number of measures remaining */
+       if (nummeas > 1 && Octave_bars[staffno] > 0) {
+               /* subtract 1 'cause the barline will count as one */
+               Octave_bars[staffno] -= nummeas - 1;
+               /* if whole octave stuff is done, re-init */
+               if (Octave_bars[staffno] < 0) {
+                       Octave_bars[staffno] = 0;
+                       Octave_count[staffno] = 0.0;
+                       Octave_adjust[staffno] = 0;
+               }
+       }
+
+       rat_nummeas.n = nummeas;
+       rat_nummeas.d = 1;
+       return(do_midi_stuff(rmul(rat_nummeas, Score.time), mfile, NO));
+}
+\f
+
+/* go through STUFF in a measure, saving away info about MIDI stuff for
+ * later use. */
+
+static void
+prepmidi_stuff(staff_p, vindex, all)
+
+struct STAFF *staff_p; /* do STUFF off of here */
+int vindex;            /* voice index, 0 or 1 for voice 1 or 2 */
+int all;               /* YES if processing 'all' stuff */
+
+{
+       struct STUFF *st_p;             /* walk through staff_p->stuff_p */
+       struct MIDISTUFF *ms_p;         /* walk through Midistufflist_p */
+       struct MIDISTUFF **ms_p_p;      /* for inserting into list */
+
+
+       Midistufflist_p = (struct MIDISTUFF *) 0;
+       for (st_p = staff_p->stuff_p; st_p != (struct STUFF *) 0;
+                                                       st_p = st_p->next) {
+
+               if (st_p->stuff_type == ST_MIDI
+                                       || st_p->stuff_type == ST_PEDAL) {
+
+                       /* only do those with proper 'all' value */
+                       if (st_p->all != all) {
+                               continue;
+                       }
+
+                       if (st_p->place == PL_ABOVE && vindex != 0) {
+                               /* above only applies to voice 1 */
+                               continue;
+                       }
+                       if (st_p->place == PL_BELOW && vindex != 1) {
+                               /* below only applies to voice 2 */
+                               if (st_p->stuff_type != ST_PEDAL) {
+                                       continue;
+                               }
+                       }
+                       if (st_p->place == PL_BETWEEN && vindex != 2) {
+                               /* between only applies to voice 3 */
+                               continue;
+                       }
+
+                       CALLOC(MIDISTUFF, ms_p, 1);
+                       /* figure out when to do this event. Have in floating
+                        * point, but need in RATIONAL. So convert. From MIDI's
+                        * point of view, the first beat of a measure occurs at
+                        * time zero, but stuff calls that time 1, and may have
+                        * things happening before that. So adjust for that,
+                        * and consider anything happening from stuff time 0 to
+                        * 1 to happen instantaneously at midi time 0. */
+                       ms_p->time.n = (UINT32B) ( (st_p->start.count - 1.0)
+                                                               * F2RFACTOR);
+                       ms_p->time.d = F2RFACTOR * Score.timeden;
+                       rred( &(ms_p->time) );
+                       if ( LT(ms_p->time, Zero) ) {
+                               ms_p->time = Zero;
+                       }
+                       ms_p->time = radd(ms_p->time, Absolute_time);
+
+                       ms_p->stuff_p = st_p;
+
+                       /* insertion sort into list */
+                       for (ms_p_p = &Midistufflist_p; *ms_p_p !=
+                                               (struct MIDISTUFF *) 0;
+                                               ms_p_p = &((*ms_p_p)->next)) {
+                               if (GT( (*ms_p_p)->time, ms_p->time)) {
+                                       break;
+                               }
+                       }
+                       ms_p->next = *ms_p_p;
+                       *ms_p_p = ms_p;
+               }
+       }
+}
+\f
+
+/* given a timeval to add to Absolute_time, see if there are any MIDI
+ * STUFF events that come before then. If so, do them first. If timeval
+ * is Zero, do any events happening exactly at Absolute_time. In any case
+ * update Absolute_time appropriately. Return number of bytes written */
+
+static UINT32B
+do_midi_stuff(timeval, mfile, all)
+
+RATIONAL timeval;
+int mfile;             /* MIDI file */
+int all;               /* YES if processing 'all' stuffs */
+
+{
+       RATIONAL new_abs_time;  /* Absolute_time plus timeval */
+       struct MIDISTUFF *ms_p; /* index through MIDISTUFF list */
+       UINT32B bytes = 0;      /* bytes written */
+
+
+       /* If need to bounce pedal, do that now */
+       if (Pedbounce == YES && NE(timeval, Zero)) {
+               RATIONAL instant;
+
+               instant.n = 1;
+               instant.d = MIDI_FACTOR;
+               Absolute_time = radd(Absolute_time, instant);
+               bytes += pedswitch(mfile, YES);
+               Absolute_time = rsub(Absolute_time, instant);
+               Pedbounce = NO;
+       }
+
+       /* find out what final time will be */
+       new_abs_time = radd(Absolute_time, timeval);
+
+       /* go through list of MIDI STUFF, to see if anything to do before
+        * final time */
+       for (ms_p = Midistufflist_p; ms_p != (struct MIDISTUFF *) 0;  ) {
+
+               if ( LT(ms_p->time, new_abs_time) || (EQ(timeval, Zero) &&
+                                       EQ(ms_p->time, new_abs_time) ) ) {
+
+                       /* an item to do. Do it */
+                       Absolute_time = ms_p->time;
+                       bytes += midi_item(ms_p->stuff_p, mfile, all);
+
+                       /* free this item and move to next one */
+                       ms_p = ms_p->next;
+                       FREE(Midistufflist_p);
+                       Midistufflist_p = ms_p;
+               }
+               else {
+                       break;
+               }
+       }
+       Absolute_time = new_abs_time;
+
+       /* return number of bytes written */
+       return(bytes);
+}
+\f
+
+/* handle a MIDI stuff item */
+
+static UINT32B
+midi_item(stuff_p, mfile, all)
+
+struct STUFF *stuff_p; /* which STUFF to process */
+int mfile;             /* the MIDI file */
+int all;               /* YES if processing "all" type items now */
+
+{
+       UINT32B bytes = 0;      /* bytes written */
+       unsigned char buff[8];
+       char *key;              /* midi directive keyword */
+       int leng;               /* length of key */
+       char *arg;              /* arg after the =  */
+       int num;                /* atoi value of argument */
+       int n;                  /* note velocity index */
+       char *nextvel_p;        /* location in string of next velocity value */
+
+
+       if (stuff_p->stuff_type == ST_PEDAL) {
+               int font, size;
+               char *string;
+
+
+               if (stuff_p->string == (char *) 0) {
+                       /* continuation of pedal into an ending or something
+                        * similar. I don't think this will every actually
+                        * happen, since that's done in a later phase. */
+                       return(0);
+               }
+
+               /* extract the pedal character */
+               font = stuff_p->string[0];
+               size = stuff_p->string[1];
+               string = stuff_p->string + 2;
+
+               /* turn pedal switch on or off as appropriate */
+               switch(next_str_char(&string, &font, &size) & 0xff) {
+
+               case C_BEGPED:
+                       bytes += pedswitch(mfile, YES);
+                       break;
+               
+               case C_PEDAL:
+                       bytes += pedswitch(mfile, NO);
+                       /* have to put pedal back up after the next chord */
+                       Pedbounce = YES;
+                       break;
+
+               case C_ENDPED:
+                       bytes += pedswitch(mfile, NO);
+                       break;
+               
+               default:
+                       pfatal("bad character in pedal string");
+                       /*NOTREACHED*/
+                       break;
+               }
+               return(bytes);
+       }
+
+       /* figure out which keyword was specified */
+       if (getkeyword(stuff_p->string + 2, &key, &leng, &arg) == NO) {
+               l_warning(stuff_p->inputfile, stuff_p->inputlineno,
+                               "midi directive not in keyword=value format");
+               return(0);
+       }
+       
+       /* do the code for the appropriate keyword. There are enough keywords
+        * that it would almost be worthwhile doing a hash or binary search
+        * rather than sequentially checking each. However, most of them will
+        * probably be rarely used, so by checking the most common ones first,
+        * there will rarely be more than half a dozen checks anyway. */
+       if (matches(key, leng, "program") == YES) {
+               if (stuff_p->all == YES) {
+                       l_warning(stuff_p->inputfile, stuff_p->inputlineno,
+                               "midi program cannot be used with 'all'");
+                       return(0);
+               }
+               if (all == YES) {
+                       return(0);
+               }
+
+               num = atoi(arg);
+               if (l_rangecheck(num, 0, 127, "program", stuff_p->inputfile,
+                               stuff_p->inputlineno) == YES) {
+                       bytes = write_delta(mfile);
+                       Status = buff[0] = (unsigned char) (0xc0 | Channel);
+                       buff[1] = (unsigned char) num;
+                       bytes += write(mfile, buff, 2);
+               }
+       }
+
+       else if (matches(key, leng, "tempo") == YES) {
+               UINT32B quarter_notes_per_minute;
+
+               /* tempo only applies to 'all' */
+               if (stuff_p->all == NO) {
+                       l_warning( stuff_p->inputfile, stuff_p->inputlineno,
+                               "midi tempo can only be set using 'all'");
+                       return(0);
+               }
+
+               if (all == NO) {
+                       return(0);
+               }
+
+               quarter_notes_per_minute = atoi(arg);
+               if (l_rangecheck(quarter_notes_per_minute, MINQNPM, MAXQNPM,
+                               "tempo", stuff_p->inputfile,
+                               stuff_p->inputlineno) == YES) {
+                       bytes = write_delta(mfile);
+                       buff[0] = (unsigned char) 0xff;
+                       buff[1] = (unsigned char) 0x51;
+                       buff[2] = (unsigned char) 0x3;
+                       Usec_per_quarter_note = USEC_PER_MINUTE
+                                               /  quarter_notes_per_minute;
+                       buff[3] = (Usec_per_quarter_note >> 16) & 0xff;
+                       buff[4] = (Usec_per_quarter_note >> 8) & 0xff;
+                       buff[5] = (Usec_per_quarter_note & 0xff);
+                       bytes += write(mfile, buff, 6);
+                       Status = 0;
+               }
+       }
+
+       else if (matches(key, leng, "onvelocity") == YES) {
+               if (stuff_p->all == YES) {
+                       l_warning(stuff_p->inputfile, stuff_p->inputlineno,
+                               "midi onvelocity cannot be used with 'all'");
+                       return(0);
+               }
+               if (all == YES) {
+                       return(0);
+               }
+               num = atoi(arg);
+               if (l_rangecheck(num, 1, 127, "onvelocity", stuff_p->inputfile,
+                               stuff_p->inputlineno) == YES) {
+                       Onvelocity[0] = (char) num;
+               }
+               /* if there are more velocities given, process them. If
+                * there are N velocities given, they give the velocities
+                * to use for the top N notes, the first for the top note,
+                * the second for the second to the top, etc. If there are
+                * more than N notes in a chord, the remaining notes are
+                * given the velocity of the final velocity specified.
+                * Thus, if only one is specified, it applies to all notes
+                * in the chord, whereas if two are given, the top note
+                * will have the first velocity and the remaining notes will
+                * have the second (which could be useful for emphasizing
+                * the melody, for example). And the user can specify each
+                * note's velocity separately if they want to.
+                */
+               nextvel_p = strchr(arg, ',');
+               for (n = 1; n < MAXHAND; n++) {
+                       
+                       /* if user has listed another velocity, save it */
+                       if (nextvel_p != (char *) 0) {
+                               num = atoi(++nextvel_p);
+                               if (l_rangecheck(num, 1, 127, "onvelocity",
+                                               stuff_p->inputfile,
+                                               stuff_p->inputlineno) == YES) {
+                                       Onvelocity[n] = (char) num;
+                               }
+
+                               /* point to next velocity, if any, for next
+                                * time through the loop */
+                               nextvel_p = strchr(nextvel_p, ',');
+                       }
+                       else {
+                               /* use the last user-specified velocity for
+                                * all subsequent notes */
+                               Onvelocity[n] = (char) num;
+                       }
+               }
+       }
+
+       /* Note: have to check "channel" before "chanpressure" so that
+        * channel takes precedence if the keyword is abbreviated */
+       else if (matches(key, leng, "channel") == YES) {
+               if (stuff_p->all == YES) {
+                       l_warning(stuff_p->inputfile, stuff_p->inputlineno,
+                               "midi channel cannot be used with 'all'");
+                       return(0);
+               }
+               if (all == YES) {
+                       return(0);
+               }
+
+               num = atoi(arg);
+               if (l_rangecheck(num, 1, 16, "channel", stuff_p->inputfile,
+                                       stuff_p->inputlineno) == YES) {
+                       /* external MIDI channel numbers are 1-16,
+                        * internal are 0-15 */
+                       Channel = num - 1;
+               }
+       }
+
+       else if (matches(key, leng, "parameter") == YES) {
+               int parmnum;    /* parameter number */
+               int parmval;    /* parameter value */
+
+               if (get_param(arg, stuff_p->inputfile, stuff_p->inputlineno,
+                                       &parmnum, &parmval) == YES) {
+                       bytes += write_delta(mfile);
+                       Status = buff[0] = 0xb0 | Channel;
+                       buff[1] = (unsigned char) parmnum;
+                       buff[2] = (unsigned char) parmval;
+                       bytes += write(mfile, buff, 3);
+               }
+       }
+
+       else if (matches(key, leng, "offvelocity") == YES) {
+               if (stuff_p->all == YES) {
+                       l_warning(stuff_p->inputfile, stuff_p->inputlineno,
+                               "midi offvelocity cannot be used with 'all'");
+                       return(0);
+               }
+               if (all == YES) {
+                       return(0);
+               }
+               num = atoi(arg);
+               if (l_rangecheck(num, 0, 127, "offvelocity", stuff_p->inputfile,
+                               stuff_p->inputlineno) == YES) {
+                       Offvelocity[0] = (char) num;
+               }
+               /* if there are more velocities given, process them. 
+                * See description of onvelocity above for details.
+                */
+               nextvel_p = strchr(arg, ',');
+               for (n = 1; n < MAXHAND; n++) {
+                       
+                       /* if user has listed another velocity, save it */
+                       if (nextvel_p != (char *) 0) {
+                               num = atoi(++nextvel_p);
+                               if (l_rangecheck(num, 1, 127, "onvelocity",
+                                               stuff_p->inputfile,
+                                               stuff_p->inputlineno) == YES) {
+                                       Offvelocity[n] = (char) num;
+                               }
+
+                               /* point to next velocity, if any, for next
+                                * time through the loop */
+                               nextvel_p = strchr(nextvel_p, ',');
+                       }
+                       else {
+                               /* use the last user-specified velocity for
+                                * all subsequent notes */
+                               Offvelocity[n] = (char) num;
+                       }
+               }
+       }
+
+       else if (matches(key, leng, "hex") == YES) {
+               return(midihex(mfile, arg, stuff_p->inputfile, stuff_p->inputlineno));
+       }
+       else if (matches(key, leng, "text") == YES) {
+               return(wr_meta(mfile, 0x01, arg));
+       }
+       else if (matches(key, leng, "copyright") == YES) {
+               return(wr_meta(mfile, 0x02, arg));
+       }
+       else if (matches(key, leng, "name") == YES) {
+               return(wr_meta(mfile, 0x03, arg));
+       }
+       else if (matches(key, leng, "instrument") == YES) {
+               return(wr_meta(mfile, 0x04, arg));
+       }
+       else if (matches(key, leng, "marker") == YES) {
+               return(wr_meta(mfile, 0x06, arg));
+       }
+       else if (matches(key, leng, "cue") == YES) {
+               return(wr_meta(mfile, 0x07, arg));
+       }
+
+       else if (matches(key, leng, "seqnum") == YES) {
+               num = atoi(arg);
+               if (l_rangecheck(num, 0, 32767, "seqnum", stuff_p->inputfile,
+                               stuff_p->inputlineno) == YES) {
+                       bytes = write_delta(mfile);
+                       buff[0] = 0xff;
+                       buff[1] = 0x00;
+                       buff[2] = 0x02;
+                       buff[3] = (num >> 8) & 0xff;
+                       buff[4] = num & 0xff;
+                       bytes += write(mfile, buff, 5);
+                       Status = 0;
+               }
+       }
+
+       else if (matches(key, leng, "port") == YES) {
+               num = atoi(arg);
+               if (l_rangecheck(num, 0, 127, "port", stuff_p->inputfile,
+                               stuff_p->inputlineno) == YES) {
+                       bytes = write_delta(mfile);
+                       buff[0] = 0xff;
+                       buff[1] = 0x21;
+                       buff[2] = 0x01;
+                       buff[3] = num;
+                       bytes += write(mfile, buff, 4);
+                       Status = 0;
+               }
+       }
+
+       /* Note: have to check "channel" before "chanpressure" so that
+        * channel takes precedence if the keyword is abbreviated */
+       else if (matches(key, leng, "chanpressure") == YES) {
+               num = atoi(arg);
+               if (l_rangecheck(num, 0, 127, "chanpressure",
+                               stuff_p->inputfile, stuff_p->inputlineno)
+                               == YES) {
+                       bytes += write_delta(mfile);
+                       buff[0] = 0xd0 | Channel;
+                       buff[1] = (unsigned char) num;
+                       bytes += write(mfile, buff, 2);
+                       Status = 0;
+               }
+       }
+
+       else {
+               l_warning(stuff_p->inputfile, stuff_p->inputlineno,
+                               "unrecognized midi item\n");
+       }
+
+       return(bytes);
+}
+\f
+
+/* handle raw hex to output to midi file. Allow white space. Set running
+ * status to 0. */
+
+static UINT32B
+midihex(mfile, str, fname, lineno)
+
+int mfile;
+char *str;
+char *fname;
+int lineno;
+
+{
+       short nibble = 0;       /* 0 = upper nibble, 1 = lower */
+       UINT32B bytes = 0;      /* how many bytes written */
+       unsigned char data;     /* a byte of data to write */
+
+
+       bytes += write_delta(mfile);
+       for (   ; *str != '\0'; str++) {
+
+               /* skip white space */
+               if (isspace(*str)) {
+                       continue;
+               }
+
+               /* collect two hex digits per byte to write */
+               if (isxdigit(*str)) {
+                       if (nibble == 0) {
+                               data = hexdig(*str) << 4;
+                       }
+                       else {
+                               data |= hexdig(*str);
+                               (void) write(mfile, &data, 1);
+                               bytes++;
+                       }
+                       nibble ^= 1;
+               }
+               else {
+                       l_ufatal(fname, lineno, "illegal hex character");
+               }
+       }
+
+       if (nibble != 0) {
+               l_ufatal(fname, lineno, "odd number of hex digits");
+       }
+
+       /* set running status to unknown and return number of bytes written */
+       Status = 0;
+       return(bytes);
+}
+\f
+
+/* write a meta event of the form
+ *     FF xx length text
+ * Return number of bytes written.
+ */
+
+static UINT32B
+wr_meta(mfile, evtype, str)
+
+int mfile;     /* midi file */
+int evtype;    /* meta event type */
+char *str;     /* text string */
+
+{
+       UINT32B bytes;
+       unsigned char buff[4];
+
+
+       bytes = write_delta(mfile);
+       buff[0] = 0xff;
+       buff[1] = (unsigned char) (evtype & 0xff);
+       (void) write(mfile, buff, 2);
+       bytes += 2;
+       bytes += midi_wrstring(mfile, str, NO);
+
+       Status = 0;
+       return(bytes);
+}
+\f
+
+/* walk through main list. For each top-visible staff, check the stuff
+ * list for any "midi all" items */
+
+static UINT32B
+all_midi(mfile)
+
+int mfile;
+
+{
+       struct MAINLL *mll_p;
+       UINT32B bytes = 0;      /* number of bytes written */
+       unsigned char buff[4];
+       int doing_repeat = NO;
+       struct MAINLL *repeat_start_p = Mainllhc_p;
+       struct GRPSYL *gs_p;
+
+
+       debug(256, "all_midi");
+
+       initstructs();
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->next) {
+               switch (mll_p->str) {
+               case S_STAFF:
+                       if ( svpath(mll_p->u.staff_p->staffno, VISIBLE)->visible
+                                                       == YES) {
+
+                               /* Find the top visible voice */
+                               int vindex;
+                               for (vindex = 0; vindex < MAXVOICES; vindex++) {
+                                       if (vvpath(mll_p->u.staff_p->staffno,
+                                                       vindex+1, VISIBLE)->
+                                                       visible == YES) {
+                                               break;
+                                       }
+                               }
+                               if (vindex >= MAXVOICES) {
+                                       pfatal("top visible staff has no visible voice");
+                               }
+
+                               prepmidi_stuff(mll_p->u.staff_p, vindex, YES);
+                               /* We have to do groups one at a time in order
+                                * to adjust for any squeezed-out spaces. */
+                               for (gs_p = mll_p->u.staff_p->groups_p[vindex];
+                                               gs_p != (struct GRPSYL *) 0;
+                                               gs_p = gs_p->next) {
+
+                                       /* if we find a squeezed-out space
+                                        * group, adjust to account for that */
+                                       if (gs_p->grpcont == GC_SPACE &&
+                                                       gs_p->grpvalue
+                                                       == GV_ZERO) {
+                                               adj4squeeze(gs_p->fulltime);
+                                               bytes += do_midi_stuff(Zero,
+                                                               mfile, YES);
+                                       }
+                                       else {
+                                               if (gs_p->basictime < -1) {
+                                                       /* multirest */
+                                                       RATIONAL fulltime;
+                                                       fulltime.n =
+                                                           gs_p->fulltime.n *
+                                                           -(gs_p->basictime);
+                                                       fulltime.d =
+                                                           gs_p->fulltime.d;
+                                                       rred( &fulltime );
+                                                       bytes += do_midi_stuff(
+                                                       fulltime,
+                                                       mfile, YES);
+                                               }
+                                               else {
+                                                       bytes += do_midi_stuff(
+                                                       gs_p->fulltime,
+                                                       mfile, YES);
+                                               }
+                                       }
+                               }
+
+                               /* do any remaining MIDI stuffs. This would
+                                * be any that occur at exactly the time
+                                * signature denominator plus one. */
+                               bytes += do_midi_stuff(Zero, mfile, YES);
+
+
+                               /* can skip any immediately following STAFFs,
+                                * because we've already found the top
+                                * visible one, which is the only one that
+                                * should have any "midi all" stuff */
+                               while (mll_p->next != (struct MAINLL *) 0 &&
+                                               mll_p->next->str == S_STAFF) {
+                                       mll_p = mll_p->next;
+                               }
+                       }
+                       break;
+
+               case S_SSV:
+                       asgnssv(mll_p->u.ssv_p);
+
+                       /* if key sig changes, handle that */
+                       if (mll_p->u.ssv_p->context == C_SCORE &&
+                                       (mll_p->u.ssv_p->used[SHARPS] == YES ||
+                                       mll_p->u.ssv_p->used[TRANSPOSITION] == YES ||
+                                       mll_p->u.ssv_p->used[ADDTRANSPOSITION] == YES) ) {
+                               bytes += midi_keysig(mfile,
+                                               eff_key(mll_p->u.ssv_p->staffno),
+                                               mll_p->u.ssv_p->is_minor);
+                       }
+
+                       /* if time signature changes, handle that */
+                       if (mll_p->u.ssv_p->used[TIME] == YES) {
+                               bytes += midi_timesig(mfile);
+                       }
+
+                       break;
+
+               case S_BAR:
+                       /* rehearsal mark --> midi cue point */
+                       if (mll_p->u.bar_p->reh_string != (char *) 0) {
+                               bytes += write_delta(mfile);
+                               buff[0] = 0xff;
+                               buff[1] = 0x07;
+                               (void) write(mfile, buff, 2);
+                               bytes += 2;
+                               bytes += midi_wrstring(mfile,
+                                       mll_p->u.bar_p->reh_string, YES);
+                       }
+
+                       repeats(&mll_p, &doing_repeat, &repeat_start_p);
+
+                       break;
+
+               default:
+                       break;
+               }
+
+               if (mll_p == (struct MAINLL *) 0) {
+                       /* shouldn't happen, but repeats() can change mll_p,
+                        * and if it became null, we'd try
+                        * to take the ->next of it, which is not good */
+                       break;
+               }
+       }
+
+       return(bytes);
+}
+\f
+
+/* go through main list and adjust for grace notes, alternation groups,
+ * staccato, etc */
+
+static void
+midi_adjust()
+
+{
+       struct MAINLL *mll_p;   /* index through main list */
+       int v;                  /* voice index */
+       int got_data = NO;      /* if got any music data yet */
+       int did_all = NO;       /* if processed "all" stuff for this meas */
+       UINT32B begin_usec;     /* usec per quarter at beginning of measure */
+
+
+       debug(256, "midi_adjust");
+
+       initstructs();
+       begin_usec = Usec_per_quarter_note;
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
+                                                       mll_p = mll_p->next) {
+               if (mll_p->str == S_STAFF) {
+
+                       if (is_tab_staff(mll_p->u.staff_p->staffno) == YES) {
+                               continue;
+                       }
+
+                       /* If accidentals on one voice should apply to notes
+                        * on the other voice, fix that */
+                       other_voice_accidentals(mll_p->u.staff_p);
+
+                       /* need to check stufflist on top visible to
+                        * update Usec_per_quarter if necessary */
+                       if (did_all == NO && svpath(mll_p->u.staff_p->staffno,
+                                       VISIBLE)->visible == YES) {
+                               begin_usec = Usec_per_quarter_note;
+                               Absolute_time = Zero;
+                               prepmidi_stuff(mll_p->u.staff_p, 0, YES);
+                               did_all = YES;
+                       }
+
+                       /* go through all groups, making adjustments */
+                       for (v = 0; v < MAXVOICES; v++) {
+                               Usec_per_quarter_note = begin_usec;
+                               Absolute_time = Zero;
+                               adjust_notes(mll_p->u.staff_p->groups_p[v],
+                                       mll_p->u.staff_p->staffno, v, mll_p);
+                       }
+                       got_data = YES;
+               }
+               else if (mll_p->str == S_SSV) {
+                       asgnssv(mll_p->u.ssv_p);
+                       if (got_data == NO &&
+                                       mll_p->u.ssv_p->context == C_SCORE) {
+                               if (mll_p->u.ssv_p->used[TIME] == YES) {
+                                       Time_specified_by_user = YES;
+                               }
+                               if (mll_p->u.ssv_p->used[SHARPS] == YES) {
+                                       Key_specified_by_user = YES;
+                               }
+                               if (mll_p->u.ssv_p->used[DIVISION] == YES) {
+                                       Division = mll_p->u.ssv_p->division;
+                               }
+                               /* setting transposition implicitly sets a key */
+                               if (mll_p->u.ssv_p->used[TRANSPOSITION] == YES ||
+                               mll_p->u.ssv_p->used[ADDTRANSPOSITION] == YES) {
+                                       Key_specified_by_user = YES;
+                               }
+                               
+                       }
+               }
+               else if (mll_p->str == S_BAR) {
+                       /* reset for next measure */
+                       did_all = NO;
+                       fix_tempo(YES);
+                       /* free up saved stuff info */
+                       free_midistuff(Midistufflist_p);
+                       Midistufflist_p = (struct MIDISTUFF *) 0;
+               }
+       }
+}
+\f
+
+/* adjust any grace notes to get a little time. We
+ * don't know for sure how much time they should get, and whether they should
+ * be on the beat or before or when, so make some guesses.
+ * Take half of the fulltime of the preceeding group and divide that time
+ * among the number of grace notes.
+ * Compare that value with 0.1 second, and use whichever is shorter.
+ * Also shorten groups slightly to give a little release time between
+ * notes (so that repeated notes don't run together so much), and
+ * shorten groups that have staccato or wedge in their "with" list, and do
+ * alternation groups and rolls */
+
+static void
+adjust_notes(gs_p, staffno, v, mll_p)
+
+struct GRPSYL *gs_p;   /* adjust groups in this list */
+int staffno;
+int v;
+struct MAINLL *mll_p;  /* groups are attached to main list here */
+
+{
+       int numgrace = 0;
+       struct GRPSYL *gracelist_p;     /* one or more grace notes */
+       RATIONAL gracetime;             /* duration of grace notes */
+       RATIONAL time_adj;              /* adjustment for alt groups */
+       int pairs;                      /* how many pair of GRPSYLS to add
+                                        * for an alt pair */
+       struct GRPSYL *add1_p, *add2_p; /* groups added for alt pairs */
+       int alt;                        /* alternation number */
+       int nn;                         /* number of number due to slashes */
+       int d;                          /* number of dots */
+       int dot, wedge, legato;         /* YES if these set in "with" list */
+       int font, size;
+       char *str;                      /* string in with list */
+       int ch;                         /* music character in with list */
+       int w;                          /* index through with list */
+       struct GRPSYL *prevgs_p;        /* group before grace note(s) */
+       RATIONAL tenthsec;              /* note value that is about 0.1 sec */
+       RATIONAL release;               /* how soon to release note */
+       RATIONAL release_adjust;        /* how soon to release current note,
+                                        * the shorter of release and 1/4
+                                        * of the group's time value */
+       RATIONAL graceadj;              /* for calculating grace durations */
+       RATIONAL fulltime;
+       RATIONAL total_time;            /* time so far in measure */
+       struct MAINLL *m_p;             /* for finding TIMEDSSVs, if any */
+       struct TIMEDSSV *tssv_p;        /* for mid-measure release changes */
+       static int had_tssv = NO;       /* If have any timed SSVs anywhere,
+                                        * we'll always call setssvstate() to
+                                        * make sure RELEASE is up to date.
+                                        * Just knowing if they were in this
+                                        * measure is not sufficient.
+                                        * Could be done on some granularity
+                                        * smaller than the whole song,
+                                        * but this is simple, and probably
+                                        * efficient enough.
+                                        */
+
+
+       /* Some compilers warn that gracelist_p might be used uninitialized.
+        * Actually it won't be, but keep them quiet.
+        */
+       gracelist_p = (struct GRPSYL *) 0;
+
+       /* See if there are any timed SSVs to worry about */
+       for (tssv_p = 0, m_p = mll_p; m_p != 0; m_p = m_p->next) {
+               if (m_p->str == S_BAR) {
+                       tssv_p = m_p->u.bar_p->timedssv_p;
+                       if (tssv_p != 0) {
+                               had_tssv = YES;
+                       }
+                       break;
+               }
+       }
+       if (had_tssv == YES) {
+               setssvstate(mll_p);
+       }
+
+       total_time = Zero;
+       for (   ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+
+               /* apply any timed SSVs */
+               if (gs_p->prev != 0) {
+                       total_time = radd(total_time, gs_p->prev->fulltime);
+               }
+               while (tssv_p != 0 && LE(tssv_p->time_off, total_time)) {
+                       asgnssv(&tssv_p->ssv);
+                       tssv_p = tssv_p->next;
+               }
+
+               if (gs_p->grpvalue == GV_ZERO)  {
+                       if (numgrace == 0) {
+                               /* save starting point of list of grace notes */
+                               gracelist_p = gs_p;
+                       }
+                       /* count how many grace notes */
+                       numgrace++;
+               }
+
+               else {
+                       /* if there were grace groups before this group,
+                        * adjust to give them some time. */
+                       if (numgrace > 0) {
+                               /* find the previous group */
+                               prevgs_p = grp_before(gracelist_p, mll_p,
+                                                               staffno, v);
+
+                               /* If the previous group is notes,
+                                * take 1/2 of that groups time value and
+                                * apportion among the grace notes.
+                                * If rest or space, we can probably afford
+                                * to use more. Exactly how much is unclear,
+                                * so we'll use 3/4 */
+                               if (prevgs_p->grpcont == GC_NOTES) {
+                                       graceadj.n = 1;
+                                       graceadj.d = 2 * numgrace;
+                               }
+                               else {
+                                       graceadj.n = 3;
+                                       graceadj.d = 4 * numgrace;
+                               }
+                               rred( &graceadj );
+                               gracetime = rmul(prevgs_p->fulltime,
+                                                               graceadj);
+
+                               /* If grace notes come out to more than
+                                * about 1/10th second, use 1/10th second
+                                * instead. First figure out what sort of
+                                * fulltime value would be 0.1 second, by
+                                * taking 1 over the number of microseconds
+                                * in a whole note divided by 100000 */
+                               tenthsec.n = 1L;
+                               tenthsec.d = 4L * Usec_per_quarter_note / 100000L;
+
+                               if (tenthsec.d == 0) {
+                                       /* we're in some outrageously fast
+                                        * tempo, over 600 quarter notes
+                                        * per minute, which is so fast
+                                        * that even a whole note
+                                        * isn't a tenth of a second.
+                                        * Make sure the denominator
+                                        * isn't zero, so we won't
+                                        * core dump. At this absurd tempo,
+                                        * we'd not going to be using this
+                                        * value anyway, except to compare
+                                        * against gracetime, so if it's
+                                        * off some, it won't matter. */
+                                       tenthsec.d = 1L;
+                               }
+                               rred ( &tenthsec );
+
+                               if ( LT(tenthsec, gracetime)) {
+                                       gracetime = tenthsec;
+                               }
+                               /* round to nearest 2048 note to try to
+                                * avoid arithmetic overflows */
+                               gracetime.n = 2048 * gracetime.n / gracetime.d;
+                               gracetime.d = 2048;
+                               rred ( &gracetime );
+
+                               /* subtract time from previous group */
+                               graceadj.n = numgrace;
+                               graceadj.d = 1;
+                               prevgs_p->fulltime = rsub(prevgs_p->fulltime,
+                                       rmul(gracetime, graceadj));
+
+                               /* give each grace note that much time */
+                               for (   ; numgrace > 0; numgrace--) {
+                                       gracelist_p->fulltime = gracetime;
+                                       gracelist_p = gracelist_p->next;
+                               }
+                       }
+                       numgrace = 0;
+                       fulltime = gs_p->fulltime;
+
+                       /* check for alternation.
+                        * For each alt, double the number
+                        * of notes and make each half as long. */
+                       if (gs_p->slash_alt < 0) {
+
+                               alt = -(gs_p->slash_alt);
+
+                               /* for long notes, adjust so we get down to
+                                * 8th notes for alternation */
+                               if (gs_p->basictime == 0) {
+                                       alt += 2;
+                               }
+                               else if (gs_p->basictime == 1) {
+                                       alt += 1;
+                               }
+                               else if (gs_p->basictime >= 4) {
+                                       alt -= 1;
+                               }
+
+                               /* adjust time values */
+                               time_adj.n = 1;
+                               time_adj.d = 1 << alt;
+                               gs_p->fulltime = rmul(gs_p->fulltime, time_adj);
+                               rred ( &(gs_p->fulltime) );
+                               gs_p->next->fulltime = gs_p->fulltime;
+
+                               /* turn off slash_alt so we won't do it again
+                                * on the added pairs */
+                               gs_p->slash_alt = 0;
+                               gs_p->next->slash_alt = 0;
+
+                               /* add as many more pairs as necessary */
+                               /* If user specifies an insane
+                                * alt number, we could try to make
+                                * millions of groups. So limit to 1000.
+                                */
+                               pairs = (1 << alt) - 1;
+                               if (pairs > 1000) {
+                                       pairs = 1000;
+                               }
+                               for (  ; pairs > 0; pairs--) {
+                                       /* create a new pair clone */
+                                       add1_p = newGRPSYL(GS_GROUP);
+                                       copy_attributes(add1_p, gs_p);
+                                       add1_p->fulltime = gs_p->fulltime;
+                                       copy_notes(add1_p, gs_p);
+                                       add2_p = newGRPSYL(GS_GROUP);
+                                       copy_attributes(add2_p, gs_p->next);
+                                       add2_p->fulltime = gs_p->next->fulltime;
+                                       copy_notes(add2_p, gs_p->next);
+
+                                       /* link pair into list */
+                                       add1_p->next = add2_p;
+                                       add2_p->prev = add1_p;
+                                       add2_p->next = gs_p->next->next;
+                                       if (add2_p->next != (struct GRPSYL *) 0) {
+                                               add2_p->next->prev = add2_p;
+                                       }
+                                       gs_p->next->next = add1_p;
+                                       add1_p->prev = gs_p->next;
+                               }
+                       }
+                       else if (gs_p->slash_alt > 0
+                                               && gs_p->grpvalue != GV_ZERO) {
+                               /* do slashed notes */
+                               /* figure out how many actual chords are
+                                * represented by the slashed chord */
+                               switch (gs_p->basictime) {
+                               case 0:
+                                       nn = 16;
+                                       break;
+                               case 1:
+                                       nn = 8;
+                                       break;
+                               case 2:
+                                       nn = 4;
+                                       break;
+                               default:
+                                       nn = 2;
+                                       break;
+                               }
+                               /* multiply by two for each additional slash
+                                * beyond the first.  Need to keep this IF
+                                * here to avoid hitting potential optimizer
+                                * bug. See comment in grpsyl.c */
+                               if (gs_p->slash_alt > 1) {
+                                       nn = nn << (gs_p->slash_alt - 1);
+                               }
+
+                               if (nn == 0) {
+                                       /* shifted left into oblivion */
+                                       /* parser should have caught this */
+                                       pfatal("bug in slash handling");
+                               }
+                               /* Add an additional 1 bit at the right for
+                                * each dot */
+                               else {
+                                       for (d = gs_p->dots; d > 0; d--) {
+                                                nn |= 1 << (drmo(nn) - 1);
+                                       }
+                               }
+                               /* adjust time of notes, by dividing the
+                                * fulltime of the group by the number of
+                                * notes. We don't look at the basictime
+                                * or dots again, so can leave them */
+                               gs_p->fulltime.d *= nn;
+                               rred ( &(gs_p->fulltime) );
+
+                               /* mark that we have done the slash */
+                               gs_p->slash_alt = 0;
+
+                               /* create as many clones of the groups as
+                                * needed. Use > 1 because we
+                                * already have the original group. */
+                               for (    ; nn > 1; nn--) {
+                                       add1_p = newGRPSYL(GS_GROUP);
+                                       copy_attributes(add1_p, gs_p);
+                                       add1_p->fulltime = gs_p->fulltime;
+                                       copy_notes(add1_p, gs_p);
+                                       /* link into list */
+                                       add1_p->next = gs_p->next;
+                                       add1_p->prev = gs_p;
+                                       gs_p->next = add1_p;
+                                       if (add1_p->next != (struct GRPSYL *) 0) {
+                                               add1_p->next->prev = add1_p;
+                                       }
+                               }
+                       }
+
+                       /* now shorten any groups with dots or wedges */
+                       dot = wedge = legato = NO;
+                       for (w = 0; w < gs_p->nwith; w++) {
+                               if (is_music_symbol(gs_p->withlist[w]) == NO) {
+                                       continue;
+                               }
+                               font = gs_p->withlist[w][0];
+                               size =  gs_p->withlist[w][1];
+                               str = gs_p->withlist[w] + 2;
+                               ch = next_str_char(&str, &font, &size);
+                               switch (ch) {
+                               case C_DOT:
+                                       dot = YES;
+                                       break;
+                               case C_WEDGE:
+                               case C_UWEDGE:
+                                       wedge = YES;
+                                       break;
+                               case C_LEG:
+                                       legato = YES;
+                                       break;
+                               }
+                       }
+                       if (wedge == YES) {
+                               /* reduce to 1/3 time, add rest for other 2/3 */
+                               add_rest(gs_p, rmul(gs_p->fulltime, Two_thirds));
+                               gs_p->fulltime = rmul(gs_p->fulltime, One_third);
+                       }
+                       else if (dot == YES) {
+                               if (legato == YES) {
+                                       /* reduce by 1/4 */
+                                       add_rest(gs_p, rmul(gs_p->fulltime,
+                                                               One_fourth));
+                                       gs_p->fulltime = rmul(gs_p->fulltime,
+                                                               Three_fourths);
+                               }
+                               else {
+                                       /* reduce by half */
+                                       add_rest(gs_p, rmul(gs_p->fulltime,
+                                                               One_half));
+                                       gs_p->fulltime = rmul(gs_p->fulltime,
+                                                               One_half);
+                               }
+                       }
+
+                       else if (gs_p->grpcont == GC_NOTES) {
+
+                               /* Figure out fulltime value for
+                                * milliseconds of release time */
+                               release.n = (UINT32B)
+                                       vvpath(staffno, v + 1, RELEASE)->release;
+                               release.d = 4L * Usec_per_quarter_note / 1000L;
+
+                               if (GT(release, Zero)) {
+                                       /* shorten by a little bit.
+                                        * Otherwise repeated notes
+                                        * run together so much they can sound
+                                        * like a single note
+                                        * on some instruments. */
+
+                                       /* round off to nearest 1024 note.
+                                        * Otherwise we can very quickly
+                                        * get to the point that the
+                                        * lowest common denominator of
+                                        * accumulated time values will get
+                                        * so big we overflow an UINT32B,
+                                        * which can cause lots of problems.
+                                        * Besides, this is going to get
+                                        * rounded off to the granularity
+                                        * of MIDI clock tick eventually anyway,
+                                        * and will be affected by MIDI latency,
+                                        * so if it is off by a few
+                                        * microseconds, it is very doubtful
+                                        * anyone will notice. */
+                                       release.n = 1024 * release.n
+                                                               / release.d;
+                                       release.d = 1024;
+
+                                       rred (&release);
+
+                                       /* Shorten by the lesser of 1/4 of the
+                                        * note time or the amount user
+                                        * asked for */
+                                       release_adjust = rmul(gs_p->fulltime,
+                                                               One_fourth);
+                                       if (LT(release, release_adjust)) {
+                                               release_adjust = release;
+                                       }
+                                       add_release(gs_p, release_adjust, mll_p);
+                               }
+                       }
+
+                       /* handle any rolls */
+                       fix_tempo(NO);
+                       midi_roll(gs_p, &(mll_p->u.staff_p->groups_p[v]));
+                       Absolute_time = radd(Absolute_time, fulltime);
+               }
+       }
+}
+\f
+
+/* Usually we can just add in the release as is. But if the next group is
+ * a grace group, it could end up being really short, because it steals
+ * from the previous group, which would be this added release rest, which
+ * is likely to be quite short. So peek ahead. If the next group is a grace,
+ * only add in the release if it is at least 135 ms per following grace
+ * group, which would allow them about 100 ms each. If it's shorter than
+ * that, don't add any release, and just let the grace(s) steal from the
+ * note group. */
+
+static void
+add_release(gs_p, release_adjust, mll_p)
+
+struct GRPSYL *gs_p;
+RATIONAL release_adjust;
+struct MAINLL *mll_p;
+
+{
+       struct GRPSYL *nextgs_p;
+       int numgrace;
+       double rel_time;        /* release adjust in milliseconds */
+
+       if ((nextgs_p = nextgrpsyl(gs_p, &mll_p)) != (struct GRPSYL *) 0) {
+               /* count how many grace notes coming up after our gs_p */
+               for (numgrace = 0; nextgs_p->grpvalue == GV_ZERO;
+                                               nextgs_p = nextgs_p->next) {
+                       numgrace++;
+               }
+
+               if (numgrace > 0) {
+                       /* Calculate length of proposed release,
+                        * by multiplying its time value by the number
+                        * of milliseconds in a whole note. */
+                       rel_time = RAT2FLOAT(release_adjust) *
+                               Usec_per_quarter_note * 4L / 1000L;
+
+                       /* now see if it's too short */
+                       if ( rel_time < 135.0 * numgrace) {
+                               return;
+                       }
+               }
+       }
+
+       /* add in a rest to accomplish the release */
+       add_rest(gs_p, release_adjust);
+       gs_p->fulltime = rsub(gs_p->fulltime, release_adjust);
+}
+\f
+
+/* turn damper pedal switch on or off. Return number of bytes written */
+
+static UINT32B
+pedswitch(mfile, on)
+
+int mfile;
+int on;                /* YES if to turn damper pedal on, NO if to turn off */
+
+{
+       UINT32B bytes;
+       unsigned char buff[4];
+
+
+       bytes = write_delta(mfile);
+       Status = buff[0] = (unsigned char) (0xb0 | Channel);
+       buff[1] = (unsigned char) 64;
+       buff[2] = (on ? 127 : 0);
+       bytes += write(mfile, buff, 3);
+       return(bytes);
+}
+\f
+
+/* do rolls. Separate into several groups with notes tied together */
+
+static void
+midi_roll(gs_p, gslist_p_p)
+
+struct GRPSYL *gs_p;
+struct GRPSYL **gslist_p_p;    /* head of list of groups for this voice/meas */
+
+{
+       RATIONAL rolltime;              /* roll time adjust per note */
+       struct GRPSYL *g_p;             /* walk through groups in roll */
+       RATIONAL shortest;              /* shortest group in roll */
+       int nnotes;                     /* how many notes in roll */
+       struct MIDIROLL *mrinfo;        /* information about a roll */
+
+
+       switch (gs_p->roll) {
+       case LONEITEM:
+               if (gs_p->nnotes  < 2) {
+                       /* degenerate roll */
+                       return;
+               }
+
+               rolltime = roll_time(gs_p->fulltime, gs_p->nnotes);
+               do_mroll(gs_p, gslist_p_p, rolltime, 0);
+               break;
+
+       case STARTITEM:
+               /* count how many notes total to roll, and get duration of
+                * shortest group in the roll */
+               nnotes = gs_p->nnotes;
+               shortest = gs_p->fulltime;
+               for (g_p = gs_p->gs_p; g_p != (struct GRPSYL *) 0;
+                                                       g_p = g_p->gs_p) {
+                       nnotes += g_p->nnotes;
+                       if (LT(g_p->fulltime, shortest)) {
+                               shortest = g_p->fulltime;
+                       }
+                       if (g_p->roll == ENDITEM) {
+                               break;
+                       }
+               }
+
+               rolltime = roll_time(shortest, nnotes);
+
+               /* do first group */
+               if (gs_p->rolldir != DOWN) {
+                       nnotes -= gs_p->nnotes;
+                       do_mroll(gs_p, gslist_p_p, rolltime, nnotes);
+               }
+               else {
+                       do_mroll(gs_p, gslist_p_p, rolltime, 0);
+                       nnotes = gs_p->nnotes;
+               }
+
+               /* now go down the chord again saving information about the
+                * roll on other groups */
+               for (g_p = gs_p->gs_p; g_p != (struct GRPSYL *) 0;
+                                                       g_p = g_p->gs_p) {
+                       if (gs_p->rolldir != DOWN) {
+                               nnotes -= g_p->nnotes;
+                               savemidiroll(g_p, nnotes, rolltime);
+                       }
+                       else {
+                               savemidiroll(g_p, nnotes, rolltime);
+                               nnotes += g_p->nnotes;
+                       }
+                       if (g_p->roll == ENDITEM) {
+                               break;
+                       }
+               }
+               break;
+
+       case INITEM:
+       case ENDITEM:
+               /* retrieve info about this roll and do it */
+               if ((mrinfo = getmidiroll(gs_p)) == (struct MIDIROLL *) 0) {
+                       /* if staff is invisible, this is okay, otherwise
+                        * something must have gone wrong */
+                       if (svpath(gs_p->staffno, VISIBLE)->visible == YES) {
+                               pfatal("info about roll is missing");
+                       }
+               }
+               else {
+                       do_mroll(gs_p, gslist_p_p, mrinfo->duration,
+                                               mrinfo->notesbefore);
+                       FREE(mrinfo);
+               }
+               break;
+
+       default:
+               break;
+       }
+}
+\f
+
+/* given a chord duration and number of notes, return how long to make
+ * each note of roll. Use 1/20 second or whatever would add up to a total
+ * of half the duration, whichever is shorter */
+
+static RATIONAL
+roll_time(grptime, nnotes)
+
+RATIONAL grptime;      /* duration of rolled chord */
+int nnotes;            /* how many notes in the chord */
+
+{
+       RATIONAL rolltime;              /* roll time adjust per note */
+       RATIONAL maxdur;                /* note equal to 0.05 second */
+
+
+       /* if not enough notes to roll, don't do anything here */
+       if (nnotes < 2) {
+               return(Zero);
+       }
+
+       /* as first guess, apportion the extra groups into half of
+        * the group time */
+       rolltime = rmul(grptime, One_half);
+       rolltime.d *= (nnotes - 1);
+       rred ( &rolltime );
+
+       /* find 0.05 second time */
+       maxdur.n = 1;
+       maxdur.d = 4L * Usec_per_quarter_note / 50000L;
+
+       /* use whichever is shorter */
+       return( LT(maxdur, rolltime) ? maxdur : rolltime);
+}
+\f
+
+/* create and link the extra groups to implement roll sound */
+
+static void
+do_mroll(gs_p, gslist_p_p, rolltime, notesbefore)
+
+struct GRPSYL *gs_p;           /* group having roll */
+struct GRPSYL **gslist_p_p;    /* addr of groups_p list containing gs_p */
+RATIONAL rolltime;             /* duration per roll note */
+int notesbefore;               /* how many notes of roll before this in
+                                * chords in other voices */
+
+{
+       register int i;
+       struct GRPSYL **link_p_p;       /* where to link added groups */
+       struct GRPSYL *prev_p;          /* previous group */
+       RATIONAL factor;                /* multiplier of duration */
+       struct GRPSYL *newgs_p;         /* added rest group */
+
+
+       /* figure out where to link added groups */
+       if (gs_p->prev == (struct GRPSYL *) 0) {
+               link_p_p = gslist_p_p;
+       }
+       else {
+               link_p_p = &( gs_p->prev->next);
+       }
+       prev_p = gs_p->prev;
+
+       /* add in groups with appropriate subset of notes, tied to
+        * the existing group */
+       if (gs_p->rolldir != DOWN) {
+               for (i = 1; i < gs_p->nnotes; i++) {
+                       addrollgrp(gs_p, rolltime, i, gs_p->nnotes - 1,
+                                               link_p_p, prev_p);
+               }
+       }
+       else {
+               for (i = gs_p->nnotes - 2; i >= 0; i--) {
+                       addrollgrp(gs_p, rolltime, 0, i,
+                                               link_p_p, prev_p);
+               }
+       }
+
+       /* adjust group time */
+       factor.n = gs_p->nnotes - 1 + notesbefore;
+       factor.d = 1;
+       gs_p->fulltime = rsub(gs_p->fulltime, rmul(rolltime, factor));
+
+       /* add rest before if necessary */
+       if (notesbefore > 0) {
+               factor.n = notesbefore;
+               CALLOC(GRPSYL, newgs_p, 1);
+               newgs_p->grpcont = GC_REST;
+               newgs_p->fulltime = rmul(rolltime, factor);
+               /* mark as internally generated, so octave adjust works */
+               newgs_p->inputlineno = -1;
+
+               /* stitch into list */
+               (*link_p_p)->prev = newgs_p;
+               newgs_p->next = *link_p_p;
+               newgs_p->prev = prev_p;
+               *link_p_p = newgs_p;
+       }
+}
+\f
+
+/* add group to form part of a roll */
+
+static void
+addrollgrp(gs_p, duration, start, end, link_p_p, prev_p)
+
+struct GRPSYL *gs_p;
+RATIONAL duration;
+int start;             /* index into notelist, where to start copying notes */
+int end;               /* index into notelist, where to stop copying notes */
+struct GRPSYL **link_p_p; /* where to link into list */
+struct GRPSYL *prev_p; /* previous group */
+
+{
+       struct GRPSYL *newgs_p;
+       int i;
+
+
+       newgs_p = newGRPSYL(GS_GROUP);
+       newgs_p->grpcont = GC_NOTES;
+       newgs_p->fulltime = duration;
+       newgs_p->nnotes = end - start + 1;
+       /* mark as internally generated, so octave adjusting will work */
+       newgs_p->inputlineno = -1;
+
+       /* copy appropriate subset of notes from original group */
+       CALLOC(NOTE, newgs_p->notelist, newgs_p->nnotes);
+       for (i = 0; start <= end; i++, start++) {
+               newgs_p->notelist[i].letter = gs_p->notelist[start].letter;
+               newgs_p->notelist[i].accidental
+                                       = gs_p->notelist[start].accidental;
+               newgs_p->notelist[i].octave = gs_p->notelist[start].octave;
+               newgs_p->tie = YES;
+       }
+       
+       /* stitch into list */
+       (*link_p_p)->prev = newgs_p;
+       newgs_p->next = *link_p_p;
+       newgs_p->prev = prev_p;
+       *link_p_p = newgs_p;
+}
+\f
+
+/* Create struct to hold info about roll that crosses groups and fill it in.
+ * Link onto list of info of this type */
+
+static void
+savemidiroll(gs_p, notesbefore, duration)
+
+struct GRPSYL *gs_p;
+int notesbefore;
+RATIONAL duration;
+
+{
+       struct MIDIROLL *new_p;
+
+       CALLOC(MIDIROLL, new_p, 1);
+       new_p->gs_p = gs_p;
+       new_p->notesbefore = (short) notesbefore;
+       new_p->duration = duration;
+       new_p->link_p = Midirollinfo_p;
+       Midirollinfo_p = new_p;
+}
+\f
+
+/* given a GRPSYL, return pointer to the MIDIROLL struct associated with it,
+ * after detaching it from the list.  Caller is responsible for freeing it.
+ * Returns null if not on the list */
+
+static struct MIDIROLL *
+getmidiroll(gs_p)
+
+struct GRPSYL *gs_p;
+
+{
+       struct MIDIROLL **mr_p_p;
+       struct MIDIROLL *the_one;       /* the one matching gs_p */
+
+
+       /* walk down list. Since there aren't likely to be all that many
+        * multi-voice rolls per measure, we just use a linked list instead
+        * of hashing or something. */
+       for (mr_p_p = &Midirollinfo_p; *mr_p_p != (struct MIDIROLL *) 0;
+                       mr_p_p = &( (*mr_p_p)->link_p) ){
+
+               if ( (*mr_p_p)->gs_p == gs_p) {
+                       /* found it. detach and return it */
+                       the_one = *mr_p_p;
+                       *mr_p_p = (*mr_p_p)->link_p;
+                       return(the_one);
+               }
+       }
+       return (struct MIDIROLL *) 0;
+}
+\f
+
+/* go through list of STUFFs for this measure. If there is a MIDI "tempo"
+ * STUFF prior to the current time, update Usec_per_quarter_note */
+
+static void
+fix_tempo(to_end)
+
+int to_end;    /* if YES, go all the way to end of Midistufflist_p */
+
+{
+       struct MIDISTUFF *ms_p;         /* index through list of STUFF */
+       char *key;                      /* to check for "tempo" */
+       int leng;                       /* length of key */
+       char *arg;                      /* tempo argument */
+       int quarter_notes_per_min;      /* notes per minute */
+
+
+       /* check stuff in this measure */
+       for (ms_p = Midistufflist_p; ms_p != (struct MIDISTUFF *) 0;
+                                       ms_p = ms_p->next) {
+               if (GE(ms_p->time, Absolute_time) && to_end == NO) {
+                       /* beyond where we are in time so far */
+                       return;
+               }
+
+               /* see if MIDI tempo */
+               if (ms_p->stuff_p->stuff_type == ST_MIDI) {
+                       if (getkeyword(ms_p->stuff_p->string + 2, &key, &leng,
+                                                       &arg) == YES) {
+                               if (matches(key, leng, "tempo") == YES) {
+                                       /* is it tempo. Update */
+                                       quarter_notes_per_min = atoi(arg);
+                                       if (quarter_notes_per_min >= MINQNPM
+                                               && quarter_notes_per_min
+                                               <= MAXQNPM)  {
+                                           Usec_per_quarter_note =
+                                               USEC_PER_MINUTE
+                                               /  quarter_notes_per_min;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+\f
+
+/* recursively free MIDISTUFF list */
+
+static void
+free_midistuff(ms_p)
+
+struct MIDISTUFF *ms_p;
+
+{
+       if (ms_p == (struct MIDISTUFF *) 0) {
+               return;
+       }
+
+       free_midistuff(ms_p->next);
+       FREE(ms_p);
+}
+\f
+
+/* when a group is squeezed to zero time because the chord was all spaces,
+ * we need to adjust the time to do any pending stuffs by the amount
+ * of time squeezed out. So go through the list of pending stuffs, and
+ * mark them as occurring that much earlier, or immediately if the time
+ * would end up negative. Octave marks are handled a measure at a time,
+ * so we don't have to worry about them.
+ * If user put a stuff in the middle of an all-space chord,
+ * maybe they really wanted the space not squeezed, but tough.
+ * If they really want time taken up they should use rest, not space.
+ * It isn't worth the effort to figure out that some particular space
+ * chord has a stuff in the middle of it, so that it should be treated
+ * specially.
+ */
+
+static void
+adj4squeeze(timeval)
+
+RATIONAL timeval;      /* adjust by this much */
+
+{
+       struct MIDISTUFF *ms_p; /* walk through list of MIDI stuff to do */
+
+
+       for (ms_p = Midistufflist_p; ms_p != (struct MIDISTUFF *) 0;
+                                       ms_p = ms_p->next) {
+
+               /* adjust the time */
+               ms_p->time = rsub(ms_p->time, timeval);
+
+               if (LT(ms_p->time, Zero)) {
+                       /* Oops. User put a stuff in the middle of an
+                        * all-space group. Schedule the stuff to happen
+                        * immediately */
+                       ms_p->time = Zero;
+               }
+       }
+}
+\f
+
+/* return YES if specified staff/voice is used somewhere in the piece */
+
+int
+voice_used(staffno, vno)
+
+int staffno;
+int vno;
+
+{
+       return (Voice2track_map [staffno] [vno] != 0 ? YES : NO);
+}
diff --git a/mup/mup/midiutil.c b/mup/mup/midiutil.c
new file mode 100644 (file)
index 0000000..85054c4
--- /dev/null
@@ -0,0 +1,1460 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* utility functions for creating MIDI output from Mup input. These functions
+ * are split out into this file to keep midi.c from being so huge */
+
+#ifdef __WATCOMC__
+#include <io.h>
+#endif
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+static struct GRPSYL *create_prev_grp P((struct MAINLL *mll_p, int staffno,
+               int v));
+static struct GRPSYL *create_meas_space P((struct MAINLL *mll_p));
+static void fix_spacechord P((struct MAINLL *chmll_p, struct CHORD *ch_p));
+static void splitspace P((struct GRPSYL *gs_p, RATIONAL duration));
+static void splicechord P((struct GRPSYL *gs_p, struct CHORD *ch_p));
+static void guitar_grpsyl_transpose P((struct GRPSYL *gs_p));
+static RATIONAL find_acc_end_time P((RATIONAL begin_time, struct GRPSYL *gs_p,
+               int n));
+static void propogate_accidental P((struct NOTE *note_p, RATIONAL begin_time,
+               RATIONAL end_time, struct GRPSYL *gs_p));
+static void mv_skipped_midi P((struct STUFF *stuff_p, int staffno,
+               struct MAINLL *topstaff_mll_p));
+\f
+
+/* seek back to where header size is in file, and fill in the correct size,
+ * now that we know what it is. */
+
+void
+fix_track_size(mfile, track_start, track_size)
+
+int mfile;             /* file descriptor of MIDI file */
+long track_start;      /* offset in file where size needs to be put */
+long track_size;       /* track length in bytes */
+
+{
+       unsigned char buff[4];
+
+
+       debug(512, "fix_track_size");
+
+       /* go to where track size is stored in file */
+       (void) lseek(mfile, track_start + 4, SEEK_SET);
+
+       /* convert to 4-byte number with correct byte ordering regardless
+        * of machine byte ordering */
+       buff[0] = (track_size >> 24) & 0xff;
+       buff[1] = (track_size >> 16) & 0xff;
+       buff[2] = (track_size >> 8) & 0xff;
+       buff[3] = track_size & 0xff;
+       (void) write(mfile, buff, 4);
+
+       /* go back to end of file in case there are more track to write */
+       (void) lseek(mfile, 0L, SEEK_END);
+}
+\f
+
+/* given an octave mark string, return number of octaves to tranpose (could
+ * be negative if transposing down) */
+
+int
+parse_octave(string, place, fname, lineno)
+
+char *string;          /* typically "8va" */
+int place;             /* PL_ABOVE or PL_BELOW */
+char *fname;           /* file name for errors */
+int lineno;
+               
+
+{
+       int font, size;
+       int octave_value = 0;
+       int code;               /* ASCII of character in string */
+
+       
+       font = string[0];
+       size = string[1];
+       string += 2;
+       code = next_str_char(&string, &font, &size);
+       if (isdigit(code)) {
+               octave_value = code - '0';
+               code = next_str_char(&string, &font, &size);
+               /* might be a second digit. If user is crazy enough to use
+                * an octave number greater than 2 digits, ignore the rest */
+               if (isdigit(code)) {
+                       octave_value = (octave_value * 10) + (code - '0');
+               }
+       }
+
+       /* must be either a non-zero multiple of 8, or things like 15, 22,
+        * etc if some musical mathematician adds 7 instead of 8 */
+       if (octave_value < 8 || ((octave_value - 8) % 7 != 0 &&
+                                (octave_value - 8) % 8 != 0)) {
+               l_ufatal(fname, lineno, "invalid octave mark string");
+       }
+       if (octave_value % 8 == 0) {
+               octave_value /= 8;
+       } else {
+               octave_value = 1 + (octave_value - 8) % 7;
+       }
+
+       return(place == PL_BELOW ? -octave_value : octave_value);
+}
+\f
+
+/* determine "clocks per metronome tick." It not entirely clear to me
+ * how that is supposed to work, but... if the time signature denominator is
+ * 4, we'll use 24. If 8, use 12, etc. Only go down as far as 3, since that's
+ * not divisible by 2. Really, in fast tempo triple time, the denominator
+ * isn't the beat, but this will do for now. */
+
+int
+clocks(num)
+
+int num;
+
+{
+       switch(num) {
+       case 1:
+               return(96);
+       case 2:
+               return(48);
+       case 4:
+               return(24);
+       case 8:
+               return(12);
+       case 16:
+               return(6);
+       default:
+               return(3);
+       }
+}
+\f
+
+/* given a string, if it contains a word followed by an =, followed by a word,
+ * any of which may be separated by white space, return, via pointers,
+ * a pointer to the beginning of the word, the length of the word, and a pointer
+ * to the first non-white-space character after the =, and return YES.
+ * Otherwise, return NO. A "word" is a sequence of non-white-space chars. */
+
+int
+getkeyword(string, key_p, leng_p, arg_p_p)
+
+char *string;          /* check this string */
+char **key_p;          /* return pointer to keyword via this */
+int *leng_p;           /* return length of keyword via this */
+char **arg_p_p;                /* return pointer to argument after = via this */
+
+{
+       char *tok;
+
+
+       /* skip leading white space */
+       for (*key_p = string; **key_p == ' ' || **key_p == '\t'; (*key_p)++) {
+               ;
+       }
+
+       /* go till hit white space or equals sign */
+       for (tok = *key_p; *tok != '\0'; tok++) {
+               if (*tok == ' ' || *tok == '\t' || *tok == '=') {
+                       break;
+               }
+       }
+
+       /* fill in length of key */
+       *leng_p = tok - *key_p;
+
+       if (*leng_p == 0) {
+               return(NO);
+       }
+
+       /* find first non-white beyond the = */
+       for (   ; *tok != '\0'; tok++) {
+               if (*tok == '=') {
+                       for (tok++; *tok != '\0'; tok++) {
+                               if (*tok != ' ' && *tok != '\t') {
+                                       *arg_p_p = tok;
+                                       return(YES);
+                               }
+                       }
+               }
+       }
+       return(NO);
+}
+\f
+
+/* given a user-specified key, see if it matches the given command name. Return
+ * YES if it does, NO if it doesn't. User only has to specify the first 3 or
+ * more characters of the command, because that's enough to make it unique,
+ * and saves them from typing longer names. */
+
+int
+matches(key, leng, cmd)
+
+char *key;             /* user specified key to be checked */
+int leng;              /* length of key */
+char *cmd;             /* check if key matches this command */
+
+{
+       if (leng < 3) {
+               return(NO);
+       }
+       return(strncmp(key, cmd, leng) == 0 ? YES : NO);
+}
+\f
+
+/* given an ASCII hex digit, return its value 0-15 */
+
+int
+hexdig(ch)
+
+int ch;
+
+{
+       if (ch >= '0' && ch <= '9') {
+               return(ch - '0');
+       }
+       else if (ch >= 'a' && ch <= 'f') {
+               return(ch - 'a' + 10);
+       }
+       else if (ch >= 'A' && ch <= 'F') {
+               return(ch - 'A' + 10);
+       }
+       pfatal("bad hex digit");
+       /*NOTREACHED*/
+       return(0);
+}
+\f
+
+/* given a string, output it to midi file, prefixed by its length. */
+/* return number of bytes written */
+
+UINT32B
+midi_wrstring(mfile, str, internalform)
+
+int mfile;     /* MIDI file */
+char *str;     /* string to write to file */
+int internalform;      /* YES if str is in Mup format, NO if just ASCII,
+                        * C-style null-terminated string to be copied */
+
+{
+       char *buff;             /* for all-ASCII version of str */
+       UINT32B bytes;          /* number of bytes in length value */
+       int length;             /* of string */
+
+
+       /* get plain ascii version of string. Write out length of
+        * string, then plain string itself */
+       if (internalform == YES) {
+               buff = ascii_str(str, NO, YES, TM_NONE);
+               length = strlen(buff);
+               bytes = wr_varlength(mfile, (UINT32B) length);
+               bytes += write(mfile, buff, (unsigned) length);
+       }
+       else {
+               length = strlen(str);
+               bytes = wr_varlength(mfile, (UINT32B) length);
+               bytes += write(mfile, str, (unsigned) length);
+       }
+
+       /* return number of bytes written */
+       return(bytes);
+}
+\f
+
+/* given a number, write to MIDI file in MIDI variable length format.
+ * Return number of bytes written. */
+
+UINT32B
+wr_varlength(mfile, num)
+
+UINT32B num;
+
+{
+       unsigned char buff[4];
+       int i;
+       int shift;
+       
+
+       /* Because only 7 bits of each MIDI byte can be used,
+        * there is only support for numbers up to 28 bits long. */
+       if ((num & 0xf0000000) != 0) {
+               ufatal("midi value too large");
+       }
+
+       /* convert value to the MIDI variable-length number, which
+        * uses the lower 7 bits of each byte as parts of the number, and
+        * the high order bit as a flag to say which is the last byte of
+        * the (potentially) multi-byte number */
+       for (i = 0, shift = 21; shift >= 7; shift -= 7) {
+               if ( (num >> shift) || (i > 0)) {
+                       buff[i++] = 0x80 | ((num >> shift) & 0x7f);
+               }
+       }
+       buff[i] = num & 0x7f;
+       (void) write(mfile, buff, (unsigned) (i + 1));
+       return (UINT32B) (i+1);
+}
+\f
+
+/* do key signature. Return number of bytes written */
+
+UINT32B
+midi_keysig(mfile, sharps, is_minor)
+
+int mfile;
+int sharps;
+int is_minor;  /* YES if minor */
+
+{
+       UINT32B bytes;
+       unsigned char buff[8];
+
+
+       bytes = write_delta(mfile);
+       buff[0] = 0xff;
+       buff[1] = 0x59;
+       buff[2] = 0x02;
+       buff[3] = (char) sharps;
+       buff[4] = (is_minor == YES ? 1 : 0);
+       (void) write(mfile, buff, 5);
+
+       return(bytes + 5);
+}
+\f
+
+/* write out the timesig in Score SSV. Return number of bytes written */
+
+UINT32B
+midi_timesig(mfile)
+
+int mfile;
+{
+       UINT32B bytes;
+       unsigned char buff[8];
+
+
+       /* With additive time signatures, it is possible to get an effective
+        * time signature that won't fit in 7 bits. In that case, we don't
+        * do any time signature, since we can't represent it. */
+       if (Score.timenum > 127) {
+               return(0);
+       }
+
+       bytes = write_delta(mfile);
+       buff[0] = 0xff;
+       buff[1] = 0x58;
+       buff[2] = 0x04;
+       buff[3] = (char) Score.timenum;
+       buff[4] = (unsigned char) drmo(Score.timeden);
+       buff[5] = clocks(Score.timeden);
+       buff[6] = 0x8;
+       bytes += write(mfile, buff, 7);
+       return(bytes);
+}
+\f
+
+/* find group before given group. If none before it in current measure,
+ * back up in main list to find corresponding group list, and use final group
+ * in that list. If no group exists, create one. */
+
+struct GRPSYL *
+grp_before(gs_p, mll_p, staffno, v)
+
+struct GRPSYL *gs_p;   /* find group before this one */
+struct MAINLL *mll_p;  /* the list containing gs_p is attached to main list here */
+int staffno;
+int v;                 /* voice */
+
+{
+       int found_bar = NO;
+
+
+       if (gs_p->prev != (struct GRPSYL *) 0) {
+               /* oh good. There's another group before this one in the
+                * current measure, so just return it */
+               return(gs_p->prev);
+       }
+
+       /* have to go back to previous measure, if any. Start searching
+        * backwards in main list. */
+       for (mll_p = mll_p->prev; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->prev) {
+               switch (mll_p->str) {
+               case S_STAFF:
+                       if (found_bar == NO) {
+                               /* still in current measure */
+                               break;
+                       }
+
+                       if (mll_p->u.staff_p->staffno == staffno) {
+                               /* we found the previous measure */
+                               if (mll_p->u.staff_p->groups_p[v]
+                                               != (struct GRPSYL *) 0) {
+                                       /* find and return last group */
+                                       for (gs_p=mll_p->u.staff_p->groups_p[v];
+                                                       gs_p->next !=
+                                                       (struct GRPSYL *) 0;
+                                                       gs_p = gs_p->next) {
+                                               ;
+                                       }
+                                       return(gs_p);
+                               }
+                               else {
+                                       /* this voice wasn't present before.
+                                        * Will have to create a measure */
+                                       return(create_meas_space(mll_p));
+                               }
+                       }
+                       else if (mll_p->u.staff_p->staffno < staffno) {
+                               /* corresponding staff does not exist in this
+                                * measure. The only time this should happen is
+                                * if user changed the number of staffs.
+                                * So create staff */
+                               return(create_prev_grp(mll_p, staffno, v));
+                       }
+                       break;
+
+               case S_BAR:
+                       found_bar = YES;
+                       break;
+
+               default:
+                       /* ignore other things */
+                       break;
+               }
+       }
+
+       /* Fell off the top of the list. This used to be possible,
+        * and we called create_prev_grp() to create a measure.
+        * But the measure really needs to be created much earlier--
+        * before makechords() is run--in order for squeezing to work right.
+        * So that's what we do now. So we should never get here. */
+       pfatal("fell off top of list in grp_before()");
+       /* NOTREACHED */
+       return(create_prev_grp(mll_p, staffno, v));
+}
+\f
+
+/* create a new STAFF struct and insert in main list, with grpcont of
+ * space and fulltime of the measure. Return pointer to the GRPSYL of
+ * appropriate voice of the STAFF that was created. */
+
+static struct GRPSYL *
+create_prev_grp(mll_p, staffno, v)
+
+struct MAINLL *mll_p;  /* insert here */
+int staffno;
+int v;
+
+{
+       struct MAINLL *new_p;   /* new STAFF */
+       int i;
+
+
+       new_p = newMAINLLstruct(S_STAFF, -1);
+       new_p->u.staff_p->staffno = (short) staffno;
+       insertMAINLL(new_p, mll_p);
+       for (i = 0; i < MAXVOICES; i++) {
+               new_p->u.staff_p->groups_p[i]
+                                       = create_meas_space(mll_p);
+       }
+
+       /* if added to beginning of list, have to add bar as well */
+       if (mll_p == (struct MAINLL *) 0) {
+               struct MAINLL *mbar_p;
+
+               mbar_p = newMAINLLstruct(S_BAR, -1);
+               insertMAINLL(mbar_p, new_p);
+       }
+
+       return(new_p->u.staff_p->groups_p[v]);
+}
+\f
+
+/* create a measure space as long as that of the reference measure (or of 4/4
+ * if no reference) and return it */
+
+static struct GRPSYL *
+create_meas_space(mll_p)
+
+struct MAINLL *mll_p;  /* use this for reference to get measure length */
+
+{
+       struct GRPSYL *gs_p;    /* new grpsyl */
+       struct GRPSYL *egs_p;   /* existing grpsyl */
+
+
+       gs_p = newGRPSYL(GS_GROUP);
+       gs_p->grpcont = GC_SPACE;
+
+       /* figure out how much full time to give the group. If mll_p is not
+        * null, we are adding a staff to an existing measure, so use
+        * length of its first voice. Count up the length of existing measure */
+       gs_p->fulltime = Zero;
+       if (mll_p != (struct MAINLL *) 0 && mll_p->str == S_STAFF) {
+               for (egs_p = mll_p->u.staff_p->groups_p[0];
+                                       egs_p != (struct GRPSYL *) 0;
+                                       egs_p = egs_p->next) {
+
+                       gs_p->fulltime = radd(gs_p->fulltime, egs_p->fulltime);
+               }
+       }
+       else {
+               /* at beginning of list, use default  of 1/1 (the reduced
+                * form of 4/4) */
+               gs_p->fulltime.n = gs_p->fulltime.d = 1;
+       }
+
+       return(gs_p);
+} 
+\f
+
+/* add a rest of the specified fulltime duration after the specified group.
+ * Since this is just for midi purposes, don't worry about filling in all
+ * the fields. */
+
+void
+add_rest(gs_p, fulltime)
+
+struct GRPSYL *gs_p;   /* add rest after this group */
+RATIONAL fulltime;     /* make it this long */
+
+{
+       struct GRPSYL *newgs_p;
+
+
+       if (gs_p == (struct GRPSYL *) 0) {
+               pfatal("null group passed to add_rest");
+       }
+
+       newgs_p = newGRPSYL(GS_GROUP);
+       newgs_p->grpcont = GC_REST;
+       rred (&fulltime);
+       newgs_p->fulltime = fulltime;
+       newgs_p->next = gs_p->next;
+       newgs_p->prev = gs_p;
+       gs_p->next = newgs_p;
+       if (newgs_p->next != (struct GRPSYL *) 0) {
+               newgs_p->next->prev = newgs_p;
+       }
+}
+\f
+
+/* when all voices have space, that should be squeezed to zero time.
+ * Go through main list. For each CHHEAD found,
+ * go down the list of chords. For each chord, see if
+ * if it is an all-space chord. If so, call fix_spacechord() to
+ * handle it.
+ */
+
+void
+midi_squeeze()
+
+{
+       struct MAINLL *mll_p;   /* walk through main list */
+       struct CHORD *ch_p;     /* walk through list of chords */
+
+
+       debug(256, "midi_squeeze");
+
+       initstructs();
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->next) {
+
+               /* skip everything except CHHEADs and SSV updates */
+               if (mll_p->str != S_CHHEAD) {
+                       if (mll_p->str == S_SSV) {
+                               asgnssv(mll_p->u.ssv_p);
+                       }
+                       continue;
+               }
+
+               /* do each chord */
+               for (ch_p = mll_p->u.chhead_p->ch_p;
+                                               ch_p != (struct CHORD *) 0;
+                                               ch_p = ch_p->ch_p) {
+
+                       if (ch_p->width == 0.0) {
+                               /* found one to squeeze, do it */
+                               fix_spacechord(mll_p, ch_p);
+                       }
+               }
+       }
+}
+\f
+
+/* given an all-space chord to crunch, split up any groups that
+ * spill into this chord or extend beyond it. Then set the grpvalue of each
+ * group in the chord to GV_ZERO.
+ */
+
+static void
+fix_spacechord(chmll_p, ch_p)
+
+struct MAINLL *chmll_p;                /* chord is hanging off this CHHEAD */
+struct CHORD *ch_p;            /* zero-width chord */
+
+{
+       struct MAINLL *mll_p;   /* walk through STAFFs in main list */
+       struct GRPSYL *gs_p;    /* walk through groups in chord */
+       struct GRPSYL *group_p; /* head of list of grpsyls in measure */
+       RATIONAL minspacetime;  /* time of shortest space in chord */
+       RATIONAL chordstart;    /* where in measure chord begins */
+       RATIONAL chordend;      /* where the space ends */
+       RATIONAL new_chordend;  /* tentative new value for chordend */
+       RATIONAL grpstart;      /* where in measure grpsyl begins */
+       int v;                  /* voice index */
+
+
+       /* first find the smallest duration in the chord. Can't use
+       * ch_p->duration here because grace notes have been adjusted
+       * by now to take some time */
+       minspacetime = ch_p->gs_p->fulltime;
+       for (gs_p = ch_p->gs_p->gs_p; gs_p != (struct GRPSYL *) 0;
+                                               gs_p = gs_p->gs_p) {
+
+               /* skip lyrics */
+               if (gs_p->grpsyl == GS_SYLLABLE) {
+                       continue;
+               }
+
+               /* skip things on tab staff--we use the associated tabnotes
+                * staff instead */
+               if (is_tab_staff(gs_p->staffno) == YES) {
+                       continue;
+               }
+
+               /* double check */
+               if (gs_p->grpcont != GC_SPACE) {
+                       pfatal("non-space in zero-width chord");
+               }
+
+               /* find minimum time value of space */
+               if (LT(gs_p->fulltime, minspacetime)) {
+                       minspacetime = gs_p->fulltime;
+               }
+       }
+
+       /* find the start of the chord. Can't use ch_p->startime because
+        * we may have squeezed out time earlier in the measure and need
+        * to compensate for that. So have to count up the time before
+        * the group at the top of the chord. */
+       for (chordstart = Zero, gs_p = ch_p->gs_p->prev;
+                               gs_p != (struct GRPSYL *) 0;
+                               gs_p = gs_p->prev) {
+               chordstart = radd(chordstart, gs_p->fulltime);
+       }
+
+       /* if spaces are overlapped in strange ways between different
+        * voices, the minspacetime we found above may actually be too long.
+        * If the time between this chord and the next is less than the
+        * minspacetime found so far, make minspacetime the time till the
+        * next chord */
+       if (ch_p->ch_p != (struct CHORD *) 0) {
+               if (LT(rsub(ch_p->ch_p->starttime, chordstart), minspacetime)) {
+                       minspacetime = rsub(ch_p->ch_p->starttime, chordstart);
+               }
+       }
+
+       /* That still isn't completely adequate to find where the space actually
+        * ends, because if there were lots of grace notes moved back into a
+        * space, and a very short space in another voice, they could overlap.
+        * So go through the list of voices, seeing where the real end is.
+        * This code is unfortunately very similar to the code below it,
+        * yet different enough to make it hard to make it
+        * into a common function. */
+       chordend = radd(chordstart, minspacetime);
+       for (mll_p = chmll_p->next; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->next) {
+
+               /* CHHEAD is followed immediately by STAFFS, so when we
+                * hit something other than STAFF, we are done */
+               if (mll_p->str != S_STAFF) {
+                       break;
+               }
+
+               /* do each voice */
+               for (v = 0; v < MAXVOICES; v++ ) {
+                       /* Check if we have a special case where the actual
+                        * space is shorter than we thought. We unfortunately
+                        * cannot use hasspace() here, because it ignores grace
+                        * notes, and by now, grace notes have some time.
+                        * Find the chord that begins the space in question. */
+                       grpstart = Zero;
+
+                       if ((gs_p = mll_p->u.staff_p->groups_p[v])
+                                               == (struct GRPSYL *) 0) {
+                               /* no voice here, so that's all space.
+                                * That's good: we're done with this voice */
+                               continue;
+                       }
+
+                       /* grace notes at the beginning of the measure
+                        * have effectively been moved timewise
+                        * into previous measure, so discount them. */
+                       for (   ; gs_p->grpvalue == GV_ZERO
+                                       && gs_p->grpcont == GC_NOTES;
+                                       gs_p = gs_p->next) {
+                               ;
+                       }
+
+                       for (  ; gs_p != (struct GRPSYL *) 0;
+                                                       gs_p = gs_p->next) {
+
+                               /* see if this group start corresponds
+                                * with start of chord, or spills into
+                                * the chord or is the last chord. If
+                                * so, that's the one we want. */
+                               if (EQ(grpstart, chordstart) ||
+                                               GT(radd(grpstart,
+                                               gs_p->fulltime),
+                                               chordstart) ||
+                                               gs_p->next ==
+                                               (struct GRPSYL *) 0) {
+                                       /* found appropriate group */
+                                       break;
+                               }
+                               else {
+                                       /* accummulate time so far */
+                                       grpstart = radd(grpstart, gs_p->fulltime);
+                               }
+                       }
+
+                       if (gs_p == (struct GRPSYL *) 0) {
+                               pfatal("failed to find space group");
+                       }
+
+                       if (gs_p->grpcont != GC_SPACE) {
+                               /* things overlapped so much after the
+                                * grace note adjustments and such
+                                * that this isn't really a
+                                * crunch-able chord after all. */
+                               return;
+                       }
+
+                       /* need to adjust amount of space we
+                        * can really crunch. Find where this chord
+                        * ends, and add in the time of any immediately
+                        * following space groups. */
+                       new_chordend = radd(grpstart, gs_p->fulltime);
+                       for (gs_p = gs_p->next; gs_p != (struct GRPSYL *) 0;
+                                               gs_p = gs_p->next) {
+
+                               if (gs_p->grpcont == GC_SPACE) {
+                                       new_chordend = radd(new_chordend,
+                                                       gs_p->fulltime);
+                               }
+                               else {
+                                       break;
+                               }
+                       }
+
+                       /* if the newly calculated end is sooner than
+                        * what we had before, then adjust accordingly. */
+                       if (LT(new_chordend, chordend)) {
+                               chordend = new_chordend;
+                       }
+               }
+       }
+
+       /* recalculate the minspace time after any adjustment */
+       minspacetime = rsub(chordend, chordstart);
+       
+
+       /* go down each voice of each staff.
+        * For each, find the space group associated with the chord.
+        * If it has the same starttime as the chord and has minspacetime
+        * duration, it's easy: we just mark it GV_ZERO. Otherwise, if
+        * it starts earlier, we have to split off a group in the front
+        * first, and if it lasts longer than the end of the chord, we
+        * have to split off a group at the end first.
+        */
+       for (mll_p = chmll_p->next; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->next) {
+               /* CHHEAD is followed immediately by STAFFS, so when we
+                * hit something other than STAFF, we are done */
+               if (mll_p->str != S_STAFF) {
+                       break;
+               }
+
+               /* do each voice */
+               for (v = 0; v < MAXVOICES; v++ ) {
+
+                       /* get shorter name for list of grpsyls */
+                       group_p = mll_p->u.staff_p->groups_p[v];
+
+                       if (group_p == (struct GRPSYL *) 0) {
+                               continue;
+                       }
+
+                       /* go through groups, add up time till we find the
+                        * group we're looking for */
+                       grpstart = Zero;
+
+                       /* grace notes at the beginning of the measure
+                        * have effectively been moved timewise
+                        * into previous measure, so discount them. */
+                       for (gs_p = group_p; gs_p->grpvalue == GV_ZERO
+                                       && gs_p->grpcont == GC_NOTES;
+                                       gs_p = gs_p->next) {
+                               ;
+                       }
+
+                       for (  ; gs_p != (struct GRPSYL *) 0;
+                                               gs_p = gs_p->next) {
+
+                               /* see if this group start corresponds with
+                                * start of chord */
+                               if (EQ(grpstart, chordstart)) {
+                                       /* found appropriate group */
+                                       break;
+                               }
+
+                               else if (GT(radd(grpstart,gs_p->fulltime),
+                                                                chordstart)) {
+                                       /* This group spills into space
+                                        * to be crunched.
+                                        * Split off beginning of group. */
+                                       splitspace(gs_p,
+                                               rsub(chordstart, grpstart));
+
+                                       /* point to added group */
+                                       gs_p = gs_p->next;
+
+                                       /* splice added group into chord */
+                                       splicechord(gs_p, ch_p);
+
+                                       /* found appropriate group */
+                                       break;
+                               }
+                               else {
+                                       /* haven't gotten to the group yet.
+                                        * Add on the time taken by this
+                                        * group in preparation for next
+                                        * trip around the loop */
+                                       grpstart = radd(grpstart, gs_p->fulltime);
+                                       /* if last group in measure, this has
+                                        * to be the appropriate one */
+                                       if (gs_p->next == (struct GRPSYL *) 0) {
+                                               break;
+                                       } 
+                               }
+                       }
+
+                       if (gs_p == (struct GRPSYL *) 0) {
+                               pfatal("failed to find space group");
+                       }
+
+                       /* if group extended beyond end of
+                        * chord, split the group and splice added group
+                        * into chord */
+                       if (GT(gs_p->fulltime, minspacetime)) {
+                               splitspace(gs_p, minspacetime);
+                               splicechord(gs_p->next, ch_p->ch_p);
+                       }
+
+                       /* mark as taking no time */
+                       gs_p->grpvalue = GV_ZERO;
+               }
+       }
+}
+\f
+
+/* split a space grpsyl into two. The original group becomes the first
+ * group, having the specified duration. A new group is added after it,
+ * having the remainder of the time taken by the original group. */
+
+static void
+splitspace(gs_p, duration)
+
+struct GRPSYL *gs_p;   /* split this group */
+RATIONAL duration;     /* make the first group of split this long */
+
+{
+       struct GRPSYL *newgs_p; /* added group */
+
+
+       /* bug insurance */
+       if (gs_p == (struct GRPSYL *) 0 ||
+                       (gs_p->grpcont != GC_SPACE &&
+                       svpath(gs_p->staffno, VISIBLE)->visible == YES) ) {
+               pfatal("bad group passed to splitspace");
+       }
+
+       /* split into 2 groups, one taking duration, and the
+        * other taking the remainder */
+       newgs_p = newGRPSYL(GS_GROUP);
+       copy_attributes(newgs_p, gs_p);
+       newgs_p->grpcont = GC_SPACE;
+       newgs_p->fulltime = rsub(gs_p->fulltime, duration);
+       gs_p->fulltime = duration;
+
+       /* link new one into list */
+       newgs_p->next = gs_p->next;
+       newgs_p->prev = gs_p;
+       gs_p->next = newgs_p;   
+       if (newgs_p->next != (struct GRPSYL *) 0) {
+               newgs_p->next->prev = newgs_p;
+       }
+}
+\f
+
+/* splice a grpsyl into a chord */
+
+static void
+splicechord(gs_p, ch_p)
+
+struct GRPSYL *gs_p;   /* splice in this group */
+struct CHORD *ch_p;    /* splice into this chord */
+
+{
+       struct GRPSYL *nxtgs_p;         /* next group in chord list */
+       struct GRPSYL **ins_p_p;        /* where to insert new grpsyl */
+
+
+       if (ch_p == (struct CHORD *) 0) {
+               /* this could happen if user gave measure of space, and
+                * then following measure started with a grace note. The
+                * grace note got moved into the space, but there was no
+                * chhead created for it. It should be safe to just
+                * not link it into a chhead, so return */
+               return;
+       }
+
+       if (gs_p == (struct GRPSYL *) 0) {
+               pfatal("null pointer in splicechord");
+       }
+
+       /* Figure out where to insert. */
+       for (ins_p_p = &(ch_p->gs_p); (*ins_p_p) != (struct GRPSYL *) 0;
+                                               ins_p_p = &((*ins_p_p)->gs_p)) {
+
+               /* gets inserted here if next group is for a higher staffno or
+                * for a higher voice number of the same staffno */
+               nxtgs_p = *ins_p_p;
+               if (nxtgs_p == (struct GRPSYL *) 0) {
+                       /* goes at end of list */
+                       break;
+               }
+               if (nxtgs_p->staffno > gs_p->staffno ||
+                                  (nxtgs_p->staffno == gs_p->staffno &&
+                                  nxtgs_p->vno > gs_p->vno)) {
+                       break;
+               }
+       }
+
+       if (ins_p_p == (struct GRPSYL **) 0) {
+               pfatal("couldn't find where to insert new grpsyl into chord");
+       }
+
+       /* insert it */
+       gs_p->gs_p = *ins_p_p;
+       *ins_p_p = gs_p;
+}
+\f
+
+/* if user specifies the default guitar tab staff, then we want to transpose
+ * everything down an octave, because a standard guitar sounds an octave
+ * lower than it is written. */
+
+void
+guitar_transpose()
+
+{
+       struct MAINLL *mll_p;
+
+
+       /* go through the main list looking for things to transpose */
+       initstructs();
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0; mll_p = mll_p->next) {
+               if (mll_p->str == S_STAFF) {
+                       /* if there is a staff below this and that staff is a
+                        * guitar tab staff, then we need to transpose.
+                        * Index into Staff by this staff's number, because
+                        * staff numbers start at 1, but Staff index starts at 0
+                        */
+                       if (mll_p->u.staff_p->staffno < Score.staffs &&
+                                       Staff[mll_p->u.staff_p->staffno]
+                                       .strinfo == Guitar) {
+                               guitar_grpsyl_transpose(mll_p->u.staff_p->groups_p[0]);
+                       }
+               }
+               else if (mll_p->str == S_SSV) {
+                       asgnssv(mll_p->u.ssv_p);
+               }
+       }
+}
+\f
+
+/* given a group, transpose everything down by an octave */
+
+static void
+guitar_grpsyl_transpose(gs_p)
+
+struct GRPSYL *gs_p;
+
+{
+       register int n;
+
+       for(   ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+               for (n = 0; n < gs_p->nnotes; n++) {
+                       if (gs_p->notelist[n].octave > 0) {
+                               (gs_p->notelist[n].octave)--;
+                       }
+                       else {
+                               pfatal("guitar transposition results in note below octave 0");
+                       }
+               }
+       }
+}
+\f
+
+/* If there is an accidental on a note on one voice, it should really apply
+ * the other voice on that same staff too. So propogate these accidentals
+ * to the other voice if necessary.
+ */
+
+void
+other_voice_accidentals(staff_p)
+
+struct STAFF *staff_p;
+
+{
+       struct GRPSYL *gs_p;
+       int v;                  /* voice */
+       int n;                  /* notelist index */
+       RATIONAL begin_time, end_time;
+
+       /* if there is only one voice on the staff, or if either
+        * voice is a measure space or rest or multirest, nothing to do. Since
+        * we're doing MIDI, we know a "measure" GRPSYL
+        * will be rest or space, not mrpt, so can just check that. */
+        if ( (staff_p->groups_p[0]->is_meas == YES) ||
+                       (staff_p->groups_p[1] == (struct GRPSYL *) 0) ||
+                       (staff_p->groups_p[1]->is_meas == YES) ) {
+               return;
+       }
+
+       /* do each voice */
+       for (v = 0; v < MAXVOICES; v++) {
+
+               /* do each note of each chord */
+               begin_time = Zero;
+               for (gs_p = staff_p->groups_p[v]; gs_p != (struct GRPSYL *) 0;
+                                                       gs_p = gs_p->next) {
+
+                       for (n = 0; n < gs_p->nnotes; n++) {
+
+                               /* if this note doesn't have an accidental
+                                * nothing more to do on it */
+                               if (gs_p->notelist[n].accidental == '\0') {
+                                       continue;
+                               }
+
+                               /* This note does have an accidental.
+                                * Go forward and see how long it lasts.
+                                * It will last until there is another
+                                * accidental on the same note letter/octave
+                                * or until end of measure.
+                                */
+                               end_time = find_acc_end_time(begin_time, gs_p, n);
+
+                               /* now check the other voice.
+                                * If the same letter/octave note appears
+                                * on that voice on or after the begin time but
+                                * before the end time, and that note
+                                * does not already have an accidental,
+                                * give it the same accidental as
+                                * was found on the other voice.
+                                */
+                               propogate_accidental( &(gs_p->notelist[n]),
+                                       begin_time, end_time,
+                                       staff_p->groups_p[v == 0 ? 1 : 0]);
+                       }
+
+                       /* accumulate time so far in measure */
+                       begin_time = radd(begin_time, gs_p->fulltime);
+               }
+       }
+}
+
+/* Given an GRPSYL and a note n in its notelist, and a begin_time, return
+ * the end_time which is either the end of the measure or the next instance
+ * of the given note which has an accidental on it. */
+
+static RATIONAL
+find_acc_end_time(begin_time, gs_p, n)
+
+RATIONAL begin_time;
+struct GRPSYL *gs_p;
+int n;
+
+{
+       RATIONAL end_time;
+       struct GRPSYL *end_gs_p;
+       int n2;
+
+
+       end_time = begin_time;
+       end_gs_p = gs_p;
+       for ( ; ; ) {
+               /* Add up time that accidental lasts */
+               end_time = radd(end_time, end_gs_p->fulltime);
+
+               if ((end_gs_p = end_gs_p->next) == (struct GRPSYL *) 0) {
+                       /* Hit end of measure */
+                       return(end_time);
+               }
+
+               /* See if this group has the same note as had the accidental,
+                * and if so, whether it has a new accidental. */
+               for (n2 = 0; n2 < end_gs_p->nnotes; n2++) {
+                       if ((gs_p->notelist[n].letter
+                                       == end_gs_p->notelist[n2].letter) &&    
+                                       (gs_p->notelist[n].octave
+                                       == end_gs_p->notelist[n2].octave)) {
+
+                               /* does have the same note. check accidental */
+                               if (end_gs_p->notelist[n2].accidental != '\0') {
+                                       /* a new accidental, so this cancels
+                                        * the one we had */
+                                       return(end_time);
+                               }
+                               break;
+                       }
+               }
+       }
+}
+\f
+
+/* Check the groups in list pointed to by gs_p.
+ * If the letter/octave of the given note_p appears on or after the begin time
+ * but before the end time, and that note does not already have an accidental,
+ * give it the same accidental as was found on note_p. */
+
+static void
+propogate_accidental(note_p, begin_time, end_time, gs_p)
+
+struct NOTE *note_p;   /* look for note matching this one */
+RATIONAL begin_time;   /* look between the begin_time and end_time */
+RATIONAL end_time;
+struct GRPSYL *gs_p;   /* look in this list and adjust if needed */
+
+{
+       RATIONAL accumulated_time;
+       int n;
+
+
+       for (accumulated_time = Zero;
+                               gs_p != (struct GRPSYL *) 0;
+                               accumulated_time = radd(accumulated_time,
+                               gs_p->fulltime), gs_p = gs_p->next) {
+
+               if (LT(accumulated_time, begin_time)) {
+                       /* haven't gotten to begin yet */
+                       continue;
+               }
+
+               if (GE(accumulated_time, end_time)) {
+                       /* reached end time */
+                       return;
+               }
+
+               /* See if this group contains the note of interest */
+               for (n = 0; n < gs_p->nnotes; n++) {
+                       if ( (gs_p->notelist[n].letter == note_p->letter) &&
+                                       (gs_p->notelist[n].octave == note_p->octave) ) {
+                               /* if note already has an accidental,
+                                * the one from the other voice doesn't
+                                * count. Otherwise propogate the
+                                * accidental from the other voice */
+                               if (gs_p->notelist[n].accidental == '\0') {
+                                       gs_p->notelist[n].accidental
+                                                       = note_p->accidental;
+                               }
+
+                               /* Found the note and fixed it if needed,
+                                * so our job here is done */
+                               return;
+                       }
+               }
+       }
+}
+\f
+
+/* If doing MIDI with the -x option, we move all the midi STUFFs in the
+ * skipped leading measures to the "extra" empty measure that exists for MIDI.
+ * This ensure that any MIDI parameters, instruments, etc are correct
+ * for the place in the song where we are actually starting.
+ */
+
+void
+mv_midi_items(mll_p, topstaff_mll_p)
+
+struct MAINLL *mll_p;  /* points to a STAFF that may have MIDI items to move */
+struct MAINLL *topstaff_mll_p; /* points to STAFF where "all" MIDI items will go */
+
+{
+       struct STUFF *stuff_p;  /* stuff currently being processed */
+       struct STUFF *next;     /* we may move the current STUFF to another
+                                * list, so need to save its "next" */
+       char *key;              /* midi directive keyword */
+       int leng;               /* length of key */
+       char *arg;              /* arg after the = */
+       int staffno;
+
+
+       staffno = mll_p->u.staff_p->staffno;
+       for (stuff_p = mll_p->u.staff_p->stuff_p; stuff_p != 0; stuff_p = next) {
+               /* keep track of next, in case we delete the current */
+               next = stuff_p->next;
+
+               if (next == stuff_p) {
+                       pfatal("loop detected in MIDI list");
+               }
+
+               if (stuff_p->stuff_type == ST_MIDI) {
+                       if (getkeyword(stuff_p->string+2, &key, &leng, &arg)
+                                                               == NO) {
+                               /* invalid, so ignore it. */
+                               continue;
+                       }
+
+                       /* Some MIDI things, like cue point should just be
+                        * ignored if we are skipping over the music,
+                        * so just check for and move things we care about.
+                        */
+                       if (matches(key, leng, "program") == YES ||
+                                       matches(key, leng, "tempo") == YES ||
+                                       matches(key, leng, "onvelocity") == YES ||
+                                       matches(key, leng, "channel") == YES ||
+                                       matches(key, leng, "parameter") == YES ||
+                                       matches(key, leng, "offvelocity") == YES ||
+                                       matches(key, leng, "name") == YES ||
+                                       matches(key, leng, "instrument") == YES ||
+                                       matches(key, leng, "hex") == YES ||
+                                       matches(key, leng, "port") == YES ||
+                                       matches(key, leng, "chanpressure") == YES) {
+                               /* Found something to move; move it */
+                               mv_skipped_midi(stuff_p, staffno, topstaff_mll_p);
+                       }
+               }
+       }
+}
+\f
+
+/* With -x option and MIDI, this moves a MIDI STUFF from where it was in
+ * a skipped measure to the special "empty" measure at the beginning of the
+ * piece.  In general, for any given MIDI thing, only the last one matters,
+ * so we only need to keep the last one.
+ */
+
+static void
+mv_skipped_midi(stuff_p, staffno, topstaff_mll_p)
+
+struct STUFF *stuff_p;                 /* Midi STUFF to be moved */
+int staffno;                   /* Which staff it is for */
+struct MAINLL *topstaff_mll_p; /* The STAFF where midi "all" STUFF go.
+                                * Other STAFFs, if any, will surround it. */
+
+{
+       int leng;                       /* length of MIDI keyword */
+       char *oldtext;                  /* text of STUFF that already
+                                        * exists in the list */
+       char *newtext;                  /* text of STUFF to be added */
+       struct MAINLL *mll_p;           /* for finding STAFF to link to */
+       struct STAFF *staff_p = 0;      /* the STAFF to link to */
+       struct STUFF **stuff_p_p;       /* for finding where to add
+                                        * the new stuff_p into list */
+       static char *alphabet = "abcdefghijklmnopqrstuvwxyz";
+
+       /* Find the correct STAFF to attach to. We all passed a pointer
+        * to the STAFF for midi "all" items. For non-"all" items,
+        * we search in the main list for the correct STAFF. 
+        */
+       if (stuff_p->all == YES || staffno == topstaff_mll_p->u.staff_p->staffno) {
+               staff_p = topstaff_mll_p->u.staff_p;
+       }
+       else if (staffno < topstaff_mll_p->u.staff_p->staffno) {
+               /* Search backward for correct staff from the "all" staff.
+                * This case probably won't happen often--only if some
+                * staffs at the top are currently invisible (so they are
+                * not the current "top visible staff").
+                */
+               for (mll_p = topstaff_mll_p; mll_p->str == S_STAFF;
+                                               mll_p = mll_p->prev) {
+                       if (mll_p->u.staff_p->staffno == staffno) {
+                               staff_p = mll_p->u.staff_p;
+                               break;
+                       }
+               }
+       }
+       else {
+               /* Search forwards for correct staff from the "all" staff. */
+               for (mll_p = topstaff_mll_p; mll_p->str == S_STAFF;
+                                               mll_p = mll_p->next) {
+                       if (mll_p->u.staff_p->staffno == staffno) {
+                               staff_p = mll_p->u.staff_p;
+                               break;
+                       }
+               }
+       }
+       if (staff_p == 0) {
+               /* User must have reduced the number of staffs during the
+                * skipped part, so this one is irrelevant. */
+               return;
+       }
+
+       /* Add to end of list. When going through the list,
+        * see if there is already an item of that type (for param
+        * have to check the specific param matches too), and if so delete
+        * the earlier one, because this new one overrides it.
+        */
+       newtext = stuff_p->string + 2;
+       for (stuff_p_p = &(staff_p->stuff_p); *stuff_p_p != 0;
+                                       stuff_p_p = &((*stuff_p_p)->next) ) {
+
+               /* If for different place,
+                * this one doesn't count for matching */
+               if ( (*stuff_p_p)->place != stuff_p->place) {
+                       continue;
+               }
+
+               oldtext = (*stuff_p_p)->string + 2;
+
+               /* Since hex is arbitrary data, we always keep it */
+               if (matches(oldtext, strlen(oldtext), "hex")) {
+                       continue;
+               }
+
+               /* Names can be abbreviated,
+                * so match up to whichever is shorter */
+               leng = MIN(strspn(oldtext, alphabet), strspn(newtext, alphabet));
+               if (matches(newtext, leng, oldtext)== YES) {
+                       /* If it's something other than param, we can get
+                        * rid of the existing one */
+                       if (strncmp(newtext, "par", 3) != 0) {
+                               *stuff_p_p = (*stuff_p_p)->next;
+                       }
+                       else {
+                               /* Compare parameter numbers and if they match,
+                                * delete the existing one.
+                                */
+                               char *new_eq_p, *old_eq_p;      /* loc of '=' */
+                               int oldparm, oldval;
+                               int newparm, newval;
+
+                               new_eq_p = strchr(newtext, '=');
+                               old_eq_p = strchr(oldtext, '=');
+                               if (new_eq_p != 0 && old_eq_p != 0) {
+                                       if (get_param(new_eq_p + 1,
+                                                       stuff_p->inputfile,
+                                                       stuff_p->inputlineno,
+                                                       &newparm, &newval)
+                                                       == YES &&
+                                                       get_param(old_eq_p + 1,
+                                                       (*stuff_p_p)->inputfile,
+                                                       (*stuff_p_p)->inputlineno,
+                                                       &oldparm, &oldval)
+                                                       == YES &&
+                                                       oldparm == newparm) {
+                                               *stuff_p_p = (*stuff_p_p)->next;
+                                       }
+                               }
+                       }
+
+                       if (*stuff_p_p == 0) {
+                               /* If deleted last item in the existing list,
+                                * jump out, so we won't try to deference
+                                * this null pointer. */
+                               break;
+                       }
+               }
+       }
+
+       /* Just do everything at beat zero. The beat at which user specified
+        * might not even exist in the current time signature, and basically
+        * we just want to do everything ASAP anyway. We know there is never
+        * a 'til' on midi, so no need to deal with that. We could end up
+        * with a lot to do at count zero, potentially enough to overwhelm
+        * the limited MIDI bandwidth and delay the first actual note.
+        * But that potential is always there, and by discarding things
+        * that were overwritten later, which we did above, unless there
+        * are an awfully lot of parameters on every possible channel,
+        * it's probably only going to take less than 0.1 second,
+        * so it doesn't seem worth the bother to try to do something
+        * fancy to calculate how much time we need for this stuff
+        * and delay the actual music by that much. */
+       stuff_p->start.count = 0.0;
+       stuff_p->start.steps = 0.0;
+
+       /* link onto end of list */
+       *stuff_p_p = stuff_p;
+       stuff_p->next = 0;
+}
+\f
+
+/* Given the argument to a MIDI "parameter" command, extract and return
+ * (via pointers) the two numbers (the parameter number and its value).
+ * If successful, returns YES, else prints a warning and returns NO.
+ * If NO is returned, the pointed to return values are not fill in.
+ */
+
+int
+get_param(arg, inputfile, inputlineno, parmnum_p, parmval_p)
+
+char *arg;             /* the argument part after "parameter=" */
+char *inputfile;       /* for error messages */
+int inputlineno;       /* for error messages */
+int *parmnum_p;                /* parameter number is returned here */
+int *parmval_p;                /* parameter value is returned here */
+
+{
+       int parmnum;    /* parameter number */
+       int parmval;    /* parameter value */
+       char *parm_p;   /* pointer to current place in string */
+
+
+       /* extract first number */
+       parmnum = strtol(arg, &parm_p, 10);
+       if (parm_p == arg) {
+               l_warning(inputfile, inputlineno,
+                       "parameter requires two values");
+               return(NO);
+       }
+       /* skip white space, if any */
+       while (*parm_p == ' ' || *parm_p == '\t') {
+               parm_p++;
+       }
+       /* next we better have a comma */
+       if (*parm_p != ','){
+               l_warning(inputfile, inputlineno,
+                       "parameter is missing required comma");
+               return(NO);
+       }
+       /* extract the second number */
+       arg = parm_p + 1;
+       parmval = strtol(arg, &parm_p, 10);
+       if (parm_p == arg) {
+               l_warning(inputfile, inputlineno,
+                       "parameter is missing second value");
+               return(NO);
+       }
+       /* verify both numbers are within range */
+       if ((l_rangecheck(parmnum, 0, 127, "parameter number",
+                       inputfile, inputlineno) == YES) &&
+                       (l_rangecheck(parmval, 0, 127, "parameter value",
+                       inputfile, inputlineno) == YES)) {
+               *parmnum_p = parmnum;
+               *parmval_p = parmval;
+               return(YES);
+       }
+       return(NO);
+}
diff --git a/mup/mup/mkchords.c b/mup/mup/mkchords.c
new file mode 100644 (file)
index 0000000..6919e60
--- /dev/null
@@ -0,0 +1,1767 @@
+/* Copyright (c) 1995, 1996, 1997, 1998, 2002, 2003, 2004, 2006
+ * by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ * Name:       mkchords.c
+ *
+ * Description:        This file contains functions for creating CHORD linked lists
+ *             and erasing invisible voices.
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+static void swingmidi P((void));
+static struct GRPSYL *voicevis P((struct GRPSYL *gs_p));
+static void combine_voices P((void));
+static void chkhand1 P((struct GRPSYL *gs1_p, struct MAINLL *staffmll_p));
+static int chk2groups P((struct GRPSYL *hi_p, struct GRPSYL *lo_p,
+               struct MAINLL *mll_p, int qual));
+static void chkhand2 P((struct GRPSYL *gs1_p, struct MAINLL *staffmll_p));
+static int chk2neighbors P((struct GRPSYL *first_p, struct GRPSYL *second_p,
+               struct GRPSYL *gs1_p, struct MAINLL *mll_p));
+static void dohand P((struct GRPSYL *gs1_p, struct MAINLL *staffmll_p));
+static void comb2groups P((struct GRPSYL *dest_p, struct GRPSYL *src_p,
+               struct MAINLL *mll_p));
+static void addsrc2dest P((struct GRPSYL *dest_p, struct GRPSYL *src_p));
+static int setgrpptrs P((struct GRPSYL *gs1_p, struct GRPSYL *v_p[]));
+static int hastieslur P((struct GRPSYL *gs_p));
+\f
+/*
+ * Name:        makechords()
+ *
+ * Abstract:    Set up the linked lists of chords.
+ *
+ * Returns:     void
+ *
+ * Description: This function scans through the main linked list looking
+ *             for STAFF structures.  It joins the GRPSYL structures in
+ *             the lists that they head, into perpendicular linked lists,
+ *             allocating a CHORD to head each of these.  It also links
+ *             the CHORDs for each measure together into a linked list.
+ *
+ *             While doing the above, it also calls voicevis() to check if a
+ *             voice should be invisible, and if so changes it to a measure
+ *             space.  It also applies the swingunit and voicecombine
+ *             parameters.
+ */
+
+
+void
+makechords()
+
+{
+       struct MAINLL *mainll_p;        /* point at item in main linked list */
+       struct MAINLL *mainch_p;        /* for headcell of a chord list */
+
+       RATIONAL *vtime;                /* cum. time of each voice and verse */
+       struct GRPSYL **grpsyl_p;       /* pointers along GRPSYL lists */
+       struct STAFF *staff_p;          /* point at a staff structure */
+
+       RATIONAL mintime;               /* the minimum vtime */
+       register int num;               /* no. of visible voices/verses */
+       register int v;                 /* index into grpsyl_p[] */
+       struct CHORD *ch_p;             /* pointer to current chord */
+       struct CHORD *och_p;            /* pointer to old chord */
+       struct GRPSYL *gs_p;            /* pointer to current group/syllable */
+       int n;                          /* loop variable */
+       int firstgs;                    /* flag for first group/syllable */
+       int quit;                       /* flag for being done */
+
+
+       debug(16, "makechords");
+       /*
+        * If we are generating MIDI, we may need to change lengths (fulltimes)
+        * of groups.  This has to be done now, before we link groups together
+        * into chords.
+        */
+       if (Doing_MIDI == YES) {
+               swingmidi();
+       }
+
+       gs_p = 0;               /* keep lint happy; will be set before used */
+
+       /* malloc enough of these for all voices and verses */
+       MALLOC(rational, vtime, MAXSTAFFS * (MAXVOICES + Maxverses));
+       MALLOC(GRPSYL *, grpsyl_p, MAXSTAFFS * (MAXVOICES + Maxverses));
+
+       mainll_p = Mainllhc_p;          /* point at first thing in main LL */
+
+       initstructs();                  /* clean out old SSV info */
+
+       /*
+        * Loop once for each measure in the input.
+        */
+       for (;;) {
+               num = 0;                /* number of linked lists in measure */
+
+               /*
+                * Look for the first structure in this measure that points off
+                * to a linked list of groups/syllables.  If we hit the end of
+                * the main linked list, we're all done, so break out.
+                */
+               while (mainll_p != 0 && mainll_p->str != S_STAFF) {
+                       if (mainll_p->str == S_SSV)
+                               asgnssv(mainll_p->u.ssv_p);
+                       mainll_p = mainll_p->next;
+               }
+
+               if (mainll_p == 0) {
+                       FREE(vtime);
+                       FREE(grpsyl_p);
+                       break;
+               }
+
+               /*
+                * We've found another measure with STAFF in it.  Allocate
+                * a chord headcell for this measure, and put it in the
+                * main linked list.
+                */
+               mainch_p = newMAINLLstruct(S_CHHEAD, 0);
+               insertMAINLL(mainch_p, mainll_p->prev);
+
+               /*
+                * Look for the last STAFF structure in the measure.  While
+                * doing this, point at first element of all the group/syllable
+                * linked lists, and keep count of them.  Ignore invisible
+                * staffs.  Skip over any grace groups.
+                */
+               while (mainll_p != 0 && mainll_p->str == S_STAFF) {
+                       staff_p = mainll_p->u.staff_p;
+
+                       if (staff_p->visible == YES) {
+
+                               /* do all the voices on this staff */
+                               for (n = 0; n < MAXVOICES &&
+                               staff_p->groups_p[n] != 0; n++) {
+                                       /*
+                                        * Zap voice if invisible.  Set both
+                                        * of these to point at the first
+                                        * GRPSYL, which will be a new one if
+                                        * we zapped it.
+                                        */
+                                       grpsyl_p[num] = staff_p->groups_p[n] =
+                                       voicevis(staff_p->groups_p[n]);
+
+                                       /* skip leading grace groups */
+                                       while (grpsyl_p[num] != 0 &&
+                                       grpsyl_p[num]->grpvalue == GV_ZERO)
+                                               grpsyl_p[num] = grpsyl_p[num]->next;
+                                       if (grpsyl_p[num] == 0)
+                                               pfatal("nothing but grace groups found");
+                                       num++;
+                               }
+
+                               /* do all the verses on this staff */
+                               for (n = 0; n < staff_p->nsyllists; n++)
+                                       grpsyl_p[num++] = staff_p->syls_p[n];
+                       }
+                       mainll_p = mainll_p->next;
+               }
+
+               /*
+                * Set up the first chord from the first note in each
+                * voice/verse.  Its linked list of GRPSYLs will include
+                * the first GRPSYL in every linked list off of a visible
+                * STAFF.
+                */
+               MALLOC(CHORD, ch_p, 1);
+               mainch_p->u.chhead_p->ch_p = ch_p; /* point at first chord */
+               ch_p->ch_p = 0;         /* only member on list so far */
+               ch_p->starttime = Zero; /* start time = any voice */
+
+               /* point headcell at first and set its first group's time */
+               ch_p->gs_p = grpsyl_p[0];
+               vtime[0] = grpsyl_p[0]->fulltime;
+
+               /* for each remaining one, point prev one at it & set time */
+               for (v = 1; v < num; v++) {
+                       grpsyl_p[v-1]->gs_p = grpsyl_p[v];
+                       vtime[v] = grpsyl_p[v]->fulltime;
+               }
+               grpsyl_p[num-1]->gs_p = 0;      /* terminate linked list */
+
+               /* point at second GRPSYL in each voice/verse, if any */
+               for (v = 0; v < num; v++)
+                       grpsyl_p[v] = grpsyl_p[v]->next;
+
+               /*
+                * Loop until groups/syllables in the voices/verses are used
+                * up.  Form a chord for each time at which any voice/verse
+                * has a GRPSYL structure, though ignore grace groups.
+                */
+               for (;;) {
+                       /*
+                        * If every GRPSYL currently pointed at by a grpsyl_p[]
+                        * is the last in its list (the measure), there are no
+                        * more chords in this measure, and quit will remain
+                        * YES.
+                        */
+                       quit = YES;             /* first assume "quit" */
+                       for (v = 0; v < num; v++) {
+                               /* find next item (if any) not a grace group */
+                               while (grpsyl_p[v] != 0 &&
+                                      grpsyl_p[v]->grpsyl == GS_GROUP &&
+                                      grpsyl_p[v]->grpvalue == GV_ZERO) {
+
+                                       grpsyl_p[v] = grpsyl_p[v]->next;
+                               }
+
+                               /* check if voice/verse has another item */
+                               if (grpsyl_p[v] != 0) {
+                                       quit = NO; /* yes, so don't quit yet */
+                               }
+                       }
+
+                       /* if time to quit, skip rest of loop, and get out */
+                       if (quit == YES)
+                               break;
+
+                       /*
+                        * At least one voice/verse has another note in it.
+                        * Find the earliest time at which something changes.
+                        */
+                       mintime = vtime[0];
+                       for (v = 1; v < num; v++)
+                               if (LT(vtime[v], mintime))
+                                       mintime = vtime[v];
+
+                       /* allocate memory for another chord */
+                       och_p = ch_p;   /* remember where previous chord is */
+                       MALLOC(CHORD, ch_p, 1);
+                       och_p->ch_p = ch_p;     /* point previous chord at it*/
+                       ch_p->ch_p = 0;         /* terminate in case last */
+
+                       ch_p->starttime = mintime; /* starting time for chord*/
+
+                       /*
+                        * Form a new linked list.  The head cell is the new
+                        * chord, and the list connects it to all the groups/
+                        * syllables that start at this time.
+                        */
+                       firstgs = YES;
+                       for (v = 0; v < num; v++) {
+                               if (EQ(vtime[v], mintime)) {
+                                       /*
+                                        * This voice/verse has a grpsyl at
+                                        * this time.  Make the previous one
+                                        * point at it, set its pointer to 0
+                                        * in case it turns out to be the last,
+                                        * and add its length to vtime[v].
+                                        */
+                                       if (firstgs == YES) {
+                                               /* point headcell at first */
+                                               ch_p->gs_p = grpsyl_p[v];
+                                               firstgs = NO;
+                                       } else {
+                                               /* point previous one at ours*/
+                                               gs_p->gs_p = grpsyl_p[v];
+                                       }
+
+                                       /* set gs_p to point at our new one */
+                                       gs_p = grpsyl_p[v];
+
+                                       vtime[v] = radd(vtime[v],
+                                                       gs_p->fulltime);
+
+                                       /* get next GRPSYL in voice/verse */
+                                       grpsyl_p[v] = gs_p->next;
+                               }
+                       }
+
+                       gs_p->gs_p = 0;         /* terminate linked list */
+               }
+
+               /*
+                * Set the duration of each chord in this measure.  It's the
+                * next chord's start time minus this chord's start time.
+                * But for the last chord, it's the time signature minus
+                * this chord's start time.  Also set pseudodur, which is a
+                * function of the duration.  The amount of width the chord
+                * "deserves" to be allocated is proportional to pseudodur.
+                */
+               for (ch_p = mainch_p->u.chhead_p->ch_p; ch_p->ch_p != 0;
+                               ch_p = ch_p->ch_p) {
+                       ch_p->duration = rsub(ch_p->ch_p->starttime,
+                                               ch_p->starttime);
+                       ch_p->pseudodur = pow(RAT2FLOAT(ch_p->duration),
+                                               Score.packexp);
+               }
+               ch_p->duration = rsub(Score.time, ch_p->starttime);
+               ch_p->pseudodur = pow(RAT2FLOAT(ch_p->duration), Score.packexp);
+       }
+
+       /* if voicecombine parm was ever set, combine voices if possible */
+       if (Vcombused == YES) {
+               combine_voices();
+       }
+}
+\f
+/*
+ * Name:       swingmidi()
+ *
+ * Abstract:   Alter groups' time to implement the "swingunit" parameter.
+ *
+ * Returns:    void
+ *
+ * Description:        This function loops through every GRPSYL in every voice,
+ *             adjusting their fulltime so that they will start and end at
+ *             different times, if necessary, to follow the "swingunit" parm.
+ *             Each measure is divided into durations of "swingunit", starting
+ *             at the beginning.  (Usually the timesig divided by swingunit
+ *             will be an integer, but if not, the last piece will be shorter.)
+ *             The time where one group ends and the next group starts will be
+ *             altered in either of these two circumstances:
+ *             1. The current boundary time is halfway into a swingunit, and
+ *                each group is at least half a swingunit long.
+ *             2. The current boundary time is 3/4 of the way into a swingunit,
+ *                and the first group is at least 3/4 of a swingunit long, and
+ *                and the second group is at least 1/4 of a swingunit long.
+ *             In both of these cases, the fulltimes are altered so that the
+ *             meeting point is 2/3 of the way into the swingunit.
+ */
+
+void
+swingmidi()
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct GRPSYL *gs_p;            /* point along a GRPSYL list */
+       struct GRPSYL *prev_p;          /* the GRPSYL before gs_p */
+       int vidx;                       /* voice index, 0 to MAXVOICES-1 */
+       RATIONAL quot;                  /* quotient */
+       RATIONAL swingunit;             /* from SSV */
+       RATIONAL starttime;             /* offset into measure of gs_p */
+       RATIONAL halfswing;             /* swingunit/2 */
+       RATIONAL sixthswing;            /* swingunit/6 */
+       RATIONAL twelfthswing;          /* swingunit/12 */
+       RATIONAL threefourthsswing;     /* 3/4 * swingunit */
+       RATIONAL onefourthswing;        /* 1/4 * swingunit */
+       static RATIONAL six = {6,1};
+       static RATIONAL twelve = {12,1};
+
+
+       initstructs();
+
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               switch (mainll_p->str) {
+               case S_SSV:
+                       /* need to keep swingunit up to date */
+                       asgnssv(mainll_p->u.ssv_p);
+                       continue;
+               case S_STAFF:
+                       break;  /* break out and handle this staff */
+               default:
+                       continue;
+               }
+
+               /* loop through every voice on this staff */
+               for (vidx = 0; vidx < MAXVOICES; vidx++) {
+
+                       swingunit = vvpath(mainll_p->u.staff_p->staffno,
+                                       vidx + 1, SWINGUNIT)->swingunit;
+
+                       /* skip this voice if swingunit was not set */
+                       if (EQ(swingunit, Zero)) {
+                               continue;
+                       }
+
+                       /* various rationals we will need in the loop below */
+                       halfswing = rdiv(swingunit, Two);
+                       threefourthsswing = rmul(swingunit, Three_fourths);
+                       onefourthswing = rmul(swingunit, One_fourth);
+                       sixthswing = rdiv(swingunit, six);
+                       twelfthswing = rdiv(swingunit, twelve);
+
+                       /* accumulate starttime */
+                       starttime = Zero;
+
+                       /* for lint; we'll never really check it when it's 0 */
+                       prev_p = 0;
+
+                       /* find first nongrace group in voice (0 if none) */
+                       gs_p = mainll_p->u.staff_p->groups_p[vidx];
+                       gs_p = gs_p != 0 && gs_p->grpvalue == GV_ZERO ?
+                                       nextnongrace(gs_p) : gs_p;
+
+                       /* loop through every nongrace group in this voice */
+                       for ( ; gs_p != 0; gs_p = nextnongrace(gs_p)) {
+
+                               quot = rdiv(starttime, swingunit);
+
+                               /* set starttime for the following group here
+                                * because we may alter fulltime below */
+                               starttime = radd(starttime, gs_p->fulltime);
+
+                               /* handle case 1 (see prolog above) */
+                               if (quot.d == 2 &&
+                                   GE(gs_p->fulltime, halfswing) &&
+                                   GE(prev_p->fulltime, halfswing)) {
+
+                                       prev_p->fulltime = radd(
+                                               prev_p->fulltime, sixthswing);
+                                       gs_p->fulltime = rsub(
+                                               gs_p->fulltime, sixthswing);
+                               }
+
+                               /* handle case 2 (see prolog above) */
+                               if (quot.d == 4 && quot.n % 4 == 3 &&
+                                   GE(gs_p->fulltime, onefourthswing) &&
+                                   GE(prev_p->fulltime, threefourthsswing)) {
+
+                                       prev_p->fulltime = rsub(
+                                               prev_p->fulltime, twelfthswing);
+                                       gs_p->fulltime = radd(
+                                               gs_p->fulltime, twelfthswing);
+                               }
+
+                               prev_p = gs_p;
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        voicevis()
+ *
+ * Abstract:    If this voice is to be invisible, make it a measure space.
+ *
+ * Returns:     pointer to first GRPSYL; this equals the input pointer if the
+ *             voice is visible, else it points at the new measure space GRPSYL
+ *
+ * Description: This function finds out if the given voice is supposed to be
+ *             invisible this measure.  If so, it throws away the current
+ *             GRPSYL list, replacing it with a single GRPSYL that is a
+ *             measure space.  See the big comment in svpath() in ssv.c.
+ */
+
+
+static struct GRPSYL *
+voicevis(gs_p)
+
+struct GRPSYL *gs_p;           /* first GRPSYL in this voice's linked list */
+
+{
+       struct GRPSYL *ngs_p;   /* pointer to the new GRPSYL */
+
+
+       /*
+        * At this point we know that the command line -s option allows this
+        * staff to be printed, and in fact this staff will be printed, because
+        * at least one of its voice(s) is supposed to be.  (We know this
+        * because where we were called from, staff_p->visible == YES, and that
+        * was set by calling svpath().)  If the staff weren't being printed,
+        * we wouldn't need to bother wiping out its invisible voice(s).
+        */
+
+       /*
+        * This voice must be changed to a measure space if the -s option says
+        * it should be invisible, or if the SSVs say so.  The vvpath function
+        * checks both things.
+        */
+       if (vvpath(gs_p->staffno, gs_p->vno, VISIBLE)->visible == NO) {
+
+               /*
+                * Allocate a new GRPSYL and make it a measure space, with the
+                * same inputlineno etc. as the first in the current list.
+                */
+               ngs_p = newGRPSYL(GS_GROUP);
+
+               ngs_p->inputlineno = gs_p->inputlineno;
+               ngs_p->inputfile = gs_p->inputfile;
+               ngs_p->staffno = gs_p->staffno;
+               ngs_p->vno = gs_p->vno;
+               ngs_p->grpsyl = GS_GROUP;
+               ngs_p->is_meas = YES;
+               ngs_p->basictime = -1;
+
+               /* in one compiler the following had to be done separately */
+               /* like this, because it couldn't do the structure assignment */
+               ngs_p->fulltime.n = Score.time.n;
+               ngs_p->fulltime.d = Score.time.d;
+
+               ngs_p->grpcont = GC_SPACE;
+               ngs_p->prev = 0;
+               ngs_p->next = 0;
+               ngs_p->gs_p = 0;
+
+               /* throw away the old GRPSYL list */
+               free_grpsyls(gs_p);
+
+               return (ngs_p); /* ret pointer to the measure space */
+       }
+
+       return (gs_p);  /* ret pointer to the original, unchanged GRPSYL */
+}
+\f
+/*
+ * Name:        combine_voices()
+ *
+ * Abstract:    Combine GRPSYLs in voices according to the voicecombine parm.
+ *
+ * Returns:     void
+ *
+ * Description: This function, if requested by the voicecombine parameter,
+ *             combines the appropriate groups in each chord on each staff
+ *             where it can.  (The set of groups in one chord on one staff is
+ *             called a "hand" in the following code and in some other places
+ *             in Mup, because I get tired of spelling out the whole phrase.)
+ *             Because of beaming and ties/slurs, some groups may need to
+ *             remain uncombined because their neighbors can't be combined.
+ *             So the work is done in three passes.  The first pass looks at
+ *             each hand individually to see what can be done there.  The
+ *             second pass applies the neighbor rules.  The third pass does
+ *             the actual combining.
+ */
+/*
+ * NOTE:  GRPSYL.pvno is used as a scratch area in these functions.  The macro
+ * below defines COMB to be pvno for this use.  We rely on the fact that CALLOC
+ * initialized it to 0.  We count the low order bit as bit 0.  Two sets of bits
+ * are used, as follows.
+ *
+ * Bit "x+y" being set to 1 means that the GRPSYLs of voices x and y can be
+ * combined (looking only at the groups in this chord, not groups they may be
+ * tie/beamed to, etc.).  This scheme works only because the only voice numbers
+ * are 1, 2, and 3, so that uses bits 3, 4, and 5.  The first pass sets them,
+ * and the second pass reads them.
+ *
+ * Bits 6 through 13 are used in pairs for voice numbers of groups that really
+ * should be combined, with all rules applied.  The SHIFT macros below give the
+ * rightmost bit of each of the voice numbers, for the two possible sources and
+ * destinations that can happen, given that only 3 voices can exist.  Pass 2
+ * sets these bits, and pass 3 reads them.
+ */
+#define COMB           pvno
+#define SRC1SHIFT      6
+#define DEST1SHIFT     8
+#define SRC2SHIFT      10
+#define DEST2SHIFT     12
+
+static void
+combine_voices()
+{
+       struct MAINLL *mll_p;   /* point along main linked list */
+       struct MAINLL *staffmll_p; /* point a group's staff's MLL struct */
+       struct CHORD *ch_p;     /* point along a chord list */
+       struct GRPSYL *gs1_p;   /* point along the GRPSYL list of a chord */
+       int staff;              /* staff number we are working on */
+       int pass;               /* the three passes we must make */
+
+
+       /* run the three passes */
+       for (pass = 1; pass <= 3; pass++) {
+
+               initstructs();                  /* clean out old SSV info */
+
+               for (mll_p = Mainllhc_p; mll_p != 0; mll_p = mll_p->next) {
+
+                       switch (mll_p->str) {
+                       case S_SSV:
+                               /* keep SSVs up to date (but midmeasure SSVs
+                                * don't matter for what we're doing here) */
+                               asgnssv(mll_p->u.ssv_p);
+                               continue;
+                       case S_CHHEAD:
+                               break;  /* break out to handle the chords */
+                       default:
+                               continue;       /* ignore everything else */
+                       }
+
+                       /*
+                        * Loop through each chord in this list.
+                        */
+                       for (ch_p = mll_p->u.chhead_p->ch_p; ch_p != 0;
+                                               ch_p = ch_p->ch_p) {
+                               /*
+                                * Loop through the linked list of GRPSYLs
+                                * hanging off this chord.  Skip the syllables;
+                                * just deal with the groups.
+                                */
+                               gs1_p = ch_p->gs_p;
+                               staff = 0;      /* before first staff */
+                               for (;;) {
+                                       /* find first group on next staff */
+                                       while (gs1_p != 0 &&
+                                              gs1_p->staffno == staff) {
+                                               gs1_p = gs1_p->gs_p;
+                                       }
+                                       if (gs1_p == 0) {  /* no next staff */
+                                               break;
+                                       }
+
+                                       /* remember this new staff number */
+                                       staff = gs1_p->staffno;
+
+                                       /* tab ignores vcombine */
+                                       if (is_tab_staff(staff)) {
+                                               continue;
+                                       }
+
+                                       /* 1-line ignores vcombine */
+                                       if (svpath(staff, STAFFLINES)->
+                                                       stafflines == 1) {
+                                               continue;
+                                       }
+
+                                       /* if no groups, only syls, ignore */
+                                       if (gs1_p->grpsyl == GS_SYLLABLE) {
+                                               continue;
+                                       }
+
+                                       /* skip staff if only one voice */
+                                       if (svpath(staff, VSCHEME)->vscheme
+                                                       == V_1) {
+                                               continue;
+                                       }
+
+                                       /* get the staff's MLL struct */
+                                       staffmll_p = chmgrp2staffm(
+                                                               mll_p, gs1_p);
+
+                                       switch (pass) {
+                                       case 1:
+                                               /*
+                                                * Set individual combineability
+                                                * in the "COMB" field.
+                                                */
+                                               chkhand1(gs1_p, staffmll_p);
+                                               break;
+                                       case 2:
+                                               /*
+                                                * Apply the neighbor rules.
+                                                */
+                                               chkhand2(gs1_p, staffmll_p);
+                                               break;
+                                       case 3:
+                                               /*
+                                                * Do the actual combining.
+                                                */
+                                               dohand(gs1_p, staffmll_p);
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        chkhand1()
+ *
+ * Abstract:    Find which voices are combineable, ignoring neighbor rules.
+ *
+ * Returns:     void
+ *
+ * Description: This function finds out which groups in this hand can be
+ *             combined, of the ones requested by the voicecombine parameter,
+ *             but ignoring neighbor rules.  It stores the results in
+ *             the COMB field of all the groups.
+ */
+
+static void
+chkhand1(gs1_p, mll_p)
+
+struct GRPSYL *gs1_p;          /* first group in this hand */
+struct MAINLL *mll_p;          /* MLL struct for this group */
+
+{
+       /*
+        * Index the following by voice number to find the expected "height" of
+        * the voices, relative to each other.  A higher number means we expect
+        * that that voice should normally be higher.
+        */                                /* v1 v2 v3 */
+       static int pitch[MAXVOICES + 1] = { 0, 3, 1, 2 };
+
+       struct SSV *ssv_p;              /* the SSV with voice combine info */
+       struct GRPSYL *gs_p;            /* point along GRPSYLs of the chord */
+       /* index the following by vno; it points at the GRPSYL for this vno */
+       struct GRPSYL *v_p[MAXVOICES + 1];
+       int slot1, slot2;               /* indices into SSV's vcombine array */
+       int firstvno, secondvno;        /* two voices from ssv_p->vcombine[] */
+       int combineable;                /* YES or NO */
+       int comb;                       /* accumulate combineable bits */
+
+
+       /* point at each group; if only one, no combining can be done */
+       if (setgrpptrs(gs1_p, v_p) == 1) {
+               return;
+       }
+
+       /* get the list of groups we want to combine */
+       ssv_p = svpath(gs1_p->staffno, VCOMBINE);
+
+       /* for each pair of voices to be combined, see if they can be */
+       comb = 0;
+       for (slot1 = 0; slot1 < MAXVOICES; slot1++) {
+               firstvno = ssv_p->vcombine[slot1];
+               if (firstvno == 0) {
+                       break;  /* end of list, done with outer loop */
+               }
+               /* voice must have a group in this chord */
+               if (v_p[firstvno] == 0) {
+                       continue;       /* skip this iteration */
+               }
+               for (slot2 = slot1 + 1; slot2 < MAXVOICES; slot2++) {
+                       secondvno = ssv_p->vcombine[slot2];
+                       if (secondvno == 0) {
+                               break;  /* end of list, done with inner loop */
+                       }
+                       /* voice must have a group in this chord */
+                       if (v_p[secondvno] == 0) {
+                               continue;       /* skip this iteration */
+                       }
+                       /* must pass higher voice first */
+                       if (pitch[firstvno] > pitch[secondvno]) {
+                               combineable = chk2groups(v_p[firstvno],
+                                       v_p[secondvno], mll_p,
+                                       ssv_p->vcombinequal);
+                       } else {
+                               combineable = chk2groups(v_p[secondvno],
+                                       v_p[firstvno], mll_p,
+                                       ssv_p->vcombinequal);
+                       }
+
+                       /* if this pair was combineable, remember that */
+                       if (combineable == YES) {
+                               comb |= 1 << (firstvno + secondvno);
+                       }
+               }
+       }
+
+       /* save comb in all the groups, for easy access */
+       for (gs_p = gs1_p; gs_p != 0 && gs_p->staffno == gs1_p->staffno &&
+                       gs_p->grpsyl == GS_GROUP; gs_p = gs_p->gs_p) {
+               gs_p->COMB = comb;
+       }
+}
+\f
+/*
+ * Name:        chk2groups()
+ *
+ * Abstract:    Find whether two groups are combineable.
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function finds out if the given groups can be combined,
+ *             ignoring beam and tie/slur issues.  If either has preceding
+ *             grace groups, they are also checked (via recursive calls) and
+ *             they must also be able to be combined, to get a YES answer.
+ */
+
+static int
+chk2groups(hi_p, lo_p, mll_p, qual)
+
+struct GRPSYL *hi_p;           /* group that should have higher pitch */
+struct GRPSYL *lo_p;           /* group that should have lower pitch */
+struct MAINLL *mll_p;          /* MLL struct for this group */
+int qual;                      /* voice combine qualifier */
+
+{
+       struct GRPSYL *phi_p;   /* group before hi_p */
+       struct GRPSYL *plo_p;   /* group before lo_p */
+       struct MAINLL *tempmll_p; /* temp copy of mll_p */
+       int widx;               /* index into "with" lists */
+       int hidx, lidx;         /* index into note lists */
+       int mintop;             /* steps above c0 of top group's lowest note */
+       int maxbot;             /* steps above c0 of bot group's highest note */
+       int n;                  /* loop variable */
+       struct NOTE *hnote_p;   /* point at a note in the high group */
+       struct NOTE *lnote_p;   /* point at a note in the low group */
+       struct SLURTO *hslur_p; /* point at a slur in the high group */
+       struct SLURTO *lslur_p; /* point at a slur in the high group */
+
+
+       /*
+        * Since the groups are in the same chord, we know they start at the
+        * same time.  Require that they end at the same time.
+        */
+       if (NE(hi_p->fulltime, lo_p->fulltime)) {
+               return (NO);
+       }
+
+       /* covered by the fulltime check, except for bizarre tuplet cases */
+       if (hi_p->basictime != lo_p->basictime) {
+               return (NO);
+       }
+       if (hi_p->dots != lo_p->dots) {
+               return (NO);
+       }
+
+       /* don't allow "mr" and "1r" (for example) to combine */
+       if (hi_p->is_meas != lo_p->is_meas) {
+               return (NO);
+       }
+
+       /* tuploc must agree */
+       if (hi_p->tuploc != lo_p->tuploc) {
+               return (NO);
+       }
+
+       /* tupcont must agree */
+       if (hi_p->tupcont != lo_p->tupcont) {
+               return (NO);
+       }
+
+       /* if printtup is set in both groups, they must agree */
+       if (hi_p->printtup != PT_DEFAULT && lo_p->printtup != PT_DEFAULT &&
+           hi_p->printtup != lo_p->printtup) {
+               return (NO);
+       }
+
+       /* if tupside is set in both groups, they must agree */
+       if (hi_p->tupside != PL_UNKNOWN && lo_p->tupside != PL_UNKNOWN &&
+           hi_p->tupside != lo_p->tupside) {
+               return (NO);
+       }
+
+       /* don't allow cross staff beamed groups */
+       if (hi_p->beamto != CS_SAME || lo_p->beamto != CS_SAME) {
+               return (NO);
+       }
+
+       /* don't allow cross staff stemmed groups */
+       if (hi_p->stemto != CS_SAME || lo_p->stemto != CS_SAME) {
+               return (NO);
+       }
+
+       /* if either is a space, there can be no other conflict */
+       if (hi_p->grpcont == GC_SPACE || lo_p->grpcont == GC_SPACE) {
+               return (YES);
+       }
+
+       /***** both groups are GC_NOTES and/or GC_REST *****/
+
+       /* group size must agree */
+       if (hi_p->grpsize != lo_p->grpsize) {
+               return (NO);
+       }
+
+       /* if both are rests, there can be no other conflict */
+       if (hi_p->grpcont == GC_REST && lo_p->grpcont == GC_REST) {
+               return (YES);
+       }
+
+       /* if only one is a rest, there is a conflict */
+       if (hi_p->grpcont == GC_REST || lo_p->grpcont == GC_REST) {
+               return (NO);
+       }
+
+       /***** both groups are GC_NOTES *****/
+
+       /* head shape must agree */
+       if (hi_p->headshape != lo_p->headshape) {
+               return (NO);
+       }
+
+       /* beaming must be the same on both, except on grace beamloc doesn't
+        * matter, since if we combine them we'll beam them all anyway */
+       if (hi_p->beamloc != lo_p->beamloc && hi_p->grpvalue == GV_NORMAL) {
+               return (NO);
+       }
+       if (hi_p->breakbeam != lo_p->breakbeam) {
+               return (NO);
+       }
+       if (hi_p->beamslope != NOBEAMANGLE && lo_p->beamslope != NOBEAMANGLE &&
+           hi_p->beamslope != lo_p->beamslope) {
+               return (NO);
+       }
+
+       /* if both stemdirs are set, they must agree */
+       if (hi_p->stemlen != STEMLEN_UNKNOWN &&
+           lo_p->stemlen != STEMLEN_UNKNOWN &&
+           hi_p->stemlen != lo_p->stemlen) {
+               return (NO);
+       }
+
+       /* if both stemdirs are forced, they must agree */
+       if (hi_p->stemdir != UNKNOWN && lo_p->stemdir != UNKNOWN &&
+           hi_p->stemdir != lo_p->stemdir) {
+               return (NO);
+       }
+
+       /* group ties out of this group must agree */
+       if (hi_p->tie != lo_p->tie) {
+               return (NO);
+       }
+
+       /* group ties into this group must agree */
+       tempmll_p = mll_p;
+       phi_p = prevgrpsyl(hi_p, &tempmll_p);
+       tempmll_p = mll_p;
+       plo_p = prevgrpsyl(lo_p, &tempmll_p);
+       if (phi_p != 0 && plo_p != 0 && phi_p->tie != plo_p->tie) {
+               return (NO);
+       }
+
+       /* tremelo slashes or alternation slashes must agree */
+       if (hi_p->slash_alt != lo_p->slash_alt) {
+               return (NO);
+       }
+
+       /* neither group can have a horizontal offset */
+       if (hi_p->ho_usage != HO_NONE || lo_p->ho_usage != HO_NONE) {
+               return (NO);
+       }
+
+       /* "with" lists must both be nonexistent, or else identical */
+       if (hi_p->nwith != lo_p->nwith) {
+               return (NO);
+       }
+       for (widx = 0; widx < hi_p->nwith; widx++) {
+               if (strcmp(hi_p->withlist[widx], lo_p->withlist[widx]) != 0) {
+                       return (NO);
+               }
+       }
+
+       /*
+        * Rolls aren't really implemented for voice 3.  Voice 3 is just along
+        * for the ride, if it's in the middle of a roll.  So we'll let it
+        * combine as long as both groups are in a roll, or not.  But for
+        * voices 1 and 2, only allow specific combinations that make sense.
+        */
+       if (hi_p->vno == 1 && lo_p->vno == 2) {
+               switch ((hi_p->roll << 8) | lo_p->roll) {
+               case (NOITEM    << 8) | NOITEM:
+                       break;
+               case (STARTITEM << 8) | INITEM:
+               case (STARTITEM << 8) | ENDITEM:
+               case (INITEM    << 8) | INITEM:
+               case (INITEM    << 8) | ENDITEM:
+                       if (hi_p->rolldir != lo_p->rolldir) {
+                               return (NO);
+                       }
+                       break;
+               default:
+                       return (NO);
+               }
+       } else {
+               if ((hi_p->roll == NOITEM) != (lo_p->roll == NOITEM)) {
+                       return (NO);
+               }
+       }
+
+       /*
+        * If each group is preceded by a grace group, those grace groups must
+        * also be combineable.  Notice that if there are multiple preceding
+        * grace groups, more recursive calls will occur.  If one is preceded
+        * and the other isn't, there is no problem and nothing to check.
+        */
+       if (hi_p->prev != 0 && hi_p->prev->grpvalue == GV_ZERO &&
+           lo_p->prev != 0 && lo_p->prev->grpvalue == GV_ZERO) {
+               if (chk2groups(hi_p->prev, lo_p->prev, mll_p, qual) == NO) {
+                       return (NO);
+               }
+       }
+
+       /* if either is a mrpt, the other must be, and there is no conflict */
+       if (hi_p->is_meas == YES) {
+               return (YES);
+       }
+
+       /***** both groups have a notelist *****/
+
+       /*
+        * Do some checks involving overlapping of the groups.  We'd like to
+        * use stepsup, but it won't be set to its correct value until
+        * setnotes.c.  Fortunately, we don't need to know the absolute
+        * vertical position, only the relative.  So just use steps above c0.
+        */
+       mintop = hi_p->notelist[hi_p->nnotes - 1].octave * 7 +
+               Letshift[hi_p->notelist[hi_p->nnotes - 1].letter - 'a'];
+       maxbot = lo_p->notelist[0].octave * 7 +
+               Letshift[lo_p->notelist[0].letter - 'a'];
+       /*
+        * If the lowest note of the high group is higher than the highest of
+        * the low group, we are okay regardless of the vcombine qualifier,
+        * and there are no shared notes to check.
+        */
+       if (mintop > maxbot) {
+               return (YES);
+       }
+
+       /* if they are equal, and parm doesn't allow it, fail */
+       if (mintop == maxbot && qual == VC_NOOVERLAP) {
+               return (NO);
+       }
+
+       /* if there is true overlap, and parm doesn't allow it, fail */
+       if (mintop < maxbot && qual != VC_OVERLAP) {
+               return (NO);
+       }
+
+       /*
+        * Any shared notes must be compatible, so check every note in the top
+        * group against every note in the bottom group.  If any are equal,
+        * they must be compatible.
+        */
+       for (hidx = 0; hidx < hi_p->nnotes; hidx++) {
+
+               hnote_p = &hi_p->notelist[hidx];
+
+               for (lidx = 0; lidx < lo_p->nnotes; lidx++) {
+
+                       lnote_p = &lo_p->notelist[lidx];
+
+                       /* if the notes aren't equal, don't check them */
+                       if (hnote_p->octave != lnote_p->octave ||
+                           hnote_p->letter != lnote_p->letter) {
+                               /* the notes differ; no problem */
+                               continue;
+                       }
+
+                       /* notes match; check all the items that must agree */
+
+                       /* any slurs they have must be the same */
+                       if (hnote_p->nslurto != lnote_p->nslurto) {
+                               return (NO);
+                       }
+                       for (n = 0; n < hnote_p->nslurto; n++) {
+                               hslur_p = &hnote_p->slurtolist[n];
+                               lslur_p = &lnote_p->slurtolist[n];
+                               if (hslur_p->letter != lslur_p->letter) {
+                                       return (NO);
+                               }
+                               if (hslur_p->octave != lslur_p->octave) {
+                                       return (NO);
+                               }
+                               if (hslur_p->slurstyle != lslur_p->slurstyle) {
+                                       return (NO);
+                               }
+                               if (hslur_p->slurdir != lslur_p->slurdir) {
+                                       return (NO);
+                               }
+                       }
+
+                       /* must have same accidental, or none */
+                       if (hnote_p->accidental != lnote_p->accidental) {
+                               return (NO);
+                       }
+
+                       /* head shape override, or none, must agree */
+                       if (hnote_p->headshape != lnote_p->headshape) {
+                               return (NO);
+                       }
+
+                       /* note size must agree */
+                       if (hnote_p->notesize != lnote_p->notesize) {
+                               return (NO);
+                       }
+
+                       /* tie related attributes must be the same */
+                       if (hnote_p->tie != lnote_p->tie) {
+                               return (NO);
+                       }
+                       if (hnote_p->tiestyle != lnote_p->tiestyle) {
+                               return (NO);
+                       }
+                       if (hnote_p->tiedir != lnote_p->tiedir) {
+                               return (NO);
+                       }
+                       if (hnote_p->is_bend != lnote_p->is_bend) {
+                               return (NO);
+                       }
+                       if (hnote_p->smallbend != lnote_p->smallbend) {
+                               return (NO);
+                       }
+               }
+       }
+
+       return (YES);   /* passed all tests, the groups are combineable */
+}
+\f
+/*
+ * Name:        chkhand2()
+ *
+ * Abstract:    Make final decision on what can be combined in this hand.
+ *
+ * Returns:     void
+ *
+ * Description: This function applies the additional rules about beaming and
+ *             ties/slurs to the results of chkhand1(), to decide what groups
+ *             in this hand truly should be combined.  It stores the results
+ *             in the COMB field of all the groups.
+ */
+
+static void
+chkhand2(gs1_p, mll_p)
+
+struct GRPSYL *gs1_p;          /* first group in this hand */
+struct MAINLL *mll_p;          /* MLL struct for this group */
+
+{
+       struct SSV *ssv_p;              /* the SSV with voice combine info */
+       /* index the following by vno; it points at the GRPSYL for this vno */
+       struct GRPSYL *v_p[MAXVOICES + 1];
+       int slot1, slot2;               /* indices into SSV's vcombine array */
+       int firstvno, secondvno;        /* two voices from ssv_p->vcombine[] */
+       int keep_going;                 /* try some more? */
+
+
+       /* if we already know no combining can be done, get out */
+       if (gs1_p->COMB == 0) {
+               return;
+       }
+
+       /* point at all the groups in this hand */
+       (void)setgrpptrs(gs1_p, v_p);
+
+       /* get the list of groups we want to combine */
+       ssv_p = svpath(gs1_p->staffno, VCOMBINE);
+
+       /* for each pair of voices to be combined, apply the neighbor rules */
+       for (slot1 = 0; slot1 < MAXVOICES; slot1++) {
+               firstvno = ssv_p->vcombine[slot1];
+               if (firstvno == 0) {
+                       break;  /* end of list, done with outer loop */
+               }
+               /* voice must have a group in this chord */
+               if (v_p[firstvno] == 0) {
+                       continue;       /* skip this iteration */
+               }
+               for (slot2 = slot1 + 1; slot2 < MAXVOICES; slot2++) {
+                       secondvno = ssv_p->vcombine[slot2];
+                       if (secondvno == 0) {
+                               break;  /* end of list, done with inner loop */
+                       }
+                       /* voice must have a group in this chord */
+                       if (v_p[secondvno] == 0) {
+                               continue;       /* skip this iteration */
+                       }
+                       /*
+                        * The group with the lower voice number should be the
+                        * one that absorbs the other.  Pass it first.
+                        */
+                       if (firstvno < secondvno) {
+                               keep_going = chk2neighbors(v_p[firstvno],
+                                               v_p[secondvno], gs1_p, mll_p);
+                       } else {
+                               keep_going = chk2neighbors(v_p[secondvno],
+                                               v_p[firstvno], gs1_p, mll_p);
+                       }
+
+                       /* get out now if we are told to */
+                       if (keep_going == NO) {
+                               return;
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        chk2neighbors()
+ *
+ * Abstract:    Apply beaming and tie/slur rules to two groups in a hand.
+ *
+ * Returns:     YES or NO: should any further combining be attempted?
+ *
+ * Description: This function checks whether the two groups should be combined,
+ *             by looking at neighboring groups if beaming or ties/slurs
+ *             are involved.  It stores the answer in the COMB field of all
+ *             the groups.
+ *
+ *             If we shouldn't combine the groups, we return YES so that we
+ *             can come back and try a different pair, if appropriate.  If we
+ *             can combine the groups, we may return YES or NO; see comments
+ *             below.
+ */
+
+static int
+chk2neighbors(dest_p, src_p, gs1_p, mll_p)
+
+struct GRPSYL *dest_p;         /* group that should absorb the other */
+struct GRPSYL *src_p;          /* group that should be absorbed */
+struct GRPSYL *gs1_p;          /* first group in staff/chord */
+struct MAINLL *mll_p;          /* MLL struct for these groups' staff */
+
+{
+       struct GRPSYL *d2_p, *s2_p;     /* point at neighboring groups */
+       struct GRPSYL *gs_p;            /* point at groups in this chord */
+       struct MAINLL *mll2_p, *mll3_p; /* more pointers into MLL */
+       short mask;                     /* to be applied to "COMB" */
+       short comb;                     /* hold combineability bits */
+       int keep_going;                 /* return code */
+
+
+       /*
+        * Set up the bit that we must check in each chord to see if these two
+        * voices are combineable.
+        */
+       mask = 1 << (dest_p->vno + src_p->vno);
+
+       /*
+        * Start at this chord, and keep looking to the right as long as the
+        * groups are beamed or tied/slurred.
+        */
+       mll2_p = mll_p;
+       for (d2_p = dest_p, s2_p = src_p; d2_p != 0 && s2_p != 0;
+                       d2_p = nextglobnongrace(d2_p, &mll2_p),
+                       s2_p = nextglobnongrace(s2_p, &mll2_p)) {
+               /*
+                * If the groups in that chord are not combineable, we must not
+                * combine our original groups either.  The same flags are set
+                * in d2_p and s2_p, so we could have checked either.
+                */
+               if ((d2_p->COMB & mask) == 0) {
+                       return (YES);
+               }
+
+               /*
+                * If the groups are not beamed or tied/slurred to the right,
+                * we don't have to look any farther.  For beams, we only have
+                * to check one group, since the other must agree or we
+                * wouldn't be here.  For ties/slurs, we only have to check the
+                * the src, since those are the ones that wouldn't work if
+                * these groups were combined and the next ones weren't.
+                */
+               if ((s2_p->beamloc == NOITEM || s2_p->beamloc == ENDITEM) &&
+                               hastieslur(s2_p) == NO) {
+                       break;
+               }
+       }
+
+       /*
+        * Start at this chord, and keep looking to the left as long as the
+        * groups are beamed or tied/slurred.
+        */
+       mll2_p = mll_p;
+       for (d2_p = dest_p, s2_p = src_p; d2_p != 0 && s2_p != 0;
+                       d2_p = prevglobnongrace(d2_p, &mll2_p),
+                       s2_p = prevglobnongrace(s2_p, &mll2_p)) {
+
+               if ((d2_p->COMB & mask) == 0) {
+                       return (YES);
+               }
+
+               mll3_p = mll2_p;        /* don't alter mll2_p */
+               if ((s2_p->beamloc == NOITEM || s2_p->beamloc == STARTITEM) &&
+                   hastieslur(prevglobnongrace(s2_p, &mll3_p)) == NO) {
+                       break;
+               }
+       }
+
+       /* for convenience, copy the COMB bits into a local variable */
+       comb = dest_p->COMB;
+
+       /*
+        * We passed all the tests, so remember that we should combine the
+        * original groups.  Also decide whether any more should be tried.
+        */
+       if (((comb >> SRC1SHIFT) & 0x3) == 0) {
+               /* first groups to be combined in this hand */
+               comb |=  src_p->vno <<  SRC1SHIFT;
+               comb |= dest_p->vno << DEST1SHIFT;
+               /*
+                * If chkhand1() said all the groups in this hand were
+                * combineable, we can come back later and try to combine the
+                * other group.  Otherwise, don't.  We know the non-combineable
+                * group will fail to combine, so don't waste the time.
+                */
+               if ((comb & 0x38) == ((1 << (1 + 2)) | (1 << (1 + 3)) |
+                               (1 << (2 + 3)))) {
+                       keep_going = YES;
+               } else {
+                       keep_going = NO;
+               }
+       } else {
+               /* second groups to be combined in this hand */
+               comb |=  src_p->vno <<  SRC2SHIFT;
+               comb |= dest_p->vno << DEST2SHIFT;
+               keep_going = NO;        /* only 2 combinings can be done */
+       }
+
+       /*
+        * Since we will combine these two groups, the new dest group has
+        * inherited any incompatibility that src might have had with the
+        * other group (if any).  So find the new value of the comb bits.
+        * Set this new comb value into all the groups in this hand.  We do
+        * this for the benefit of later chords on this staff, if they are
+        * beamed or tied/slurred to us.
+        */
+       switch (dest_p->vno + src_p->vno) {
+       case 1 + 2:     /* combined 2 into 1 */
+               /* if 2 and 3 can't combine, now 1 and 3 can't */
+               if ((comb & (1 << (2 + 3))) == 0) {
+                       comb &= ~(1 << (1 + 3));
+               }
+               break;
+       case 1 + 3:     /* combined 3 into 1 */
+               /* if 3 and 2 can't combine, now 1 and 2 can't */
+               if ((comb & (1 << (3 + 2))) == 0) {
+                       comb &= ~(1 << (1 + 2));
+               }
+               break;
+       case 2 + 3:     /* combined 3 into 2 */
+               /* if 3 and 1 can't combine, now 2 and 1 can't */
+               if ((comb & (1 << (3 + 1))) == 0) {
+                       comb &= ~(1 << (2 + 1));
+               }
+               break;
+       }
+       for (gs_p = gs1_p; gs_p != 0 && gs_p->staffno == gs1_p->staffno &&
+                       gs_p->grpsyl == GS_GROUP; gs_p = gs_p->gs_p) {
+               gs_p->COMB = comb;
+       }
+
+       return (keep_going);
+}
+\f
+/*
+ * Name:        dohand()
+ *
+ * Abstract:    Combine the appropriate GRPSYLs in one chord on one staff.
+ *
+ * Returns:     void
+ *
+ * Description: This function combines GRPSYLs in one chord on one staff.  It
+ *             uses the previously determined list of what is combineable in
+ *             gs1_p->COMB.
+ */
+
+static void
+dohand(gs1_p, mll_p)
+
+struct GRPSYL *gs1_p;          /* first group on this staff in this chord */
+struct MAINLL *mll_p;          /* MLL struct for this group */
+
+{
+       /* index the following by vno; it points at the GRPSYL for this vno */
+       struct GRPSYL *v_p[MAXVOICES + 1];
+       int srcv, destv;        /* src and dest voice numbers */
+
+
+       /* if we already know no combining can be done, get out */
+       if (gs1_p->COMB == 0) {
+               return;
+       }
+
+       /* point at all the groups in this hand */
+       (void)setgrpptrs(gs1_p, v_p);
+
+       /* get first src group's voice number */
+       srcv = (gs1_p->COMB >> SRC1SHIFT) & 0x3;
+
+       if (srcv != 0) {
+               /* find the dest's voice and combine */
+               destv = (gs1_p->COMB >> DEST1SHIFT) & 0x3;
+               comb2groups(v_p[destv], v_p[srcv], mll_p);
+
+               /* get second src group's voice number */
+               srcv = (gs1_p->COMB >> SRC2SHIFT) & 0x3;
+
+               if (srcv != 0) {
+                       /* find the dest's voice and combine */
+                       destv = (gs1_p->COMB >> DEST2SHIFT) & 0x3;
+                       comb2groups(v_p[destv], v_p[srcv], mll_p);
+               }
+       }
+}
+\f
+/*
+ * Name:        comb2groups()
+ *
+ * Abstract:    Combine one group into another.
+ *
+ * Returns:     void
+ *
+ * Description: This function combines the src group into the dest group,
+ *             including handling any preceding grace groups.
+ */
+
+static void
+comb2groups(dest_p, src_p, mll_p)
+
+struct GRPSYL *dest_p;         /* group that should absorb the other */
+struct GRPSYL *src_p;          /* group that should be absorbed */
+struct MAINLL *mll_p;          /* MLL struct for these groups' staff */
+
+{
+       struct GRPSYL *dgrace_p;        /* dest grace group */
+       struct GRPSYL *sgrace_p;        /* src grace group */
+       struct GRPSYL *dmem_p;          /* remember a group from dest voice */
+       struct GRPSYL *smem_p;          /* remember a group from src voice */
+       struct GRPSYL *temp_p;          /* temp pointer */
+       struct GRPSYL *fgs_p;           /* first grace in src voice */
+
+
+       /*
+        * Add the src into the dest, and make the src group into a space if it
+        * isn't already a space.
+        */
+       addsrc2dest(dest_p, src_p);
+       if (src_p->grpcont != GC_SPACE) {
+               src_p->grpcont = GC_SPACE;
+               src_p->grpvalue = GV_NORMAL;
+               src_p->grpsize = GS_NORMAL;
+               src_p->headshape = HS_UNKNOWN;
+               src_p->beamloc = NOITEM;
+               src_p->beamslope = NOBEAMANGLE;
+               src_p->stemlen = STEMLEN_UNKNOWN;
+               src_p->stemdir = UNKNOWN;
+               src_p->breakbeam = NO;
+               src_p->beamloc = NOITEM;
+               src_p->notelist = 0;
+               src_p->nnotes = 0;
+               src_p->tie = NO;
+               src_p->slash_alt = 0;
+               src_p->restdist = NORESTDIST;
+               src_p->nwith = 0;
+               src_p->roll = NOITEM;
+       }
+
+       /* if source has no grace notes, we're done */
+       if (src_p->prev == 0 || src_p->prev->grpvalue == GV_NORMAL) {
+               return;
+       }
+
+       /*
+        * Loop through the matching grace groups preceding the src and dest
+        * groups, adding the src into the dest.  Remember the leftmost pair,
+        * or the nongrace groups if there are no matching pairs.
+        */
+       dmem_p = dest_p;
+       smem_p = src_p;
+       for (sgrace_p = src_p->prev, dgrace_p = dest_p->prev;
+            sgrace_p != 0 && sgrace_p->grpvalue == GV_ZERO &&
+            dgrace_p != 0 && dgrace_p->grpvalue == GV_ZERO;
+            sgrace_p = sgrace_p->prev, dgrace_p = dgrace_p->prev) {
+
+               addsrc2dest(dgrace_p, sgrace_p);
+               dmem_p = dgrace_p;      /* remember last one done */
+               smem_p = sgrace_p;
+       }
+
+       if (sgrace_p != 0 && sgrace_p->grpvalue == GV_ZERO) {
+               /* extra src grace group(s) left over must be moved */
+
+               /* sgrace_p is the last (rightmost) grace to move */
+               for (temp_p = sgrace_p; temp_p != 0 && temp_p->grpvalue ==
+                               GV_ZERO; temp_p = temp_p->prev) {
+                       fgs_p = temp_p;
+               }
+               /* fgs_p is the first (leftmost) grace to move */
+
+               if (dgrace_p == 0) {    /* at start of measure? */
+                       /* in src voice, skip over all the graces */
+                       mll_p->u.staff_p->groups_p[src_p->vno-1] = src_p;
+                       src_p->prev = 0;
+
+                       /* splice the left grace into the dest voice */
+                       mll_p->u.staff_p->groups_p[dest_p->vno-1] = fgs_p;
+                       fgs_p->prev = 0;
+               } else {
+                       /* in src voice, skip over all the graces */
+                       fgs_p->prev->next = src_p;
+                       src_p->prev = fgs_p->prev;
+
+                       /* splice the left grace into the dest voice */
+                       dgrace_p->next = fgs_p;
+                       fgs_p->prev = dgrace_p;
+               }
+
+               /* splice the rightmost left over grace into the dest voice */
+               dmem_p->prev = sgrace_p;
+               sgrace_p->next = dmem_p;
+
+               /*
+                * If there is now more than one grace in the dest, we have to
+                * correct beamloc in a couple places.
+                */
+               if (fgs_p != dest_p->prev) {
+                       /*
+                        * If the dest voice had multiple graces before, the
+                        * leftmost one, which was STARTITEM, must be made
+                        * INITEM.  If it had only one, it was NOITEM and
+                        * must be made ENDITEM, but go ahead and set INITEM;
+                        * it'll be set correctly below.
+                        */
+                       if (dmem_p != dest_p) {   /* if dest had grace(s) */
+                               dmem_p->beamloc = INITEM;
+                       }
+
+                       /* rightmost dest grace must always be made ENDITEM */
+                       dest_p->prev->beamloc = ENDITEM;
+               }
+
+               /* change the voice number of the moved graces */
+               for (temp_p = fgs_p; temp_p != sgrace_p->next;
+                               temp_p = temp_p->next) {
+                       temp_p->vno = dest_p->vno;
+               }
+       } else {
+               /* no extra src grace group(s); just remove all src graces */
+               if (sgrace_p == 0) {
+                       mll_p->u.staff_p->groups_p[src_p->vno-1] = src_p;
+                       src_p->prev = 0;
+               } else {
+                       smem_p->prev->next = src_p;
+                       src_p->prev = smem_p->prev;
+               }
+       }
+       /* could free the src graces, but is it worth the trouble? */
+}
+\f
+/*
+ * Name:        addsrc2dest()
+ *
+ * Abstract:    Adds src group to dest group.
+ *
+ * Returns:     void
+ *
+ * Description: This function adds the src group info (if the src group exists)
+ *             into the dest group.  But it doesn't mess with linkages.  That
+ *             is the calling function's job.
+ */
+
+static void
+addsrc2dest(dest_p, src_p)
+
+struct GRPSYL *dest_p;         /* destination group must exist */
+struct GRPSYL *src_p;          /* source group, or can be NULL */
+
+{
+       struct NOTE *dnote_p;   /* point at a note in the destination group */
+       struct NOTE *snote_p;   /* point at a note in the source group */
+       struct NOTE *newlist;   /* combined notelist */
+       int didx, sidx;         /* index into dest and src note lists */
+       int totnotes;           /* total number of notes after combining */
+       int n;                  /* loop variable */
+
+
+       /* if src doesn't exist, there is nothing to do */
+       if (src_p == 0) {
+               return;
+       }
+
+       /* move references to the src group's coords */
+       upd_ref(src_p->c, dest_p->c);
+
+       /* if src is space, nothing to do except carry over this space field */
+       if (src_p->grpcont == GC_SPACE) {
+               if (dest_p->grpcont == GC_SPACE &&
+                               src_p->uncompressible == YES) {
+                       dest_p->uncompressible = YES;
+               }
+               return;
+       }
+
+       /* padding is the max of the two groups */
+       dest_p->padding = MAX(dest_p->padding, src_p->padding);
+
+       /*
+        * Some fields were allowed to disagree between the groups as long as
+        * one was defaulted.  The non-default value should prevail.
+        */
+       if (src_p->printtup != PT_DEFAULT) {
+               dest_p->printtup = src_p->printtup;
+       }
+       if (src_p->tupside != PL_UNKNOWN) {
+               dest_p->tupside = src_p->tupside;
+       }
+       if (src_p->beamslope != NOBEAMANGLE) {
+               dest_p->beamslope = src_p->beamslope;
+       }
+       if (src_p->stemlen != STEMLEN_UNKNOWN) {
+               dest_p->stemlen = src_p->stemlen;
+       }
+       if (src_p->stemdir != UNKNOWN) {
+               dest_p->stemdir = src_p->stemdir;
+       }
+
+       /* only when combining 1 & 2 might we have to adjust roll */
+       if (dest_p->vno == 1 && src_p->vno == 2) {
+               switch ((dest_p->roll << 8) | src_p->roll) {
+               case (NOITEM    << 8) | NOITEM:
+                       /* dest remains NOITEM */
+                       break;
+               case (STARTITEM << 8) | INITEM:
+                       /* dest remains STARTITEM */
+                       break;
+               case (STARTITEM << 8) | ENDITEM:
+                       dest_p->roll = LONEITEM;
+                       break;
+               case (INITEM    << 8) | INITEM:
+                       /* dest remains INITEM */
+                       break;
+               case (INITEM    << 8) | ENDITEM:
+                       dest_p->roll = ENDITEM;
+                       break;
+               }
+       }
+
+       /* if one is a rest, so is the other; combine */
+       if (dest_p->grpcont == GC_REST) {
+               /* throw away any restdist; probably would be inappropriate */
+               dest_p->restdist = 0;
+               return;
+       }
+
+       /* if either is a mrpt, the other must be; nothing to copy */
+       if (dest_p->is_meas == YES) {
+               return;
+       }
+
+       /* at this point we know src has notes, & dest has notes or is space */
+
+       /*
+        * Make a new notelist.  First copy the old dest notes into there, and
+        * then add the src notes.  We can't just realloc the dest, since
+        * pointers into the array must be updated by calling upd_ref for each
+        * array element.  If any notes are shared, we won't really need this
+        * many, but it doesn't waste much memory.
+        */
+       MALLOC(NOTE, newlist, dest_p->nnotes + src_p->nnotes);
+       for (n = 0; n < dest_p->nnotes; n++) {
+               newlist[n] = dest_p->notelist[n];
+       }
+
+       /*
+        * Keep track of the number of total resulting notes, which starts out
+        * as the number of notes in dest.  Loop through the src notes.
+        */
+       totnotes = dest_p->nnotes;
+       for (sidx = 0; sidx < src_p->nnotes; sidx++) {
+               snote_p = &src_p->notelist[sidx];
+
+               /* see if it matches any of the dest notes in the result array*/
+               for (didx = 0; didx < dest_p->nnotes; didx++) {
+                       dnote_p = &newlist[didx];
+                       if (dnote_p->octave == snote_p->octave &&
+                           dnote_p->letter == snote_p->letter) {
+                               /*
+                                * If one has parens on the note or acc and the
+                                * other doesn't, ensure no parens in result.
+                                */
+                               if (dnote_p->note_has_paren !=
+                                   snote_p->note_has_paren) {
+                                       dnote_p->note_has_paren = NO;
+                               }
+                               if (dnote_p->acc_has_paren !=
+                                   snote_p->acc_has_paren) {
+                                       dnote_p->acc_has_paren = NO;
+                               }
+                               break;
+                       }
+               }
+               if (didx == dest_p->nnotes) {
+                       /* didn't find a match, so add it to the end */
+                       newlist[totnotes++] = *snote_p;
+               }
+       }
+
+       /* sort the combined list in pitch order */
+       qsort((char *)newlist, (unsigned int)totnotes,
+                       sizeof (struct NOTE), notecomp);
+
+       /*
+        * For every original dest and src note, find out where it ended up in
+        * the combined list, and update and location tag references.
+        */
+       for (didx = 0; didx < dest_p->nnotes; didx++) {
+               dnote_p = &dest_p->notelist[didx];
+               for (n = 0; n < totnotes; n++) {
+                       if (newlist[n].octave == dnote_p->octave &&
+                           newlist[n].octave == dnote_p->letter) {
+                               upd_ref(newlist[n].c, dnote_p->c);
+                       }
+               }
+       }
+       for (sidx = 0; sidx < src_p->nnotes; sidx++) {
+               dnote_p = &src_p->notelist[sidx];
+               for (n = 0; n < totnotes; n++) {
+                       if (newlist[n].octave == dnote_p->octave &&
+                           newlist[n].octave == dnote_p->letter) {
+                               upd_ref(newlist[n].c, dnote_p->c);
+                       }
+               }
+       }
+
+       /* free old dest list, and install the new one and its note count */
+       if (dest_p->notelist != 0) {    /* not a space */
+               FREE(dest_p->notelist);
+       }
+       dest_p->notelist = newlist;
+       dest_p->nnotes = totnotes;
+}
+\f
+/*
+ * Name:        setgrpptrs()
+ *
+ * Abstract:    Set pointers to the groups in a hand.
+ *
+ * Returns:     number of GRPSYLs found in this hand
+ *
+ * Description: This function fill in the given array with pointers to the
+ *             groups in this hand.  When a group doesn't exist for some
+ *             voice, a null pointer is used.
+ */
+
+static int
+setgrpptrs(gs1_p, v_p)
+
+struct GRPSYL *gs1_p;          /* first group in this hand */
+struct GRPSYL *v_p[];          /* fill this in, index by voice number */
+
+{
+       struct GRPSYL *gs_p;    /* point along GRPSYLs of the chord */
+       int v;                  /* a voice number */
+       int num;                /* number of groups found */
+
+
+       /* null out the list of pointers initially (note [0] is not used) */
+       for (v = 1; v <= MAXVOICES; v++) {
+               v_p[v] = 0;
+       }
+       /* for each group in the hand, set pointer to it */
+       num = 0;
+       for (gs_p = gs1_p; gs_p != 0 && gs_p->staffno == gs1_p->staffno &&
+                       gs_p->grpsyl == GS_GROUP; gs_p = gs_p->gs_p) {
+               v_p[gs_p->vno] = gs_p;
+               num++;
+       }
+
+       return (num);
+}
+\f
+/*
+ * Name:        hastieslur()
+ *
+ * Abstract:    Is this group tied/slurred/bent to the next?
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function checks whether there are any ties/slurs/bends to
+ *             the next group.  If the given group doesn't exist, the answer
+ *             is NO.
+ */
+
+static int
+hastieslur(gs_p)
+
+struct GRPSYL *gs_p;           /* group to check */
+
+{
+       int idx;                /* index into note list */
+
+
+       /* if there's no group, it isn't tied/slurred */
+       if (gs_p == 0) {
+               return (NO);
+       }
+
+       /* check group tie */
+       if (gs_p->tie == YES) {
+               return (YES);
+       }
+
+       /* check note ties and slurs (bends are covered by slurs) */
+       for (idx = 0; idx < gs_p->nnotes; idx++) {
+               if (gs_p->notelist[idx].tie == YES ||
+                   gs_p->notelist[idx].nslurto != 0) {
+                       return (YES);
+               }
+       }
+
+       return (NO);
+}
diff --git a/mup/mup/muschar.h b/mup/mup/muschar.h
new file mode 100644 (file)
index 0000000..b32dd5b
--- /dev/null
@@ -0,0 +1,113 @@
+
+/* Copyright (c) 1995, 1999, 2000, 2004 by Arkkra Enterprises */
+/* All rights reserved */
+
+/*
+ * Define the list of all the special music symbols.
+ */
+
+/* The following set of symbols is in font FONT_MUSIC.
+ * Mapping between name and number is done via Mus_char_table[0][].
+ */
+#define C_GCLEF        (32)     /* G clef (treble clef) */
+#define C_FCLEF        (33)     /* F clef (bass clef) */
+#define C_CCLEF        (34)     /* C clef (alto, tenor, etc. clef) */
+#define C_DBLWHOLE     (35)     /* double whole note */
+#define C_1N           (36)     /* whole note */
+#define C_2N           (37)     /* half note head */
+#define C_4N           (38)     /* quarter (and shorter) note head */
+#define C_UPFLAG       (39)     /* upward flag */
+#define C_DNFLAG       (40)     /* downward flag */
+#define C_QWHREST      (41)     /* quad rest */
+#define C_DWHREST      (42)     /* double whole rest */
+#define C_1REST        (43)     /* whole rest */
+#define C_2REST        (44)     /* half rest */
+#define C_4REST        (45)     /* quarter rest */
+#define C_8REST        (46)     /* eighth rest */
+#define C_16REST       (47)     /* sixteenth rest */
+#define C_32REST       (48)     /* thirty-second rest */
+#define C_64REST       (49)     /* sixty-fourth rest */
+#define C_128REST      (50)     /* 128th rest */
+#define C_256REST      (51)     /* 256th rest */
+#define C_LL1REST      (52)     /* legerline-less version of whole rest */
+#define C_LL2REST      (53)     /* legerline-less version of half rest */
+#define C_DOT          (54)     /* dot, as for after a note */
+#define C_NAT          (55)     /* natural sign (n) */
+#define C_SHARP        (56)     /* sharp sign (#) */
+#define C_FLAT                 (57)     /* flat sign (&) */
+#define C_DBLSHARP     (58)     /* double sharp */
+#define C_DBLFLAT      (59)     /* double flat */
+#define C_XNOTE        (60)     /* X-shaped note head */
+#define C_DWHDIAMOND   (61)     /* double-whole diamond shaped note */
+#define C_DIAMOND      (62)     /* diamond-shaped note head */
+#define C_FILLDIAMOND  (63)     /* filled diamond note head */
+#define C_UP2N                 (64)     /* half note with stem up */
+#define C_DN2N                 (65)     /* half note with stem down */
+#define C_UP4N                 (66)     /* quarter note with stem up */
+#define C_DN4N                 (67)     /* quarter note with stem down */
+#define C_COM          (68)     /* common time */
+#define C_CUT          (69)     /* cut time */
+#define C_BEGPED       (70)     /* begin pedal */
+#define C_PEDAL        (71)     /* pedal up/down */
+#define C_ENDPED       (72)     /* end pedal */
+#define C_DNBOW        (73)     /* down bow */
+#define C_UPBOW        (74)     /* up bow */
+#define C_WEDGE        (75)     /* wedge mark */
+#define C_UWEDGE       (76)     /* upside-down wedge */
+#define C_FERM                 (77)     /* fermata */
+#define C_UFERM        (78)     /* upside-down fermata */
+#define C_SIGN                 (79)     /* for D.S. */
+#define C_CODA                 (80)     /* the + over circle for jumping to coda */
+#define C_MOR          (81)     /* mordent */
+#define C_INVMOR       (82)     /* inverted mordent */
+#define C_TURN                 (83)     /* "turn" ornament */
+#define C_INVTURN      (84)     /* inverted turn */
+#define C_ACC_GT       (85)     /* accent that looks like > */
+#define C_ACC_HAT      (86)     /* accent that looks like ^ */
+#define C_ACC_UHAT     (87)     /* upside down hat accent */
+#define C_TR           (88)     /* trill */
+#define C_LEG          (89)     /* legato mark */
+#define C_RR           (90)     /* railroad tracks */
+#define C_DIM          (91)     /* diminished (small circle) */
+#define C_HALFDIM      (92)     /* half diminished (small circle with slash) */
+#define C_TRIANGLE     (93)     /* triangle, as for a major 7th chord */
+#define C_MEASRPT      (94)     /* measure repeat */
+#define C_COPYRIGHT    (95)     /* c in circle */
+#define C_UP8N                 (96)     /* 1/8 note with stem up */
+#define C_DN8N                 (97)     /* 1/8 note with stem down */
+#define C_UP16N        (98)     /* 1/16 note with stem up */
+#define C_DN16N        (99)     /* 1/16 note with stem down */
+#define C_UP32N        (100)    /* 1/32 note with stem up */
+#define C_DN32N        (101)    /* 1/32 note with stem down */
+#define C_UP64N        (102)    /* 1/64 note with stem up */
+#define C_DN64N        (103)    /* 1/64 note with stem down */
+#define C_UP128N       (104)    /* 1/128 note with stem up */
+#define C_DN128N       (105)    /* 1/128 note with stem down */
+#define C_UP256N       (106)    /* 1/256 note with stem up */
+#define C_DN256N       (107)    /* 1/256 note with stem down */
+
+/* The following set of symbols is in font FONT_MUSIC2.
+ * Mapping between name and number is done via Mus_char_table[1][].
+ */
+#define C_DWHRIGHTTRIANGLE     (32)     /* double whole right triangle */
+#define C_RIGHTTRIANGLE        (33)     /* hollow right triangle */
+#define C_FILLRIGHTTRIANGLE    (34)     /* filled right triangle */
+#define C_UDWHRIGHTTRIANGLE    (35)     /* upside down double whole right tri*/
+#define C_URIGHTTRIANGLE       (36)     /* upside down hollow right triangle */
+#define C_UFILLRIGHTTRIANGLE   (37)     /* upside down filled right triangle */
+#define C_DWHRECTANGLE         (38)     /* double whole rectangle */
+#define C_RECTANGLE    (39)     /* hollow rectangle */
+#define C_FILLRECTANGLE        (40)     /* filled rectangle */
+#define C_DWHISOSTRIANGLE      (41)     /* double whole isosceles triangle */
+#define C_ISOSTRIANGLE         (42)     /* hollow isosceles triangle */
+#define C_FILLISOSTRIANGLE     (43)     /* filled isosceles triangle */
+#define C_DWHPIEWEDGE  (44)     /* double whole pie wedge */
+#define C_PIEWEDGE     (45)     /* hollow pie wedge */
+#define C_FILLPIEWEDGE         (46)     /* filled pie wedge */
+#define C_DWHSEMICIRCLE        (47)     /* double whole semicircle */
+#define C_SEMICIRCLE   (48)     /* hollow semicircle */
+#define C_FILLSEMICIRCLE       (49)     /* filled semicircle */
+#define C_DWHSLASHHEAD         (50)     /* double whole slash note head */
+#define C_SLASHHEAD    (51)     /* hollow slash note head */
+#define C_FILLSLASHHEAD        (52)     /* filled slash note head */
+#define C_BLANKHEAD    (53)     /* blank note head */
diff --git a/mup/mup/muschtbl.c b/mup/mup/muschtbl.c
new file mode 100644 (file)
index 0000000..320805e
--- /dev/null
@@ -0,0 +1,113 @@
+/* Copyright (c) 1995, 1999, 2000, 2004 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* Machine-generated mapping of music char names to code numbers */
+
+#include "defines.h"
+#include "structs.h"
+
+struct SPECCHAR Mus_char_table[NUM_MFONTS][CHARS_IN_FONT+1] = {
+    {
+       { "128rest", C_128REST },
+       { "16rest", C_16REST },
+       { "1n", C_1N },
+       { "1rest", C_1REST },
+       { "256rest", C_256REST },
+       { "2n", C_2N },
+       { "2rest", C_2REST },
+       { "32rest", C_32REST },
+       { "4n", C_4N },
+       { "4rest", C_4REST },
+       { "64rest", C_64REST },
+       { "8rest", C_8REST },
+       { "acc_gt", C_ACC_GT },
+       { "acc_hat", C_ACC_HAT },
+       { "acc_uhat", C_ACC_UHAT },
+       { "begped", C_BEGPED },
+       { "cclef", C_CCLEF },
+       { "coda", C_CODA },
+       { "com", C_COM },
+       { "copyright", C_COPYRIGHT },
+       { "cut", C_CUT },
+       { "dblflat", C_DBLFLAT },
+       { "dblsharp", C_DBLSHARP },
+       { "dblwhole", C_DBLWHOLE },
+       { "diamond", C_DIAMOND },
+       { "dim", C_DIM },
+       { "dn128n", C_DN128N },
+       { "dn16n", C_DN16N },
+       { "dn256n", C_DN256N },
+       { "dn2n", C_DN2N },
+       { "dn32n", C_DN32N },
+       { "dn4n", C_DN4N },
+       { "dn64n", C_DN64N },
+       { "dn8n", C_DN8N },
+       { "dnbow", C_DNBOW },
+       { "dnflag", C_DNFLAG },
+       { "dot", C_DOT },
+       { "dwhdiamond", C_DWHDIAMOND },
+       { "dwhrest", C_DWHREST },
+       { "endped", C_ENDPED },
+       { "fclef", C_FCLEF },
+       { "ferm", C_FERM },
+       { "filldiamond", C_FILLDIAMOND },
+       { "flat", C_FLAT },
+       { "gclef", C_GCLEF },
+       { "halfdim", C_HALFDIM },
+       { "invmor", C_INVMOR },
+       { "invturn", C_INVTURN },
+       { "leg", C_LEG },
+       { "ll1rest", C_LL1REST },
+       { "ll2rest", C_LL2REST },
+       { "measrpt", C_MEASRPT },
+       { "mor", C_MOR },
+       { "nat", C_NAT },
+       { "pedal", C_PEDAL },
+       { "qwhrest", C_QWHREST },
+       { "rr", C_RR },
+       { "sharp", C_SHARP },
+       { "sign", C_SIGN },
+       { "tr", C_TR },
+       { "triangle", C_TRIANGLE },
+       { "turn", C_TURN },
+       { "uferm", C_UFERM },
+       { "up128n", C_UP128N },
+       { "up16n", C_UP16N },
+       { "up256n", C_UP256N },
+       { "up2n", C_UP2N },
+       { "up32n", C_UP32N },
+       { "up4n", C_UP4N },
+       { "up64n", C_UP64N },
+       { "up8n", C_UP8N },
+       { "upbow", C_UPBOW },
+       { "upflag", C_UPFLAG },
+       { "uwedge", C_UWEDGE },
+       { "wedge", C_WEDGE },
+       { "xnote", C_XNOTE },
+       { (char *) 0, 0 }
+    },    {
+       { "blankhead", C_BLANKHEAD },
+       { "dwhisostriangle", C_DWHISOSTRIANGLE },
+       { "dwhpiewedge", C_DWHPIEWEDGE },
+       { "dwhrectangle", C_DWHRECTANGLE },
+       { "dwhrighttriangle", C_DWHRIGHTTRIANGLE },
+       { "dwhsemicircle", C_DWHSEMICIRCLE },
+       { "dwhslashhead", C_DWHSLASHHEAD },
+       { "fillisostriangle", C_FILLISOSTRIANGLE },
+       { "fillpiewedge", C_FILLPIEWEDGE },
+       { "fillrectangle", C_FILLRECTANGLE },
+       { "fillrighttriangle", C_FILLRIGHTTRIANGLE },
+       { "fillsemicircle", C_FILLSEMICIRCLE },
+       { "fillslashhead", C_FILLSLASHHEAD },
+       { "isostriangle", C_ISOSTRIANGLE },
+       { "piewedge", C_PIEWEDGE },
+       { "rectangle", C_RECTANGLE },
+       { "righttriangle", C_RIGHTTRIANGLE },
+       { "semicircle", C_SEMICIRCLE },
+       { "slashhead", C_SLASHHEAD },
+       { "udwhrighttriangle", C_UDWHRIGHTTRIANGLE },
+       { "ufillrighttriangle", C_UFILLRIGHTTRIANGLE },
+       { "urighttriangle", C_URIGHTTRIANGLE },
+       { (char *) 0, 0 }
+    }
+};
diff --git a/mup/mup/nxtstrch.c b/mup/mup/nxtstrch.c
new file mode 100644 (file)
index 0000000..44be372
--- /dev/null
@@ -0,0 +1,938 @@
+/* Copyright (c) 1999, 2000, 2002, 2004, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* Functions related to walking through strings, to get each character
+ * in turn, along with any font/size changes and horizontal/vertical
+ * motions that should be done before printing that character.
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+/* when entering pile, adjust size by PILE_A / PILE_B and when
+ * exiting pile, adjust by the recipocal of that. */
+#define PILE_A         65
+#define PILE_B 100
+
+
+/* This structure contains information about one line in a set of lines
+ * that are piled on top of one another. This might be used for figured
+ * bass or superscript/subscript or things like that. */
+struct PILED_LINE {
+       char *text;             /* points to start of piled line */
+       short align_offset;     /* where the alignment is, relative to text */
+       short length;           /* bytes in this line */
+       short last_char_offset; /* where the last character is */
+       short last_digit_offset;/* where the last digit is */
+       float width_left_of_align;      /* width for this line */
+       float width_right_of_align;
+       struct PILED_LINE *next;/* the next line in the pile */
+};
+
+/* This keep track of an entire piled section of a string */
+struct PILED {
+       float curr_x, curr_y;   /* where we are now, relative to pile start */
+       struct PILED_LINE *lines_p;     /* list of lines in pile */
+       struct PILED_LINE *curr_line_p; /* which piled line we're processing */
+       short curr_offset;              /* offset into curr_line_p->text */
+       float width_left_of_align;      /* width of the entire pile */
+       float width_right_of_align;
+       short orig_font;                /* font coming into the pile */
+       short orig_size;                /* size coming into the pile */
+       short new_size;                 /* size at beginning of pile */
+       char *pile_end;                 /* last character of pile */
+};
+
+/* One of these structs is passed to get_piled() with the current
+ * font and size filled in. If we are in piled mode, it will return 1 and
+ * will have filled in all the field. Otherwise it will return 0.
+ */
+
+struct PILE_INFO {
+       char    font;
+       char    size;
+       char    ch;     /* the next character in the pile, or \0 if
+                        * this only indicates motion */
+       double  hor;    /* how much to adjust before printing ch */
+       double  vert;   /* how much to adjust before printing ch */
+};
+
+/* When a backspace is returned, this keeps track of its width, to
+ * potentially be returned via backsp_width() */
+static int Backspace_dist;
+
+/* This is all the info about the piled section we are currently processing.
+ * We only deal with one pile at a time, so a single static structure
+ * meets our needs. */
+static struct PILED Pile_info;
+
+static void begin_pile P((struct PILE_INFO *pile_info_p));
+static char *prep_pile P((char *string, struct PILE_INFO *pile_info_p));
+static int get_piled P((struct PILE_INFO *pile_info_p));
+static double vert_distance P((int vert_arg, int font, int size));
+\f
+
+/* When a STR_PILE is encountered, this should be called to gather all
+ * the information we might need about how to align everything in the pile.
+ * Then other functions like get_piled() can be called to retrieve info.
+ * The passed-in pile_info_p contains the font and size at the beginning
+ * of the pile, and on return will contain the new size and the vertical
+ * and horizontal offsets before the first character of the pile.
+ * Return value points to the last character that was processed from string.
+ */
+
+static char *
+prep_pile(string, pile_info_p)
+
+char *string;          /* place in string where piling begins */
+struct PILE_INFO *pile_info_p; /* passed in font and size, returns size and vert */
+
+{
+       struct PILED_LINE **piled_line_p_p;     /* where to link on next line */
+       struct PILED_LINE *line_p;              /* the current line of pile */
+       char *s;                                /* to walk through string */
+       int alignments = 0;                     /* how many align points found */
+       int lines = 0;                          /* how many lines in pile */
+       float width_contribution;               /* width of current char */
+       int i;                                  /* index though a line */
+       int orig_i;                             /* value of i when current
+                                                * character began (some
+                                                * things take up multiple
+                                                * bytes and we need to know
+                                                * where it began. */
+       int font, size;
+
+       /* initialize */
+       Pile_info.width_left_of_align = Pile_info.width_right_of_align = 0.0;
+       Pile_info.lines_p = (struct PILED_LINE *) 0;
+       Pile_info.curr_line_p = (struct PILED_LINE *) 0;
+       Pile_info.curr_offset = 0;
+       piled_line_p_p = &(Pile_info.lines_p);
+       line_p = *piled_line_p_p;
+
+       Pile_info.orig_font = font = pile_info_p->font;
+
+       /* Adjust size for entering the pile */
+       size = Pile_info.new_size = pile_size(pile_info_p->size, NO);
+
+       /* Walk through the piled things, skipping past the initial STR_PILE,
+        * this time just to find the line boundaries and alignment offsets. */
+       for (s = string + 1; *s != '\0'; s++) {
+
+               /* if end piling, jump out */
+               int curr_char;  
+               curr_char = *s & 0xff;
+               if ( curr_char == STR_PILE || curr_char == STR_BOX_END
+                                               || curr_char == STR_CIR_END) {
+                       if (line_p != (struct PILED_LINE *) 0) {
+                               line_p->length = s - line_p->text;
+                       }
+                       line_p = (struct PILED_LINE *) 0;
+                       s++;
+                       break;
+               }
+
+               /* If we don't have a current PILED_LINE struct,
+                * get one, and initialize it. */
+               if (line_p == (struct PILED_LINE *) 0) {
+                       MALLOC(PILED_LINE, *piled_line_p_p, 1);
+                       line_p = *piled_line_p_p;
+                       line_p->text = s;
+                       line_p->align_offset = -1;
+                       line_p->last_digit_offset = -1;
+                       line_p->last_char_offset = -1;
+                       line_p->length = -1;
+                       line_p->width_left_of_align = 0.0;
+                       line_p->width_right_of_align = 0.0;
+                       line_p->next = (struct PILED_LINE *) 0;
+                       lines++;
+               }
+
+               switch (*s & 0xff) {
+
+               case STR_C_ALIGN:
+               case STR_L_ALIGN:
+                       /* Point the offset at the following character,
+                        * because for C_ALIGN that character will straddle
+                        * the alignment point, and we can easily make
+                        * L_ALIGN work with that convention too. */
+                       line_p->align_offset = s - line_p->text + 1;
+                       alignments++;
+                       break;
+
+               case '\n':
+                       /* if newline, finish this line by saving its length,
+                        * then prepare for next line by moving the place at
+                        * which to add a line to the current line's 'next' */
+                       line_p->length = s - line_p->text;
+                       piled_line_p_p = &(line_p->next);
+                       line_p = (struct PILED_LINE *) 0;
+                       break;
+
+               case STR_FONT:
+               case STR_SIZE:
+               case STR_BACKSPACE:
+               case STR_VERTICAL:
+                       /* need to skip past its argument byte */
+                       s++;
+                       break;
+
+               case STR_MUS_CHAR:
+               case STR_MUS_CHAR2:
+                       /* Mark as last character so far, in case we need
+                        * to use that as default alignment */
+                       line_p->last_char_offset = s - line_p->text;
+                       /* need to skip past its 2 argument bytes */
+                       s += 2;
+                       break;
+
+               case STR_PAGENUM:
+               case STR_NUMPAGES:
+                       /* We actually don't allow this, but can get to this
+                        * code in error cases. Skip past argument. */
+                       s++;
+                       break;
+
+               default:
+                       /* Mark as last character so far, in case we need
+                        * to use that as default alignment */
+                       line_p->last_char_offset = s - line_p->text;
+
+                       /* remember location of last digit, in case we
+                        * need to use as default aligment */
+                       if ( isdigit(*s) ) {
+                               line_p->last_digit_offset = s - line_p->text;
+                       }
+                       break;
+               }
+       }
+
+       if (*s == '\0' && line_p != (struct PILED_LINE *) 0) {
+               line_p->length = s - line_p->text;
+       }
+
+       /* if there are lines with unspecified alignment points, find them */
+       if (alignments < lines) {
+               for (line_p = Pile_info.lines_p;
+                               line_p != (struct PILED_LINE *) 0;
+                               line_p = line_p->next) {
+                       /* If no user-specified alignment point in this line,
+                        * use last digit if any, else last char. If there was
+                        * no last char (empty line, maybe to get subscript
+                        * without superscript, for example) this will end
+                        * up with an offset of -1. */
+                       if (line_p->align_offset < 0) {
+                               line_p->align_offset =
+                                   ((line_p->last_digit_offset >= 0)
+                                   ? line_p->last_digit_offset
+                                   : line_p->last_char_offset);
+                       }
+               }
+       }
+
+       /* Find left and right of alignment for each line and the
+        * widest overall for the pile. */
+       for (line_p = Pile_info.lines_p;
+                                       line_p != (struct PILED_LINE *) 0;
+                                       line_p = line_p->next) {
+
+               /* Some items take more than one byte. In that case,
+                * the index 'i' in this 'for' loop will get more added to it
+                * than just the increment at the end of each loop.
+                * When this happens, orig_i keeps track of where the
+                * multi-byte item began. */
+               for (i = 0; i < line_p->length; i++) {
+                       
+                       orig_i = i;
+                       width_contribution = 0.0;
+
+                       switch (line_p->text[i] & 0xff) {
+
+                       case STR_MUS_CHAR:
+                       case STR_MUS_CHAR2:
+                               /* get its width and skip past its args */
+                               width_contribution += width(
+                                               str2mfont(line_p->text[i] & 0xff),
+                                               line_p->text[i+1],
+                                               line_p->text[i+2]);
+                               i += 2;
+                               break;
+
+                       case STR_FONT:
+                               /* Remember the font, may need for getting
+                                * widths of future characters */
+                               font = line_p->text[++i];
+                               break;
+
+                       case STR_SIZE:
+                               /* remember the size, may need for getting
+                                * widths of future characters */
+                               size = line_p->text[++i];
+                               break;
+
+                       case STR_C_ALIGN:
+                       case STR_L_ALIGN:
+                       case STR_SLASH:
+                               /* irrelevant for width, no args */
+                               break;
+
+                       case STR_VERTICAL:
+                               /* irrelevant for width, 1 byte arg to skip */
+                               i++;
+                               break;
+
+                       case STR_BACKSPACE:
+                               width_contribution -= ((line_p->text[++i] *
+                                       size) / DFLT_SIZE) / BACKSP_FACTOR;
+                               break;
+
+                       case STR_BOX:
+                       case STR_BOX_END:
+                       case STR_CIR:
+                       case STR_CIR_END:
+                               /* not relevant here */
+                               break;
+
+                       case STR_PAGENUM:
+                       case STR_NUMPAGES:
+                               /* we don't really know how wide this will
+                                * end up being, so just use the width of
+                                * the following byte (% or #).
+                                */
+                               width_contribution = width(font, size,
+                                                line_p->text[++i]);
+                               break;
+                       default:
+                               if ( IS_STR_COMMAND(line_p->text[i]) & 0xff) {
+                                       pfatal("unexpected STR_ value 0x%x in prep_pile()",
+                                               line_p->text[i] & 0xff);
+                               }
+
+                               /* ordinary character, look up its width */
+                               width_contribution = width(font, size,
+                                               line_p->text[i]);
+                               break;
+                       }
+
+                       /* Figure out which side of alignment.
+                        * Anything before align_offset goes on left,
+                        * while anything after goes on the right.
+                        * If we're right at the alignment offset,
+                        * and the alignment type is STR_C_ALIGN,
+                        * split the width. Otherwise goes on right. */
+                       if (orig_i < line_p->align_offset) {
+                               line_p->width_left_of_align
+                                       += width_contribution;
+                       }
+                       else if (orig_i == line_p->align_offset &&
+                                       (line_p->text[orig_i - 1] & 0xff)
+                                       != STR_L_ALIGN) {
+                               /* put half on each side */
+                               width_contribution /= 2.0;
+                               line_p->width_left_of_align
+                                       += width_contribution;
+                               line_p->width_right_of_align
+                                       += width_contribution;
+                       }
+                       else {
+                               line_p->width_right_of_align
+                                       += width_contribution;
+                       }
+               }
+
+               /* find widest line */
+               if (line_p->width_left_of_align
+                                       > Pile_info.width_left_of_align) {
+                       Pile_info.width_left_of_align
+                                               = line_p->width_left_of_align;
+               }
+               if (line_p->width_right_of_align
+                                       > Pile_info.width_right_of_align) {
+                       Pile_info.width_right_of_align
+                                               = line_p->width_right_of_align;
+               }
+       }
+
+       /* start at first character of first line of pile */
+       begin_pile(pile_info_p);
+
+       Pile_info.pile_end = s;
+       return(s);
+}
+\f
+
+/* fill in the fields of pile_info_p for starting at the beginning of
+ * the current pile. */
+
+static void
+begin_pile(pile_info_p)
+
+struct PILE_INFO *pile_info_p;
+
+{
+       /* begin at first line of pile */
+       Pile_info.curr_line_p = Pile_info.lines_p;
+       Pile_info.curr_offset = -1;
+
+       /* if user ended a string with a pile indicator (which is a bit
+        * silly, but could happen...) get out now,
+        * to avoid dereferencing a line that doesn't exist. */
+       if (Pile_info.curr_line_p == (struct PILED_LINE *) 0) {
+               return;
+       }
+
+       /* fill in rest of returned data */
+       pile_info_p->hor = Pile_info.curr_x = Pile_info.width_left_of_align
+                               - Pile_info.lines_p->width_left_of_align;
+       /* Adjust vertical by half the unpiled line height, but less a little
+        * (there is some white space padding, usually piles are numbers
+        * without descenders, and they are smaller anyway, so looks better
+        * to jam things together a bit more than normal). */
+       pile_info_p->vert = Pile_info.curr_y
+               = fontheight(Pile_info.orig_font, Pile_info.orig_size) / 2.0 
+               - POINT * Pile_info.new_size / DFLT_SIZE;
+       pile_info_p->size = Pile_info.new_size;
+
+       pile_info_p->ch = '\0';
+}
+\f
+
+/* Get the next character in piled segment, along with any horizontal
+ * and/or vertical motion that should be done before printing that
+ * character. Info is placed into the struct passed in. If the returned
+ * ->ch is '\0', that means this call only returned motion information.
+ * Returns NO at end of pile, otherwise YES.
+ */
+
+static int
+get_piled(pile_info_p)
+
+struct PILE_INFO *pile_info_p;
+
+{
+       char *text = 0;         /* Piled text to process. The initialization
+                                * is just to avoid bogus "used before set"
+                                * warning. It will always get set to a real
+                                * string before actually being used. */
+       float backdist;         /* width of backspace */
+       int mfont;              /* FONT_MUSIC*  */
+
+
+       /* Move on to next character. */
+       ++(Pile_info.curr_offset);
+
+       if (Pile_info.curr_line_p != (struct PILED_LINE *) 0) {
+
+               /* Check if we've gotten to end of pile. We are if we're
+                * past the last character of the last line of the pile */
+               if (Pile_info.curr_line_p->next == (struct PILED_LINE *) 0 &&
+                               Pile_info.curr_offset
+                               >= Pile_info.curr_line_p->length) {
+                       /* yes, at end of pile */
+                       Pile_info.curr_line_p = (struct PILED_LINE *) 0;
+               }
+               else {
+                       text = Pile_info.curr_line_p->text;
+               }
+       }
+
+       /* check for end of pile */
+       if (Pile_info.curr_line_p == (struct PILED_LINE *) 0) {
+
+               /* Adjust vertical and horizontal to past pile.
+                * Horizontal adjust is the total width of the
+                * pile minus where we are currently. */
+               pile_info_p->hor = (Pile_info.width_left_of_align
+                                       + Pile_info.width_right_of_align)
+                                       - Pile_info.curr_x;
+               /* Vertical adjust is the negative of the current
+                * y, since that gets us back to zero relative to
+                * where we started. */
+               pile_info_p->vert = - (Pile_info.curr_y);
+
+               /* Restore size for leaving the pile. */
+               pile_info_p->size = pile_size(pile_info_p->size, YES);
+
+               /* mark as not being an actual character, just motion */
+               pile_info_p->ch = '\0';
+
+               return(NO);
+       }
+
+       /* handle newline -- go to next line of pile */
+       if (text[Pile_info.curr_offset] == '\n') {
+               /* prepare for next line, if any */
+               Pile_info.curr_line_p = Pile_info.curr_line_p->next;
+               Pile_info.curr_offset = -1;
+
+               /* Adjust vertical and horizontal to start next line of pile.
+                * For horizontal, go back to beginning of pile,
+                * then add the difference between this line's
+                * left of align and the pile's. */
+               if (Pile_info.curr_line_p != (struct PILED_LINE *) 0) {
+                       pile_info_p->hor = - Pile_info.curr_x;
+                       Pile_info.curr_x = Pile_info.width_left_of_align
+                               - Pile_info.curr_line_p->width_left_of_align;
+                       pile_info_p->hor += Pile_info.curr_x;
+
+                       /* vertical is adjusted by height of font, less
+                        * a little to jam together to look better. */
+                       pile_info_p->vert = - fontheight(pile_info_p->font,
+                               pile_info_p->size)
+                               + POINT * pile_info_p->size / DFLT_SIZE;
+                       Pile_info.curr_y += pile_info_p->vert;
+               }
+               else {
+                       pile_info_p->vert = pile_info_p->hor = 0.0;
+               }
+
+               /* only motion */
+               pile_info_p->ch = '\0';
+
+       }
+
+       else {
+               pile_info_p->hor = pile_info_p->vert = 0.0;
+
+               switch (text[Pile_info.curr_offset] & 0xff) {
+
+               case STR_MUS_CHAR:
+               case STR_MUS_CHAR2:
+                       mfont = str2mfont( text[Pile_info.curr_offset] & 0xff);
+                       pile_info_p->font = mfont;
+                       pile_info_p->size = text[Pile_info.curr_offset+1];
+                       pile_info_p->ch = text[Pile_info.curr_offset+2];
+                       Pile_info.curr_x += width(mfont,
+                                       pile_info_p->size, pile_info_p->ch);
+                       Pile_info.curr_offset += 2;
+                       break;
+
+               case STR_FONT:
+                       (Pile_info.curr_offset)++;
+                       pile_info_p->font = text[Pile_info.curr_offset];
+                       pile_info_p->ch = '\0';
+                       break;
+
+               case STR_SIZE:
+                       (Pile_info.curr_offset)++;
+                       pile_info_p->size = text[Pile_info.curr_offset];
+                       pile_info_p->ch = '\0';
+                       break;
+
+               case STR_SLASH:
+                       pile_info_p->ch = (char) STR_SLASH;
+                       break;
+
+               case STR_C_ALIGN:
+               case STR_L_ALIGN:
+                       pile_info_p->ch = '\0';
+                       break;
+
+               case STR_VERTICAL:
+                       (Pile_info.curr_offset)++;
+                       pile_info_p->vert = vert_distance(
+                               DECODE_VERT(text[Pile_info.curr_offset]),
+                               pile_info_p->font, pile_info_p->size);
+                       pile_info_p->ch = '\0';
+                       break;
+
+               case STR_BACKSPACE:
+                       (Pile_info.curr_offset)++;
+                       Backspace_dist = text[Pile_info.curr_offset];
+                       backdist = backsp_width(pile_info_p->size);
+                       pile_info_p->hor -= backdist;
+                       Pile_info.curr_x -= backdist;
+                       pile_info_p->ch = '\0';
+                       break;
+
+               case STR_PAGENUM:
+               case STR_NUMPAGES:
+                       /* These aren't really allowed in piles,
+                        * but we can hit this code under some error cases,
+                        * so we recognize them and do something reasonable.
+                        */
+                       (Pile_info.curr_offset)++;
+                       pile_info_p->ch = text[Pile_info.curr_offset];
+                       break;
+               
+               default:
+                       if ( IS_STR_COMMAND(text[Pile_info.curr_offset]) & 0xff) {
+                               pfatal("unexpected STR_ value 0x%x in get_piled()",
+                                       text[Pile_info.curr_offset] & 0xff);
+                       }
+
+                       /* ordinary character */
+                       Pile_info.curr_x += width(pile_info_p->font,
+                                       pile_info_p->size,
+                                       text[Pile_info.curr_offset]);
+                       pile_info_p->ch = text[Pile_info.curr_offset];
+                       break;
+               }
+       }
+
+       return(YES);
+}
+\f
+
+/* given a pointer into a string, return the code for the next
+ * character in the string. This will be either the ASCII code
+ * or the music symbol code. This function will also update the
+ * pointer into the string and the font and size if appropriate.
+ * If there happens to be a music character in the middle of a string,
+ * the font (and maybe size) will temporarily be changed for the music
+ * font. This function keeps track of that.
+ *
+ * Restrictions: This function must be used by calling it on the beginning
+ * of a string, then to walk through that string. You don't have to go all the
+ * way to the end of a given string, but once you switch to a new string
+ * (from which you must begin at its beginning) you cannot go back to the
+ * middle of some other string that you had been working on before.
+ *
+ * This function calls the more general function which can also update
+ * vertical motion and alignment information. It is retained for backward
+ * compatibility for the places that don't care about those things.
+ */
+
+int
+next_str_char(str_p_p, font_p, size_p)
+
+char **str_p_p;        /* address of pointer into string. Will be incremented
+                * to beyond current character on return (this might
+                * be several bytes into the string if current char
+                * is a special string command */
+int *font_p;   /* pointer to font. Will be updated to new font if
+                * appropriate */
+int *size_p;   /* pointer to size. Will be updated to new size if
+                * appropriate */
+
+{
+       /* place to hold things we don't care about from general function */
+       double dummy_vertical, dummy_horizontal;
+       int dummy_in_pile;
+       int dummy_textfont;
+
+       return(nxt_str_char(str_p_p, font_p, size_p, &dummy_textfont,
+               &dummy_vertical, &dummy_horizontal, &dummy_in_pile, NO));
+}
+\f
+
+/* returns the next character in string, along with any font/size changes
+ * and horizontal/vertical motions that should happen before that character.
+ */
+
+int
+nxt_str_char(str_p_p, font_p, size_p, textfont_p, vertical_p, horizontal_p, in_pile_p, slash)
+
+char **str_p_p;
+int *font_p;
+int *size_p;
+int *textfont_p;       /* font disregarding music characters */
+double *vertical_p;    /* if non-zero, do vertical motion */
+double *horizontal_p;  /* if non-zero, do horizontal motion */
+int *in_pile_p;                /* will be set to YES if inside a pile */
+int slash;             /* if YES, return any STR_SLASH's found,
+                        * else ignore them */
+
+{
+       static char *prev_str_p;        /* most recent value of *str_p_p */
+       static int textfont;            /* current font, ignoring music chars */
+       static int textsize;            /* current size, ignoring music chars */
+       static int pile_mode;           /* if inside a pile */
+       int code;
+       struct PILE_INFO pile_info;
+
+       /* initialize to assume no vertical motion or alignment at this char */
+       *horizontal_p = *vertical_p = 0.0;
+
+       if (*str_p_p == (char *) 0) {
+               return(0);
+       }
+
+       for ( ; ; ) {
+
+               if (prev_str_p != *str_p_p) {
+                       /* must be starting on a different string. Our
+                        * remembered text font/size are no longer valid */
+                       textfont = *font_p;
+                       *textfont_p = textfont;
+                       textsize = *size_p;
+                       pile_mode = NO;
+               }
+
+               if (pile_mode == YES) {
+                       /* call the special function for piled to get next */
+                       pile_info.font = textfont;
+                       pile_info.size = textsize;
+                       pile_mode = get_piled(&pile_info);
+
+                       /* save what it returned */
+                       *font_p = pile_info.font;
+                       *size_p = pile_info.size;
+                       if (pile_info.font != FONT_MUSIC) {
+                               textfont = pile_info.font;
+                               *textfont_p = textfont;
+                               textsize = pile_info.size;
+                       }
+
+                       /* Add motion to any accumulated so far */
+                        *vertical_p += pile_info.vert;
+                        *horizontal_p += pile_info.hor;
+
+                       if (pile_info.ch == '\0') {
+                               /* only motion this time, keep going */
+                               continue;
+                       }
+                       else if ( (pile_info.ch & 0xff) == STR_SLASH &&
+                                               slash == NO) {
+                               /* caller doesn't care about slashes */
+                               continue;
+                       }
+                       else {
+                               *in_pile_p = pile_mode;
+                               return (pile_info.ch);
+                       }
+               }
+               *in_pile_p = NO;
+
+               if (**str_p_p == '\0') {
+                       /* end of string */
+                       *font_p = textfont;
+                       *size_p = textsize;
+                       return(0);
+               }
+
+               if ( ! IS_STR_COMMAND(**str_p_p)) {
+                       /* just an ordinary character. Return it after updating
+                        * pointer to point past it */
+                       code = **str_p_p & 0xff;
+                       ++(*str_p_p);
+                       prev_str_p = *str_p_p;
+
+                       /* if last chacter was music character, put back real                            * font and size */
+                       if (IS_MUSIC_FONT(*font_p)) {
+                               *font_p = textfont;
+                               *size_p = textsize;
+                       }
+                       return(code);
+               }
+
+               /* special command. see which one */
+               switch ( (unsigned) (**str_p_p & 0xff) ) {
+
+               case STR_FONT:
+                       /* change font to specified font and point past it */
+                       *font_p = *++(*str_p_p);
+                       ++(*str_p_p);
+                       textfont = *font_p;
+                       *textfont_p = textfont;
+                       break;
+
+               case STR_SIZE:
+                       /* change size to specified size and point past it */
+                       *size_p = *++(*str_p_p);
+                       ++(*str_p_p);
+                       textsize = *size_p;
+                       break;
+
+               case STR_PAGENUM:
+                       /* Page number and number of pages are strange cases.
+                        * We don't necessarily know at this point
+                        * how many digits long they will be. So we punt:
+                        * just return % or #. For height, ascent, and descent,
+                        * the % or # will be the same as any number
+                        * of digits (or at least close enough, we hope).
+                        * That means the only problem is when we are getting
+                        * the width of a string or actually printing
+                        * it, so we'll deal with those as special cases */
+                       *str_p_p += 2;
+                       prev_str_p = *str_p_p;
+                       return('%');
+               case STR_NUMPAGES:
+                       *str_p_p += 2;
+                       prev_str_p = *str_p_p;
+                       return('#');
+
+
+               case STR_MUS_CHAR:
+               case STR_MUS_CHAR2:
+                       /* music character */
+                       *font_p = str2mfont( (unsigned) (**str_p_p & 0xff) );
+                       *size_p = *++(*str_p_p);
+                       code = (*++(*str_p_p)) & 0xff;
+                       ++(*str_p_p);
+                       prev_str_p = *str_p_p;
+                       return(code);
+
+               case STR_BACKSPACE:
+                       Backspace_dist = (*++(*str_p_p)) & 0xff;
+                       ++(*str_p_p);
+                       prev_str_p = *str_p_p;
+                       *font_p = textfont;
+                       *size_p = textsize;
+                       return('\b');
+
+               case STR_PRE:
+               case STR_U_PRE:
+               case STR_PRE_END:
+               case STR_PST:
+               case STR_U_PST:
+               case STR_PST_END:
+               case STR_BOX:
+               case STR_BOX_END:
+               case STR_CIR:
+               case STR_CIR_END:
+                       ++(*str_p_p);
+                       break;
+
+               case STR_VERTICAL:
+                       *vertical_p += vert_distance(
+                                       DECODE_VERT( *++(*str_p_p) ),
+                                       textfont, textsize);
+                       ++(*str_p_p);
+                       break;
+
+               case STR_C_ALIGN:
+               case STR_L_ALIGN:
+                       ++(*str_p_p);
+                       break;
+
+               case STR_PILE:
+                       pile_info.font = textfont;
+                       pile_info.size = textsize;
+                       *str_p_p = prep_pile(*str_p_p, &pile_info);
+                       *vertical_p += pile_info.vert;
+                       *horizontal_p += pile_info.hor;
+                       *size_p = pile_info.size;
+                       textsize = *size_p;
+                       pile_mode = YES;
+                       break;
+
+               case STR_SLASH:
+                       ++(*str_p_p);
+                       prev_str_p = *str_p_p;
+                       if (slash == YES) {
+                               return(STR_SLASH);
+                       }
+                       break;
+
+               default:
+                       pfatal("bad internal format for string (%x)",
+                                       **str_p_p & 0xff);
+                       /*NOTREACHED*/
+                       break;
+               }
+               prev_str_p = *str_p_p;
+       }
+}
+\f
+
+/* Given an argument to STR_VERTICAL and a font and size,
+ * return the distance in inches to move vertically. */
+
+static double
+vert_distance(vert_arg, font, size)
+
+int vert_arg;
+int font;
+int size;
+
+{
+       double ratio;
+
+       /* first convert to ratio relative to font height */
+       if (vert_arg >= 0) {
+               ratio = (double) vert_arg / (double) MAXVERTICAL;
+       }
+       else {
+               ratio = (double) vert_arg / (double) (-MINVERTICAL);
+       }
+       return(ratio * fontheight(font, size));
+}
+\f
+
+/* return width of most recent backspace returned by next_str_char() */
+
+double
+backsp_width(size)
+
+int size;      /* adjust to this point size */
+
+{
+       return ( (double) Backspace_dist * ((double) size / (double) DFLT_SIZE)
+                                       / BACKSP_FACTOR);
+}
+
+
+/* Return width of current pile */
+
+double
+pile_width()
+
+{
+       return(Pile_info.width_left_of_align + Pile_info.width_right_of_align);
+}
+\f
+
+/* adjust size when entering/leaving a pile. Called with current size and
+ * whether we are entering or leaving. It returns the new size. */
+
+int
+pile_size(size, in_pile)
+
+int size;      /* current size */
+int in_pile;   /* if YES, we are currently in a pile and are about to leave
+                * it; if NO, we are about to enter the pile */
+
+{
+       int new_size;
+
+       if (in_pile == NO) {
+               /* entering pile. Save current size, and return new size */
+               Pile_info.orig_size = size;
+               /* constrain new size to be at least MINSIZE */
+               if ((Pile_info.new_size = PILE_A * size / PILE_B) < MINSIZE) {
+                       Pile_info.new_size = MINSIZE;
+               }
+               return(Pile_info.new_size);
+       }
+       else {
+               /* leaving pile */
+               /* Restore size. If we're still at the size at the beginning
+                * of the pile, use the orginal value before the pile to avoid
+                * any possible roundoff errors going back and forth,
+                * otherwise adjust by inverse of the factor used when
+                * entering the pile. */
+               if (size == Pile_info.new_size) {
+                       return(Pile_info.orig_size);
+               }
+               else {
+                       if ((new_size = (size * PILE_B) / PILE_A) > MAXSIZE) {
+                               /* constrain to no larger than MAXSIZE */
+                               new_size = MAXSIZE;
+                       }
+                       return(new_size);
+               }
+       }
+}
+\f
+
+/* given where a pile begins and the font/size at that point, return the
+ * width from the beginning to the pile to the alignment point of the pile. */
+
+double
+align_distance(string, font, size)
+
+char *string;  /* pile starts here */
+int font;
+int size;
+
+{
+       struct PILE_INFO pile_info;
+
+       pile_info.font = font;
+       pile_info.size = size;
+       (void) prep_pile(string, &pile_info);
+       return(Pile_info.width_left_of_align);
+}
diff --git a/mup/mup/parstssv.c b/mup/mup/parstssv.c
new file mode 100644 (file)
index 0000000..bf79df2
--- /dev/null
@@ -0,0 +1,297 @@
+/* Copyright (c) 2003 by Arkkra Enterprises. */
+/* All rights reserved. */
+
+/* This file contains parse-time functions related to TIMEDSSVs.
+ * These are used to specify mid-measure parameter changes,
+ * like change of clef.
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+/* Mid-measure SSV's eventually get attached to the BAR, but we need
+ * to point to the list temporarily while the BAR doesn't exist yet. */
+static struct TIMEDSSV *Timedssv_p;
+
+/* When there is more than one TIMEDSSV at the same moment in time,
+ * we use user input order, so we add items to the end of the list.
+ * This keeps track of where to put the next one.
+ */
+static struct TIMEDSSV **Timed_tail_p_p = &Timedssv_p;
+
+static struct TIMEDSSV *tssv_new P((int context));
+\f
+
+/* Allocate and initalize a TIMEDSSV for each staff/voice being defined,
+ *  and return pointer to the first one.
+ */
+
+struct TIMEDSSV *
+tssv_create(context)
+
+int context;
+
+{
+       struct SVRANGELIST *svr_p;      /* list of staffs/voices being entered */
+       struct RANGELIST *srange_p;     /* list of staffs being entered */
+       struct RANGELIST *vrange_p;     /* list of voices being entered */
+       struct TIMEDSSV *new_p;
+       struct TIMEDSSV *first_p = 0;   /* first one created */
+       int s;                          /* staff number */
+       int v;                          /* voice number */
+
+       /* Create as many new TIMEDSSVs as needed, based on the current list
+        * of staffs/voices being defined,
+        * link them onto the temporary list for the current measure.
+        */
+
+       switch (context) {
+       case C_SCORE:
+               first_p = new_p = tssv_new(context);
+               break;
+       case C_STAFF:
+       case C_VOICE:
+               for (svr_p = Svrangelist_p; svr_p != 0; svr_p = svr_p->next) {
+                       for (srange_p = svr_p->stafflist_p; srange_p != 0;
+                                               srange_p = srange_p->next) {
+                               for (s = srange_p->begin; s <= srange_p->end; s++) {
+                                       if (context == C_STAFF) {
+                                               new_p = tssv_new(context);
+                                               if (first_p == 0) {
+                                                       first_p = new_p;
+                                               }
+                                               new_p->ssv.staffno = s;
+                                       }
+                                       else {
+                                               for (vrange_p = svr_p->vnolist_p;
+                                                               vrange_p != 0;
+                                                               vrange_p = vrange_p->next) {
+                                                       for (v = vrange_p->begin;
+                                                               v <= vrange_p->end;
+                                                               v++) {
+                                                          new_p = tssv_new(context);
+                                                          if (first_p == 0) {
+                                                               first_p = new_p;
+                                                          }
+                                                          new_p->ssv.staffno = s;
+                                                          new_p->ssv.voiceno = v;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               break;
+       default:
+               pfatal("invalid context %d when creating TIMEDSSV", context);
+               /*NOTREACHED*/
+               break;
+       }
+       return(first_p);
+}
+\f
+
+/* Create a single TIMEDSSV and link it onto the list */
+
+static struct TIMEDSSV *
+tssv_new(context)
+
+int context;
+
+{
+       struct TIMEDSSV *curr_tssv_p;
+
+       CALLOC(TIMEDSSV, curr_tssv_p, 1);
+       zapssv( & (curr_tssv_p->ssv) );
+       curr_tssv_p->ssv.context = context;
+       curr_tssv_p->grpsyl_p = 0;
+       curr_tssv_p->time_off.n = -1;
+       curr_tssv_p->time_off.d = 1;
+
+       curr_tssv_p->next = 0;
+       *Timed_tail_p_p = curr_tssv_p;
+       Timed_tail_p_p = &(curr_tssv_p->next);
+
+       return(curr_tssv_p);
+}
+\f
+
+/* Save a parameter setting in the given TIMEDSSV. We only support a very
+ * limited list of parameters that can be changed mid-measure,
+ * so this checks for valid ones.
+ */
+
+void
+tssv_update(timedssv_p, param, value)
+
+struct TIMEDSSV *timedssv_p;
+int param;
+int value;
+
+{
+       /* Could be multiple staffs/voices, so do them all */
+       for (  ; timedssv_p != 0; timedssv_p = timedssv_p->next) {
+               switch (param) {
+               case CLEF:
+                       timedssv_p->ssv.clef = value;
+                       break;
+               case RELEASE:
+                       if (rangecheck(value, MINRELEASE, MAXRELEASE,
+                                       "mid-measure release change") == YES) {
+                               timedssv_p->ssv.release = value;
+                       }
+                       break;
+               case DEFOCT:
+                       if (rangecheck(value, MINOCTAVE, MAXOCTAVE,
+                                       "mid-measure defoct change") == YES) {
+                               timedssv_p->ssv.defoct = value;
+                       }
+                       break;
+
+               default:
+                       yyerror("only clef, defoct, and release parameters can be changed mid-measure");
+                       return;
+               }
+               if (timedssv_p->ssv.used[param] == YES) {
+                       warning("multiple changes of the same parameter; last used");
+               }
+               timedssv_p->ssv.used[param] = YES;
+       }
+}
+\f
+
+/* Associate grpsyl with TIMEDSSV. This should be called at the end of
+ * parsing of a grpsyl, in case it has at least one timed ssv. */
+
+void
+tssv_setgrpsyl(gs_p)
+
+struct GRPSYL *gs_p;
+
+{
+       struct TIMEDSSV *tssv_p;
+
+       /* User could input multiple << >> things, and each gets their
+        * own TIMEDSSV, so we need to associate this grpsyl with
+        * all that don't yet have one.  */
+       for (tssv_p = Timedssv_p; tssv_p != 0; tssv_p = tssv_p->next) {
+               if (tssv_p->grpsyl_p == 0) {
+                       tssv_p->grpsyl_p = gs_p;
+
+                       /* Do some error checks */
+                       if (tssv_p->ssv.used[CLEF] == YES) {
+                               if (tssv_p->ssv.context == C_STAFF
+                                               && is_tab_staff(tssv_p->ssv.staffno)) {
+                                       yyerror("can't change clef of tab staff");
+                               }
+                               if (tssv_p->ssv.context == C_VOICE) {
+                                       yyerror("can't change clef in voice context");
+                               }
+                       }
+               }
+       }
+}
+
+\f
+
+/* Do processing on one input line worth of TIMEDSSVs.
+ */
+
+void
+tssv_line()
+{
+       struct TIMEDSSV *ts_p;
+       struct GRPSYL *gs_p;
+
+       /* First we have to find the time offsets of each TIMEDSSV.
+        * We can't necessarily calculate them at the time
+        * they were added to the list, since for tuplets
+        * we don't know fulltimes till we reach the end
+        * of the tuplet, and know how to adjust.
+        * So we just save the GRPSYL* at that point,
+        * and now we go through and find all the actual times.
+        */
+       for (ts_p = Timedssv_p; ts_p != 0; ts_p = ts_p->next) {
+               if (GE(ts_p->time_off, Zero)) {
+                       /* already set from some previous line */
+                       continue;
+               }
+
+               if (ts_p->grpsyl_p == 0) {
+                       /* This could happen if there was a user input
+                        * error, because we could have set up the TIMEDSSV
+                        * and then not been able to parse the GRPSYL that
+                        * was intended to go with it.  Set time offset to
+                        * a safe value, and skip the rest of the loop,
+                        * so we don't try to dereference the null ptr. */
+                       ts_p->time_off = Zero;
+                       continue;
+               }
+
+               /* Count up the time before the group where the timed
+                * SSV was specified. */
+               for (ts_p->time_off = Zero, gs_p = ts_p->grpsyl_p->prev;
+                                               gs_p != 0; gs_p = gs_p->prev) {
+                       /* Alt groups have not yet had their time adjusted,
+                        * so we have to compensate for that. */
+                       if (gs_p->slash_alt < 0 || (gs_p->prev != 0
+                                       && gs_p->prev->slash_alt < 0) ) {
+                               ts_p->time_off = radd(ts_p->time_off,
+                                               rdiv(gs_p->fulltime, Two));
+                       }
+                       else if (gs_p->grpvalue != GV_ZERO) {
+                               ts_p->time_off = radd(ts_p->time_off,
+                                                       gs_p->fulltime);
+                       }
+               }
+       }
+}
+\f
+
+/* Sort the current TIMEDSSV list by time and return pointer to the head
+ * of the sorted list. The sorting is done by time. When there is a tie
+ * things are put in user input order. Also re-inits for the next measure.
+ */
+
+struct TIMEDSSV *
+tssv_sort()
+
+{
+       struct TIMEDSSV *ret;   /* return value is pointer to sorted list */
+       short moved;            /* YES if something was moved during sort */
+
+       /* Most of the time, the list will be empty. */
+       if (Timedssv_p == 0) {
+               return(0);
+       }
+
+       /* Sort in time order.
+        * The list is almost certain to be very short,
+        * so sort needn't be very efficient. So we check pairs
+        * and swap ones that are backwards. */
+       do {
+               struct TIMEDSSV **ts_p_p;
+               struct TIMEDSSV *tmp_ts_p;
+
+               moved = NO;
+               for (ts_p_p = &Timedssv_p; (*ts_p_p)->next != 0;
+                                               ts_p_p = &((*ts_p_p)->next) ) {
+                       if ( GT( (*ts_p_p)->time_off, (*ts_p_p)->next->time_off ) ) {
+                               /* Wrong order. Swap them */
+                               tmp_ts_p = (*ts_p_p)->next;
+                               (*ts_p_p)->next = (*ts_p_p)->next->next;
+                               tmp_ts_p->next = *ts_p_p;
+                               *ts_p_p = tmp_ts_p;
+                               moved = YES;
+                               break;
+                       }
+               }
+       } while (moved == YES);
+       ret = Timedssv_p;
+
+       /* re-init for next measure */
+       Timedssv_p = 0;
+       Timed_tail_p_p = &(Timedssv_p);
+       return(ret);
+}
diff --git a/mup/mup/parstuff.c b/mup/mup/parstuff.c
new file mode 100644 (file)
index 0000000..dff001d
--- /dev/null
@@ -0,0 +1,1501 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* parser functions related to STUFF */
+
+
+#include <string.h>
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+/* if user specifies a "til" clause on stuff with a number of measures > 0,
+ * we need to save away info about where the til clause will end, to make sure
+ * that it doesn't fall off the end of the measure or the piece. This is the
+ * struct we use to save this info. */
+static struct TIL_INFO {
+       char    *inputfile;     /* where STUFF was defined */
+       int     inputlineno;    /* where STUFF was defined */
+       int     measnum;        /* number of measure in which til clause ends */
+       float   count;          /* count in measure where til clause ends */
+       struct TIL_INFO *next;  /* for linked list */
+} *Til_info_list_p;
+
+/* info about the STUFF currently being collected from input */
+static int Curr_stuff_type;    /* ST_* */
+static int Stuff_size;         /* point size of stuff text string */
+static int Modifier;           /* TM_* for text, L_* for phrase */
+static int Measnum = 1;                /* to check til clauses. Can't use Meas_num
+                                * global because it doesn't count invisible
+                                * bars but til clauses do */
+static int Multi_adjust;       /* adjustment to Measnum to account
+                                * for multirests */
+
+/* head and tail of list of STUFF currently being collected from input */
+static struct STUFF *Head_stufflist_p;
+static struct STUFF *Tail_stufflist_p;
+
+/* current pedal state for each staff. YES if in the middle of doing pedal,
+ * NO if not. */
+static short Pedal_state[MAXSTAFFS + 1];
+static char *Ped_begin_str;    /* will point to "\(begped)" */
+static char *Ped_up_down_str;  /* will point to "\(pedal)" */
+
+/* static functions */
+static struct STUFF *clone_stufflist P((struct STUFF *stufflist_p,
+                       int staffno, int all));
+static void do_attach P((int staffno, int all, struct RANGELIST *vno_range_p));
+static void midi_attach P((int staffno, struct STAFF *staff_p,
+                       struct RANGELIST *vno_range_p, int all));
+static void free_stufflist P((struct STUFF *stuff_P));
+static void free_tils P((struct TIL_INFO *til_p));
+static void fix_pedal P((int staffno, struct STUFF *stuff_p));
+static void ped_order_chk P((void));
+\f
+
+/* save current stuff type value. Also check that we are in data (music)
+ * context */
+
+void
+set_stuff_type(stuff_type)
+
+int stuff_type;
+
+{
+       Curr_stuff_type = stuff_type;
+
+       (void) contextcheck(C_MUSIC, "statement");
+}
+\f
+
+/* return current stuff type */
+
+int
+get_stuff_type()
+
+{
+       return(Curr_stuff_type);
+}
+\f
+
+/* check all the things in an input line of stuff, up to the colon,
+ * for consistency, and save interesting info away for later use. */
+
+void
+chk_stuff_header(size, modifier, place, dist_usage)
+
+int size;              /* point size, or -1 if to use default */
+int modifier;          /* TM_* for text, L_* for phrase */
+int place;             /* PL_* */
+int dist_usage;                /* SD_* */
+
+{
+
+       debug(4, "chk_stuff_header");
+
+       switch (Curr_stuff_type) {
+       case ST_ROM:
+       case ST_BOLD:
+       case ST_ITAL:
+       case ST_BOLDITAL:
+       case ST_MUSSYM:
+               break;
+       case ST_PEDAL:
+               if (place != PL_BELOW && place != PL_UNKNOWN) {
+                       yyerror("pedal must be below");
+               }
+               /*FALLTHRU*/
+       default:
+               if (size != -1) {
+                       yyerror("can't specify size except with a font or mussym");
+               }
+               if (modifier != TM_NONE && Curr_stuff_type != ST_PHRASE) {
+                       l_yyerror(Curr_filename, yylineno,
+                                       "can't specify %s except with a font",
+                                       stuff_modifier(modifier));
+               }
+               if (Curr_stuff_type == ST_PHRASE && modifier != L_NORMAL &&
+                               modifier != L_DOTTED && modifier != L_DASHED) {
+                       l_yyerror(Curr_filename, yylineno,
+                                       "only dotted or dashed line type can be specified for phrase");
+               }
+               break;
+       }
+
+       if (Curr_stuff_type == ST_OCTAVE) {
+               if (is_tab_range() == YES) {
+                       yyerror("octave not allowed on tablature staff");
+               }
+               else if(place == PL_BETWEEN) {
+                       yyerror("octave must be above or below");
+                       place = PL_ABOVE;
+               }
+       }
+
+       if (Curr_stuff_type == ST_PHRASE && place == PL_BETWEEN) {
+               yyerror("phrase must be above, below, or omitted");
+               place = PL_ABOVE;
+       }
+
+       if (dist_usage != SD_NONE) {
+               if (Curr_stuff_type == ST_PEDAL) {
+                       yyerror("dist not allowed on pedal");
+               }
+               else if (Curr_stuff_type == ST_PHRASE) {
+                       yyerror("dist not allowed on phrase");
+               }
+               else if (Curr_stuff_type == ST_MIDI) {
+                       yyerror("dist not allowed on midi");
+               }
+
+               if (place == PL_BETWEEN) {
+                       yyerror("dist not allowed with 'between'");
+               }
+       }
+
+       /* Save the modifier value.
+        * Have to set this before calling dflt_place() */
+       Modifier = modifier;
+
+       /* fill in default values if user didn't specify */
+       if (place == PL_UNKNOWN) {
+               place = dflt_place();
+       }
+
+       Stuff_size = size;
+       Place = (short) place;
+
+       /* make sure current list of stuff is empty */
+       Head_stufflist_p = Tail_stufflist_p = (struct STUFF *) 0;
+}
+\f
+
+/* return default value for place depending on value of Curr_stuff_type */
+
+int
+dflt_place()
+
+{
+       switch (Curr_stuff_type) {
+
+       case ST_PEDAL:
+               return(PL_BELOW);
+
+       case ST_OCTAVE:
+               yyerror("must specify above or below with octave");
+               /* arbitrarily return above. If we leave it as unknown,
+                * we can get double error messages in some cases */
+               return(PL_ABOVE);
+
+       case ST_PHRASE:
+               /* stays unknown at this point */
+               return(PL_UNKNOWN);
+
+       default:
+               if (Modifier == TM_ANALYSIS || Modifier == TM_FIGBASS) {
+                       return(PL_BELOW);
+               }
+               /* default for everything else is above */
+               return(PL_ABOVE);
+       }
+}
+\f
+
+/* Add a space padding to a string (except if is it boxed).
+ * If padding was added, free the passed-in string and return the padded string,
+ * else return the string as is. The incoming string
+ * is expected to already be converted to font/size/string
+ * internal format by this time, although still in input ASCII form.
+ */
+
+char *
+pad_string(string, modifier)
+
+char *string;
+int modifier;  /* TM_* */
+
+{
+       char *padded_string;            /* string with 1-space padding at end */
+       char *str_p;                    /* walk through padded_string */
+       int len;                        /* length of string */
+       int last_was_backslash;         /* YES/NO */
+       int count_backslashed;          /* YES/NO if to count backslashed or
+                                        * unbackslashed colons */
+       int colons;                     /* how many colons found */
+       int extra;                      /* how many extra bytes to malloc */
+
+       /* Boxed and circled strings don't get any extra padding,
+        * so we can use what we have */
+       if (string[2] == '\\' && (string[3] == '[' || string[3] == '{')) {
+               return(string);
+       }
+
+       /* Make a new copy with a space at the end.
+        * But if the string ends in the middle of a pile,
+        * we need to implicitly end the pile before adding the space.
+        * Since the string is still in ASCII form,
+        * we have to count up the number of colons
+        * to see if we are mid-pile. In chord/analysis/figbass
+        * we need to count unbackslashed colon,
+        * otherwise backslashed.*/
+       count_backslashed = (IS_CHORDLIKE(modifier) ? NO : YES);
+       /* figbass implicitly begins with a pile */
+       colons = (modifier == TM_FIGBASS ? 1 : 0);
+       last_was_backslash = NO;
+       for (str_p = string + 2; *str_p != '\0'; str_p++) {
+               if (last_was_backslash == YES) {
+                       if (*str_p == ':' && count_backslashed == YES) {
+                               colons++;
+                       }
+                       last_was_backslash = NO;
+               }
+               else {
+                       if (*str_p ==  ':' && count_backslashed == NO) {
+                               colons++;
+                       }
+                       last_was_backslash = (*str_p == '\\' ? YES : NO);
+               }
+       }
+
+       /* If odd number of colons, we are mid-pile.  Will need
+        * add extra byte to hold the colon to implicitly end the
+        * pile, and if it needs to be a backslashed colon,
+        * another extra byte for that. */
+       if (colons & 1) {
+               extra = (count_backslashed == YES ? 2 : 1);
+       }
+       else {
+               extra = 0;
+       }
+
+       len = strlen(string);
+
+       /* +2 is for space/null at end */
+       MALLOCA(char, padded_string, len + 2 + extra);
+       (void) memcpy(padded_string, string, len);
+       str_p = padded_string + len;
+
+       /* add implicit end-pile if needed */
+       if (extra == 2) {
+               *str_p++ = '\\';
+       }
+       if (extra > 0) {
+               *str_p++ = ':';
+       }
+
+       /* now add space padding */
+       *str_p++ = ' ';
+       *str_p = '\0';
+       FREE(string);
+       return(padded_string);
+}
+\f
+
+/* check a "stuff" item  and add to list */
+
+void
+add_stuff_item(start_count, start_steps, gracebackup, string, bars, count,
+               dist, dist_usage)
+
+double start_count;            /* where in measure to start this stuff */
+double start_steps;            /* offset by this many stepsizes */
+int gracebackup;       /* how many grace notes to back up from start */
+char *string;          /* what to print */
+int bars;              /* how many bar lines to cross with this stuff */
+double count;          /* how many beats into last measure */
+int dist;              /* dist for this specific STUFF, to override param */
+int dist_usage;                /* meaning of dist, SD_*  */
+
+{
+       struct STUFF *new_p;            /* where to store STUFF */
+       struct TIL_INFO *til_info_p;    /* to save info about til clause */
+       int len;                        /* length of stuff text string */
+       char *padded_string;            /* string with 1-space padding at end */
+       char lch;                       /* last character of string */
+
+
+       if (bars != 0 || count != 0.0) {
+               /* has a "til" clause. Check if that is valid */
+               if (Curr_stuff_type == ST_MUSSYM) {
+                       if (string == (char *) 0) {
+                               yyerror("missing string");
+                               return;
+                       }
+
+                       /* not yet changed to internal form, need to compare
+                        * in ASCII form */
+                       if ((strcmp(string + 2, "tr") != 0) &&
+                                       (strcmp(string + 2, "\\(tr)") != 0)) {
+                               yyerror("til not allowed on mussym except on trills");
+                       }
+               }
+
+               else if (Curr_stuff_type == ST_PEDAL) {
+                       yyerror("til not allowed on pedal");
+               }
+
+               else if (Curr_stuff_type == ST_MIDI) {
+                       yyerror("til not allowed on midi");
+               }
+
+               if (Curr_stuff_type != ST_PHRASE &&
+                       (Modifier == TM_CHORD || Modifier == TM_ANALYSIS) ) {
+                       l_yyerror(Curr_filename, yylineno,
+                                       "til not allowed with %s",
+                                       stuff_modifier(Modifier));
+               }
+
+               if (bars == 0) {
+                       if (count > Score.timenum + 1) {
+                               yyerror("'til' value must be <= numerator of time signature + 1");
+                       }
+
+                       if (count < start_count) {
+                               yyerror("til value must be >= start value");
+                       }
+               }
+
+       }
+       else {
+               /* doesn't have a "til" clause. Check if one is required */
+               if (Curr_stuff_type == ST_CRESC ||
+                                               Curr_stuff_type == ST_DECRESC) {
+                       yyerror("til required on cresc/decresc");
+               }
+       }
+       
+       if (start_count > Score.timenum + 1) {
+               yyerror("beat offset must be <= numerator of time signature + 1");
+       }
+
+       if (Curr_stuff_type == ST_CRESC || Curr_stuff_type == ST_DECRESC) {
+               if (string != (char *) 0) {
+                       yyerror("string not allowed with cresc/decresc");
+               }
+               Modifier = TM_DYN;
+       }
+
+       else if (Curr_stuff_type == ST_PHRASE) {
+               if (string != (char *) 0) {
+                       yyerror("string not allowed with phrase");
+               }
+       }
+
+       else if (Curr_stuff_type == ST_PEDAL) {
+               if ( (string != (char *) 0)
+                               && (strcmp(string + 2, "\\(endped)") != 0) ) {
+                       yyerror("pedal string must be either blank or *");
+               }
+       }
+
+       else {
+               if (string == (char *) 0) {
+                       yyerror("string is required");
+                       return;
+               }
+       }
+
+       if (gracebackup != 0 && Place == PL_BETWEEN) {
+               yyerror("grace backup not allowed with 'between'");
+       }
+
+       /* we can't deal with step offset on phrase marks very well,
+        * so warn and ignore if we get one */
+       if (start_steps != 0.0 && Curr_stuff_type == ST_PHRASE) {
+               l_warning(Curr_filename, yylineno, "step offset ignored on phrase mark");
+               start_steps = 0.0;
+       }
+
+       switch (Curr_stuff_type) {
+       case ST_ROM:
+       case ST_BOLD:
+       case ST_ITAL:
+       case ST_BOLDITAL:
+               /* the text-type stuffs are supposed to have a 1-space padding
+                * at the end of them */
+               if (bars != 0 || count != 0.0) {
+                       /* don't add padding if has wavy or solid line
+                        * til clause */
+                       lch = last_char(string);
+                       if (lch == '~' || lch == '_') {
+                               break;
+                       }
+               }
+               string = pad_string(string, Modifier);
+               break;
+
+       case ST_MUSSYM:
+               /* in mussym, user can specify things without the usual
+                * \(---) convention. Change to include them */
+               if (string[2] == '\\' && string[3] == '(') {
+                       /* if user unnecessarily put in the \(--), leave it */
+                       break;
+               }
+
+               len = strlen(string + 2);
+               MALLOCA(char, padded_string, len + 6);
+               (void) sprintf(padded_string, "%c%c\\(%s)", FONT_TR, DFLT_SIZE,
+                                               string + 2);
+               FREE(string);
+               string = padded_string;
+               break;
+
+       default:
+               break;
+       }
+
+       /* fill in a new STUFF struct with appropriate info */
+       new_p = newSTUFF(string, dist, dist_usage, start_count, start_steps,
+               gracebackup, bars, count,
+               Curr_stuff_type, Modifier, Place, Curr_filename, yylineno);
+
+       /* if bars > 0, need to save away til info for later error
+        * checking */
+       if (bars > 0) {
+               CALLOC(TIL_INFO, til_info_p, 1);
+               til_info_p->measnum = Measnum + bars;
+               til_info_p->count = count;
+               til_info_p->inputfile = new_p->inputfile;
+               til_info_p->inputlineno = new_p->inputlineno;
+               til_info_p->next = Til_info_list_p;
+               Til_info_list_p = til_info_p;
+       }
+
+       /* above/between go on the head of the list, below goes on the
+        * tail of the list, so that things come out in the right order.
+        * Midi always goes at the end */
+       if (Place == PL_BELOW || Curr_stuff_type == ST_MIDI) {
+               /* link onto list tail */
+               if ( Tail_stufflist_p == (struct STUFF *) 0) {
+                       Head_stufflist_p = new_p;
+               }
+               else {
+                       Tail_stufflist_p->next = new_p;
+               }
+               Tail_stufflist_p = new_p;
+       }
+       else {
+               /* link onto head of list */
+               new_p->next = Head_stufflist_p;
+               Head_stufflist_p = new_p;
+               if (Tail_stufflist_p == (struct STUFF *) 0) {
+                       Tail_stufflist_p = new_p;
+               }
+       }
+}
+\f
+
+/* return YES if given string consists entirely of the specific music symbol */
+/* the string should be in the internal format of font/size/string */
+
+int
+string_is_sym(string, sym, symfont)
+
+char *string;  /* which string to check */
+int sym;       /* check for this music symbol */
+int symfont;   /* FONT_MUSIC*  */
+
+{
+       int font, size;
+
+
+       if (string == (char *) 0) {
+               return(NO);
+       }
+
+       font = *string++;
+       size = *string++;
+       if (next_str_char(&string, &font, &size) != sym) {
+               return(NO);
+       }
+       if (font != symfont) {
+               return(NO);
+       }
+       if (next_str_char(&string, &font, &size)  == '\0') {
+               return(YES);
+       }
+       return (NO);
+}
+\f
+
+/* connect a list of STUFF to a STAFF. If there is already something on
+ * that STAFF's STUFF list, attach at the end or beginning as appropriate
+ * depending on place. */
+
+void
+attach_stuff()
+
+{
+       struct SVRANGELIST *svr_p;      /* to walk through Svrangelist */
+       struct RANGELIST *r_p;          /* to walk through staff range list */
+       short staffno;
+
+
+       debug(4, "attach_stuff");
+
+       /* make sure we've got STAFF structs for this measure */
+       create_staffs();
+
+       for (svr_p = Svrangelist_p; svr_p != (struct SVRANGELIST *) 0;
+                                               svr_p = svr_p->next) {
+               for (r_p = svr_p->stafflist_p; r_p != (struct RANGELIST *) 0;
+                                               r_p = r_p->next) {
+       
+                       for (staffno = r_p->begin; staffno <= r_p->end
+                                       && staffno <= MAXSTAFFS; staffno++) {
+                               do_attach(staffno, r_p->all, svr_p->vnolist_p);
+
+                               if (Place == PL_BETWEEN) {
+                                       /* between has 2 staffs in its range,
+                                        * but stuff is only associated
+                                        * with the top staff */
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       free_rlists();
+
+       /* have made copies of stuff for each staff that gets one, with
+        * the proper font/size etc, so need to free master stufflist copy */
+       free_stufflist(Head_stufflist_p);
+}
+\f
+
+/* Attach STUFF for a specific staff. */
+
+static void
+do_attach(staffno, all, vno_range_p)
+
+int staffno;
+int all;
+struct RANGELIST *vno_range_p;
+
+{
+       struct STAFF *staff_p;          /* where to attach STUFF */
+       struct STUFF *stufflist_p;      /* current copy of STUFF list */
+
+
+       if (staffno > Score.staffs) {
+               l_yyerror(Head_stufflist_p->inputfile,
+                               Head_stufflist_p->inputlineno,
+                               "staff number out of range");
+               return;
+       }
+
+       staff_p = Staffmap_p[staffno]->u.staff_p;
+
+       if (Place == PL_BETWEEN) {
+               if (staffno + 1 > Score.staffs) {
+                       /* will have already exclaimed about
+                        * this error before, so no need to print message,
+                        * but better skip next check */
+                       return;
+               }
+
+               /* if either staff of a between is invisible,
+                * throw this stuff away */
+               if (svpath(staffno, VISIBLE)->visible == NO ||
+                               svpath(staffno + 1,
+                               VISIBLE)->visible == NO) {
+                       return;
+               }
+       }
+
+       /* handle MIDI stuff specially */
+       if (Curr_stuff_type == ST_MIDI) {
+               if (all == YES) {
+                       /* need to find top visible staff/voice to attach to */
+                       int s;          /* staff number */
+                       int v;          /* voice number */
+                       struct RANGELIST range;
+       
+                       v = 1;  /* avoid bogus "used before set" warning */
+                       for (s = 1; s <= MAXSTAFFS; s++) {
+                               if (svpath(s, VISIBLE)->visible == YES) {
+                                       for (v = 1; v <= MAXVOICES; v++) {
+                                               if (vvpath(s, v, VISIBLE)->visible == YES) {
+                                                       break;
+                                               }
+                                       }
+                                       if (v <= MAXVOICES) {
+                                               break;
+                                       }
+                               }
+                       }
+                       if (s > MAXSTAFFS || v > MAXVOICES) {
+                               pfatal("failed to find top visible staff/voice");
+                       }
+                       /* make a special RANGELIST for this */
+                       range.begin = range.end = v;
+                       range.all = YES;
+                       range.next = 0;
+                       midi_attach(s, Staffmap_p[s]->u.staff_p, &range, all);
+               }
+               else {
+                       midi_attach(staffno, staff_p, vno_range_p, all);
+               }
+       }
+
+       else {
+               /* make the copy for this staff from master copy */
+               stufflist_p = clone_stufflist(Head_stufflist_p, staffno, all);
+
+               if (Curr_stuff_type == ST_PEDAL) {
+                       fix_pedal(staffno, stufflist_p);
+               }
+
+               connect_stuff(staff_p, stufflist_p);
+       }
+}
+\f
+
+/* attach MIDI stuff. This is slightly different than other stuff because
+ * it can be applied to one or both voices. */
+
+static void
+midi_attach(staffno, staff_p, vno_range_p, all)
+
+int staffno;           /* attach to this staff number */
+struct STAFF *staff_p; /* attach to this staff struct */
+struct RANGELIST *vno_range_p;
+int all;               /* if associated with "all" */
+
+{
+       struct RANGELIST *r_p;          /* walk through vno_range_p */
+       int vno;                        /* voice number */
+       struct STUFF *stufflist_p;      /* copy of stuff */
+       struct STUFF *st_p;             /* walk through stufflist_p */
+       short place;
+
+
+       /* do for each voice that MIDI stuff applies to */
+       for (r_p = vno_range_p; r_p != (struct RANGELIST *) 0; r_p = r_p->next) {
+               for (vno = r_p->begin; vno <= r_p->end; vno++) {
+
+                       /* make the copy for this staff from master copy */
+                       stufflist_p = clone_stufflist(Head_stufflist_p,
+                                               staffno, all);
+
+                       /* fix up place based on voice number */
+                       switch (vno) {
+                       case 1:
+                               place = PL_ABOVE;
+                               break;
+                       case 2:
+                               place = PL_BELOW;
+                               break;
+                       case 3:
+                               place = PL_BETWEEN;
+                               break;
+                       default:
+                               pfatal("illegal vno for midi");
+                               /*NOTREACHED*/
+                               place = PL_UNKNOWN;  /* avoid "used before set" warning */
+                               break;
+                       }
+                       for (st_p = stufflist_p; st_p != (struct STUFF *) 0;
+                                               st_p = st_p->next) {
+                               st_p->place = place;
+                       }
+
+                       connect_stuff(staff_p, stufflist_p);
+               }
+       }
+}
+\f
+
+/* connect a new stuff list into an existing stuff list. Add below stuff and
+ * MIDI stuff to the end of the list,
+ * and others to beginning of list, but make sure any
+ * "above all" comes after any above non-all, and that any below non-all
+ * comes before any "below all."
+ */
+
+void
+connect_stuff(staff_p, stufflist_p)
+
+struct STAFF *staff_p;         /* connect to stuff off of this staff */
+struct STUFF *stufflist_p;     /* connect this list  of stuff */
+
+{
+       struct STUFF *st_p;             /* to find link place in STUFF list */
+       struct STUFF *s_p;              /* to find end of stufflist_p */
+       struct STUFF **ins_p_p;         /* where to insert in list */
+
+
+       if (staff_p == (struct STAFF *) 0 || stufflist_p == (struct STUFF *) 0) {
+               return;
+       }
+
+       if (staff_p->stuff_p == (struct STUFF *) 0) {
+               /* no list before, so attach this one
+                * directly to STAFF */
+               staff_p->stuff_p = stufflist_p;
+       }
+
+       else if (Place == PL_BELOW || stufflist_p->stuff_type == ST_MIDI) {
+               /* if this set of stuff isn't associated with
+                * "all", then it goes before any below "all" stuff */
+               if (stufflist_p->all == NO) {
+                       for (ins_p_p = &(staff_p->stuff_p); 
+                                       *ins_p_p != (struct STUFF *) 0;
+                                       ins_p_p = &((*ins_p_p)->next)) {
+                               if ( (*ins_p_p)->place == PL_BELOW &&
+                                               (*ins_p_p)->all == YES) {
+                                       break;
+                               }
+                       }
+                       /* find end of list to be inserted */
+                       for (s_p = stufflist_p; s_p->next != (struct STUFF *) 0;
+                                                       s_p = s_p->next) {
+                               ;
+                       }
+
+                       /* insert */
+                       s_p->next = *ins_p_p;
+                       *ins_p_p = stufflist_p;
+               }
+
+               else {
+                       /* goes at end of list. find the end */
+                       for (st_p = staff_p->stuff_p;
+                                       st_p->next != (struct STUFF *)0;
+                                       st_p = st_p->next) {
+                               ;
+                       }
+
+                       /* connect in the new list */
+                       st_p->next = stufflist_p;
+               }
+       }
+       else {
+               /* find end of new list */
+               for (s_p = stufflist_p;
+                               s_p->next != (struct STUFF *) 0;
+                               s_p = s_p->next) {
+                       ;
+               }
+
+               if (stufflist_p->all == NO) {
+                       /* goes at the head of the list */
+                       s_p->next = staff_p->stuff_p;
+                       staff_p->stuff_p = stufflist_p;
+               }
+               else {
+                       /* goes before any existing above all */
+                       for (ins_p_p = &(staff_p->stuff_p); 
+                                       *ins_p_p != (struct STUFF *) 0;
+                                       ins_p_p = &((*ins_p_p)->next)) {
+                               if ( (*ins_p_p)->place == PL_ABOVE &&
+                                               (*ins_p_p)->all == YES) {
+                                       break;
+                               }
+                       }
+                       /* find end of list to be inserted */
+                       for (s_p = stufflist_p; s_p->next != (struct STUFF *) 0;
+                                                       s_p = s_p->next) {
+                               ;
+                       }
+
+                       /* insert */
+                       s_p->next = *ins_p_p;
+                       *ins_p_p = stufflist_p;
+               }
+       }
+}
+\f
+
+/* given a list of STUFF, return a clone of the list */
+
+static struct STUFF *
+clone_stufflist(stufflist_p, staffno, all)
+
+struct STUFF *stufflist_p;     /* what stuff to clone */
+int staffno;                   /* which staff, to get proper point size */
+int all;                       /* YES if was "above all" or "below all" */
+
+{
+       struct STUFF *new_p;    /* copy of STUFF */
+       char *newstring;        /* copy of text string */
+       int font;
+       int fontfamily;
+       int size;
+
+
+       if (stufflist_p == (struct STUFF *) 0) {
+               return( (struct STUFF *) 0 );
+       }
+
+       /* make copy of string with appropriate font and size */
+       if (stufflist_p->string != (char *) 0) {
+               switch(stufflist_p->stuff_type) {
+               case ST_BOLD:
+                       font = FONT_TB;
+                       break;
+               case ST_OCTAVE:
+                       Stuff_size = DFLT_SIZE;
+                       font = FONT_TI;
+                       break;
+               case ST_ITAL:
+                       font = FONT_TI;
+                       break;
+               case ST_BOLDITAL:
+                       font = FONT_TX;
+                       break;
+               default:
+                       font = FONT_TR;
+                       break;
+               }
+
+               /* figure out the proper size if not already determined */
+               if (Stuff_size  < 0) {
+                       if (all == YES) {
+                               size = Score.size;
+                       }
+                       else {
+                               size = svpath(staffno, SIZE)->size;
+                       }
+               }
+               else {
+                       size = Stuff_size;
+               }
+
+               /* determine fontfamily and font if not already known */
+               if (Curr_family == FAMILY_DFLT) {
+                       if (all == YES) {
+                               fontfamily = Score.fontfamily;
+                       }
+                       else {
+                               fontfamily = svpath(staffno, FONTFAMILY)->
+                                                       fontfamily;
+                       }
+               }
+               else {
+                       fontfamily = Curr_family;
+               }
+
+               /* clone text string */
+               newstring = copy_string(stufflist_p->string + 2, font, size);
+               if (IS_CHORDLIKE(Modifier)) {
+                       newstring = modify_chstr(newstring, Modifier);
+               }
+               fix_string(newstring, fontfamily + font, size,
+                       stufflist_p->inputfile, stufflist_p->inputlineno);
+               if (Modifier == TM_FIGBASS || Modifier == TM_ANALYSIS) {
+                       newstring = acc_trans(newstring);
+               }
+       }
+       else {
+               newstring = (char *) 0;
+       }
+       
+       /* create and fill in clone of stuff, then return it */
+       new_p = newSTUFF(newstring, stufflist_p->dist,
+                               stufflist_p->dist_usage,
+                               stufflist_p->start.count,
+                               stufflist_p->start.steps,
+                               stufflist_p->gracebackup,
+                               stufflist_p->end.bars, stufflist_p->end.count,
+                               stufflist_p->stuff_type, stufflist_p->modifier,
+                               stufflist_p->place, stufflist_p->inputfile,
+                               stufflist_p->inputlineno);
+       new_p->all = (short) all;
+       new_p->next = clone_stufflist(stufflist_p->next, staffno, all);
+       return(new_p);
+}
+\f
+
+/* allocate a STUFF and fill in all the values given. Initialize carry fields
+ * and "all" to NO. Leave coordinates and next link as 0.
+ * Note that the string pointer
+ * is copied; it does not make a copy of the string itself, so never call this
+ * function more than once with the same string--make a copy. */
+
+struct STUFF *
+newSTUFF(string, dist, dist_usage, start_count, start_steps, gracebackup, bars, count,
+               stuff_type, modifier, place, inputfile, inputlineno)
+
+char *string;          /* text string of stuff */
+int dist;              /* dist for this STUFF to override dist parameter */
+int dist_usage;                /* meaning of dist, SD_* */
+double start_count;    /* count at which to begin stuff */
+double start_steps;    /* offset by this many steps */
+int gracebackup;       /* how many grace notes to back up from start */
+int bars;              /* bars in "til" clasue */
+double count;          /* counts in "til" clause */
+int stuff_type;                /* ST_* */
+int modifier;          /* TM_* */
+int place;             /* PL_* */
+char *inputfile;       /* which file stuff was defined in */
+int inputlineno;       /* where stuff was defined in input file */
+
+{
+       struct STUFF *new_p;    /* the new STUFF to fill in */
+
+
+       CALLOC(STUFF, new_p, 1);
+       new_p->string = string;
+       new_p->start.count = start_count;
+       new_p->start.steps = start_steps;
+       new_p->gracebackup = (short) gracebackup;
+       new_p->dist = (short) dist;
+       new_p->dist_usage = (short) dist_usage;
+       new_p->end.bars = (short) bars;
+       new_p->end.count = count;
+       new_p->stuff_type = (short) stuff_type;
+       new_p->modifier = (short) modifier;
+       new_p->place = (short) place;
+       new_p->carryin = new_p->carryout = new_p->all = NO;
+       new_p->costuff_p = 0;
+       new_p->inputfile = inputfile;
+       new_p->inputlineno = (short) inputlineno;
+
+       return(new_p);
+}
+\f
+
+/* recursively free up a stufflist and any strings hanging off of it */
+
+static void
+free_stufflist(stuff_p)
+
+struct STUFF *stuff_p;
+
+{
+       if (stuff_p == (struct STUFF *) 0 ) {
+               return;
+       }
+
+       free_stufflist(stuff_p->next);
+       if (stuff_p->string != (char *) 0) {
+               FREE(stuff_p->string);
+       }
+       FREE(stuff_p);
+}
+\f
+
+/* at each bar line, see if there are any "til" clauses that are supposed
+ * to end in this measure. If so, make sure they end within the time
+ * signature for this measure. */
+
+void
+meas_stuff_chk()
+
+{
+       struct TIL_INFO *til_info_p;            /* to index thru list */
+       struct TIL_INFO **del_place_p_p;        /* for deleting from list */
+       struct TIL_INFO *one2free_p;            /* pointer to which element
+                                                * to free */
+
+       debug(2, "meas_chk_stuff");
+
+       /* update measure number to conpensate for any multirests */
+       Measnum += Multi_adjust;
+       Multi_adjust = 0;
+
+       /* go through list of in-progress til clauses */
+       for (til_info_p = Til_info_list_p, del_place_p_p = &Til_info_list_p;
+                               til_info_p != (struct TIL_INFO *) 0;  ) {
+
+               if (til_info_p->measnum == Measnum) {
+
+                       /* at measure where this til clause ends */
+                       /* check if within time signature */
+                       if (til_info_p->count > Score.timenum + 1.0) {
+                               l_yyerror(til_info_p->inputfile,
+                                       til_info_p->inputlineno,
+                                       "beats in 'til' clause must be <= numerator of time signature + 1 of the measure in which the 'til' clause ends (i.e., <= %d)",
+                                       Score.timenum);
+                       }
+
+                       /* this one has been taken care of: delete from list */
+                       *del_place_p_p = til_info_p->next;
+                       one2free_p = til_info_p;
+               }
+               else if (til_info_p->measnum < Measnum) {
+                       /* must have ended inside a multirest, so delete
+                        * from list */
+                       *del_place_p_p = til_info_p->next;
+                       one2free_p = til_info_p;
+               }
+               else {
+                       /* this one stays on the list for now, so move pointer
+                        * to where to potentially delete to next element */
+                       del_place_p_p = &(til_info_p->next);
+                       one2free_p = (struct TIL_INFO *) 0;
+               }
+
+               /* have to move to next element
+                * before freeing the current one */
+               til_info_p = til_info_p->next;
+
+               if (one2free_p != (struct TIL_INFO *) 0) {
+                       FREE(one2free_p);
+               }
+       }
+
+       /* update number of measures. */
+       Measnum++;
+
+       /* make sure pedal marks are in proper order */
+       ped_order_chk();
+}
+\f
+
+/* adjust number of measures to account for multirests. Called when there is
+ * a multirest. Saved the number of measures in the multirest (minus 1 since
+ * the barline at the end will count for one measure) */
+
+void
+multi_stuff(nmeas)
+
+int nmeas;     /* number of measures in multirest */
+
+{
+       /* subtract 1 to account for the fact that at the bar line at the
+        * end of the multirest we will peg the measure counter */
+       Multi_adjust = nmeas - 1;
+}
+\f
+
+/* handle pedal going into endings. When we hit a first ending, save the
+ * state of the pedal for all staffs. On subsequent endings in the set,
+ * reset the pedal state to what it was at the beginning of the first ending.
+ * At the endending, go back to normal operation. This is similar to
+ * the saveped() function used at print time. */
+
+void
+ped_endings(endingloc)
+
+int endingloc;         /* STARTITEM, INITEM, etc */
+
+{
+       register int s;         /* staff index */
+
+
+       if (endingloc == STARTITEM) {
+               if (Ped_snapshot[0] == YES) {
+
+                       /* starting 2nd ending: restore pedal state as it was
+                        * at beginning of first ending */
+                       for (s = 1; s <= MAXSTAFFS; s++) {
+                               Pedal_state[s] = Ped_snapshot[s];
+                       }
+               }
+
+               else {
+                       /* starting a set of endings,
+                        * need to save pedal state at this
+                        * point so we can carry it into subsequent endings */
+                       for (s = 1; s <= Score.staffs; s++) {
+                               Ped_snapshot[s] = Pedal_state[s];
+                       }
+                       /* make sure any remaining staffs are set to pedal off,
+                        * in case user increases the number of staffs
+                        * during the endings... */
+                       for (   ; s <= MAXSTAFFS; s++) {
+                               Ped_snapshot[s] = NO;
+                       }
+
+                       /* mark that we now have a snapshot */
+                       Ped_snapshot[0] = YES;
+               }
+       }
+
+       else if (endingloc == ENDITEM) {
+               /* at end of endings, discard snapshot of pedal states */
+               Ped_snapshot[0] = NO;
+       }
+}
+\f
+
+/* When all input has been processed, or when changing the number
+ * of staffs, we better not have any 'til' clauses
+ * still unfinished. If we do, print a warning message. */
+
+void
+chk4dangling_til_clauses(boundary_desc)
+
+char *boundary_desc;           /* "the end of the song" or
+                                * "a change in number of staffs" */
+
+{
+       struct TIL_INFO *til_info_p;
+
+
+       debug(2, "chk4dangling_til_clauses");
+
+       /* Go through the whole list of remaining til clauses,
+        * and print a warning message for each. */
+       for (til_info_p = Til_info_list_p; til_info_p != (struct TIL_INFO *) 0;
+                                       til_info_p = til_info_p->next) {
+
+               /* If right on the boundary or spills over only a very tiny
+                * amount, don't bother to complain */
+               if (til_info_p->measnum - Measnum == 0
+                                               && til_info_p->count < .001) {
+                       continue;
+               }
+
+               l_warning(til_info_p->inputfile, til_info_p->inputlineno,
+                               "'til' clause extends beyond %s by %dm + %.3f",
+                               boundary_desc, til_info_p->measnum - Measnum,
+                               til_info_p->count);
+       }
+
+       /* mop up. */
+       free_tils(Til_info_list_p);
+       Til_info_list_p = (struct TIL_INFO *) 0;
+}
+\f
+
+/* recursively free a list of TIL_INFO structs */
+
+static void
+free_tils(til_p)
+
+struct TIL_INFO *til_p;                /* free this list */
+
+{
+       if (til_p == (struct TIL_INFO *) 0) {
+               return;
+       }
+
+       free_tils(til_p->next);
+       FREE(til_p);
+}
+\f
+
+/* user only has to specify when pedal marks end. We deduce from current
+ * pedal state whether a pedal mark is begin or up/down. This gets called
+ * whenever we have a list of pedal STUFFs. Later we enforce that pedal
+ * marks are put in in ascending order only, so that if user enters more
+ * than one pedal line for the same staff, that will be handled properly. */
+
+static void
+fix_pedal(staffno, stuff_p)
+
+int staffno;                   /* pedal is for this staff */
+struct STUFF *stuff_p;         /* list of pedal mark info */
+
+{
+       /* walk through list of pedal marks */
+       for (  ; stuff_p != (struct STUFF *) 0; stuff_p = stuff_p->next) {
+
+               if (stuff_p->string == (char *) 0) {
+                       /* no star, so have to deduce state */
+
+                       if (Pedal_state[staffno] == NO) {
+                               /* pedal currently off, so begin pedal */
+                               Pedal_state[staffno] = YES;
+                               stuff_p->string = copy_string(Ped_begin_str + 2,
+                                       (int) Ped_begin_str[0],
+                                       (int) Ped_begin_str[1]);
+                       }
+                       else {
+                               /* pedal currently down, so pedal up/down */
+                               stuff_p->string = copy_string(Ped_up_down_str + 2,
+                                       (int) Ped_up_down_str[0],
+                                       (int) Ped_up_down_str[1]);
+                       }
+               }
+
+               else if (Pedal_state[staffno] == NO) {
+                       yyerror("can't end pedal -- none in progress");
+               }
+
+               else {
+                       /* user gave star, so end pedal */
+                       Pedal_state[staffno] = NO;
+               }
+       }
+}
+\f
+
+/* reset pedal states for all staffs. This should be called at init time
+ * and at any time when the number of staffs changes. This function also
+ * initializes the Ped_begin_str and Ped_up_down_str. */
+
+void
+reset_ped_state()
+
+{
+       static int first_time = YES;    /* flag if function called before */
+       register int s;                 /* index through staffs */
+
+
+       /* mark pedal off for all staffs */
+       for (s = 1; s <= Score.staffs; s++) {
+               Pedal_state[s] = NO;
+       }
+       Ped_snapshot[0] = NO;
+
+       /* the first time this function is called, initialize the strings
+        * for pedal begin and pedal end. We just have one copy of these
+        * and then make as many copies from these as necessary */
+       if (first_time == YES) {
+               first_time = NO;
+               Ped_begin_str = copy_string("\\(begped)", FONT_MUSIC,
+                                                       DFLT_SIZE);
+               Ped_up_down_str = copy_string("\\(pedal)", FONT_MUSIC,
+                                                       DFLT_SIZE);
+               fix_string(Ped_begin_str, FONT_MUSIC, DFLT_SIZE,
+                                       Curr_filename, -1);
+               fix_string(Ped_up_down_str, FONT_MUSIC, DFLT_SIZE,
+                                        Curr_filename, -1);
+       }
+}
+\f
+
+/* fill in rehearsal mark string. This doesn't go in a STUFF, but it's
+ * sort of like stuff and there didn't seem to be any more appropriate file for
+ * this function */
+
+
+static int Reh_let = 0;                /* current value of rehearsal letter. 0 == "A",
+                                * 25 == "Z", 26 == "AA", etc to 701 == "ZZ" */
+static int Reh_num = 1;                /* current value of rehearsal number */
+
+
+void
+set_reh_string(bar_p, fontfamily, font, size, string)
+
+struct BAR *bar_p;     /* which bar gets the rehearsal mark */
+int fontfamily;                /* what font family to use, or FAMILY_DFLT
+                        * if to use current default */
+int font;              /* what font to use, or FONT_UNKNOWN if to use the
+                        * current default font */
+int size;              /* font size to use, or -1 if to use current default */
+char *string;          /* string for rehearsal mark */
+
+{
+       char reh_str[12];       /* temporary buff for string version of
+                                * rehearsal number or letter */
+       static int reh_size = DFLT_SIZE;        /* size to use for reh marks */
+       static int reh_family = FAMILY_DFLT;    /* font family to use */
+       static int reh_font = FONT_TB;          /* font to use */
+
+
+       /* if first time through, init the font family to the score family */
+       if (reh_family == FAMILY_DFLT) {
+               reh_family = Score.fontfamily;
+       }
+
+       /* if user specified a new size, save that */
+       if (size != -1) {
+               if (size > 100) {
+                       yyerror("reh mark size too large");
+                       return;
+               }
+               else {
+                       reh_size = size;
+               }
+       }
+
+       /* if user specified new font or font family, save that */
+       if (font != FONT_UNKNOWN) {
+               reh_font = font;
+       }
+       if (fontfamily != FAMILY_DFLT) {
+               reh_family = fontfamily;
+       }
+
+       switch(bar_p->reh_type) {
+
+       case REH_NUM:
+               /* get string version of current rehearsal number, and
+                * incrment it */
+               bar_p->reh_string = copy_string(num2str(Reh_num++) + 2,
+                               reh_family + reh_font, reh_size);
+               break;
+
+       case REH_LET:
+               /* Get string version of current rehearsal letter.
+                * Start with A-Z, then AA, AB, AC, ... BA, BB, ... up to ZZ.
+                */
+               if (Reh_let < 26) {
+                       /* 1-letter long mark */
+                       (void) sprintf(reh_str, "%c", Reh_let + 'A');
+               }
+               else if (Reh_let < 27 * 26) {
+                       /* 2-letter long mark */
+                       (void) sprintf(reh_str, "%c%c",
+                               (Reh_let / 26) + 'A' - 1, (Reh_let % 26) + 'A');
+               }
+               else {
+                       ufatal("too many rehearsal letters!");
+               }
+               bar_p->reh_string = copy_string(reh_str,
+                               reh_family + reh_font, reh_size);
+               /* increment for next time around */
+               Reh_let++;
+               break;
+
+       case REH_MNUM:
+               /* get string version of current measure number */
+               bar_p->reh_string = copy_string(num2str(Meas_num) + 2,
+                               reh_family + reh_font, reh_size);
+               break;
+
+       case REH_STRING:
+               /* user-specified string */
+               bar_p->reh_string = fix_string(string,
+                               reh_family + reh_font, reh_size,
+                               Curr_filename, yylineno);
+               break;
+
+       case REH_NONE:
+               break;
+
+       default:
+               pfatal("set_reh_string passed bad value");
+               break;
+       }
+}
+\f
+
+/* Set rehearsal letter or number to user-specified value.
+ * If the current bar has a rehearsal mark of the type being changed,
+ * also replace its current mark with the changed one. This allows user
+ * to say either
+ *     reh num num=5
+ * or
+ *     num=5 reh num
+ * and get the same results, which is consistent with how mnum= setting
+ * had worked.
+ */
+
+void
+init_reh(rehnumber, rehletter, mainbar_p)
+
+int rehnumber;         /* New value for Reh_num or negative if setting Reh_let */
+char *rehletter;       /* "A" to "ZZ" or null if setting number */
+struct MAINLL *mainbar_p;      /* points to the current BAR */
+
+{
+       struct BAR *bar_p;
+       char *oldstr;           /* previous reh_string */
+
+       if (mainbar_p == 0 || mainbar_p->str != S_BAR) {
+               pfatal("bad mainbar_p passed to init_reh");
+       }
+       bar_p = mainbar_p->u.bar_p;
+       oldstr = bar_p->reh_string;
+
+       if (rehnumber >= 0) {
+               Reh_num = rehnumber;
+               /* If this bar has a rehearsal number on this bar,
+                * replace it, and free the old one. */
+               if (bar_p->reh_type == REH_NUM) {
+                       set_reh_string(bar_p, FAMILY_DFLT, FONT_UNKNOWN, -1,
+                                                               (char *) 0);
+                       FREE(oldstr);
+               }
+       }
+
+       if (rehletter != 0) {
+               /* Letter is stored internally as a number,
+                * which is then converted, so we have to convert in reverse.
+                * We only allow "A" through "ZZ" */
+               if (isupper(rehletter[0]) && rehletter[1] == '\0') {
+                       Reh_let = rehletter[0] - 'A';
+               }
+               else if (isupper(rehletter[0]) && isupper(rehletter[1])
+                                               && rehletter[2] == '\0') {
+                       Reh_let = 26 + (rehletter[1] - 'A')
+                                       + (rehletter[0] - 'A') * 26;
+               }
+               else {
+                       yyerror("rehearsal letter setting must be \"A\" through \"ZZ\"");
+                       return;
+               }
+               /* If this bar has a rehearsal letter on this bar,
+                * replace it, and free the old one. */
+               if (bar_p->reh_type == REH_LET) {
+                       set_reh_string(bar_p, FAMILY_DFLT, FONT_UNKNOWN, -1,
+                                                               (char *) 0);
+                       FREE(oldstr);
+               }
+       }
+}
+\f
+
+/* go through all stuff lists and verify that pedal marks are given in
+ * ascending order. If not, error. Some code in both parse and
+ * placement phases requires that pedal marks be in order. */
+
+static void
+ped_order_chk()
+
+{
+       int staffno;
+       struct STUFF *stuff_p;  /* walk through stuff list */
+       float last_ped_count;   /* count where last pedal occurred */
+       int last_backup;        /* gracebackup of last pedal */
+
+
+       /* check every staff */
+       for (staffno = 1; staffno <= Score.staffs; staffno++) {
+
+               /* initialize for current staff */
+               last_ped_count = -1.0;
+               last_backup = 0;
+
+               /* go through stuff list for current staff, looking for pedal */
+               for (stuff_p = Staffmap_p[staffno]->u.staff_p->stuff_p;
+                                       stuff_p != (struct STUFF *) 0;
+                                       stuff_p = stuff_p->next) {
+                       if (stuff_p->stuff_type == ST_PEDAL) {
+
+                               /* found a pedal. Make sure it is later than
+                                * the previous pedal */
+                               if (stuff_p->start.count < last_ped_count ||
+                                               (stuff_p->start.count
+                                               == last_ped_count
+                                               && stuff_p->gracebackup
+                                               > last_backup) ) {
+                                       l_yyerror(stuff_p->inputfile,
+                                               stuff_p->inputlineno,
+                                               "pedal must be specified in ascending order");
+                                       /* no need to print error more than
+                                        * once if multiple errors */
+                                       continue;
+                               }
+
+                               /* keep track of where this pedal is, for
+                                * comparing with the next one */
+                               last_ped_count = stuff_p->start.count;
+                               last_backup = stuff_p->gracebackup;
+                       }
+               }
+       }
+}
+\f
+
+/* Translate STUFF text modifier to a printable string. */
+
+char *
+stuff_modifier(modifier)
+
+int modifier;
+
+{
+       switch (modifier) {
+
+       case TM_CHORD:
+               return("chord");
+       case TM_ANALYSIS:
+               return("analysis");
+       case TM_FIGBASS:
+               return("figbass");
+       case TM_DYN:
+               return("dyn");
+       case TM_NONE:
+               return("(no modifier)");
+       default:
+               return("(invalid modifier)");
+       }
+}
diff --git a/mup/mup/phrase.c b/mup/mup/phrase.c
new file mode 100644 (file)
index 0000000..9cd6fa6
--- /dev/null
@@ -0,0 +1,2148 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions to determine the curves that make up phrase marks,
+ * ties and slurs. */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+/* distance to the top/bottom of a V-shape (indicating a bend) relative to
+ * the line connecting the endpoints of the V */
+#define V_HEIGHT (2.7 * Stepsize)
+
+/* How much bulge to allow in curves. There are three slightly different
+ * approaches that are tried, each succeeding approach allows more bulge
+ * in a more despearate attempt to get a reasonable curve. */
+#define MINBULGE       (1.2)
+#define MAXBULGE       (2.1)
+#define MIN2BULGE      (1.4)
+#define MAX2BULGE      (4.1)
+#define MIN3BULGE      (1.8)
+#define MAX3BULGE      (5.6)
+
+/* We'd normally want curves to begin and end (in the x direction) exactly in
+ * the middle of their note. But if one curve ends and another begins on
+ * the same note, the curve endpoints would collide, which could look bad.
+ * So we always offset the endpoints by a tiny amount (ends end a little
+ * west of center, and beginnings begin a little east) so they don't touch.
+ * This is the amount they are shifted from center.
+ */
+#define XOFFSET4CURVE  (0.75 * Stdpad)
+
+/* Curves must be at least this far away from notes */
+#define CLEARANCE      (3.0 * Stdpad)
+
+/* try_bulge() is called lots of times in a row with mostly the same values,
+ * and it needs lots of values, so it is convenient to put them in a struct,
+ * and just pass a pointer to it */
+struct TRYBULGE {
+       struct MAINLL *mll_p;           /* STUFF hangs off here */
+       struct GRPSYL *begin_gs_p;      /* group at left end of curve */
+       struct GRPSYL *end_gs_p;        /* group at right end of curve */
+       int place;                      /* PL_*  */
+       struct CRVLIST *curvelist_p;    /* points to beginning of curve */
+       struct CRVLIST *endlist_p;      /* points to end of curve */
+       double xlen;                    /* distance to midpoint */
+       double ylen;                    /* how much bulge to add */
+       double sintheta;                /* for rotation from horizontal */
+       double costheta;
+       double minbulge;                /* first bulge factor to try */
+       double maxbulge;                /* last bulge to try before giving up */
+       int leftcount;                  /* value is returned here. Count of
+                                        * how many "stick-outs" are near the
+                                        * left end of the curve */
+       int rightcount;                 /* similar for right end */
+};
+
+static int nowhere_slide P((struct STUFF *stuff_p));
+static void do_nowhere P((struct STUFF *stuff_p, double x1, double y1,
+               double x2, double y2));
+static void curve_points P((struct MAINLL *mll_p, struct STUFF *stuff_p,
+               int is_phrase));
+static double inner_adj P((struct GRPSYL *gs_p, struct NOTE *note_p,
+               double y_adj, int place));
+static double stick_out P((struct TRYBULGE *info_p));
+static double try_bulge P((struct TRYBULGE *info_p));
+static double tieslurx P((struct GRPSYL *gs_p, struct NOTE *note_p, int place));
+static struct MAINLL *next_staff P((int staff, struct MAINLL *mll_p));
+static void redo_steep P((struct CRVLIST *first_p, struct CRVLIST *last_p,
+               int place));
+static void final_touches P((struct MAINLL *mll_p, struct GRPSYL *begin_gs_p,
+               struct GRPSYL *end_gs_p, struct CRVLIST *crvlist_p, int place));
+static double eff_tupext P((struct GRPSYL * gs_p, struct STAFF *staff_p, int side));
+static int bulge_direction P((struct MAINLL *mll_p, struct GRPSYL *gs1_p,
+               int note_index, int curveno));
+\f
+
+/* figure out what points are needed for a phrase mark */
+/* attach a linked list of x,y coordinates that show where to draw the curve.
+ * The curve will be out of the way of any groups within the phrase. */
+
+void
+phrase_points(mll_p, stuff_p)
+
+struct MAINLL *mll_p;          /* MAINLL that stuff_p hangs off of */
+struct STUFF *stuff_p;         /* info about the phrase mark */
+
+{
+       curve_points(mll_p, stuff_p, YES);
+}
+\f
+
+/* figure out what points are needed for a tie or slur mark */
+
+void
+tieslur_points(mll_p, stuff_p)
+
+struct MAINLL *mll_p;          /* MAINLL that stuff_p hangs off of */
+struct STUFF *stuff_p;         /* info about the phrase mark */
+
+{
+       /* if slide to/from nowhere in particular, do that */
+       if (nowhere_slide(stuff_p) == YES) {
+               return;
+       }
+
+       curve_points(mll_p, stuff_p, NO);
+}
+\f
+
+/* determine the 3 points that define a V_shaped bend indicator on the tabnote
+ * staff associated with a tab staff, and put them in the stuff crvlist */
+
+void
+bend_points(mll_p, stuff_p)
+
+struct MAINLL *mll_p;
+struct STUFF *stuff_p;
+
+{
+       struct CRVLIST *first_point_p, *last_point_p;   /* the beginning
+                                * and end points of the curve */
+       struct CRVLIST *mid_point_p;            /* middle of the V-shape */
+       struct CRVLIST *one2discard_p;          /* a point to discard */
+       double midx, midy;                      /* midpoint between the ends */
+       double v_height;                        /* V_HEIGHT, or less than
+                                                * that for narrow V's */
+       double xlen;                            /* to help find v_height */
+       double slope;                           /* of perpendicular line from
+                                                * (midx, midy) to the point
+                                                * of the V, v_height away. */
+
+
+       /* first figure everything out as if it were a normal slur */
+       curve_points(mll_p, stuff_p, NO);
+
+       /* Now make into V-shaped curve.
+        * First throw away the inner points that we had found.
+        * It's a bit unfortunate to do all that work, then throw it
+        * away, but the curve_point() function that finds all the points
+        * also does lots of other good things that we want, so rather than
+        * make it more complicated than it already is by having it know
+        * about bends, we just save the things it did that help us here.
+        */
+       first_point_p = stuff_p->crvlist_p;
+       for (last_point_p = first_point_p->next;
+                       last_point_p->next != (struct CRVLIST *) 0;  ) {
+               one2discard_p = last_point_p;
+               last_point_p = last_point_p->next;
+               FREE(one2discard_p);
+       }
+
+       /* get a midpoint struct and stitch it into the list */
+       MALLOC(CRVLIST, mid_point_p, 1);
+       first_point_p->next = mid_point_p;
+       last_point_p->prev = mid_point_p;
+       mid_point_p->prev = first_point_p;
+       mid_point_p->next = last_point_p;
+
+       /* find the midpoint of the line between the endpoints */
+       midx = (last_point_p->x + first_point_p->x) / 2.0;
+       midy = (last_point_p->y + first_point_p->y) / 2.0;
+
+       /* get height. Use V_HEIGHT, except adjust for narrow V's */
+       xlen = fabs(last_point_p->x - first_point_p->x);
+       if (xlen < 2.0 * V_HEIGHT) {
+               v_height = 0.35 * V_HEIGHT;
+       }
+       else if (xlen < 3.5 * V_HEIGHT) {
+               v_height = 0.65 * V_HEIGHT;
+       }
+       else {
+               v_height = V_HEIGHT;
+       }
+
+       /* if the y's of the endpoints are equal or nearly so, finding the
+        * midpoint of the V is easy: the x is midx, and the y is midy offset
+        * by v_height in the appropriate direction */
+       if (fabs(last_point_p->y - first_point_p->y) < 0.001) {
+               mid_point_p->x = midx;
+               mid_point_p->y = midy + v_height *
+                               (stuff_p->place == PL_ABOVE ? 1.0 : -1.0);
+               return;
+       }
+
+       /* find the slope of the perpendicular */
+       slope = (first_point_p->x - last_point_p->x) /
+                               (last_point_p->y - first_point_p->y);
+
+       /* we want the length of the perpendicular line from (midx, midy)
+        * to the point at the top (or bottom) of the V to be v_height.
+        * Using that line as the hypotenuse of a triangle, we know that
+        * we can find the x and y relative to (midx, midy) by using
+        * Pythagorean   x^2 + y^2 = v_height^2. Furthermore, we calculated 
+        * the slope of the line earlier, and knowing that slope = y/x,
+        * we now solve 2 equations in 2 unknowns:
+        *      x^2 + y^2 = v_height^2
+        *      slope = y / x
+        * Rearranging the first equation and substituing (slope * x) for y:
+        *      x^2 + (slope * x)^2 = v_height^2
+        * solve for x:
+        *      (1 + slope^2) * x^2 = v_height^2
+        *      x = sqrt( v_height^2 / (1 + slope^2))
+        * Then having found x, solve the second equation for y.
+        *      y = x * slope
+        * Adjust for being relative to (midx, midy) and for bend direction
+        * and slope direction, and we are done.
+        */
+       mid_point_p->x = (sqrt((v_height * v_height) / (1.0 + (slope * slope))))
+                       * (first_point_p->y > last_point_p->y ? 1.0 : -1.0)
+                       * (stuff_p->place == PL_ABOVE ? 1.0 : -1.0);
+       mid_point_p->y = (slope * mid_point_p->x) + midy;
+       mid_point_p->x += midx;
+}
+\f
+
+/* determine the 2 points that define a line indicating a slide for a
+ * tab or tabnote staff, and put the points in the stuff crvlist */
+
+void
+tabslur_points(mll_p, stuff_p)
+
+struct MAINLL *mll_p;
+struct STUFF *stuff_p;
+
+{
+       struct CRVLIST *curvelist_p;
+       struct GRPSYL *beggrp_p;
+       struct GRPSYL *endgrp_p;
+       struct NOTE *begnote_p;
+       struct NOTE *endnote_p;
+       float slant;            /* 0, 1 or -1 to show slant direction */
+       int acc1, acc2;         /* effective accidentals on the 2 groups,
+                                * -2 to +2 */
+       int n, st;              /* index through notelist and slurtolist */
+
+
+       /* if slide to/from nowhere in particular, do that */
+       if (nowhere_slide(stuff_p) == YES) {
+               return;
+       }
+
+       /* find the end note */
+       if (stuff_p->carryin == YES) {
+               /* on carryin, beggrp_p is really the ending group,
+                * and the previous group is the real beggrp_p */
+               endgrp_p = stuff_p->beggrp_p;
+               endnote_p = stuff_p->begnote_p;
+               beggrp_p = prevgrpsyl(stuff_p->beggrp_p, &mll_p);
+
+               /* go through all the notes in the previous group,
+                * to find the one that has a slide to the note being
+                * carried into. If there is more than one, use the first
+                * one we find. */
+               for (n = 0; n < beggrp_p->nnotes; n++) {
+                       for (st = 0; st < beggrp_p->notelist[n].nslurto; st++) {
+                               if (endnote_p->letter ==
+                                 beggrp_p->notelist[n].slurtolist[st].letter
+                                 && (is_tab_staff(endgrp_p->staffno) == YES
+                                 || endnote_p->octave ==
+                                 beggrp_p->notelist[n].slurtolist[st].octave)) {
+                                       /* found the one sliding to us */
+                                       break;
+                               }
+                       }
+                       if (st < beggrp_p->notelist[n].nslurto) {
+                               /* found it, so need to jump out */
+                               break;
+                       }
+               }
+               if (n == beggrp_p->nnotes) {
+                       pfatal("can't find note being slid from");
+               }
+               begnote_p = &(beggrp_p->notelist[n]);
+       }
+       else {
+               beggrp_p = stuff_p->beggrp_p;
+               begnote_p = stuff_p->begnote_p;
+               if ((endgrp_p = nextgrpsyl(stuff_p->beggrp_p, &mll_p))
+                                               == (struct GRPSYL *) 0) {
+                       pfatal("failed to find next group in tabslur_points");
+               }
+               endnote_p = find_matching_note (endgrp_p,
+                               stuff_p->begnote_p->slurtolist
+                               [stuff_p->curveno].letter,
+                               stuff_p->begnote_p->slurtolist
+                               [stuff_p->curveno].octave, "slide");
+
+               if (endnote_p == (struct NOTE *) 0) {
+                       pfatal("failed to find endnote in tabslur_points");
+               }
+       }
+
+       if (is_tab_staff(mll_p->u.staff_p->staffno) == YES) {
+               /* figure out whether to slant up or down based on whether
+                * first or second fret is higher */
+               if (begnote_p->FRETNO > endnote_p->FRETNO) {
+                       slant = 1;
+               }
+               else {
+                       slant = -1;
+               }
+       }
+       else {
+               /* on non-tab staff, usually the line goes to the midpoint of
+                * the note head, so no need to adjust, so set slant to 0 */
+               slant = 0;
+
+               /* there are two exceptions: first, if both notes have the same
+                * letter/octave, but different accidentals, then we have to
+                * determine the slant based on the accidental. */
+               if (begnote_p->letter == endnote_p->letter
+                               && begnote_p->octave == endnote_p->octave) {
+
+                       /* if the accidental on the begin note is higher than
+                        * the accidental on the end note, then it slants
+                        * down from left to right, and vice versa. Get the
+                        * effective accidental on each group,
+                        * accounting for key signature, accidentals earlier
+                        * in the measure, etc. */
+                       acc1 = eff_acc(beggrp_p, begnote_p, mll_p);
+                       acc2 = eff_acc(endgrp_p, endnote_p, mll_p);
+
+                       /* error if the slide is between identical notes */
+                       if (acc1 == acc2) {
+                               l_ufatal(endgrp_p->inputfile,
+                                               endgrp_p->inputlineno,
+                                               "can't slide to the same note");
+                       }
+                       else if (acc1 > acc2) {
+                               slant = 1;
+                       }
+                       else {
+                               slant = -1;
+                       }
+               }
+
+               /* second exception: if the slide is carried in, then it needs
+                * to be slanted, so figure out which way */
+               if (stuff_p->carryin == YES) {
+#ifdef __STDC__
+                       switch(notecomp( (const void *) begnote_p,
+                                               (const void *) endnote_p)) {
+#else
+                       switch(notecomp( (char *) begnote_p, (char *) endnote_p)) {
+#endif
+                       case 1:
+                               slant = 0.5;
+                               break;
+                       case -1:
+                               slant = -0.5;
+                               break;
+                       default:
+                               /* same note, so have to use accidental as
+                                * the deciding factor */
+                               acc1 = eff_acc(beggrp_p, begnote_p, mll_p);
+                               acc2 = eff_acc(endgrp_p, endnote_p, mll_p);
+
+                               /* error if the slide is
+                                * between identical notes */
+                               if (acc1 == acc2) {
+                                       l_ufatal(endgrp_p->inputfile,
+                                               endgrp_p->inputlineno,
+                                               "can't slide to the same note");
+                               }
+                               else if (acc1 > acc2) {
+                                       slant = 0.5;
+                               }
+                               else {
+                                       slant = -0.5;
+                               }
+                               break;
+                       }
+               }
+       }
+
+       /* find beginning point of line */
+       MALLOC(CRVLIST, curvelist_p, 1);
+       curvelist_p->prev = (struct CRVLIST *) 0;
+       if (stuff_p->carryin == YES) {
+               /* start a bit west of the end note */
+               curvelist_p->x = stuff_p->beggrp_p->c[AX] +
+                       notehorz(stuff_p->beggrp_p, stuff_p->begnote_p, RW)
+                       - 3.0 * Stepsize;
+               curvelist_p->y = endnote_p->c[RY] + (slant * Stepsize);
+       }
+       else {
+               /* start just beyond east of begin note */
+               curvelist_p->x = begnote_p->c[AE] + Stdpad;
+               curvelist_p->y = stuff_p->begnote_p->c[RY] + (slant * Stepsize);
+       }
+
+       /* end point of line */
+       MALLOC(CRVLIST, curvelist_p->next, 1);
+       curvelist_p->next->prev = curvelist_p;
+       curvelist_p->next->next = (struct CRVLIST *) 0;
+       if (stuff_p->carryout == YES) {
+               /* extend to near end of score */
+               curvelist_p->next->x = PGWIDTH - eff_rightmargin(mll_p) - Stepsize;
+       }
+       else  {
+               /* go to just before west of end note */
+               curvelist_p->next->x = endgrp_p->c[AX] +
+                               notehorz(endgrp_p, endnote_p, RW) - Stdpad;
+       }
+       curvelist_p->next->y = endnote_p->c[RY] - (slant * Stepsize);
+
+       /* attach to stuff */
+       stuff_p->crvlist_p = curvelist_p;
+
+       /* place doesn't really make sense, so set arbitrarily */
+       stuff_p->place = PL_ABOVE;
+}
+\f
+
+/* if the slide for given tabslur stuff is to/from nowhere in particular,
+ * then handle that here and return YES. Otherwise return NO. */
+
+static int
+nowhere_slide(stuff_p)
+
+struct STUFF *stuff_p;
+
+{
+       double boundary;        /* east or west boundary of note, with
+                                * the slide included */
+       double adjust = 0.0;    /* to move the slanted line slightly when
+                                * there is a note on the other side of
+                                * the stem that is in the way. */
+       struct GRPSYL *gs_p;
+       struct NOTE *note_p;
+       int n;
+       float slidexlen;        /* SLIDEXLEN * Staffscale */
+
+
+       if (stuff_p->curveno < 0) {
+               return(NO);
+       }
+
+       if (stuff_p->begnote_p->nslurto == 0) {
+               return(NO);
+       }
+
+       /* find which note it is in the chord, so check later for possible
+        * collisions between the slide and a neighboring note */
+       gs_p = stuff_p->beggrp_p;
+       note_p = stuff_p->begnote_p;
+       for (n = 0; n < gs_p->nnotes; n++) {
+               if ( &(gs_p->notelist[n]) == note_p) {
+                       break;
+               }
+       }
+       if (n == gs_p->nnotes) {
+               pfatal("couldn't find note in chord for slide");
+       }
+
+       slidexlen = SLIDEXLEN * Staffscale;
+
+       /* for each type, find the outer boundary of the note with the
+        * nowhere slide included and draw a line from there towards the
+        * note, slanted the appropriate direction */
+       switch (stuff_p->begnote_p->slurtolist[stuff_p->curveno].octave) {
+
+       case IN_UPWARD:
+               boundary = stuff_p->beggrp_p->c[AX] +
+                       notehorz(stuff_p->beggrp_p, stuff_p->begnote_p, RW);
+               /* If there is a note one stepsize below this note, and it's
+                * to the left of the stem while the target note is on the
+                * right side, move the slide up a
+                * tiny bit so it doesn't get swallowed up in that other note
+                * and/or a slide coming into it.
+                * If we're sliding into the middle of a cluster with
+                * wrong-side notes both above and below the target note, it
+                * will still get somewhat swallowed, but that's unlikely to
+                * happen very often, and if it does, this is still about the
+                * best we can manage in that case. */
+               n++;
+               if (n < gs_p->nnotes && gs_p->notelist[n].stepsup
+                               == note_p->stepsup - 1 &&
+                               gs_p->notelist[n].c[AX] < note_p->c[AX]) {
+                       adjust = Stdpad;
+               }
+               do_nowhere(stuff_p,
+                       boundary, stuff_p->begnote_p->c[RY] - Stepsize + adjust,
+                       boundary + slidexlen, stuff_p->begnote_p->c[RY] + adjust);
+               return(YES);
+
+       case IN_DOWNWARD:
+               boundary = stuff_p->beggrp_p->c[AX] +
+                       notehorz(stuff_p->beggrp_p, stuff_p->begnote_p, RW);
+               /* if there is a note just above that we might
+                * collide with, adjust to dodge it. */
+               n--;
+               if (n >= 0 && gs_p->notelist[n].stepsup
+                               == note_p->stepsup + 1 &&
+                               gs_p->notelist[n].c[AX] < note_p->c[AX]) {
+                       adjust = Stdpad;
+               }
+               do_nowhere(stuff_p,
+                       boundary, stuff_p->begnote_p->c[RY] + Stepsize - adjust,
+                       boundary + slidexlen, stuff_p->begnote_p->c[RY] - adjust);
+               return(YES);
+
+       case OUT_UPWARD:
+               boundary = stuff_p->beggrp_p->c[AX] +
+                       notehorz(stuff_p->beggrp_p, stuff_p->begnote_p, RE);
+               /* If note just above this one that we might collide with,
+                * dodge it */
+               n--;
+               if (n >= 0 && gs_p->notelist[n].stepsup
+                               == note_p->stepsup + 1 &&
+                               gs_p->notelist[n].c[AX] > note_p->c[AX]) {
+                       adjust = Stdpad;
+               }
+               do_nowhere(stuff_p,
+                       boundary - slidexlen, stuff_p->begnote_p->c[RY] - adjust,
+                       boundary, stuff_p->begnote_p->c[RY] + Stepsize - adjust);
+               return(YES);
+
+       case OUT_DOWNWARD:
+               boundary = stuff_p->beggrp_p->c[AX] +
+                       notehorz(stuff_p->beggrp_p, stuff_p->begnote_p, RE);
+               /* If note below we might collide with, dodge it */
+               n++;
+               if (n < gs_p->nnotes && gs_p->notelist[n].stepsup
+                               == note_p->stepsup - 1 &&
+                               gs_p->notelist[n].c[AX] > note_p->c[AX]) {
+                       adjust = Stdpad;
+               }
+               do_nowhere(stuff_p,
+                       boundary - slidexlen, stuff_p->begnote_p->c[RY] + adjust,
+                       boundary, stuff_p->begnote_p->c[RY] - Stepsize + adjust);
+               return(YES);
+
+       default:
+               return(NO);
+       }
+}
+\f
+
+/* make a CRVLIST with the 2 given points and put it in the given stuff */
+
+static void
+do_nowhere(stuff_p, x1, y1, x2, y2)
+
+struct STUFF *stuff_p;
+double x1, y1, x2, y2;
+
+{
+       MALLOC(CRVLIST, stuff_p->crvlist_p, 1);
+       stuff_p->crvlist_p->x = x1;
+       stuff_p->crvlist_p->y = y1;
+       MALLOC(CRVLIST, stuff_p->crvlist_p->next, 1);
+       stuff_p->crvlist_p->next->x = x2;
+       stuff_p->crvlist_p->next->y = y2;
+
+       stuff_p->crvlist_p->prev = stuff_p->crvlist_p->next->next
+                                                       = (struct CRVLIST *) 0;
+       stuff_p->crvlist_p->next->prev = stuff_p->crvlist_p;
+
+       /* place is not really relevant, but put something in it */
+       stuff_p->place = PL_ABOVE;
+}
+\f
+
+/* Figure out what points are needed for a curve, either a phrase mark
+ * or a tie/slur, or a bend.
+ * First it figures out where the endpoints should be,
+ * then finds a curve that will be beyond all the groups that it covers.
+ */
+
+static void
+curve_points(mll_p, stuff_p, is_phrase)
+
+struct MAINLL *mll_p;          /* MAINLL that stuff_p hangs off of */
+struct STUFF *stuff_p;         /* info about the phrase mark or tie/slur */
+int is_phrase;                 /* YES if phrase, NO if tie or slur */
+
+{
+       struct GRPSYL *begin_gs_p;      /* curve starts on this group */
+       struct GRPSYL *end_gs_p;        /* curve ends on this group */
+       struct NOTE *begnote_p;         /* first note for tie/slur */
+       struct NOTE *endnote_p = 0;     /* last note of tie/slur */
+       int place;                      /* bend PL_ABOVE or PL_BELOW */
+       int side;                       /* RN or RS */
+       int side_adj;                   /* AN or AS. This field is used to
+                                        * adjust for nested phrase marks */
+       double bulgeval;                /* bulge factor of curve */
+       int try;                        /* count of tries to get a good curve */
+       int found_good;                 /* YES if found a good-looking curve */
+       struct TRYBULGE tb;             /* Info for try_bulge() */
+       struct TRYBULGE *try_p;         /*  = &tb */
+       float sign;                     /* based on if curve is up or down */
+       struct CRVLIST *curvelist_p;    /* beginning of curve */
+       struct CRVLIST *endlist_p;      /* last point of curve */
+       struct CRVLIST *new_p;          /* point to add to list of points */
+       struct MAINLL *bar_mll_p = 0;   /* to find bar or pseudo bar */
+       float length;                   /* length of curve */
+       float ylen;             /* length of segment in y direction before
+                                * rotation */
+       float y_adj = 0.0, y2_adj = 0.0;/* if moved because was an end note */
+       char *name;             /* "phrase" or "tie/slur" */
+       float sintheta, costheta;/* for rotating */
+
+
+       debug(32, "curve_points lineno %d", stuff_p->inputlineno );
+
+       /* get short names to groups and notes we'll use a lot */
+       begin_gs_p = stuff_p->beggrp_p;
+       end_gs_p = stuff_p->endgrp_p;
+       begnote_p = stuff_p->begnote_p;
+       
+       /* figure out what string ("phrase" or "tie/slur") to use for error
+        * messages and make sure begin group is not null */
+       if (is_phrase == YES) {
+               name = "phrase";
+               if ( (begin_gs_p == (struct GRPSYL *) 0)
+                               || (end_gs_p == (struct GRPSYL *) 0) ) {
+                       pfatal("no group associated with phrase");
+               }
+       }
+       else {
+               int indx;
+
+               name = "tie/slur";
+               if (begin_gs_p == (struct GRPSYL *) 0) {
+                       pfatal("no group associated with tie/slur");
+               }
+               /* figure out which direction to bend the tie/slur */
+               if (stuff_p->carryin == YES) {
+                       struct MAINLL *m_p;
+                       struct GRPSYL *g_p;
+                       struct STUFF *st_p;
+
+                       /* Need to base bend direction on the
+                        * group/note/curve that was the carryout,
+                        * otherwise the carryin and carryout could have
+                        * different bend directions.
+                        * We also need the costuff_p to get
+                        * any user override of bend direction.
+                        *
+                        * Find the MAINLL pointing to the STAFF that
+                        * should contain the costuff. Use prevgrpsyl,
+                        * since it knows how to deal with endings,
+                        * but we're really interested in the MAINLL
+                        * pointing to the GRPSYL
+                        * rather than the GRPSYL itself.
+                        */
+
+                       /* First make sure we have the first group
+                        * in the measure. */
+                       for (g_p = begin_gs_p; g_p->prev != 0; g_p = g_p->prev) {
+                               ;
+                       }
+
+                       /* Now find the MAINLL pointing to the prev meas */
+                       m_p = mll_p;
+                       (void) prevgrpsyl(g_p, &m_p);
+                       if (m_p == 0 || m_p->str != S_STAFF) {
+                               pfatal("failed to find costaff_p's mainll");
+                       }
+
+                       /* Locate the costuff. We could just use
+                        * stuff_p->costuff_p, but by searching for it here,
+                        * we double check that we really found the right
+                        * MAINLL, and can pfatal if not. */
+                       for (st_p = m_p->u.staff_p->stuff_p; st_p != 0;
+                                                       st_p = st_p->next) {
+                               if (st_p == stuff_p->costuff_p) {
+                                       break;
+                               }
+                       }
+                       if (st_p == 0) {
+                               pfatal("failed to find costaff_p from mainll");
+                       }
+
+                       indx = st_p->begnote_p - &(st_p->beggrp_p->notelist[0]);
+                       stuff_p->place = (bulge_direction(m_p, st_p->beggrp_p,
+                               indx, st_p->curveno) == UP
+                               ? PL_ABOVE : PL_BELOW);
+               }
+               else {
+                       indx = begnote_p - &(begin_gs_p->notelist[0]);
+                       stuff_p->place = (bulge_direction(mll_p, begin_gs_p,
+                               indx, stuff_p->curveno) == UP
+                               ? PL_ABOVE : PL_BELOW);
+               }
+       }
+
+       place = stuff_p->place;
+
+       /* determine whether to use north or south of groups, and what sign to
+        * use to get the bends in the correct direction */
+       if (place == PL_ABOVE) {
+               side = RN;
+               side_adj = AN;
+               sign = 1.0;
+       }
+       else {
+               side = RS;
+               side_adj = AS;
+               sign = -1.0;
+       }
+
+       /* set up the beginning coord */
+       MALLOC(CRVLIST, curvelist_p, 1);
+       curvelist_p->prev = (struct CRVLIST *) 0;
+       if (is_phrase == YES) {
+               /* Start slightly to east of center, so that if another
+                * curves ends on this group, they won't quite touch */
+               curvelist_p->x = begin_gs_p->c[AX] + XOFFSET4CURVE;
+               if (begin_gs_p->grpcont != GC_SPACE) {
+                       curvelist_p->y = begin_gs_p->c[side]
+                               + eff_tupext(begin_gs_p, mll_p->u.staff_p, place)
+                               + (sign * 2.0 * Stdpad);
+                       /* If there is something in [side_adj] there
+                        * was another phrase on this group. But if that phrase
+                        * ended on this group, it can be ignored. */
+                       if (begin_gs_p->c[side_adj] != 0.0 &&
+                                       (begin_gs_p->phraseside & EAST_SIDE)) {
+                               curvelist_p->y += begin_gs_p->c[side_adj];
+                       }
+               }
+               else {
+                       /* bizarre case. first group is a space.
+                        * Use 1 step from top or bottom of staff for y coord */
+                       curvelist_p->y = sign * (1 + halfstaffhi(begin_gs_p->staffno));
+               }
+       }
+
+       else { /* is tie or slur */
+
+               curvelist_p->y = begnote_p->c[RY];
+               y_adj = 0.0;
+
+               /* if on the "end" note of a group,
+                * the curve can probably be moved
+                * to the x of the note instead of the edge of the group.
+                * We assume it can if the curve bends away
+                * from the stem and there are no "with"
+                * list items on the group. If there is a with list, move
+                * a little bit, but not enough to hit with items */
+               if (begin_gs_p->stemdir == UP && place == PL_BELOW
+                               && begnote_p == &(begin_gs_p->notelist
+                               [begin_gs_p->nnotes - 1])) {
+                       if (begin_gs_p->nwith == 0 || begin_gs_p->normwith == NO) {
+                               curvelist_p->x = begnote_p->c[AX]
+                                                       + (2.0 * Stdpad);
+                               y_adj = (Stepsize * (begnote_p->notesize
+                                               == GS_NORMAL ? 1.7 : 1.2));
+                               curvelist_p->y -= y_adj;
+                       }
+                       else {
+                               curvelist_p->x = begnote_p->c[AE];
+                               y_adj = (Stepsize * (begnote_p->notesize
+                                               == GS_NORMAL ? 1.2 : 0.9));
+                               curvelist_p->y -= y_adj;
+                       }
+               }
+               else if (begin_gs_p->stemdir == DOWN && place == PL_ABOVE
+                               && begnote_p == &(begin_gs_p->notelist[0])) {
+                       if (begin_gs_p->nwith == 0
+                                               || begin_gs_p->normwith == NO) {
+                               curvelist_p->x = begnote_p->c[AX]
+                                       + (2.0 * Stdpad);
+                               y_adj = (Stepsize * (begnote_p->notesize
+                                               == GS_NORMAL ? 1.7 : 1.2));
+                               curvelist_p->y += y_adj;
+                       }
+                       else {
+                               curvelist_p->x = begnote_p->c[AE];
+                               y_adj = (Stepsize * (begnote_p->notesize
+                                               == GS_NORMAL ? 1.2 : 0.9));
+                               curvelist_p->y += y_adj;
+                       }
+               }
+
+               /* whole notes and longer don't really have a stem, so top
+                * note of "stem up" can be moved. Stemless grace notes also
+                * don't have a stem, so the same logic applies. */
+               else if ( (begin_gs_p->basictime < 2
+                               || (begin_gs_p->grpvalue == GV_ZERO
+                               && begin_gs_p->basictime < 8))
+                               && begin_gs_p->stemdir == UP
+                               && place == PL_ABOVE &&
+                               begnote_p == &(begin_gs_p->notelist[0])) {
+                       if (begin_gs_p->nwith == 0
+                                       || begin_gs_p->normwith == YES) {
+                               curvelist_p->x = begnote_p->c[AX] + Stdpad;
+                               y_adj = (Stepsize * (begnote_p->notesize
+                                               == GS_NORMAL ? 1.7 : 1.2));
+                               curvelist_p->y += y_adj;
+                       }
+                       else {
+                               curvelist_p->x = begnote_p->c[AE];
+                               y_adj = (Stepsize * (begnote_p->notesize
+                                               == GS_NORMAL ? 1.2 : 0.9));
+                               curvelist_p->y += y_adj;
+                       }
+               }
+
+               /* can also be moved if bottom note of stem-down group */
+               else if (begin_gs_p->stemdir == DOWN && place == PL_BELOW
+                               && begnote_p == &(begin_gs_p->notelist
+                               [begin_gs_p->nnotes - 1])  &&
+                               stuff_p->carryin == NO) {
+                       if (begin_gs_p->basictime < 2 && begin_gs_p->nwith > 0
+                                       && begin_gs_p->normwith == NO) {
+                               curvelist_p->x = begin_gs_p->c[AE];
+                               y_adj = (Stepsize * (begnote_p->notesize
+                                               == GS_NORMAL ? 1.2 : 0.9));
+                               curvelist_p->y -= y_adj;
+                       }
+                       else {
+                               curvelist_p->x = begin_gs_p->c[AX];
+                               y_adj = (Stepsize * (begnote_p->notesize
+                                               == GS_NORMAL ? 1.7 : 1.2));
+                               curvelist_p->y -= y_adj;
+                       }
+               }
+               else {
+                       curvelist_p->x = begin_gs_p->c[AX] +
+                                       notehorz(begin_gs_p, begnote_p, RE) +
+                                       Stdpad;
+               }
+
+               /* If two notes are a stepsize apart and the curve from the
+                * west note is bending towards the east note,
+                * then the x should be moved east a little.
+                * First case: this isn't the top note, but the note just
+                * above is 1 stepsize away and on the east side, and the
+                * curve is going up and it's not a carryin. */
+               if (begnote_p != &(begin_gs_p->notelist[0]) &&
+                               begnote_p->stepsup ==
+                               begnote_p[-1].stepsup - 1 &&
+                               begnote_p->c[RX] < begnote_p[-1].c[RX] &&
+                               place == PL_ABOVE &&
+                               stuff_p->carryin == NO) {
+                       curvelist_p->x += 1.5 * Stepsize;
+               }
+               /* Second case: not bottom note, note just
+                * below is one step away and on the east side, the curve
+                * is going down, and it's not a carryin. */
+               else if (begnote_p != &(begin_gs_p->notelist[begin_gs_p->nnotes-1]) &&
+                               begnote_p->stepsup ==
+                               begnote_p[1].stepsup + 1 &&
+                               begnote_p->c[RX] < begnote_p[1].c[RX] &&
+                               place == PL_BELOW &&
+                               stuff_p->carryin == NO) {
+                       curvelist_p->x += 1.5 * Stepsize;
+               }
+                               
+       }
+
+       /* if carried over from previous score, start a bit farther left */
+       if (stuff_p->carryin == YES) {
+
+               /* find the pseudo bar and set x to that */
+               for (bar_mll_p = mll_p->prev;
+                                       bar_mll_p != (struct MAINLL *) 0;
+                                       bar_mll_p = bar_mll_p->prev) {
+                       if (bar_mll_p->str == S_CLEFSIG) {
+                               if (bar_mll_p->u.clefsig_p->bar_p
+                                                       == (struct BAR *) 0) {
+                                       /* carryin to an ending */
+                                       continue;
+                               }
+                               curvelist_p->x =
+                                       bar_mll_p->u.clefsig_p->bar_p->c[AE]
+                                       - (TIESLURPAD * Staffscale);
+
+                               /* Long notes (wholes, etc) generally get
+                                * more space on their left than short notes,
+                                * so a curve carried in to a long note
+                                * may look overly long, especially if other
+                                * scores on the same page have carryins
+                                * to short notes. So limit carryin curve
+                                * length to 5 stepsizes.
+                                */
+                               if (begin_gs_p->c[AW] - curvelist_p->x > 5.0 * Stepsize) {
+                                       curvelist_p->x = begin_gs_p->c[AW]
+                                                       - 5.0 * Stepsize;
+                               }
+                               break;
+                       }
+                       else if (bar_mll_p->str == S_BAR) {
+                               /* carryin to an ending */
+                               curvelist_p->x = begin_gs_p->c[AW];
+                               break;
+                       }
+               }
+
+               if (bar_mll_p == (struct MAINLL *) 0) {
+                       pfatal("missing CELFSIG when carrying over %s mark",
+                                                               name);
+               }
+       }
+
+       /* set up ending coord */
+       MALLOC(CRVLIST, endlist_p, 1);
+       if (is_phrase == YES) {
+               /* End slightly to west of group center, so that another
+                * curve can start on this group (if needed) with
+                * touching this curve. */
+               endlist_p->x = end_gs_p->c[AX] - XOFFSET4CURVE;
+               if (end_gs_p->grpcont != GC_SPACE) {
+                       endlist_p->y = end_gs_p->c[side]
+                               + eff_tupext(end_gs_p, mll_p->u.staff_p, place)
+                               + (sign * 2.0 * Stdpad);
+                       /* Add in space for any relevant nested phrases */
+                       if (end_gs_p->c[side_adj] != 0.0 &&
+                                       (end_gs_p->phraseside & WEST_SIDE)) {
+                               endlist_p->y += end_gs_p->c[side_adj];
+                       }
+               }
+               else {
+                       /* bizarre case. last group is a space.  Use 1 stepsize
+                        * from top or bottom of staff for y coord */
+                       endlist_p->y = sign * (1 + halfstaffhi(begin_gs_p->staffno));
+               }
+       }
+       else {
+               if (stuff_p->carryin == YES) {
+                       /* in case of carryin, the "begin" group is actually
+                        * the ending group, so set the end group, and
+                        * adjust the beginning y */
+                       endlist_p->x = begin_gs_p->c[AW];
+
+                       /* adjust things carried into endings to account for
+                        * the padding that was added */
+                       if (bar_mll_p->str == S_BAR) {
+                               endlist_p->x += TIESLURPAD * Staffscale;
+                       }
+
+                       endlist_p->y = curvelist_p->y;
+                       end_gs_p = begin_gs_p;
+
+                       /* if end note, adjust */
+                       if (place == PL_ABOVE && begnote_p
+                                               == &(begin_gs_p->notelist[0])) {
+                               endlist_p->x = begnote_p->c[AX];
+                               if ((begin_gs_p->basictime > 1) &&
+                                               (begin_gs_p->stemdir == UP)) {
+                                       endlist_p->y += Stepsize;
+                                       curvelist_p->y += Stepsize;
+                               }
+                       }
+                       else if (place == PL_BELOW && begnote_p ==
+                                               &(begin_gs_p->notelist
+                                               [begin_gs_p->nnotes - 1])
+                                               && (begin_gs_p->stemdir == UP
+                                               || begin_gs_p->basictime < 2)) {
+                               endlist_p->x = begnote_p->c[AX];
+                               if ((begin_gs_p->basictime < 2) &&
+                                               (begin_gs_p->stemdir == DOWN)) {
+                                       endlist_p->y -= Stepsize;
+                                       curvelist_p->y -= Stepsize;
+                               }
+                       }
+               }
+               else {
+                       /* not carryin */
+                       end_gs_p = find_next_group (mll_p, begin_gs_p,
+                               (stuff_p->curveno == -1 ? "tie" : "slur"));
+                       if (stuff_p->curveno == -1) {
+                               /* this is a tie */
+                               endnote_p = find_matching_note (end_gs_p,
+                                               begnote_p->letter,
+                                               begnote_p->octave, "tie");
+                       }
+                       else {
+                               if (IS_NOWHERE(begnote_p->slurtolist
+                                               [stuff_p->curveno].octave)) {
+                                       pfatal("curve_points called on slide to nowhere");
+                               }
+
+                               endnote_p = find_matching_note (end_gs_p,
+                                               begnote_p->slurtolist
+                                               [stuff_p->curveno].letter,
+                                               begnote_p->slurtolist
+                                               [stuff_p->curveno].octave,
+                                               "slur/slide");
+                       }
+
+                       endlist_p->y = endnote_p->c[RY];
+
+                       y2_adj = 0.0;
+
+                       /* move if below curve and bottom note with stem up */
+                       if (end_gs_p->stemdir == UP && place == PL_BELOW
+                                       && endnote_p == &(end_gs_p->notelist
+                                       [end_gs_p->nnotes - 1])) {
+                               if (end_gs_p->nwith == 0
+                                               || end_gs_p->normwith == NO) {
+                                       endlist_p->x = endnote_p->c[AX]
+                                               - (2.0 * Stdpad);
+                                       y2_adj = (Stepsize *
+                                               (endnote_p->notesize
+                                               == GS_NORMAL ? 1.7 : 1.2));
+                                       endlist_p->y -= y2_adj;
+                               }
+                               else {
+                                       endlist_p->x = endnote_p->c[AW];
+                                       y2_adj = (Stepsize *
+                                               (endnote_p->notesize
+                                               == GS_NORMAL ? 1.2 : 0.9));
+                                       endlist_p->y -= y2_adj;
+                               }
+                       }
+
+                       /* move if above and top note with stem down */
+                       else if (end_gs_p->stemdir == DOWN && place == PL_ABOVE
+                                    && endnote_p == &(end_gs_p->notelist[0])) {
+                               if (end_gs_p->nwith == 0
+                                               || end_gs_p->normwith == NO) {
+                                       endlist_p->x = endnote_p->c[AX]
+                                                       - (2.0 * Stdpad);
+                                       y2_adj = (Stepsize *
+                                               (endnote_p->notesize
+                                               == GS_NORMAL ? 1.7 : 1.2));
+                                       endlist_p->y += y2_adj;
+                               }
+                               else {
+                                       endlist_p->x = endnote_p->c[AW];
+                                       y2_adj = (Stepsize *
+                                               (endnote_p->notesize
+                                               == GS_NORMAL ? 1.2 : 0.9));
+                                       endlist_p->y += y2_adj;
+                               }
+                       }
+
+                       /* whole and longer don't have stem, so end note where
+                        * a stem would be (if there were one) can be moved */
+                       else if (end_gs_p->basictime < 2 &&
+                                       end_gs_p->stemdir == DOWN
+                                       && place == PL_BELOW
+                                       && endnote_p == &(end_gs_p->notelist
+                                       [end_gs_p->nnotes - 1])) {
+                               if (end_gs_p->nwith == 0
+                                               || end_gs_p->normwith == YES) {
+                                       endlist_p->x = endnote_p->c[AX]
+                                                               - Stdpad;
+                                       y2_adj = (Stepsize *
+                                               (endnote_p->notesize
+                                               == GS_NORMAL ? 1.7 : 1.2));
+                                       endlist_p->y -= y2_adj;
+                               }
+                               else {
+                                       endlist_p->x = endnote_p->c[AW];
+                                       y2_adj = (Stepsize *
+                                               (endnote_p->notesize
+                                               == GS_NORMAL ? 1.2 : 0.9));
+                                       endlist_p->y -= y2_adj;
+                               }
+                       }
+
+                       /* move if above and top note of stem up */
+                       else if (end_gs_p->stemdir == UP && place == PL_ABOVE
+                                       && endnote_p ==
+                                       &(end_gs_p->notelist[0]) ) {
+                               endlist_p->x = end_gs_p->c[AX];
+                               y2_adj = (Stepsize * (endnote_p->notesize
+                                               == GS_NORMAL ? 1.7 : 1.2));
+                               endlist_p->y += y2_adj;
+
+                               /* if tied from note is also the top of its
+                                * group, level the tie/slur */
+                               if (begin_gs_p->stemdir == UP &&
+                                               begnote_p ==
+                                               &(begin_gs_p->notelist[0])  &&
+                                               begin_gs_p->basictime > 1 ) {
+                                       curvelist_p->y += (Stepsize *
+                                               (begnote_p->notesize
+                                               == GS_NORMAL ? 1.7 : 1.2));
+                               }
+                       }
+                       else if (begin_gs_p->grpvalue == GV_ZERO) {
+                               /* grace note to main note, can't use the west
+                                * of the end group because that would include
+                                * the grace note. */
+                               endlist_p->x = endnote_p->c[AX] +
+                                       notehorz(end_gs_p, endnote_p, RW);
+                       }
+                       else {
+                               endlist_p->x = tieslurx(end_gs_p, endnote_p,
+                                       stuff_p->place) - (2.0 * Stdpad);
+                       }
+
+                       /* if note tied from is bottom of group with stem down,
+                        * level the tie/slur */
+                       if (end_gs_p->stemdir == DOWN && place == PL_BELOW
+                                       && endnote_p == &(end_gs_p->notelist
+                                       [end_gs_p->nnotes - 1]) &&
+                                       begin_gs_p->stemdir == DOWN &&
+                                       begnote_p == &(begin_gs_p->notelist
+                                       [begin_gs_p->nnotes - 1]) &&
+                                       end_gs_p->basictime > 1 ) {
+                               endlist_p->y -= (Stepsize *
+                                               (begnote_p->notesize
+                                               == GS_NORMAL ? 1.7 : 1.2));
+                       }
+
+                       /* if beginning of curve was adjusted and this is
+                        * an inner note, but there is room on the relevant
+                        * side, and this is a tie, then adjust this end's y
+                        * to level the curve */
+                       else if (y_adj != 0.0 && stuff_p->curveno == -1) {
+                               endlist_p->y += inner_adj(end_gs_p, endnote_p,
+                                                       y_adj, place);
+                       }
+
+                       /* level beginning if the note in the previous
+                        * chord was the same note but wasn't the top,
+                        * but the next note is more than a stepsize
+                        * away. */
+                       if (y2_adj != 0.0 && stuff_p->curveno == -1) {
+                               curvelist_p->y += inner_adj(begin_gs_p,
+                                       begnote_p, y2_adj, place);
+                       }
+               }
+       }
+
+       /* one final adjustment. If the stem of first group is up and stem
+        * of second group is down, and the notes being tied/slurred are both
+        * the tops notes if the place is above or both bottom notes if the
+        * place is below, then move the y coord on the side that wasn't
+        * already moved, to level the curve. Do only if the note is shorter
+        * than a whole note, because longer notes were already moved because
+        * they had no stem. */
+       if (is_phrase == NO && begin_gs_p->stemdir == UP
+                                       && end_gs_p != (struct GRPSYL *) 0
+                                       && end_gs_p->stemdir == DOWN) {
+               if (place == PL_ABOVE && begnote_p ==
+                               &(begin_gs_p->notelist[0])
+                               && endnote_p == &(end_gs_p->notelist[0])
+                               && begin_gs_p->basictime > 1) {
+                       curvelist_p->y += (Stepsize * (begnote_p->notesize
+                                               == GS_NORMAL ? 1.7 : 1.2));
+               }
+               else if (place == PL_BELOW && begnote_p ==
+                               &(begin_gs_p->notelist[begin_gs_p->nnotes - 1])
+                               && endnote_p ==
+                               &(end_gs_p->notelist[end_gs_p->nnotes - 1])
+                               && end_gs_p->basictime > 1) {
+                       endlist_p->y -= (Stepsize * (endnote_p->notesize
+                                               == GS_NORMAL ? 1.7 : 1.2));
+               }
+       }
+
+       endlist_p->next = (struct CRVLIST *) 0;
+       /* no need to set other links now because we will be added other nodes
+        * in between in a moment anyway */
+       
+       /* if carrying over, extend x to margin */
+       if (stuff_p->carryout) {
+               endlist_p->x = PGWIDTH - eff_rightmargin(mll_p);
+       }
+
+       /* find length of curve by Pythagorean */
+       length = sqrt(SQUARED(endlist_p->x - curvelist_p->x)
+                               + SQUARED(endlist_p->y - curvelist_p->y));
+
+       /* Find y length for creating bulge in the curve.
+        * Make bigger bend if longer curve, but not too big or too small.
+        */
+       ylen = length / 16;
+       if (ylen > 2.2 * Stepsize) {
+               ylen = 2.2 * Stepsize;
+       }
+       else if (ylen < (Stepsize * 0.75)) {
+               ylen = Stepsize * 0.75;
+       }
+       ylen = ylen * sign;
+
+       /* we figure out curve as if endpoints were on the x axis, then adjust
+        * with the proper sin and cos factors to get them where they really
+        * belong */
+       sintheta = (endlist_p->y - curvelist_p->y) / length;
+       costheta = (endlist_p->x - curvelist_p->x) / length;
+
+       /* set up node for another point on curve */
+       MALLOC(CRVLIST, new_p, 1);
+       new_p->prev = curvelist_p;
+       new_p->next = endlist_p;
+       curvelist_p->next = new_p;
+       endlist_p->prev = new_p;
+
+       if (stuff_p->carryout == YES) {
+               if (is_phrase == YES) {
+                       endlist_p->y += ylen / 2.0;
+               }
+               else {
+                       end_gs_p = begin_gs_p;
+               }
+       }
+
+       /* First try a single point in the middle. Try bigger bulge
+        * value if some groups stick out, up to a maximum. */
+       tb.mll_p = mll_p;
+       tb.begin_gs_p = begin_gs_p;
+       tb.end_gs_p = end_gs_p;
+       tb.place = place;
+       tb.curvelist_p = curvelist_p;
+       tb.endlist_p = endlist_p;
+       tb.xlen = length / 2.0;
+       tb.ylen = ylen;
+       tb.sintheta = sintheta;
+       tb.costheta = costheta;
+       tb.minbulge = MINBULGE;
+       tb.maxbulge = MAXBULGE;
+       try_p = &tb;
+       if ((bulgeval = try_bulge(try_p)) < MAXBULGE) {
+               /* This curve works. Go with it */
+               if (bulgeval == MINBULGE) {
+                       /* The very first try worked with nothing in the way,
+                        * so may be safe to try to
+                        * beautify any really steep curves.
+                        * So try to redo and see if still okay.
+                        * If not, put back the original.
+                        */
+                       double save_x, save_y;
+                       save_x = curvelist_p->next->x;
+                       save_y = curvelist_p->next->y;
+                       redo_steep(curvelist_p, endlist_p, place);
+                       if (stick_out(try_p) > 0.0) {
+                               curvelist_p->next->x = save_x;
+                               curvelist_p->next->y = save_y;
+                       }
+               }
+               /* adjust group boundaries to include the curve */
+               final_touches(mll_p, begin_gs_p, end_gs_p, curvelist_p, place);
+
+               /* attach the curve to the stuff */
+               stuff_p->crvlist_p = curvelist_p;
+               return;
+       }
+
+       /* Using a single inner point didn't give a good curve.
+        * So we'll try two inner points. Add another point to the curve. */
+       MALLOC(CRVLIST, new_p, 1);
+       new_p->prev = endlist_p->prev;
+       new_p->next = endlist_p;
+       new_p->prev->next = new_p;
+       endlist_p->prev = new_p;
+
+       /* We now have three segments, each 1/3 of total length */
+       tb.xlen = length / 3.0;
+
+       /* We're a little more desperate, so allow more bulge */
+       tb.minbulge = MIN2BULGE;
+       tb.maxbulge = MAX2BULGE;
+
+       if ((bulgeval = try_bulge(try_p)) < MAXBULGE) {
+               /* This curve works. Go with it */
+               final_touches(mll_p, begin_gs_p, end_gs_p, curvelist_p, place);
+
+               /* attach the curve to the stuff */
+               stuff_p->crvlist_p = curvelist_p;
+               return;
+       }
+
+       /* Really getting desperate now, so allow even more bulge */
+       tb.minbulge = MIN3BULGE;
+       tb.maxbulge = MAX3BULGE;
+
+       /* Just adjusting bulge didn't work,
+        * so we try repeatedly moving the ends slightly
+        * and trying again until something works.
+        * Worst case should be something like an above curve encompassing c0
+        * to b9 back to c0, with a stem up on the b9. That would be about 80
+        * stepsizes. But if an end is a cross-staff stem group completely
+        * on the other staff, and if that other staff is ridiculously
+        * far away because of very tall STUFF, even 100 iterations
+        * of moving by a Stepsize sometimes isn't enough.
+        * So we'll try 200 times before giving up with a pfatal.
+        */
+       found_good = NO;
+       for (try = 0; try < 200; try++) {
+               double mvbegin, mvend, mvboth;
+               int leftcount, rightcount;
+
+               /* Try moving each end individually and both together,
+                * then try to  go with whatever gave the best results
+                * with the least movement.
+                */
+
+               /* try with just begin point moved */
+               curvelist_p->y += Stepsize * sign;
+               mvbegin = try_bulge(try_p);
+
+               /* try with both endpoints moved */
+               endlist_p->y += Stepsize * sign;
+               mvboth = try_bulge(try_p);
+               leftcount = tb.leftcount;
+               rightcount = tb.rightcount;
+
+               /* try with just end point moved */
+               curvelist_p->y -= Stepsize * sign;
+               mvend = try_bulge(try_p);
+
+               /* See which of the three attempts seemed best */
+               if ( (mvend < mvbegin && mvend < mvboth)
+                               || (try < 5 && leftcount == 0 && rightcount > 0) ) {
+                       /* moving just the end was best */
+                       if (mvend < MAX3BULGE) {
+                               found_good = YES;
+                               break;
+                       }
+               }
+               else if ( (mvbegin < mvend && mvbegin < mvboth)
+                               || (try < 5 && leftcount > 0 && rightcount == 0) ) {
+                       /* moving just the beginning was best */
+                       curvelist_p->y += Stepsize * sign;
+                       endlist_p->y -=  Stepsize * sign;
+                       if (mvbegin < MAX3BULGE) {
+                               found_good = YES;
+                               break;
+                       }
+               }
+               else {
+                       /* move both ends */
+                       curvelist_p->y += Stepsize * sign;
+                       if (mvboth < MAX3BULGE) {
+                               found_good = YES;
+                               break;
+                       }
+               }
+       }
+
+       if (found_good == YES) {
+               /* Call try_bulge again to set the inner points (the one
+                * we chose might not be the last one we tried. */
+               (void) try_bulge(try_p);
+               final_touches(mll_p, begin_gs_p, end_gs_p, curvelist_p, place);
+
+               /* attach the curve to the stuff */
+               stuff_p->crvlist_p = curvelist_p;
+               return;
+       }
+
+       pfatal("unable to find a usable curve");
+}
+\f
+
+/* 
+ * Returns the smallest bulge factor that worked, or a value >= maxbulge if
+ * nothing worked. The more the return value exceeds maxbulge, the worse
+ * the amount of "stick out." The curvelist_p should point to a curve with
+ * 3 or 4 points.
+ */
+
+static double
+try_bulge(info_p)
+
+struct TRYBULGE *info_p;       /* points to all the info this func needs */
+
+{
+       struct CRVLIST *mid_p;          /* interior point of curve */
+       struct CRVLIST *mid2_p;         /* second inner point, if any */
+       double bulge_factor;            /* how much to bulge */
+       double amount = 0.0;            /* amount of stick out */
+
+
+       /* Get pointer to the midpoint(s) */
+       mid_p = info_p->curvelist_p->next;
+       if (mid_p->next != info_p->endlist_p) {
+               mid2_p = mid_p->next;
+       }
+       else {
+               mid2_p = 0;
+       }
+
+       /* Keep trying bigger bulge until we find one that clears all the
+        * groups or until the specified maximum is reached. */
+       for (bulge_factor = info_p->minbulge; bulge_factor < info_p->maxbulge;
+                                               bulge_factor += 0.25) {
+
+               /* find (x,y) values for midpoint(s) taking the rotation
+                * from horizontal into account. */
+               mid_p->x = info_p->curvelist_p->x
+                       + (info_p->xlen * info_p->costheta)
+                       - (bulge_factor * info_p->ylen * info_p->sintheta);
+               mid_p->y = info_p->curvelist_p->y
+                       + (bulge_factor * info_p->ylen * info_p->costheta)
+                       + (info_p->xlen * info_p->sintheta);
+
+               if (mid2_p != 0) {
+                       mid2_p->x = info_p->curvelist_p->x
+                               + (2.0 * info_p->xlen * info_p->costheta)
+                               - (bulge_factor * info_p->ylen * info_p->sintheta);
+                       mid2_p->y = info_p->curvelist_p->y
+                               + (bulge_factor * info_p->ylen * info_p->costheta)
+                               + (2.0 * info_p->xlen * info_p->sintheta);
+               }
+
+               if ((amount = stick_out(info_p)) <= 0.0) {
+                       /* This curve works. Go with it */
+                       break;
+               }
+       }
+
+       /* Even max allowed bulge value was not enough. Returning the max bulge
+        * allowed tells caller we failed, and adding on how much
+        * "stick-out" gives an indication of how badly we failed.
+        */
+       return(bulge_factor + amount);
+}
+\f
+
+/* adjust the endpoint of an inner note if the opposite end was adjusted,
+ * and there is room to adjust this end. */
+
+static double
+inner_adj(gs_p, note_p, y_adj, place)
+
+struct GRPSYL *gs_p;   /* not is in this group */
+struct NOTE *note_p;   /* this is the note being tied to */
+double y_adj;          /* how much other end of tie was adjusted */
+int place;             /* PL_ABOVE or PL_BELOW */
+
+{
+       int i;
+
+
+       if (gs_p->nnotes <= 2) {
+               /* can't possibly be an inner note, so no adjust */
+               return(0.0);
+       }
+
+       /* find index of note */
+       for (i = 0; i < gs_p->nnotes; i++) {
+               if (note_p == &(gs_p->notelist[i])) {
+                       break;
+               }
+       }
+
+       if (i == gs_p->nnotes) {
+               pfatal("couldn't find note in chord");
+       }
+
+       if (i == 0 || i == gs_p->nnotes - 1) {
+               /* not an inner note. no adjust */
+               return(0.0);
+       }
+
+       /* check if next note in chord is within STEPSIZE away. If not,
+        * we can adjust this end */
+       if (place == PL_ABOVE && gs_p->notelist[i-1].stepsup
+                                       > gs_p->notelist[i].stepsup + 1) {
+               return(y_adj);
+       }
+       else if (place == PL_BELOW && gs_p->notelist[i+1].stepsup
+                                       < gs_p->notelist[i].stepsup - 1) {
+               /* y_adj will always come in as a positive number and will be
+                * added on return, so return negative value for below curves */
+               return(-y_adj);
+       }
+       return(0.0);
+}
+\f
+
+/* Returns the sum of the "stick out" of groups in the given curve.
+ * If all groups are inside, this will be 0.0
+ * Also counts number of "stickouts" that are near each end,
+ * in case that might be useful in deciding which endpoint to move.
+ * These counts are stored in the leftcount and rightcount fields of
+ * the passed-in struct.
+ */
+
+static double
+stick_out(info_p)
+
+struct TRYBULGE *info_p;
+
+{
+       struct GRPSYL *gs_p;    /* to walk through list */
+       struct GRPSYL *begin_gs_p, *end_gs_p;
+       double yleft, yright;   /* y value of point on the line that is
+                                * at the x position of the left and right
+                                * sides of the current GRPSYL, */
+       double yg;              /* y of group accounting for other phrases */
+       struct MAINLL *mll_p;   /* the curve's STUFF hangs off of here */
+       int place;              /* PL_* */
+       struct CRVLIST *curvelist_p;    /* beginning of curve to check */
+       struct CRVLIST *endlist_p;      /* end of curve to check */
+       int staff;
+       int voice;
+       double stickout;        /* return value */
+       double len;             /* length that is deemed "near the end" of the
+                                * curve, for setting left/right counts */
+
+
+       begin_gs_p = info_p->begin_gs_p;
+       end_gs_p = info_p->end_gs_p;
+       if (begin_gs_p == 0 || end_gs_p == 0) {
+               pfatal("got null pointer when checking phrase marks");
+       }
+
+       info_p->leftcount = 0;
+       info_p->rightcount = 0;
+
+       /* If starting phrase on last note of score or ending one on first
+        * note of a score, begin and end will be the same. We know that
+        * note has already been accounted for, so nothing to do. */
+       if (begin_gs_p == end_gs_p) {
+               return(0.0);
+       }
+
+       staff = begin_gs_p->staffno;
+       voice = begin_gs_p->vno;
+       curvelist_p = info_p->curvelist_p;
+       endlist_p = info_p->endlist_p;
+       mll_p = info_p->mll_p;
+       place = info_p->place;
+       stickout = 0.0;
+       /* We will be counting up how many groups stick out near each end,
+        * to potentially help decide which endpoint to move to avoid
+        * collisions. For that purpose, we'll define "near the end"
+        * as being within 1/4 of the total x distance from an endpoint.
+        */
+       len = (endlist_p->x - curvelist_p->x) / 4.0;
+
+       /* Go through each group between the beginning and end. We've
+        * already set the curve endings to clear the group boundaries */
+       for (gs_p = begin_gs_p->next; gs_p != end_gs_p; gs_p = gs_p->next) {
+
+               /* If hit end of measure go to next measure */
+               if (gs_p == (struct GRPSYL *) 0) {
+                       mll_p = next_staff(staff, mll_p->next);
+                       if (info_p->mll_p == (struct MAINLL *) 0) {
+                               pfatal("fell off end of list while doing phrase marks");
+                       }
+                       gs_p = mll_p->u.staff_p->groups_p[voice - 1];
+               }
+
+               if (gs_p == end_gs_p) {
+                       break;
+               }
+
+               /* Find out where the y of the curve is at this group.
+                * We actually check two points, one each slightly
+                * to the east and west of the group's x.
+                * It would even more accurate to figure out the actual
+                * width of whatever is at the end (a notehead, a stem,
+                * a rest, stem with flag, etc) but just taking 1.5 Stepsizes
+                * on either side generally gives adequate results and
+                * is a lot simpler.
+                */
+               yleft = curve_y_at_x(curvelist_p, gs_p->c[AX] - 1.5 * Stepsize);
+               yright = curve_y_at_x(curvelist_p, gs_p->c[AX] + 1.5 * Stepsize);
+
+               /* See if this group is within the curve */
+               if (info_p->place == PL_ABOVE) {
+                       /* Consider the group (RN) plus any relevant
+                        * nested phrase marks (their space is stored in AN).
+                        * It is relevant unless it's for the begin group
+                        * and that group's east is not relevent, or it's the
+                        * end group and that group's west is not relevant */
+                       yg = gs_p->c[RN] + CLEARANCE
+                               + eff_tupext(gs_p, mll_p->u.staff_p, place);
+                       if ( (gs_p != begin_gs_p ||
+                                       ((gs_p->phraseside & EAST_SIDE) == 0))
+                                       && (gs_p != end_gs_p ||
+                                       ((gs_p->phraseside & WEST_SIDE) == 0)) ) {
+                               yg += gs_p->c[AN];
+                       }
+                       if (yleft > yg && yright > yg) {
+                               /* Good. It's inside */
+                               continue;
+                       }
+                       else {
+                               /* Bad. It stuck over */
+                               stickout += yg - MIN(yleft, yright);
+                               /* If near either end, make a note of that */
+                               if (gs_p->c[AX] - curvelist_p->x < len) {
+                                       info_p->leftcount += 1;
+                               }
+                               else if (endlist_p->x - gs_p->c[AX] < len) {
+                                       info_p->rightcount +=1;
+                               }
+                       }
+               }
+               else {
+                       /* Do the same for curve going down */
+                       yg = gs_p->c[RS] - CLEARANCE
+                               + eff_tupext(gs_p, mll_p->u.staff_p, place);
+                       if ( (gs_p != begin_gs_p ||
+                                       ((gs_p->phraseside & EAST_SIDE) == 0))
+                                       && (gs_p != end_gs_p ||
+                                       ((gs_p->phraseside & WEST_SIDE) == 0)) ) {
+                               yg += gs_p->c[AS];
+                       }
+                       if (yleft < yg && yright < yg) {
+                               continue;
+                       }
+                       else {
+                               stickout += MAX(yleft, yright) - yg;
+                               if (gs_p->c[AX] - curvelist_p->x < len) {
+                                       info_p->leftcount++;
+                               }
+                               else if (endlist_p->x - gs_p->c[AX] < len) {
+                                       info_p->rightcount++;
+                               }
+                       }
+               }
+       }
+       return(stickout);
+}
+\f
+
+/* find the x of the end of a tie/slur. Usually we could just used the west of
+ * the group, but if there are lots of accidentals on notes that are far
+ * away from the note in question, the end of the tie can come out rather
+ * far away from its note. So try to see if we can move it closer, by
+ * checking to see if there are any accidentals on notes nearby. This
+ * function is not foolproof, sometimes leaving space when the tie/slur
+ * could actually get threaded through a tiny opening, and sometimes
+ * overwriting the edge of an accidental somewhat, but tries to do a better
+ * job than the original single line of code for figuring this out had done. */
+
+static double
+tieslurx(gs_p, note_p, place)
+
+struct GRPSYL *gs_p;   /* check notes in this group */
+struct NOTE *note_p;   /* check for accidentals near this note */
+int place;             /* PL_ABOVE or PL_BELOW to tell which side to look on */
+
+{
+       int n;          /* index through notelist */
+       int acc;        /* accidental */
+
+
+       /* if "wrong" side of a stem up group, better use group boundary */
+       if (note_p->c[AX] > gs_p->c[AX] && gs_p->stemdir == UP) {
+               return(gs_p->c[AW]);
+       }
+
+       /* if there is another note nearby,
+        * and that note has an accidental, better use
+        * the west of the group to be safe, otherwise
+        * use the west of the note. */
+       for (n = 0; n < gs_p->nnotes; n++) {
+
+               acc = gs_p->notelist[n].accidental;
+               switch (gs_p->notelist[n].stepsup - note_p->stepsup) {
+               case 1:
+               case 2:
+                       /* close enough that sharp, flat, and dblflat may
+                        * interfere, if coming in from above */
+                       if (place == PL_ABOVE && (acc == '#' || acc == '&'
+                                                       || acc == 'B')) {
+                               return(gs_p->c[AW]);
+                       }
+                       break;
+               case 3:
+                       /* close enough that sharp may interfere, if coming
+                        * in from above */
+                       if (place == PL_ABOVE && acc == '#') {
+                               return(gs_p->c[AW]);
+                       }
+                       break;
+               case 0:
+                       /* the note itself */
+                       break;
+               case -1:
+                       /* sharp, flat, and dblflat may interfere from
+                        * either direction */
+                       if (acc == '#' || acc == '&' || acc == 'B') {
+                               return(gs_p->c[AW]);
+                       }
+                       break;
+
+               case -2:
+               case -3:
+               case -4:
+                       /* close enough that things may interfere */
+                       if (place == PL_BELOW && (acc == '#' || acc == '&'
+                                                       || acc == 'B')) {
+                               return(gs_p->c[AW]);
+                       }
+                       break;
+
+               default:
+                       /* this note is too far away to matter */
+                       break;
+               }
+       }
+
+       /* it seems there are no accidentals in the way, so use the note
+        * boundary, rather than group boundary */
+       return(gs_p->c[AX] + notehorz(gs_p, note_p, AW));
+}
+\f
+
+/* given a main list struct, search forward from there for the STAFF matching
+ * the given staff. If fall off end of main list, return NULL */
+
+static struct MAINLL *
+next_staff(staff, mll_p)
+
+int staff;             /* find this staff number */
+struct MAINLL *mll_p;  /* where to start */
+
+{
+       /* walk through main list looking for desired staff */
+       for (  ; mll_p != (struct MAINLL *) 0; mll_p = mll_p->next) {
+               if (mll_p->str == S_STAFF) {
+                       if (mll_p->u.staff_p->staffno == staff) {
+                               return(mll_p);
+                       }
+               }
+       }
+
+       /* didn't find it */
+       return( (struct MAINLL *) 0);
+}
+\f
+/*
+ * Name:       redo_steep()
+ *
+ * Abstract:   Redo curves that are very steep.
+ *
+ * Returns:    void
+ *
+ * Description:        If the curve is "too steep", it redoes it
+ *             so that it's horizontal at the outer end, rather than already
+ *             sloping in towards the inner end.
+ *             Caller needs to verify the redone curve doesn't collide
+ *             with any groups. Assumes the curve contains 3 points.
+ */
+
+static void
+redo_steep (first_p, last_p, place)
+
+struct CRVLIST *first_p;       /* left endpoint of curve */
+struct CRVLIST *last_p;                /* right endpoint of curve */
+int place;                     /* above or below */
+
+{
+       struct CRVLIST *mid_p;          /* new midpoint of curve */
+       float delx;                     /* distance from the end to test */
+       float a, b;                     /* some distances, see below */
+       float midoff;                   /* vert offset of midpoint */
+
+
+       /*
+        * We need to test whether either end of the curve is sloping in.  So
+        * we really should find the derivative at the endpoints.  But we can
+        * approximate it close enough by finding the y value at a point "near"
+        * the end and comparing it to the end's y value.  "delx" tells how
+        * near.  We'd like to set it to a millionth of an inch, but due to
+        * apparent roundoff errors in curve_y_at_x(), we make it bigger than
+        * that: 1/4 the curve length, but never more than 2 stepsizes.
+        */
+       if (last_p->x - first_p->x > 8 * Stepsize) {
+               delx = 2 * Stepsize;
+       } else {
+               delx = (last_p->x - first_p->x) / 4.0;
+       }
+       if (place == PL_ABOVE) {
+               /* if both near points are higher than end points, return */
+               if (curve_y_at_x(first_p, first_p->x + delx) >= first_p->y &&
+                   curve_y_at_x(first_p, last_p->x  - delx) >= last_p->y) {
+                       return;
+               }
+       } else {
+               /* if both near points are lower than end points, return */
+               if (curve_y_at_x(first_p, first_p->x + delx) <= first_p->y &&
+                   curve_y_at_x(first_p, last_p->x  - delx) <= last_p->y) {
+                       return;
+               }
+       }
+
+       /*
+        * The curve is steep.  First, we choose a new point,
+        * horizontally in the middle.  We are
+        * going to choose its vertical position so that the outer end of the
+        * curve starts out horizontal.
+        *
+        * Imagine the case of PL_BELOW where the left end is the outer (lower)
+        * end.  (The other 3 cases are symmetrical to this, and we can use the
+        * analogous result.)  Set the axes so that the left end is at the
+        * origin, and the right end is at (2*a, b).  The new point will be at
+        * (a, y), and we have to find y.  We know that y will be between 0 and
+        * b/2.  (Draw a picture.)
+        *
+        * Draw segments from (0, 0) to (a, y), and (a, y) to (2*a, b).  Then
+        * draw a line through (a, y) such that it forms the same angle theta
+        * with each of these segments.  The way calccurve() works, it will
+        * form two cubic arcs (in rotated coordinate systems) through the
+        * three points, such that the slope of each arc at each point forms
+        * the same angle theta with the segment next to it.  The last line we
+        * drew hits the X axis at a point which, with (0, 0) and (a, y) forms
+        * an isoceles triangle, where the angles at (0, 0) and (a, y) are
+        * both theta (because we're saying the arc at (0, 0) is horizontal).
+        * So the other angle is 180 degrees minus 2*theta.  That means the
+        * other angle the line forms with the X axis is 2*theta.  And that
+        * means the angle between the horizontal line through (a, y) and the
+        * second segment (a, y) to (2*a, b) is 3*theta.
+        *
+        * Looking at triangle (0, 0) to (a, 0) to (a, y), we see that
+        *      tan(theta) = y/a
+        * Looking at triangle (a, y) to (2*a, y) to (2*a, b), we see that
+        *      tan(3*theta) = (b-y)/a
+        * There is a trig identity
+        *                      3*tan(theta) - (tan(theta))^3
+        *      tan(3*theta) =  ------------------------------
+        *                              1 - 3*(tan(theta))^2
+        * Plug into this our values for tan(theta) and tan(3*theta), and you
+        * end up with
+        *      4 y^3 - 3 b y^2 - 4 a^2 y + a^2 b = 0
+        * To solve this cubic, we could do a whole routine for solving cubics,
+        * but it's easier to approximate as follows.
+        *
+        # Define
+        *      F(x) = 4 x^3 - 3 b x^2 - 4 a^2 x + a^2 b
+        * a and b are positive.  So at x = 0, F(x) > 0.  At x=b/2, F(x) < 0.
+        * Thus, as we expect, F(x) = 0 somewhere in between.  For the
+        * following algorithm to work, we need to know that F(x) is strictly
+        * decreasing (the slope is always negative).  The slope is
+        *      F'(x) = 12 x^2 - 6 b x - 4 a^2
+        * (the derivative).  It is a parabola opening upward and going through
+        * (0, -4a^2) and (b/2, -4a^2).  So it is always negative in this
+        * interval.
+        *
+        * The algorithm starts with lo = 0 and hi = b/2.  It draws a straight
+        * line between (lo, F(lo)) and (hi, F(hi)).  The point where this
+        * crosses the X axis we call "mid".  Based on whether F(mid) is
+        * positive or negative, we reset lo or hi to mid, and repeat the
+        * process until F(mid) is within b/1000 of the axis.  Then we will use
+        * mid as our y value in the picture.
+        */
+       a = ABSDIFF(first_p->x, last_p->x) / 2.0;
+       b = ABSDIFF(first_p->y, last_p->y);
+
+       midoff= solvecubic(4.0, -3.0*b, -4.0*a*a, a*a*b, 0.0, b/2.0, POINT/2.0);
+
+       mid_p = first_p->next;
+       mid_p->x = first_p->x + a;      /* horizontally halfway between */
+
+       /* handle the 4 cases, using the "mid" value for y in the diagram */
+       if (place == PL_ABOVE) {
+               if (first_p->y < last_p->y) {
+                       mid_p->y = last_p->y - midoff;
+               } else {
+                       mid_p->y = first_p->y - midoff;
+               }
+       } else {
+               if (first_p->y < last_p->y) {
+                       mid_p->y = first_p->y + midoff;
+               } else {
+                       mid_p->y = last_p->y + midoff;
+               }
+       }
+}
+\f
+
+/* do final refinements of curve.
+ * Remove any really tiny line segments.
+ * Then reset the group north or south boundaries to reflect
+ * the inclusion of the phrase mark.
+ */
+
+static void
+final_touches(mll_p, begin_gs_p, end_gs_p, curvelist_p, place)
+
+struct MAINLL *mll_p;                  /* points to first group in curve */
+struct GRPSYL *begin_gs_p;             /* first group in curve */
+struct GRPSYL *end_gs_p;               /* last group in curve */
+struct CRVLIST *curvelist_p;           /* the curve */
+int place;                             /* PL_ABOVE or PL_BELOW */
+
+{
+       int voice;      
+       int staff;
+       int index;      /* in coord array: RN or RS */
+       int adj_index;  /* in coord array: AN or AS. Used to store how much
+                        * to adjust for this phrase, in case there are
+                        * nested phrases. */
+       float y_c;      /* y of curve */
+       float x1, y1;   /* lengths of segments in each dimension */
+       float length;   /* of line segment */
+       struct CRVLIST *crvlist_p;
+       struct CRVLIST *extra_p;        /* pointer to point to be freed */
+       struct GRPSYL *gs_p;    /* index through groups */
+
+
+       if ( (mll_p == (struct MAINLL *) 0)
+                       || (begin_gs_p == (struct GRPSYL *) 0)
+                       || (end_gs_p == (struct GRPSYL *) 0)
+                       || (curvelist_p == (struct CRVLIST *) 0) ) {
+               pfatal("null pointer in final_touches()");
+       }
+
+       /* If there are really tiny line segments in a curve, the code for
+        * tapering the curve has problems because if the width of the curve
+        * is more than the length of the line and the angles work out just
+        * wrong, various warts, sometimes huge ones, appear on the curves.
+        * So go through the curve and if there are any really tiny lines,
+        * throw away one of the points and make the remaining point the
+        * average of what it was and what the discarded one was.
+        * With the new way of calculating curves, this is probably now
+        * unnecessary, but it seems safer to leave it in, just in case.
+        */
+       for (crvlist_p = curvelist_p; crvlist_p->next != (struct CRVLIST *) 0;
+                                               crvlist_p = crvlist_p->next) {
+               x1 = crvlist_p->next->x - crvlist_p->x;
+               y1 = crvlist_p->next->y - crvlist_p->y;
+               length = sqrt(SQUARED(x1) + SQUARED(y1));
+               if (length < 0.01) {
+                       /* replace with average */
+                       crvlist_p->x = (crvlist_p->x + crvlist_p->next->x)
+                                                               / 2.0;
+                       crvlist_p->y = (crvlist_p->y + crvlist_p->next->y)
+                                                               / 2.0;
+                       /* take the extra out of the list */
+                       extra_p = crvlist_p->next;
+                       if (crvlist_p->next->next != (struct CRVLIST *) 0) {
+                               crvlist_p->next->next->prev = crvlist_p;
+                       }
+                       crvlist_p->next = crvlist_p->next->next;
+                       if (crvlist_p->next == (struct CRVLIST *) 0) {
+                               /* avoid trying to take ->next of null ptr */
+                               break;
+                       }
+                       FREE(extra_p);
+               }
+       }
+
+       /* adjust north or south of each group within the curve to account for
+        * the space needed for the curve */
+       voice = begin_gs_p->vno;
+       staff = begin_gs_p->staffno;
+       if (place == PL_ABOVE) {
+               index = RN;
+               adj_index = AN;
+       }
+       else {
+               index = RS;
+               adj_index = AS;
+       }
+
+       for (gs_p = begin_gs_p;     ; gs_p = gs_p->next) {
+
+               /* if hit end of measure go to next measure, skipping over
+                * any empty measure (which could happen if vscheme changed
+                * from 2 to 1 and back in the middle of the phrase) */
+               while (gs_p == (struct GRPSYL *) 0) {
+                       mll_p = next_staff(staff, mll_p->next);
+                       if (mll_p == (struct MAINLL *) 0) {
+                               pfatal("fell off end of list while doing phrase marks");
+                       }
+                       gs_p = mll_p->u.staff_p->groups_p[voice - 1];
+               }
+
+               /* find where the curve y is at the x of the group, and
+                * adjust the north or south of the group appropriately,
+                * to be used later by any nesting phrase marks */
+               y_c = curve_y_at_x(curvelist_p, gs_p->c[AX]);
+
+               /* check for an inner tie. They don't affect the boundary */
+               if ( ((index == RN) && (y_c < gs_p->c[index])) ||
+                               ((index == RS) && (y_c > gs_p->c[index]))) {
+                       gs_p->c[adj_index] = 0.0;
+               }
+               else {
+                       if (place == PL_ABOVE) {
+                               gs_p->c[adj_index] = (y_c - gs_p->c[index]
+                                                               + Stepsize);
+                       }
+                       else {
+                               gs_p->c[adj_index] =  - (gs_p->c[index] - y_c
+                                                               + Stepsize);
+                       }
+               }
+
+               if (gs_p == end_gs_p) {
+                       /* On the last group on the phrase, this phrase
+                        * only affects the west side--another phrase can
+                        * start on this same group with considering this one */
+                       gs_p->phraseside |= WEST_SIDE;
+                       /* We are done with this curve */
+                       break;
+               }
+               else if (gs_p == begin_gs_p){
+                       /* Only affects east side of first group */
+                       gs_p->phraseside |= EAST_SIDE;
+               }
+               else {
+                       /* not of the end, so both side are relevant */
+                       gs_p->phraseside |= (EAST_SIDE | WEST_SIDE);
+               }
+       }
+}
+\f
+
+/* determine effective tuplet extension value. Normally, the tupext tells
+ * us how much room to leave to allow for the tuplet bracket. However,
+ * if the tuplet doesn't get a bracket, this can cause us to leave extra
+ * space. Unfortunately, we do still need to leave room for the tuplet
+ * number even if the bracket isn't there, and it's hard to know exactly
+ * where the number is going to be. So we do the best we can: if the
+ * group is the start or end of a tuplet and the tuplet does not get a
+ * bracket, we ignore the tupext on that group. If it's in the middle
+ * of a tuplet, we leave the tupext as is, because we can't tell for sure
+ * whether we'll need it to get out of the way of the tuplet number or not.
+ * But if this isn't a tuplet, or its bracket is on the opposite side
+ * as where we're trying to put a curve, then it doesn't count as all.
+ */
+
+static double
+eff_tupext(gs_p, staff_p, side)
+
+struct GRPSYL *gs_p;
+struct STAFF *staff_p;
+int side;              /* where the curve will be */
+
+{
+       /* if not a tuplet, return tupextend as is */
+       if (gs_p->tuploc == NOITEM) {
+               return(gs_p->tupextend);
+       }
+
+       /* if curve is on opposite side as tuplet bracket, ignore tupextend */
+       if (side != tupdir(gs_p, staff_p)) {
+               return(0.0);
+       }
+       /* if group passed in is first group in a tuplet,
+        * but the tuplet gets no bracket, ignore the tupextend */
+       if (gs_p->tuploc == STARTITEM) {
+               if (tupgetsbrack(gs_p) == NO) {
+                       return(0.0);
+               }
+       }
+
+       /* if group passed in is last group in a tuplet,
+        * but the tuplet gets no bracket, ignore the tupextend */
+       if (gs_p->tuploc == ENDITEM) {
+               /* first have to back up to find first group of tuplet,
+                * because that's what tupgetsbrack() wants */
+               do {
+                       gs_p = gs_p->prev;
+                       if (gs_p == (struct GRPSYL *) 0) {
+                               pfatal("can't find tuplet start in eff_tupext");
+                       }
+               } while (gs_p->tuploc != STARTITEM);
+
+               if (tupgetsbrack(gs_p) == NO) {
+                       return(0.0);
+               }
+       }
+
+       /* if no special case applies, just return tupextend as is */
+       return(gs_p->tupextend);
+}
+\f
+
+/* determine correct bend direction for curve, return UP or DOWN */
+
+static int
+bulge_direction(mll_p, gs1_p, note_index, curveno)
+
+struct MAINLL *mll_p;  /* main list struct pointing to gs1_p */
+struct GRPSYL *gs1_p;  /* curve will be from note in gs1_p to note in gs2_p */
+int note_index;                /* which note in first group to tie */
+int curveno;           /* index into slurto, or -1 for a tie */
+
+{
+       struct GRPSYL *gs_p;
+       RATIONAL vtime1, vtime2;        /* beginning and ending time of group */
+       int othervoice;                 /* array index of other voice */
+
+
+       /* If user explicitly set a bend direction, use that */
+       if (curveno == -1 && gs1_p->notelist[note_index].tiedir != UNKNOWN) {
+               return(gs1_p->notelist[note_index].tiedir);
+       }
+       else if (curveno >= 0 && gs1_p->notelist[note_index]
+                               .slurtolist[curveno].slurdir != UNKNOWN) {
+               return(gs1_p->notelist[note_index].slurtolist[curveno].slurdir);
+       }
+
+       /* If there are 2 voices on the staff, bend is toward the stem */
+       /* However, if the other voice is all spaces, pretend there is only
+        * one voice */
+       if ( (mll_p->u.staff_p->groups_p[0] != (struct GRPSYL *) 0)
+                               && (mll_p->u.staff_p->groups_p[1]
+                               != (struct GRPSYL *) 0) ) {
+
+               /* there are 2 voices */
+
+               /* calculate begin and end time of tied group */
+               vtime1 = Zero;
+               for (gs_p = mll_p->u.staff_p->groups_p[gs1_p->vno - 1];
+                                       gs_p != gs1_p; gs_p = gs_p->next) {
+                       vtime1 = radd(vtime1, gs_p->fulltime);
+               }
+
+               /* ending time is vtime1 plus the length of group 1. If group
+                * 1 is a grace note, use a very short time */
+               if (EQ(gs1_p->fulltime, Zero)) {
+                       RATIONAL tiny;
+
+                       tiny.n = 1;
+                       tiny.d = 4 * MAXBASICTIME;
+                       vtime2 = radd(vtime1, tiny);
+               }
+               else {
+                       vtime2 = radd(vtime1, gs1_p->fulltime);
+               }
+
+               /* get array index of other voice to check it */
+               othervoice = (gs1_p->vno == 1 ? 1 : 0);
+
+               if (hasspace(mll_p->u.staff_p->groups_p[othervoice],
+                                       vtime1, vtime2) == NO) {
+                       /* there IS another voice, so stem goes opposite */
+                       return(gs1_p->stemdir);
+               }
+       }
+
+       /* if only one voice (either because there is actually only one
+        * or because there is effectively only one since the other is space)
+        * and there is only one note in group, then bend is opposite stem */
+       if (gs1_p->nnotes < 2) {
+               /* quarter note grace groups are a special case, since they
+                * don't have a stem (they are for showing prebends). So we
+                * put the bend opposite the stem of the following group. */
+               if (gs1_p->grpvalue == GV_ZERO && gs1_p->basictime == 4 &&
+                               gs1_p->next != (struct GRPSYL *) 0) {
+                       return(gs1_p->next->stemdir == UP ? DOWN : UP);
+               }
+               return(gs1_p->stemdir == UP ? DOWN : UP);
+       }
+       
+       /* if one voice on staff with more than one note in the group, all
+        * bend opposite the stem except the top if the stem is up or the
+        * bottom if the stem is down */
+       if ( ((gs1_p->stemdir == DOWN) && (note_index == gs1_p->nnotes - 1))
+                       || ((gs1_p->stemdir == UP) && (note_index == 0)) ) {
+               return(gs1_p->stemdir);
+       }
+       else {
+               return(gs1_p->stemdir == UP ? DOWN : UP);
+       }
+}
diff --git a/mup/mup/plutils.c b/mup/mup/plutils.c
new file mode 100644 (file)
index 0000000..98f37fc
--- /dev/null
@@ -0,0 +1,2327 @@
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ * 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ * Name:       plutils.c
+ *
+ * Description:        This file contains utility functions belonging to the placement
+ *             phase.  Some of them are also used by other phases.
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+static int phrase_tieslur_note P((struct GRPSYL *gs_p, int nidx, int side,
+               int interfere));
+static int tied_to_nidx P((struct GRPSYL *gs_p, int nidx));
+static int slurred_to_nidx P((struct GRPSYL *gs_p, int nidx, int sidx));
+static RATIONAL lefttime P((double count, struct GRPSYL *firstgs_p,
+               int timeden));
+static RATIONAL righttime P((double count, struct GRPSYL *firstgs_p,
+               int timeden));
+
+/*
+ * Name:        nextnongrace()
+ *
+ * Abstract:    Return next nongrace group in a GRPSYL list.
+ *
+ * Returns:     pointer to GRPSYL of next nongrace group, 0 if none
+ *
+ * Description: This function loops down the GRPSYL linked list from the given
+ *             starting point.  It returns the next nongrace GRPSYL, or 0
+ *             if none.
+ */
+
+struct GRPSYL *
+nextnongrace(gs_p)
+
+struct GRPSYL *gs_p;   /* current group */
+
+{
+       gs_p = gs_p->next;
+       while (gs_p != 0 && gs_p->grpvalue == GV_ZERO)
+               gs_p = gs_p->next;
+       return (gs_p);
+}
+\f
+/*
+ * Name:        prevnongrace()
+ *
+ * Abstract:    Return previous nongrace group in a GRPSYL list.
+ *
+ * Returns:     pointer to GRPSYL of previous nongrace group, 0 if none
+ *
+ * Description: This function loop up the GRPSYL linked list from the given
+ *             starting point.  It returns the previous nongrace GRPSYL, or 0
+ *             if none.
+ */
+
+struct GRPSYL *
+prevnongrace(gs_p)
+
+struct GRPSYL *gs_p;   /* current group */
+
+{
+       gs_p = gs_p->prev;
+       while (gs_p != 0 && gs_p->grpvalue == GV_ZERO)
+               gs_p = gs_p->prev;
+       return (gs_p);
+}
+\f
+/*
+ * Name:        nextglobnongrace()
+ *
+ * Abstract:    Return next nongrace group in this voice.
+ *
+ * Returns:     pointer to GRPSYL of next nongrace group, 0 if none
+ *
+ * Description: This function, given a nongrace and the MLL structure it hangs
+ *             off of, returns the next nongrace in this voice, even if it's in
+ *             the next measure.  If it is in the next measure, *mll_p_p gets
+ *             updated.  But if that next measure is a second or later ending,
+ *             it's not considered to be a "next" measure, so return 0.
+ */
+
+struct GRPSYL *
+nextglobnongrace(gs_p, mll_p_p)
+
+struct GRPSYL *gs_p;           /* current group */
+struct MAINLL **mll_p_p;       /* MLL structure it is hanging off of */
+
+{
+       do {
+               gs_p = nextgrpsyl(gs_p, mll_p_p);
+       } while (gs_p != 0 && gs_p->grpvalue == GV_ZERO);
+       return (gs_p);
+}
+\f
+/*
+ * Name:        prevglobnongrace()
+ *
+ * Abstract:    Return previous nongrace group in this voice.
+ *
+ * Returns:     pointer to GRPSYL of previous nongrace group, 0 if none
+ *
+ * Description:        This function, given a nongrace and the MLL structure it hangs
+ *             off of, returns the prev nongrace in this voice, even if it's
+ *             in an earlier measure.  If we are at the start of an ending,
+ *             it skips over any previous ending and goes to the measure
+ *             preceding the first ending.  If the resulting nongrace is in a
+ *             previous measure, *mll_p_p gets updated.
+ */
+
+struct GRPSYL *
+prevglobnongrace(gs_p, mll_p_p)
+
+struct GRPSYL *gs_p;           /* current group */
+struct MAINLL **mll_p_p;       /* MLL structure it is hanging off of */
+
+{
+       do {
+               gs_p = prevgrpsyl(gs_p, mll_p_p);
+       } while (gs_p != 0 && gs_p->grpvalue == GV_ZERO);
+       return (gs_p);
+}
+\f
+/*
+ * Name:        drmo()
+ *
+ * Abstract:    Detect rightmost one.
+ *
+ * Returns:     void
+ *
+ * Description: This function returns the bit position of the rightmost bit
+ *             that is a 1 in the given number, the low order bit being
+ *             bit 0.  The given number must not be 0.
+ */
+
+int
+drmo(num)
+
+register int num;
+
+{
+       register int n;
+
+       for (n = 0; n < 8 * sizeof(int); n++) {
+               if ( (num & (1 << n)) != 0 )
+                       return (n);
+       }
+       pfatal("0 was passed to drmo");
+       return (0);     /* dead code, but keeps lint happy */
+}
+\f
+/*
+ * Name:        tieslurpad()
+ *
+ * Abstract:    How much tie/slur padding is needed after this group?
+ *
+ * Returns:     Padding in inches.
+ *
+ * Description: This function returns the amount of padding needed after a
+ *             group due to ties or slurs, if the given group is tied to the
+ *             next group, or any note in it is tied or slurred to a note
+ *             in the following group.  Otherwise it returns zero.
+ *             NOTE:  This function ignores staffscale.
+ */
+
+double
+tieslurpad(staff_p, gs_p)
+
+struct STAFF *staff_p;         /* the staff the group is connected to */
+struct GRPSYL *gs_p;           /* the group after which padding may occur */
+
+{
+       struct NOTE *note_p;    /* point at a note structure */
+       struct GRPSYL *gtemp_p; /* temp GRPSYL pointer */
+       struct GRPSYL *this_p;  /* first GRPSYL in this voice */
+       struct GRPSYL *that_p;  /* first GRPSYL in other voice */
+       RATIONAL starttime;     /* time into measure where *gs_p starts */
+       float pad;              /* how much padding is needed */
+       int interfere;          /* does other voice have notes/rests here? */
+       int stepdiff;           /* vertical reach of a curve */
+       int n;                  /* index into notes in group */
+       int s;                  /* index into notes slurred to */
+
+
+       /* syllables can't have ties or slurs */
+       if (gs_p->grpsyl != GS_GROUP)
+               return (0);
+
+       /* rests and spaces can't have ties or slurs */
+       if (gs_p->grpcont != GC_NOTES)
+               return (0);
+
+       /* if last group in measure, don't need any more space */
+       if (gs_p->next == 0)
+               return (0);
+
+       /*
+        * Find the first group in this measure, and total time preceding the
+        * group we were given.  We need this to figure out which voice we are
+        * in, and, if there is another voice, whether it has only spaces
+        * during the time of our group, which affects how the curves should
+        * look.
+        */
+       starttime = Zero;
+       for (gtemp_p = gs_p->prev, this_p = gs_p; gtemp_p != 0;
+                       this_p = gtemp_p, gtemp_p = gtemp_p->prev)
+               starttime = radd(starttime, gtemp_p->fulltime);
+
+       /* point at other voice, or null pointer if none */
+       if (staff_p->groups_p[0] == this_p)
+               that_p = staff_p->groups_p[1];  /* might be 0 */
+       else if (staff_p->groups_p[1] == this_p)
+               that_p = staff_p->groups_p[0];  /* might be 0 */
+       else
+               that_p = 0;     /* we are voice 3, ignore other voices */
+
+       if (that_p == 0 || hasspace(that_p, starttime,
+                               radd(starttime, gs_p->fulltime)))
+               interfere = NO;
+       else
+               interfere = YES;
+
+       pad = 0;                /* start with no padding */
+
+       /*
+        * Loop through every note in this group.  If it's tied, check each
+        * note to see if either it or the note it's tied to is ineligible for
+        * phrase-like curves.  If so, there will be a horizontally aligned
+        * curve, and we need to pad.  The note must be the same in both
+        * groups, so there's no need to consider vertical distances at this
+        * point.  Then loop through the 0 or more slurs from this note to
+        * note(s) in the next group.  For each one, find the vertical distance
+        * between the two notes.  The padding it needs is based on this and on
+        * whether phrase-like curves can be drawn.  Keep track of the maximum
+        * padding needed by any pair of notes.
+        * We also need to pad if the stems are UP-DOWN, because that leaves no
+        * room for the curve.
+        */
+       for (n = 0; n < gs_p->nnotes; n++) {
+               note_p = &gs_p->notelist[n];
+               if (note_p->tie == YES) {
+                       if (gs_p->stemdir == UP && gs_p->next->stemdir == DOWN
+                       || phrase_tieslur_note(gs_p, n, STARTITEM, interfere)
+                       == NO || phrase_tieslur_note(gs_p->next, tied_to_nidx(
+                       gs_p, n), ENDITEM, interfere) == NO)
+                               pad = MAX(pad, TIESLURPAD);
+               }
+               for (s = 0; s < note_p->nslurto; s++) {
+                       /*
+                        * If it's a slur to/from nowhere, don't deal with it
+                        * here.  It is considered along with the width of the
+                        * individual note.
+                        */
+                       if (IS_NOWHERE(note_p->slurtolist[s].octave))
+                               continue;       /* from nowhere */
+
+                       stepdiff = abs(
+                                       ( note_p->octave * 7 +
+                                       Letshift[ note_p->letter - 'a' ] ) -
+                                       ( note_p->slurtolist[s].octave * 7 +
+                                       Letshift[ note_p->slurtolist[s].letter
+                                               - 'a' ] )
+                                       );
+                       if (gs_p->stemdir == UP && gs_p->next->stemdir == DOWN
+                       || phrase_tieslur_note(gs_p, n, STARTITEM, interfere)
+                       == NO || phrase_tieslur_note(gs_p->next,
+                       slurred_to_nidx(gs_p, n, s), ENDITEM, interfere) == NO){
+                               pad = MAX(pad, stepdiff <= 3 ? TIESLURPAD :
+                               TIESLURPAD + (stepdiff - 3) * STEPSIZE / 2);
+                       } else {
+                               pad = MAX(pad, stepdiff <= 3 ? 0 :
+                               (stepdiff - 3) * STEPSIZE / 2);
+                       }
+               }
+       }
+
+       return (pad);           /* max padding needed by any pair of notes */
+}
+\f
+/*
+ * Name:        phrase_tieslur_note()
+ *
+ * Abstract:    Is the given note the end note and eligible for "new" tie/slur?
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function determines whether a tie or slur to/from the
+ *             given note is to be drawn like a phrase mark (as opposed to
+ *             drawing it vertically aligned with the note).
+ */
+
+static int
+phrase_tieslur_note(gs_p, nidx, side, interfere)
+
+struct GRPSYL *gs_p;           /* point at note's group */
+int nidx;                      /* index to this note in notelist */
+int side;                      /* STARTITEM (curve here to right) or ENDITEM */
+int interfere;                 /* does the other voice have notes/rests here?*/
+
+{
+       /* check for each bad condition, returning NO if it exists */
+
+       /* inner note of a group */
+       if (nidx != 0 && nidx != gs_p->nnotes - 1)
+               return (NO);
+
+       /* bottom note of voice 1 and other voice interferes */
+       if (gs_p->vno == 1 && nidx == gs_p->nnotes - 1 && interfere)
+               return (NO);
+
+       /* top note of voice 2 and other voice interferes */
+       if (gs_p->vno == 2 && nidx == 0 && interfere)
+               return (NO);
+
+       /* antistem note if "with" list is present */
+       /*  (don't need to check normwith; if it weren't YES we would have */
+       /*  returned above) */
+       if (gs_p->nwith != 0 && gs_p->stemdir == UP && nidx == gs_p->nnotes - 1)
+               return (NO);
+
+       /* antistem note if "with" list is present */
+       /*  (don't need to check normwith; if it weren't YES we would have */
+       /*  returned above) */
+       if (gs_p->nwith != 0 && gs_p->stemdir == DOWN && nidx == 0)
+               return (NO);
+
+       /* stem in the way of left end of curve */
+       if (side == STARTITEM && gs_p->basictime >= 2 && gs_p->stemdir == UP &&
+                       nidx == 0 && gs_p->nnotes > 1)
+               return (NO);
+
+       /* stem in the way of right end of curve */
+       if (side == ENDITEM && gs_p->basictime >= 2 && gs_p->stemdir == DOWN &&
+                       nidx == gs_p->nnotes - 1 && gs_p->nnotes > 1)
+               return (NO);
+
+       return (YES);
+}
+\f
+/*
+ * Name:        tied_to_nidx()
+ *
+ * Abstract:    Return the note index of the note the given note is tied to.
+ *
+ * Returns:     index into gs_p->next->notelist
+ *
+ * Description: This function is given a valid group (not the last one in the
+ *             measure) and an index into its notelist to a note that is tied
+ *             to the next group.  It returns the index into the next group's
+ *             notelist to the note that the first group's note is tied to.
+ */
+
+static int
+tied_to_nidx(gs_p, nidx)
+
+struct GRPSYL *gs_p;           /* point at note's group */
+int nidx;                      /* index to this note in notelist */
+
+{
+       struct NOTE *nl_ptr;    /* ptr to next group's notelist */
+       int n;
+
+
+       nl_ptr = gs_p->next->notelist;
+
+       for (n = 0; n < gs_p->next->nnotes; n++) {
+               if (gs_p->notelist[nidx].letter == nl_ptr[n].letter &&
+                   gs_p->notelist[nidx].octave == nl_ptr[n].octave)
+                       return (n);
+       }
+
+       pfatal("tied_to_nidx: can't find note tied to");
+       return (0);             /* to keep lint happy */
+}
+\f
+/*
+ * Name:        slurred_to_nidx()
+ *
+ * Abstract:    Return the note index of the note the given note is slurred to.
+ *
+ * Returns:     index into gs_p->next->notelist
+ *
+ * Description: This function is given a valid group (not the last one in the
+ *             measure) and an index into its notelist to a note that is tied
+ *             to the next group.  It returns the index into the next group's
+ *             notelist to the note that the first group's note is tied to.
+ */
+
+static int
+slurred_to_nidx(gs_p, nidx, sidx)
+
+struct GRPSYL *gs_p;           /* point at note's group */
+int nidx;                      /* index to this note in notelist */
+int sidx;                      /* index to slurred to note in slurto list */
+
+{
+       struct NOTE *nl_ptr;    /* ptr to next group's notelist */
+       int n;
+
+
+       nl_ptr = gs_p->next->notelist;
+
+       for (n = 0; n < gs_p->next->nnotes; n++) {
+               if (gs_p->notelist[nidx].slurtolist[sidx].letter ==
+                                       nl_ptr[n].letter &&
+                   gs_p->notelist[nidx].slurtolist[sidx].octave ==
+                                       nl_ptr[n].octave)
+                       return (n);
+       }
+
+       pfatal("slurred_to_nidx: can't find note slurred to");
+       return (0);             /* to keep lint happy */
+}
+\f
+/*
+ * Name:        hasspace()
+ *
+ * Abstract:    Finds out if the given voice has space during given time.
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function is given a linked list of groups to check
+ *             during a given time interval.  If the list consists entirely
+ *             of space(s) during the time interval, the function returns
+ *             YES.  Otherwise it returns NO.  If vtime2 is greater than the
+ *             length of a measure, the extra, nonexistent time is regarded
+ *             as all spaces.  If the linked list of groups doesn't exist
+ *             (gs_p is a null pointer), the function returns YES, since
+ *             there is nothing there but "space".
+ */
+
+int
+hasspace(gs_p, vtime, vtime2)
+
+register struct GRPSYL *gs_p;  /* starts pointing at the first GRPSYL list */
+RATIONAL vtime, vtime2;        /* time when to start and stop checking for space */
+
+{
+       RATIONAL t;             /* accumulate time */
+       int oldcont;            /* content of previous group */
+
+
+       /* "no linked list exists" counts as all spaces */
+       if (gs_p == 0)
+               return (YES);
+
+       oldcont = GC_SPACE;     /* prevent useless 'used before set' warning */
+
+       /* accumulate time until crossing vtime boundary */
+       for (t = Zero; LT(t, vtime); gs_p = gs_p->next) {
+               if (gs_p->grpvalue == GV_ZERO)
+                       continue;
+               t = radd(t, gs_p->fulltime);
+               oldcont = gs_p->grpcont;
+       }
+
+       if (GT(t, vtime) && oldcont != GC_SPACE)
+               return (NO);
+
+       for ( ; gs_p != 0 && LT(t, vtime2); gs_p = gs_p->next) {
+               if (gs_p->grpvalue == GV_ZERO)
+                       continue;
+               if (gs_p->grpcont != GC_SPACE)
+                       return (NO);
+               t = radd(t, gs_p->fulltime);
+       }
+
+       return (YES);
+}
+\f
+/*
+ * Name:        closestgroup()
+ *
+ * Abstract:    Find closest nongrace group in this voice to given time value.
+ *
+ * Returns:     pointer to the closest nongrace GRPSYL
+ *
+ * Description: This function finds the GRPSYL in the given linked list that is
+ *             closest, timewise, to the given count number, ignoring grace
+ *             groups.
+ */
+
+struct GRPSYL *
+closestgroup(count, firstgs_p, timeden)
+
+double count;                  /* which count of the measure */
+struct GRPSYL *firstgs_p;      /* first GRPSYL of relevant voice in measure */
+int timeden;                   /* denominator of current time signature */
+
+{
+       RATIONAL reqtime;       /* time requested */
+       RATIONAL tottime;       /* total time in measure so far */
+       RATIONAL otottime;      /* old total time in measure so far */
+       struct GRPSYL *gs_p;    /* point along group list */
+       struct GRPSYL *ogs_p;   /* (old) point along group list */
+
+
+       /* skip over any initial grace groups */
+       if (firstgs_p->grpvalue == GV_ZERO)
+               firstgs_p = nextnongrace(firstgs_p);
+
+       /* if at or before the first count, it's closest to first group */
+       if (count <= 1)
+               return (firstgs_p);
+
+       /* get requested time to nearest tiny part of a count, in lowest terms*/
+       reqtime.n = 4 * MAXBASICTIME * (count - 1) + 0.5;
+       reqtime.d = 4 * MAXBASICTIME * timeden;
+       rred(&reqtime);
+
+       /*
+        * Loop through this voice accumulating time values.  As soon as we
+        * equal or exceed the requested time value, check whether the
+        * requested time is closer to the new accumulated time, or that before
+        * this last group.  Return the closest one.
+        */
+       tottime = Zero;
+       for (ogs_p = firstgs_p, gs_p = nextnongrace(ogs_p); gs_p != 0;
+                               ogs_p = gs_p, gs_p = nextnongrace(gs_p)) {
+               otottime = tottime;
+               tottime = radd(tottime, ogs_p->fulltime);
+               if (GE(tottime, reqtime)) {
+                       if (GT( rsub(reqtime,otottime), rsub(tottime,reqtime) ))
+                               return (gs_p);
+                       else
+                               return (ogs_p);
+               }
+       }
+
+       /* requested time is after last group; return last group */
+       return (ogs_p);
+}
+\f
+/*
+ * Name:        chkallspace()
+ *
+ * Abstract:    Check if voice is all spaces for the voice this stuff is on.
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function checks where one voice seems to be all spaces
+ *             during the duration of a phrase mark, or other stuff which must
+ *             be associated with a definite group.  The tricky thing is that
+ *             until we've decided which voice the stuff is intended to
+ *             apply to, we don't exactly know what the endpoints of the
+ *             stuff are going to be.  All we know is the "count" values the
+ *             user asked for, which may or may not equal the positions of
+ *             GRPSYLs in the voices.  So we look at voices 1 and 2 and take
+ *             the worst (widest) case as the endpoints.  (This is called only
+ *             when both of these voices exist.  We ignore any voice 3.)
+ */
+
+int
+chkallspace(msbeg_p, stuff_p, vno)
+
+struct MAINLL *msbeg_p;        /* staff at beginning of the stuff */
+struct STUFF *stuff_p; /* the STUFF */
+int vno;               /* voice being tested for being all spaces */
+
+{
+       static RATIONAL tiny = {1, 4 * MAXBASICTIME};
+       struct MAINLL *msend_p;         /* staff at end of the phrase */
+       int timeden;                    /* denom of time sig at end of stuff */
+       RATIONAL begtime, endtime;      /* time into measures of begin & end */
+       RATIONAL temptime;              /* temp var for storing time */
+
+
+       /*
+        * Find what measure this stuff ends in.  Along the way, keep
+        * track of the time signature denominator, in case it changes.
+        */
+       msend_p = getendstuff(msbeg_p, stuff_p, &timeden);
+
+       /*
+        * If we hit a multirest, bail out, arbitrarily returning NO.  This
+        * stuff will be thrown away later anyway.
+        */
+       if (msend_p == 0)
+               return (NO);
+
+       /*
+        * If the second voice doesn't exist (because vscheme changed),
+        * it's like all spaces in that voice.  So if we're asking about that
+        * voice, return YES.  If asking about the first voice, return NO.
+        */
+       if (msend_p->u.staff_p->groups_p[1] == NULL) {
+               return (vno == 1 ? YES : NO);
+       }
+
+       /*
+        * Find time values that are sure to contain the stuff.  Take the
+        * outermost values of the two voices.
+        */
+       begtime = lefttime(stuff_p->start.count,
+                               msbeg_p->u.staff_p->groups_p[0], Score.timeden);
+       temptime = lefttime(stuff_p->start.count,
+                               msbeg_p->u.staff_p->groups_p[1], Score.timeden);
+       if (LT(temptime, begtime))
+               begtime = temptime;
+       endtime = righttime(stuff_p->end.count,
+                               msend_p->u.staff_p->groups_p[0], timeden);
+       temptime = righttime(stuff_p->end.count,
+                               msend_p->u.staff_p->groups_p[1], timeden);
+       if (GT(temptime, endtime))
+               endtime = temptime;
+
+       /*
+        * If the beginning and end are in the same measure and at the same
+        * time, this phrase would normally be thrown away later, but we need
+        * to deal with it because the case of a phrase from a grace to its
+        * main note.  It doesn't make sense to ask what a zero time contains,
+        * so to handle this, add a tiny time value to the end time.
+        */
+       if (msbeg_p == msend_p && EQ(begtime, endtime))
+               endtime = radd(endtime, tiny);
+
+       return (allspace(vno, msbeg_p, begtime, msend_p, endtime));
+}
+\f
+/*
+ * Name:        allspace()
+ *
+ * Abstract:    Finds out if the given voice has space for the given time.
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function is a multi-measure version of hasspace(), and in
+ *             fact works by calling hasspace() repeatedly.  It is given the
+ *             linked list of groups for the voice in the first measure in
+ *             question.  It checks whether the voice consists entirely of
+ *             spaces from the duration point given for this first measure,
+ *             until the endpoint, which may or may not be in the same measure.
+ */
+
+int
+allspace(vno, msbeg_p, begtime, msend_p, endtime)
+
+int vno;               /* voice number, numbering from voice 1 == 0 */
+struct MAINLL *msbeg_p;        /* point at MLL (staff) where duration begins */
+RATIONAL begtime;      /* time where duration begins */
+struct MAINLL *msend_p;        /* point at MLL (staff) where duration ends */
+RATIONAL endtime;      /* time where duration ends */
+
+{
+       struct MAINLL *mainll_p;                /* point along MLL */
+       int staffno;
+
+
+       /* if the time starts and ends in the same measure, let hasspace do it*/
+       if (msbeg_p == msend_p) {
+               return (hasspace(msbeg_p->u.staff_p->groups_p[vno],
+                               begtime, endtime));
+       }
+
+       /*
+        * If the first measure contains non-spaces, return NO.  Rather than
+        * keeping track of time signatures, we're going to pretend that we
+        * are in the longest possible time.  This relies on the fact that
+        * hasspace() in effect assumes that any phony time past the end of
+        * the actual measure is spaces.
+        */
+       if (hasspace(msbeg_p->u.staff_p->groups_p[vno], begtime, Maxtime) == NO)
+               return (NO);
+
+       staffno = msbeg_p->u.staff_p->staffno;
+
+       /* if any intermediate measures contain non-spaces, return NO */
+       for (mainll_p = msbeg_p->next; mainll_p != 0 && mainll_p != msend_p;
+                       mainll_p = mainll_p->next) {
+
+               /* skip everything but STAFFs for our staff number */
+               if (mainll_p->str != S_STAFF ||
+                               mainll_p->u.staff_p->staffno != staffno)
+                       continue;
+
+               if (hasspace(mainll_p->u.staff_p->groups_p[vno], Zero, Maxtime)
+                               == NO)
+                       return (NO);
+       }
+
+       if (mainll_p == 0)
+               pfatal("bug found in allspace");
+
+       /* the result is now determined by the last measure */
+       return (hasspace(msend_p->u.staff_p->groups_p[vno], Zero, endtime));
+}
+\f
+/*
+ * Name:        getendstuff()
+ *
+ * Abstract:    Find staff and time signature denominator for end of a stuff.
+ *
+ * Returns:     pointer to MLL structure for staff containing end of stuff, or 0
+ *
+ * Description: This function finds the staff for the end of the given stuff.
+ *             As a byproduct, it also finds the denominator of the time
+ *             signature at that place.  If a multirest is encountered, a null
+ *             pointer is returned, and timeden is not guaranteed.
+ *             If the end of the piece is encountered, it returns the last
+ *             staff.
+ */
+
+struct MAINLL *
+getendstuff(mainll_p, stuff_p, timeden_p)
+
+struct MAINLL *mainll_p;/* staff at beginning of stuff, gets changed to end */
+struct STUFF *stuff_p; /* the STUFF */
+int *timeden_p;                /* gets set to denom of time sig at end of stuff */
+
+{
+       int staffno;            /* staff number where stuff is */
+       struct MAINLL *mst_p;   /* point at the last staffno staff seen */
+       int timenum;            /* remember the last time sig numerator */
+       int b;                  /* count bar lines */
+
+
+       /* bail out if multirest */
+       if (mainll_p->u.staff_p->groups_p[0]->basictime < -1)
+               return (0);
+
+       timenum = Score.timenum;        /* init to current time sig numerator*/
+       *timeden_p = Score.timeden;     /* init to current time sig denom */
+
+       /* if stuff doesn't cross any bar lines, we can return right away */
+       if (stuff_p->end.bars == 0)
+               return (mainll_p);
+
+       mst_p = mainll_p;       /* remember last staff of this number */
+
+       staffno = mainll_p->u.staff_p->staffno;
+
+       /*
+        * Count past the right number of  bar lines, keeping the time sig
+        * denominator up to date.
+        */
+       for (b = 0; b < stuff_p->end.bars; b++) {
+               for (mainll_p = mainll_p->next;
+                               mainll_p != 0 && mainll_p->str != S_BAR;
+                               mainll_p = mainll_p->next) {
+
+                       if (mainll_p->str == S_SSV &&
+                                   mainll_p->u.ssv_p->used[TIME] == YES) {
+                               timenum = mainll_p->u.ssv_p->timenum;
+                               *timeden_p = mainll_p->u.ssv_p->timeden;
+                       }
+
+                       /* bail out if multirest encountered */
+                       if (mainll_p->str == S_STAFF && mainll_p->u.staff_p->
+                                               groups_p[0]->basictime < -1)
+                               return (0);
+
+                       /* remember last staff of this number */
+                       if (mainll_p->str == S_STAFF && mainll_p->u.staff_p->
+                                               staffno == staffno)
+                               mst_p = mainll_p;
+               }
+               /* if end of song, set to last bar line and return this staff*/
+               if (mainll_p == 0) {
+                       stuff_p->end.count = timenum + 1;
+                       return (mst_p);
+               }
+       }
+
+       /*
+        * mainll_p points at the bar line preceding the place where the stuff
+        * ends.  Continue forward to find the correct STAFF.
+        */
+       for (mainll_p = mainll_p->next ;
+                       mainll_p != 0 && mainll_p->str != S_BAR;
+                       mainll_p = mainll_p->next) {
+
+               if (mainll_p->str == S_SSV &&
+                               mainll_p->u.ssv_p->used[TIME] == YES)
+                       *timeden_p = mainll_p->u.ssv_p->timeden;
+
+               if (mainll_p->str == S_STAFF &&
+                               mainll_p->u.staff_p->staffno == staffno)
+                       break;
+       }
+
+       /* if end of song, set to last bar line and return this staff */
+       if (mainll_p == 0) {
+               stuff_p->end.count = timenum + 1;
+               return (mst_p); /* hit end of song, return last meas */
+       }
+       if (mainll_p->str == S_BAR)
+               pfatal("stuff crosses FEED where number of staffs changes");
+       if (mainll_p->u.staff_p->groups_p[0]->basictime < -1)
+               return (0);
+
+       return (mainll_p);
+}
+\f
+/*
+ * Name:        lefttime()
+ *
+ * Abstract:    Find time value of the nongrace group left of the given count.
+ *
+ * Returns:     time value into measure
+ *
+ * Description: This function finds the nongrace GRPSYL in the given linked
+ *             list that is at or left of the given count number.  If the
+ *             count is less 1, we return time zero, even though technically
+ *             time zero is to the right of the given count number.
+ */
+
+static RATIONAL
+lefttime(count, firstgs_p, timeden)
+
+double count;                  /* which count of the measure */
+struct GRPSYL *firstgs_p;      /* first GRPSYL of relevant voice in measure */
+int timeden;                   /* denominator of current time signature */
+
+{
+       RATIONAL reqtime;       /* time requested */
+       RATIONAL tottime;       /* total time in measure so far */
+       RATIONAL otottime;      /* old total time in measure so far */
+       struct GRPSYL *gs_p;    /* point along group list */
+       struct GRPSYL *ogs_p;   /* (old) point along group list */
+
+
+       /* skip over any initial grace groups */
+       if (firstgs_p->grpvalue == GV_ZERO)
+               firstgs_p = nextnongrace(firstgs_p);
+
+       /* if at or before the first count, have to use first group */
+       if (count <= 1)
+               return (Zero);
+
+       /*
+        * Get requested time to the nearest half of the smallest fraction of a
+        * count that a user can specify, +1, in lowest terms.  The +1 is so
+        * that if the user isn't too accurate, we still land on the intended
+        * group.
+        */
+       reqtime.n = 2 * MAXBASICTIME * (count - 1) + 0.5 + 1.0;
+       reqtime.d = 2 * MAXBASICTIME * timeden;
+       rred(&reqtime);
+
+       /*
+        * Loop through this voice accumulating time values.  As soon as we
+        * equal or exceed the requested time value, return the previous
+        * group's time.
+        */
+       otottime = tottime = Zero;
+       for (ogs_p = firstgs_p, gs_p = nextnongrace(ogs_p); gs_p != 0;
+                               ogs_p = gs_p, gs_p = nextnongrace(gs_p)) {
+               otottime = tottime;
+               tottime = radd(tottime, ogs_p->fulltime);
+               if (GE(tottime, reqtime))
+                       return (otottime);
+       }
+
+       /* requested time is after last group; return time of last group */
+       return (otottime);
+}
+\f
+/*
+ * Name:        righttime()
+ *
+ * Abstract:    Find time value of the nongrace group right of the given count.
+ *
+ * Returns:     time value into measure
+ *
+ * Description: This function finds the nongrace GRPSYL in the given linked
+ *             list that is at or right of the given count number.  If the
+ *             count is greater then the rightmost group in the measure, we
+ *             return the time up to the rightmost group, even though
+ *             technically that time is to the left of the given count number.
+ */
+
+static RATIONAL
+righttime(count, firstgs_p, timeden)
+
+double count;                  /* which count of the measure */
+struct GRPSYL *firstgs_p;      /* first GRPSYL of relevant voice in measure */
+int timeden;                   /* denominator of current time signature */
+
+{
+       RATIONAL reqtime;       /* time requested */
+       RATIONAL tottime;       /* total time in measure so far */
+       struct GRPSYL *gs_p;    /* point along group list */
+       struct GRPSYL *ogs_p;   /* (old) point along group list */
+
+
+       /* skip over any initial grace groups */
+       if (firstgs_p->grpvalue == GV_ZERO)
+               firstgs_p = nextnongrace(firstgs_p);
+
+       /* if at or before the first count, use first group */
+       if (count <= 1)
+               return (Zero);
+
+       /*
+        * Get requested time to the nearest half of the smallest fraction of a
+        * count that a user can specify, -1, in lowest terms.  The -1 is so
+        * that if the user isn't too accurate, we still land on the intended
+        * group.
+        */
+       reqtime.n = 2 * MAXBASICTIME * (count - 1) + 0.5 - 1.0;
+       reqtime.d = 2 * MAXBASICTIME * timeden;
+       rred(&reqtime);
+
+       /*
+        * Loop through this voice accumulating time values.  As soon as we
+        * equal or exceed the requested time value, return that new time,
+        * although don't go beyond the last group's time value.
+        */
+       tottime = Zero;
+       for (ogs_p = firstgs_p, gs_p = nextnongrace(ogs_p); gs_p != 0;
+                               ogs_p = gs_p, gs_p = nextnongrace(gs_p)) {
+               tottime = radd(tottime, ogs_p->fulltime);
+               if (GE(tottime, reqtime))
+                       return (tottime);
+       }
+
+       /* requested time is after last group; but must return last group */
+       return (tottime);
+}
+\f
+/*
+ * Name:        accdimen()
+ *
+ * Abstract:    Find the dimensions of a note's accidental.
+ *
+ * Returns:     void
+ *
+ * Description: This function finds the ascent, descent, and width of an
+ *             accidental, and returns them through pointers.  If a pointer
+ *             is null, it doesn't try to fill it in.  An accidental char of
+ *             '\0' gives zero for each dimension.  The function takes into
+ *             account whether the accidental is normal or small size, and
+ *             whether it has parentheses around it.
+ *             NOTE:  This function ignores staffscale.
+ */
+
+void
+accdimen(note_p, ascent_p, descent_p, width_p)
+
+struct NOTE *note_p;           /* the note whose accidental we're working on*/
+float *ascent_p;               /* ascent, to be filled in */
+float *descent_p;              /* descent, to be filled in */
+float *width_p;                        /* width, to be filled in */
+
+{
+       char accchar;           /* accidental character number */
+       int size;               /* which size of character */
+       float halfhigh;         /* half the height of a parenthesis */
+
+
+       if (note_p->accidental == '\0') {
+               if (ascent_p != 0) {
+                       *ascent_p  = 0.0;
+               }
+               if (descent_p != 0) {
+                       *descent_p = 0.0;
+               }
+               if (width_p != 0) {
+                       *width_p   = 0.0;
+               }
+               return;
+       }
+
+       /* find character name and size of this accidental */
+       accchar = acc2char(note_p->accidental);
+       size = (note_p->notesize == GS_NORMAL ? DFLT_SIZE : SMALLSIZE);
+
+       /* get the requested dimensions of this accidental */
+       if (ascent_p != 0) {
+               *ascent_p  =  ascent(FONT_MUSIC, size, accchar);
+       }
+       if (descent_p != 0) {
+               *descent_p = descent(FONT_MUSIC, size, accchar);
+       }
+       if (width_p != 0) {
+               *width_p   =   width(FONT_MUSIC, size, accchar);
+       }
+
+       /*
+        * If it has parentheses around it, account for that.  Assume the left
+        * and right parens are symmetrical.  They will be centered on the line
+        * or space of the note.
+        */
+       if (note_p->acc_has_paren) {
+               if (width_p != 0) {
+                       *width_p += 2 * width(FONT_TR, size, '(');
+               }
+               halfhigh = height(FONT_TR, size, '(') / 2.0;
+               if (ascent_p != 0 && halfhigh > *ascent_p) {
+                       *ascent_p = halfhigh;
+               }
+               if (descent_p != 0 && halfhigh > *descent_p) {
+                       *descent_p = halfhigh;
+               }
+       }
+}
+\f
+/*
+ * Name:        staffvertspace()
+ *
+ * Abstract:    Find the minimum amount of vertical space a staff should have.
+ *
+ * Returns:     the amount of vertical distance in inches
+ *
+ * Description: This function finds the minimum amount of vertical space that
+ *             should be allocated for a staff, based on how many lines it has
+ *             and whether it is tablature.  This does not take into account
+ *             the extra space required by things sticking out farther; it's
+ *             just for the staff itself, plus the extra white space required
+ *             by staffs that have few lines.  The SSVs must be up to date.
+ *             NOTE:  This function takes staffscale into account.
+ */
+
+double
+staffvertspace(s)
+
+int s;                         /* staff number */
+
+{
+       float space;            /* the answer */
+
+
+       /*
+        * Base space on number of steps between top and bottom lines.  But for
+        * tablature, it must be scaled because the lines are farther apart.
+        */
+       space = (svpath(s, STAFFLINES)->stafflines - 1) * 2 * STEPSIZE;
+       if (is_tab_staff(s))
+               space *= TABRATIO;
+
+       /* but don't ever return less than a (scaled) regular 5 line staff */
+       return (svpath(s, STAFFSCALE)->staffscale * MAX(space, 8.0 * STEPSIZE));
+}
+\f
+/*
+ * Name:        halfstaffhi()
+ *
+ * Abstract:    Find half of the staff height.
+ *
+ * Returns:     half the staff height in inches
+ *
+ * Description: This function finds half of the staff's height, based on how
+ *             many lines it has and whether it is tablature.  This does not
+ *             take into account the extra space required by things sticking
+ *             out farther; it's just for the staff itself, except that one
+ *             line staffs are given a minimum instead of the zero you would
+ *             expect.  The SSVs must be up to date.
+ *             NOTE:  This function takes staffscale into account.
+ */
+
+double
+halfstaffhi(s)
+
+int s;                         /* staff number */
+
+{
+       float space;            /* the answer */
+
+
+       /*
+        * Base space on the number of steps between the top line and the
+        * middle of the staff.  But for tablature, it must be scaled because
+        * the lines are farther apart.
+        */
+       space = (svpath(s, STAFFLINES)->stafflines - 1) * STEPSIZE;
+       if (is_tab_staff(s))
+               space *= TABRATIO;
+
+       /* but don't ever return less than one (scaled) stepsize */
+       return (MAX(space, STEPSIZE) * svpath(s, STAFFSCALE)->staffscale);
+}
+\f
+/*
+ * Name:        ratbend()
+ *
+ * Abstract:    Convert a bend distance to rational.
+ *
+ * Returns:     the rational number answer; 0/1 if null bend or no bend
+ *
+ * Description: This function, given a NOTE structure from a tab staff, returns
+ *             the amount of the bend (if any) as a rational number.
+ */
+
+RATIONAL
+ratbend(note_p)
+
+struct NOTE *note_p;
+
+{
+       RATIONAL answer;
+
+
+       if (note_p->BEND == 0)
+               return (Zero);
+
+       answer.d = BENDDEN(*note_p);
+       answer.n = BENDNUM(*note_p) + BENDINT(*note_p) * answer.d;
+       rred(&answer);
+
+       return (answer);
+}
+\f
+/*
+ * Name:        notehorz()
+ *
+ * Abstract:    Find horizontal boundary of note and associated things.
+ *
+ * Returns:     the RE or RW
+ *
+ * Description: This function finds the horizontal boundary of a note,
+ *             including accidentals, dots, etc., all the things that can be
+ *             on the note.  The note's own RE and RW only tell about the note
+ *             head itself.
+ *             NOTE:  This function takes staffscale into account.  The SSVs
+ *             need not be up to date, but Staffscale and Stdpad must be set.
+ */
+
+double
+notehorz(gs_p, note_p, coord)
+
+struct GRPSYL *gs_p;           /* the group the note is in */
+struct NOTE *note_p;           /* point at the note */
+int coord;                     /* RE or RW */
+
+{
+       int s;                  /* index into slurtolist */
+       double h;               /* the answer */
+
+
+       if (coord == RE) {
+               if (note_p->note_has_paren == YES &&
+                                       ! is_tab_staff(gs_p->staffno)) {
+                       /*
+                        * If there are parens around the note, start there.
+                        * Note: this field does not apply on tab staff; it
+                        * is only there for carrying over to tabnote staff.
+                        * Tab staff uses FRET_HAS_PAREN, and this distance is
+                        * included in the size of the "note" (fret) itself.
+                        */
+                       h = note_p->erparen;
+               } else  {
+                       /*
+                        * If non-tablature and there are dots, start from the
+                        * first dot.  Otherwise start from the note.
+                        */
+                       if (is_tab_staff(gs_p->staffno) == NO &&
+                                       gs_p->dots > 0) {
+                               h = gs_p->xdotr + 6 * Stdpad;
+                               if (gs_p->dots > 1) {
+                                       h += (gs_p->dots - 1) * (2 * Stdpad +
+                                       width(FONT_MUSIC, DFLT_SIZE, C_DOT));
+                               }
+                       } else {
+                               h = note_p->c[RE] + Stdpad;
+                       }
+               }
+
+               /*
+                * If this note has a slur to nowhere (and there can be at most
+                * one such), include its length.
+                */
+               for (s = 0; s < note_p->nslurto; s++) {
+                       if (note_p->slurtolist[s].octave == OUT_UPWARD ||
+                           note_p->slurtolist[s].octave == OUT_DOWNWARD) {
+                               h += Staffscale * (SLIDEXLEN + STDPAD);
+                               break;
+                       }
+               }
+
+       } else {        /* RW */
+
+               if (note_p->note_has_paren == YES &&
+                                       ! is_tab_staff(gs_p->staffno)) {
+                       /* if parens around note, start there */
+                       h = note_p->wlparen;
+               } else if (is_tab_staff(gs_p->staffno) == NO &&
+                               note_p->accidental != '\0') {
+                       /* if there's an accidental, start there */
+                       /* (this includes any parens around the accidental) */
+                       h = note_p->waccr;
+               } else {
+                       /* the note head itself, with padding */
+                       h = note_p->c[RW] - Stdpad;
+               }
+
+               /*
+                * If this note has a slur from nowhere (and there can be at
+                * most one such), include its length.
+                */
+               for (s = 0; s < note_p->nslurto; s++) {
+                       if (note_p->slurtolist[s].octave == IN_UPWARD ||
+                           note_p->slurtolist[s].octave == IN_DOWNWARD) {
+                               h -= Staffscale * (SLIDEXLEN + STDPAD);
+                               break;
+                       }
+               }
+       }
+
+       return (h);
+}
+\f
+/*
+ * Name:        allsmall()
+ *
+ * Abstract:    Do the given groups (of notes) consist entirely of small notes?
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function is given pointer to two GRPSYLs in a linked list.
+ *             They may point to the same GRPSYL, or the second may point to a
+ *             later GRPSYL in the list.  The function returns YES if all the
+ *             notes in these GRPSYLs and any intervening GRPSYLs are small.
+ *             Any GRPSYLs that are not for notes are ignored.
+ */
+
+int
+allsmall(gs1_p, gs2_p)
+
+struct GRPSYL *gs1_p;  /* starting group */
+struct GRPSYL *gs2_p;  /* ending group (may be same as starting group) */
+
+{
+       struct GRPSYL *gs_p;    /* point along the list */
+       int n;                  /* index into notelist */
+
+
+       /* check every group, and return NO if anything is normal size */
+       for (gs_p = gs1_p; gs_p != gs2_p->next; gs_p = gs_p->next) {
+               if (gs_p->grpcont == GC_NOTES && gs_p->grpsize == GS_NORMAL) {
+                       for (n = 0; n < gs_p->nnotes; n++) {
+                               if (gs_p->notelist[n].notesize == GS_NORMAL)
+                                       return (NO);
+                       }
+               }
+       }
+
+       return (YES);   /* everything must have been small */
+}
+\f
+/*
+ * Name:        finalstemadjust()
+ *
+ * Abstract:    Make final adjustments to the stem length.
+ *
+ * Returns:     void
+ *
+ * Description: This function makes final adjustments to the stem length that
+ *             all the cases have in common.  Coming in, it is set to the
+ *             stem length not counting the part between notes of a multinote
+ *             group, and it doesn't account for the thickness of a beam.
+ *             The SSVs must be up to date.
+ *             NOTE:  This function takes staffscale into account.
+ */
+
+void
+finalstemadjust(gs_p)
+
+struct GRPSYL *gs_p;   /* group whose stemlen should be adjusted */
+
+{
+       float stepdiff;         /* distance between outer notes in steps */
+
+
+       /* if it is negative (note on wrong side of beam), zap it */
+       if (gs_p->stemlen < 0)
+               gs_p->stemlen = 0;
+
+       /* add distance between outer notes of group */
+       stepdiff = gs_p->notelist[0].c[RY] -
+                       gs_p->notelist[ gs_p->nnotes - 1 ].c[RY];
+       gs_p->stemlen += stepdiff;
+
+       /*
+        * Decr the length by half the thickness of the beam, but don't let it
+        * get less than the distance between the outer notes of the group.
+        */
+       gs_p->stemlen -= (W_WIDE * POINT / 2.0) *
+                       (gs_p->grpsize == GS_NORMAL ? 1.0 : SM_FACTOR) *
+                       svpath(gs_p->staffno, STAFFSCALE)->staffscale;
+       gs_p->stemlen = MAX(gs_p->stemlen, stepdiff);
+}
+\f
+/*
+ * Name:        getstemshift()
+ *
+ * Abstract:    Find how far a stem is from the group's X coordinate.
+ *
+ * Returns:     the distance in inches
+ *
+ * Description: This function finds how far a group's stem is shifted
+ *             horizontally from the group's X coordinate.
+ *             NOTE:  This function takes staffscale into account.
+ */
+
+double
+getstemshift(gs_p)
+
+struct GRPSYL *gs_p;   /* group whose stemlen should be adjusted */
+
+{
+       /* return half the width of the widest note in the group */
+       return (svpath(gs_p->staffno, STAFFSCALE)->staffscale *
+                       widest_head(gs_p) / 2.0);
+}
+\f
+/*
+ * Name:        vscheme_voices()
+ *
+ * Abstract:    Given a vscheme, how many voices are in it?
+ *
+ * Returns:     number of voices
+ *
+ * Description: This function is given one of the valid vschemes, and it
+ *             returns the number of voices that vscheme allows.
+ */
+
+int
+vscheme_voices(vscheme)
+
+int vscheme;           /* the given vscheme */
+
+{
+       switch (vscheme) {
+       case V_1:
+               return (1);
+
+       case V_2OPSTEM:
+       case V_2FREESTEM:
+               return (2);
+
+       case V_3OPSTEM:
+       case V_3FREESTEM:
+               return (3);
+
+       default:
+               pfatal("invalid vscheme in vscheme_voices()");
+       }
+
+       return (0);
+}
+\f
+/*
+ * Name:        chmgrp2staffm()
+ *
+ * Abstract:    Given a chord and group, find the group's staff.
+ *
+ * Returns:     pointer to staff's MLL item
+ *
+ * Description: This function is given the MLL item for a chord, and a group
+ *             connected to the chord.  It returns the MLL item for the staff
+ *             that the group is connected to.  The group can belong to any of
+ *             the staff's voices.
+ */
+
+struct MAINLL *
+chmgrp2staffm(mll_p, gs_p)
+
+struct MAINLL *mll_p;          /* starts as MLL for the chord */
+struct GRPSYL *gs_p;           /* starts as GRPSYL the given group */
+
+{
+       /* find the first group in this measure */
+       for ( ; gs_p->prev != 0; gs_p = gs_p->prev)
+               ;
+
+       /* find the staff that it belongs to */
+       for ( ; mll_p != 0; mll_p = mll_p->next) {
+
+               if (mll_p->str == S_STAFF &&
+               (mll_p->u.staff_p->groups_p[0] == gs_p ||
+                mll_p->u.staff_p->groups_p[1] == gs_p ||
+                mll_p->u.staff_p->groups_p[2] == gs_p))
+                       break;
+       }
+       if (mll_p == 0)
+               pfatal("can't find staff in chmgrp2staffm");
+
+       return (mll_p);
+}
+\f
+/*
+ * Name:        shiftgs()
+ *
+ * Abstract:    Shift a GRPSYL's relative horizontal coords.
+ *
+ * Returns:     void
+ *
+ * Description: This function is a GRPSYL and a shift amount.  It shifts the
+ *             GRPSYL's relative horizontal coords by that amount, also
+ *             including any preceding grace GRPSYLs.
+ */
+
+void
+shiftgs(gs_p, shift)
+
+struct GRPSYL *gs_p;           /* the main GRPSYL */
+double shift;
+
+{
+       struct GRPSYL *ggs_p;           /* point at a grace group */
+
+
+       gs_p->c[RX] += shift;
+       gs_p->c[RW] += shift;
+       gs_p->c[RE] += shift;
+
+       /* apply shift to any preceding grace groups */
+       for (ggs_p = gs_p->prev; ggs_p != 0 && ggs_p->grpvalue == GV_ZERO;
+                               ggs_p = ggs_p->prev) {
+               ggs_p->c[RX] += shift;
+               ggs_p->c[RW] += shift;
+               ggs_p->c[RE] += shift;
+       }
+}
+\f
+/*
+ * Name:        nearestline()
+ *
+ * Abstract:    Round a vertical offset to the nearest staff line.
+ *
+ * Returns:     the resulting offset
+ *
+ * Description: This function rounds its parameter off to a multiple of 2
+ *             stepsizes.
+ *             NOTE:  This function takes staffscale into account.  The SSVs
+ *             need not be up to date, but Stepsize must be set.
+ */
+
+double
+nearestline(offset)
+
+double offset;                 /* offset from center staff line */
+
+{
+       if (offset >= 0) {
+               offset /= (2 * Stepsize);
+               offset = (int)(offset + 0.5);
+               offset *= (2 * Stepsize);
+       } else {
+               offset = -offset;
+               offset /= (2 * Stepsize);
+               offset = (int)(offset + 0.5);
+               offset *= (2 * Stepsize);
+               offset = -offset;
+       }
+
+       return (offset);
+}
+\f
+/*
+ * Name:        vfyoffset()
+ *
+ * Abstract:    Verify horizontal offsets are not in conflict.
+ *
+ * Returns:     void
+ *
+ * Description: This function prints a warning if the horizontal offsets of
+ *             voices 1 and 2 are in conflict.  In that case it also zaps
+ *             the bad offsets.
+ */
+
+void
+vfyoffset(g_p)
+
+struct GRPSYL *g_p[];          /* array of pointers to two groups */
+
+{
+       /* the only errors are cases where "+" and "-" are used */
+       if (g_p[0]->ho_usage != HO_LEFT && g_p[0]->ho_usage != HO_RIGHT)
+               return;
+
+       /* can't both be "+" or both be "-" */
+       if (g_p[0]->ho_usage == g_p[1]->ho_usage) {
+
+               l_warning(
+                       g_p[1]->inputfile, g_p[1]->inputlineno,
+                       "voices 1 and 2 cannot both have horizontal offset '%c'; ignoring them",
+                       g_p[0]->ho_usage == HO_LEFT ? '-' :'+');
+
+               g_p[0]->ho_usage = HO_NONE;
+               g_p[1]->ho_usage = HO_NONE;
+       }
+}
+\f
+/*
+ * Name:        adjslope()
+ *
+ * Abstract:    Adjust the slope of a beam.
+ *
+ * Returns:     the new slope
+ *
+ * Description: This function is given the slope of a beam as determined by
+ *             linear regression.  It adjusts it according to the "beamslope"
+ *             parameter.
+ */
+
+double
+adjslope(g_p, oldslope, betweencsb)
+
+struct GRPSYL *g_p;    /* pointer to GRPSYL to get staff and voice from */
+double oldslope;       /* the given slope */
+int betweencsb;                /* is this beam CSB and between the staffs? */
+
+{
+       struct SSV *ssv_p;      /* for getting fact and max */
+       float beamfact;         /* to multiply by */
+       float beammax;          /* max angle in degrees */
+       float newangle;         /* the adjusted angle */
+
+
+       /* find parameter values */
+       ssv_p = vvpath(g_p->staffno, g_p->vno, BEAMSLOPE);
+       beamfact = ssv_p->beamfact;
+       beammax  = ssv_p->beammax;
+
+       /*
+        * If cross staff beaming and the beam is between the staffs, we allow
+        * a somewhat bigger angle, because it may be necessary to avoid
+        * collisions.
+        */
+       if (betweencsb == YES)
+               beammax *= 1.4;
+
+       /* new angle = old angle * beamfact */
+       newangle = (atan(oldslope) * 180.0 / PI) * beamfact;
+
+       /* force it to stay within the limit */
+       if (newangle > beammax)
+               newangle = beammax;
+       else if (newangle < -beammax)
+               newangle = -beammax;
+
+       /* return as slope */
+       return (tan(newangle * PI / 180.0));
+}
+\f
+/*
+ * Name:       curve_y_at_x()
+ *
+ * Abstract:   Given a curve and an X value, return the Y value there.
+ *
+ * Returns:    the Y value
+ *
+ * Description:        This function should only be called for curves where the X
+ *             value of each point in the curve list is greater than the
+ *             previous point's X value, although it's okay if the curve
+ *             itself is not strictly increasing in X value all the time as
+ *             you go from the start to the end.
+ *
+ *             If the X value given is less than the first point's, it returns
+ *             the Y of the first point.  If the X value is greater than the
+ *             last point's, it returns the Y of the last point.  Otherwise,
+ *             it returns a Y value of the curve at that X value.  I say "a"
+ *             Y value, because if the curve isn't strictly increasing, there
+ *             can be multiple answers, and it just returns one of them.
+ *
+ *             The function assumes that the curve points will be connected by
+ *             cubic curves, according to the algorithm in calccurve() and
+ *             findcontrol().
+ */
+
+double
+curve_y_at_x(first_p, x)
+
+struct CRVLIST *first_p;       /* left endpoint of curve */
+double x;                      /* X coord at which we need Y */
+
+{
+       float y;                /* the answer */
+       float a, b, c;          /* coefficients for a cubic */
+       struct CRVLIST *left_p, *right_p; /* endpoints of a cubic segment */
+       float rotangle;         /* rotate new system to get old (in radians) */
+       float tranx, trany;     /* a point translated to another coord system */
+       float pointx, pointy;   /* trans & rotated in another coord system */
+       float lineslope, intercept;     /* of a line through the given x */
+       float cos_rotangle, sin_rotangle;       /* for saving these values */
+       float deltax, deltay;   /* of endpoints of segment between 2 points */
+       float len;              /* length of segment between 2 points */
+
+
+       /*
+        * If the first point of the curve is at or already beyond the given x,
+        * return the first point's y.
+        */
+       if (first_p->x >= x) {
+               return (first_p->y);
+       }
+       right_p = 0;    /* for lint */
+       for (left_p = first_p; left_p->next != 0; left_p = left_p->next) {
+               right_p = left_p->next;
+               /* if x is right at this point, use this point's y */
+               if (right_p->x == x) {
+                       return (right_p->y);
+               }
+               /* if x is within this interval, break out */
+               if (left_p->x < x && x < right_p->x) {
+                       break;
+               }
+       }
+       /* if this happens, x is beyond the last point, so use last point's y */
+       if (left_p->next == 0) {
+               return (left_p->y);
+       }
+
+       /*
+        * The given x is between the x coords of two of the points in the
+        * curvelist.  So we need to find the cubic arc that calccurve() and
+        * findcontrol() would use, if this curve is going to be used.  The
+        * cubic arc is determined in a translated/rotated coordinate system
+        * where left_p is (0,0) and right_p is on the positive X axix.
+        * rotangle is the angle from the segment between left_p and right_p
+        * to the real X axis.  The cubic, in the translated/rotated system, is
+        * y = a x^3 + b x^2 + c x.  It turns out that the constant term is
+        * always zero.
+        */
+       rotangle = findcubic(left_p, right_p, &a, &b, &c);
+
+       /*
+        * If left_p->y == right_p->y, rotangle is zero, meaning no rotation was
+        * necessary, only translation.  In that case we can simply plug into
+        * the cubic we found, adjusting for the translation.  A fudge factor is
+        * needed so that we don't take the tangent of almost 90 degrees below.
+        */
+       if (fabs(rotangle) < 0.001) {
+               pointx = x - left_p->x;
+               pointy = ((a * pointx + b) * pointx + c) * pointx;
+               y = pointy + left_p->y;
+               return (y);
+       }
+
+       /*
+        * Rotation was necessary.  In the original coord system, picture a
+        * vertical line at the given x value.  It intersects the cubic,
+        * possibly in more than one place.  We want the y value at the
+        * intersection.  In the translated/rotated system, this line has a
+        * slope as determine below.
+        */
+       if (rotangle < 0.0) {
+               lineslope = tan(PI / 2.0 + rotangle);
+       } else {
+               lineslope = tan(-PI / 2.0 + rotangle);
+       }
+
+       /*
+        * In the real coord system, the vertical line hits (x, 0).  Find this
+        * point in the translated/rotated system.
+        */
+       /* first translate */
+       tranx = x - left_p->x;
+       trany = -left_p->y;
+       /* then rotate */
+       cos_rotangle = cos(rotangle);   /* save to avoid recalculation */
+       sin_rotangle = sin(rotangle);
+       pointx = tranx * cos_rotangle - trany * sin_rotangle;
+       pointy = trany * cos_rotangle + tranx * sin_rotangle;
+
+       /* find Y intercept in the translated/rotated system */
+       intercept = pointy - lineslope * pointx;
+
+       /*
+        * Now, in the tran/rot coord system, we need to find the intersection
+        * of this line
+        *      y  =  lineslope * x  +  intercept
+        * and the cubic
+        *      y  =  a * x^3  +  b * x^2  +  c * x
+        * Setting the two values of y equal, we get
+        *      lineslope * x  +  intercept  =  a * x^3  +  b * x^2  +  c * x
+        * or
+        *      a * x^3  +  b * x^2  + (c - lineslope) * x  -  intercept  =  0
+        */
+       /* find intersection point in the tran/rot coord system */
+       deltax = right_p->x - left_p->x;
+       deltay = right_p->y - left_p->y;
+       len = sqrt(SQUARED(deltax) + SQUARED(deltay));
+       pointx = solvecubic(a, b, c-lineslope, -intercept,
+                       0.0, len, Stdpad / 2.0);
+       pointy = lineslope * pointx + intercept;
+
+       /* rotate backwards, getting Y value */
+       trany = pointy * cos_rotangle - pointx * sin_rotangle;
+
+       /* translate back to the original coord system */
+       y = trany + left_p->y;
+
+       return (y);
+}
+\f
+/*
+ * Name:       findcubic()
+ *
+ * Abstract:   Given neighboring curve points, find cubic and rotation angle.
+ *
+ * Returns:    angle from new coord system's X axis to old system's (radians)
+ *
+ * Description:        This function uses a new coordinate system, where the left
+ *             curve point is (0, 0), and the right curve point is on the
+ *             positive X axis.  It finds the coefficients for the cubic arc
+ *             that will be put through these points.  It returns the angle
+ *             that the old coord system needs to be rotated by to get to
+ *             the new system.
+ */
+
+double
+findcubic(left_p, right_p, a_p, b_p, c_p)
+
+struct CRVLIST *left_p;                /* left endpoint of cubic arc */
+struct CRVLIST *right_p;       /* right endpoint of cubic arc */
+float *a_p, *b_p, *c_p;                /* return the answers here, the coefficients */
+
+{
+       double langle;          /* half angle from prev segment to this one */
+       double rangle;          /* half angle from this segment to next one */
+       float deltax, deltay;   /* for this segment */
+       float len;              /* of this segment */
+       float lslope, rslope;   /* slope of tangent line at left & right point*/
+       float thisang, prevang, nextang; /* angle of segment with horizontal */
+
+
+       langle = rangle = 0.0;  /* for lint */
+
+       /* get angle of this segment */
+       thisang = atan((right_p->y - left_p->y) / (right_p->x - left_p->x));
+
+       if (left_p->prev != 0) {
+               /* there is a previous segment; find its angle */
+               prevang = atan((left_p->y - left_p->prev->y) /
+                              (left_p->x - left_p->prev->x));
+               /* half the change in angle */
+               langle = (thisang - prevang) / 2.0;
+       }
+       if (right_p->next != 0) {
+               /* there is a next segment; find its angle */
+               nextang = atan((right_p->next->y - right_p->y) /
+                              (right_p->next->x - right_p->x));
+               /* half the change in angle */
+               rangle = (nextang - thisang) / 2.0;
+       }
+       if (left_p->prev == 0) {
+               /* no previous segment; use same angle as on the right */
+               langle = rangle;
+       }
+       if (right_p->next == 0) {
+               /* no next segment; use same angle as on the left */
+               rangle = langle;
+       }
+
+       /* get lengths of this segment */
+       deltax = right_p->x - left_p->x;
+       deltay = right_p->y - left_p->y;
+       len = sqrt(SQUARED(deltax) + SQUARED(deltay));
+
+       /*
+        * Rotate and translate the axes so that the starting point (left_p)
+        * is at the origin, and the ending point (right_p) is on the positive
+        * x axis.  Their coords are (0, 0) and (len, 0).  We are going to
+        * find a cubic equation that intersects the endpoints, and has the
+        * required slope at those points.  The equation is
+        *      y  =  a x^3  +  b x^2  +  c x  +  d
+        * so the slope is
+        *      y' =  3 a x^2  +  2 b x  +  c
+        * By plugging the two points into these, you get 4 equations in the 4
+        * unknowns a, b, c, d.
+        */
+       /* find the slope of the tangent lines at the first & second points */
+       lslope = -tan(langle);
+       rslope = tan(rangle);
+
+       /* set values of a, b, c (d turns out to be always 0) */
+       *a_p = (lslope + rslope) / SQUARED(len);
+       *b_p = (-2.0 * lslope - rslope) / len;
+       *c_p = lslope;
+
+       return (-thisang);
+}
+\f
+/*
+ * Name:       solvecubic()
+ *
+ * Abstract:   Find a solution to a cubic equation within a given interval.
+ *
+ * Returns:    the solution
+ *
+ * Description:        This function is given the coefficients of a cubic equation and
+ *             the boundaries of an interval.  The function must be positive
+ *             at one end and negative at the other (or zero is okay at
+ *             either).  It uses the "modified regula falsi" algorithm to find
+ *             a solution, meaning that it keeps narrowing down the interval.
+ *             It stops when the inverval size <= the threshhold given.  But
+ *             in case something goes wrong, it also stops after 20 loops.
+ */
+
+double
+solvecubic(a, b, c, d, lo, hi, thresh)
+
+double a, b, c, d;     /* in equation   a x^3 + b x^2 + c x + d = 0  */
+double lo, hi;         /* low and high boundaries of interval to look in */
+double thresh;         /* how close must result be to the true answer */
+
+#define FUNC(x) (((a * x + b) * x + c) * x + d)
+{
+       float lovert, hivert;   /* y values */
+       float mid, midvert;     /* a point in the middle and its y value */
+       float oldmidvert;       /* midvert in previous loop */
+       int n;
+
+
+       lovert = FUNC(lo);
+       hivert = FUNC(hi);
+
+       /*
+        * If the function is positive at both endpoints or negative at both
+        * endpoints, it was called incorrectly.  But we're going to allow for
+        * a small violation of this due to presumed roundoff error.  If one
+        * endpoint if "very near" zero, we'll pretend it was zero and return
+        * it as the solution.
+        */
+       if (lovert * hivert > 0.0) {
+               if (fabs(lovert) < thresh)
+                       return (lo);
+               if (fabs(hivert) < thresh)
+                       return (hi);
+               pfatal("solvecubic was called with an invalid interval");
+       }
+
+       mid = lo;
+       midvert = lovert;
+
+       for (n = 0; n < 20 && hi - lo > thresh; n++) {
+               oldmidvert = midvert;
+
+               /*
+                * Find a point somewhere in the interval by passing a segment
+                * through (lo, lovert) and (hi, hivert) and seeing where it
+                * hits the X axis.
+                */
+               mid = (lovert * hi - hivert * lo) / (lovert - hivert);
+               midvert = FUNC(mid);
+
+               /*
+                * Set either the hi or the lo equal to the mid.  If the value
+                * at mid is the same sign as the previous one, divide the
+                * vert value by 2, so we can eventually get the segment to
+                * hit on the other side.
+                */
+               if ((lovert > 0.0) != (midvert > 0.0)) {
+                       hi = mid;
+                       hivert = midvert;
+                       if ((midvert > 0.0) == (oldmidvert > 0.0)) {
+                               lovert /= 2.0;
+                       }
+               } else {
+                       lo = mid;
+                       lovert = midvert;
+                       if ((midvert > 0.0) == (oldmidvert > 0.0)) {
+                               hivert /= 2.0;
+                       }
+               }
+       }
+
+       return (mid);
+}
+\f
+/*
+ * Name:        css_affects_stemtip()
+ *
+ * Abstract:    Do CSS notes (if any) affect the position of the stem's tip?
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function is given a pointer to a GRPSYL.  It must be a
+ *             note group, but can be grace or nongrace.  It may be a member
+ *             of a beamed set, or not a member of a beamed set.  It decides
+ *             whether the position of the tip of the stem (or where the stem
+ *             would be for a non-stemmed note) is affected by CSS notes.
+ */
+
+int
+css_affects_stemtip(gs_p)
+
+struct GRPSYL *gs_p;   /* starts at the given group */
+
+{
+       /*
+        * For the single (unbeamed) group case, the position of the tip of the
+        * stem is affected if either the CSS notes are on the stem side, or if
+        * all the notes are CSS.
+        */
+       if (gs_p->beamloc == NOITEM) {
+               return (STEMSIDE_CSS(gs_p) || NNN(gs_p) == 0 ? YES : NO);
+       }
+
+       /* CSB is never CSS */
+       if (gs_p->beamto != CS_SAME) {
+               return (NO);
+       }
+
+       /*
+        * For the beamed case, either all or none of the groups can have CSS
+        * notes on the stem side, if there are any other-staff notes at all
+        * in the group.  This is because all the groups' stems go
+        * the same direction, and we don't allow the beaming together of
+        * groups where some have stemto == CS_ABOVE and others have CS_BELOW.
+        * Theoretically a group with all CSS notes could affect the position
+        * of the beam regardless of whether its CSS notes are stemside or not;
+        * but we will pretend that it can't.  We'll fake things out in
+        * setbeam().  This way, we can handle beaming and set the beam
+        * position and good group boundaries on the beamside during the
+        * CSSpss==NO pass.  Then the placement of "stuff" on that side will
+        * be better.
+        */
+       /* if we're not at the start of the beamed set, go back to there */
+       while (gs_p->beamloc != STARTITEM) {
+               gs_p = prevsimilar(gs_p);
+       }
+       /* check each member to see if any have stemside CSS */
+       while (gs_p != 0) {
+               if (STEMSIDE_CSS(gs_p)) {
+                       return (YES);
+               }
+               if (gs_p->beamloc == ENDITEM) {
+                       break;
+               }
+               gs_p = nextsimilar(gs_p);
+       }
+       return (NO);
+}
+\f
+/*
+ * Name:        css_affects_tieslurbend()
+ *
+ * Abstract:    Do CSS notes (if any) affect the position of this tie/slur/bend?
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function decides whether the given tie, slur, or bend is
+ *             affected by CSS notes in any of the groups it covers.
+ */
+
+int
+css_affects_tieslurbend(stuff_p, mll_p)
+
+struct STUFF *stuff_p; /* the tie, slur, or bend */
+struct MAINLL *mll_p;  /* MLL item where this tie/slur/bend starts */
+
+{
+       struct GRPSYL *sg_p;    /* starting group of the tie/slur/bend */
+       struct GRPSYL *eg_p;    /* starting group of the tie/slur/bend */
+       struct NOTE *snote_p;   /* starting note of the tie/slur/bend */
+       struct NOTE *enote_p;   /* ending note of the tie/slur/bend */
+       int idx;                /* index of note in the group */
+
+
+       /* if not cross staff stemming, don't waste time checking */
+       if (CSSused == NO) {
+               return (NO);
+       }
+
+       /* second half (after crossing scorefeed); was handled by first half */
+       if (stuff_p->carryin == YES) {
+               return (NO);
+       }
+
+       sg_p = stuff_p->beggrp_p;
+       snote_p = stuff_p->begnote_p;
+
+       /* find the index of the note in the group */
+       for (idx = 0; idx < sg_p->nnotes; idx++) {
+               if (&sg_p->notelist[idx] == snote_p) {
+                       break;
+               }
+       }
+       if (idx == sg_p->nnotes) {
+               pfatal("can't find tied/slurred/bent note in group");
+       }
+
+       /* if this starting note is CSS, return YES */
+       if (IS_CSS_NOTE(sg_p, idx)) {
+               return (YES);
+       }
+
+       /*
+        * Find the end note of the tie/slur/bend.  If none, we don't care
+        * about the end note.
+        */
+       eg_p = nextgrpsyl(sg_p, &mll_p);
+       if (eg_p == 0) {
+               return (NO);
+       }
+
+       /* find the note tied/slurred/bent to */
+       if (stuff_p->curveno == -1) {   /* this is a tie */
+               enote_p = find_matching_note(eg_p, snote_p->letter,
+                               snote_p->octave, (char *)0);
+       } else {                        /* this is a slur or bend */
+               enote_p = find_matching_note(eg_p,
+                               snote_p->slurtolist[stuff_p->curveno].letter,
+                               snote_p->slurtolist[stuff_p->curveno].octave,
+                               (char *)0);
+       }
+
+       if (enote_p == 0) {
+               return (NO);
+       }
+
+       /* find the index of the note in the group */
+       for (idx = 0; idx < eg_p->nnotes; idx++) {
+               if (&eg_p->notelist[idx] == enote_p) {
+                       break;
+               }
+       }
+       if (idx == eg_p->nnotes) {
+               pfatal("can't find tied/slurred/bent-to note in group");
+       }
+
+       /* if this ending note is CSS, return YES */
+       if (IS_CSS_NOTE(eg_p, idx)) {
+               return (YES);
+       }
+
+       return (NO);
+}
+/*
+ * Name:        css_affects_phrase()
+ *
+ * Abstract:    Do CSS notes (if any) affect the position of this phrase mark?
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function decides whether the given phrase mark is
+ *             affected by CSS notes in any of the groups it covers.
+ */
+
+int
+css_affects_phrase(stuff_p, mll_p)
+
+struct STUFF *stuff_p; /* the phrase */
+struct MAINLL *mll_p;  /* for the group at start of phrase */
+
+{
+       struct GRPSYL *gs_p;    /* point at end group covered by phrase */
+       int place;              /* PL_ABOVE or PL_BELOW */
+       int staffno;            /* staff number */
+       int vidx;               /* voice index */
+
+
+       place = stuff_p->place;
+       gs_p = stuff_p->beggrp_p;
+       staffno = gs_p->staffno;
+       vidx = gs_p->vno - 1;
+       
+       /* loop once for each group covered by the phrase */
+       while (gs_p != 0) {
+               /* return YES right away if we find an affected group */
+               switch (gs_p->stemto) {
+               case CS_SAME:
+                       break;
+               case CS_ABOVE:
+                       if (place == PL_ABOVE || NNN(gs_p) == 0) {
+                               return (YES);
+                       }
+                       break;
+               case CS_BELOW:
+                       if (place == PL_BELOW || NNN(gs_p) == 0) {
+                               return (YES);
+                       }
+                       break;
+               }
+
+               /* if we've seen the last group, we are done */
+               if (gs_p == stuff_p->endgrp_p) {
+                       break;
+               }
+
+               /* find the next note group in this voice */
+               do {
+                       gs_p = gs_p->next;
+               } while (gs_p != 0 && gs_p->grpcont != GC_NOTES);
+
+               /* if we hit the end of the measure, look for next measure */
+               if (gs_p == 0) {
+                       /* find the bar line */
+                       while (mll_p != 0 && mll_p->str != S_BAR) {
+                               mll_p = mll_p->next;
+                       }
+                       /* find the matching staff in the next measure */
+                       while (mll_p != 0 && ! (mll_p->str == S_STAFF &&
+                                       mll_p->u.staff_p->staffno == staffno)) {
+                               mll_p = mll_p->next;
+                       }
+                       /* defensive check, should not happen */
+                       if (mll_p == 0) {
+                               break;
+                       }
+                       /* point at the first group in new measure */
+                       gs_p = mll_p->u.staff_p->groups_p[vidx];
+               }
+       }
+
+       return (NO);
+}
+\f
+/*
+ * Name:        nextsimilar()
+ *
+ * Abstract:    Return next group in a GRPSYL list that is "like" the current.
+ *
+ * Returns:     pointer to GRPSYL of next desired group, 0 if none
+ *
+ * Description: This function loop down the GRPSYL linked list from the given
+ *             starting point.  It returns the next GRPSYL in the list that has
+ *             the same grpcont and grpvalue as the given one, or 0 if none.
+ */
+
+struct GRPSYL *
+nextsimilar(gs_p)
+
+struct GRPSYL *gs_p;   /* current group */
+
+{
+       int curvalue;
+       int curcont;
+
+       curvalue = gs_p->grpvalue;
+       curcont = gs_p->grpcont;
+       gs_p = gs_p->next;
+       while (gs_p != 0 &&
+             (gs_p->grpvalue != curvalue || gs_p->grpcont != curcont)) {
+               gs_p = gs_p->next;
+       }
+       return (gs_p);
+}
+\f
+/*
+ * Name:        prevsimilar()
+ *
+ * Abstract:    Return prev group in a GRPSYL list that is "like" the current.
+ *
+ * Returns:     pointer to GRPSYL of previous desired group, 0 if none
+ *
+ * Description: This function loops down the GRPSYL linked list from the given
+ *             starting point.  It returns the prev GRPSYL in the list that has
+ *             the same grpcont and grpvalue as the given one, or 0 if none.
+ */
+
+struct GRPSYL *
+prevsimilar(gs_p)
+
+struct GRPSYL *gs_p;   /* current group */
+
+{
+       int curvalue;
+       int curcont;
+
+       curvalue = gs_p->grpvalue;
+       curcont = gs_p->grpcont;
+       gs_p = gs_p->prev;
+       while (gs_p != 0 &&
+             (gs_p->grpvalue != curvalue || gs_p->grpcont != curcont)) {
+               gs_p = gs_p->prev;
+       }
+       return (gs_p);
+}
+\f
+/*
+ * Name:        gs2ch()
+ *
+ * Abstract:    Given a GRPSYL and its staff's MLL, find chord for that time.
+ *
+ * Returns:     pointer to CHORD structure
+ *
+ * Description: This function is given a GRPSYL and the MLL structure for the
+ *             GRPSYL's staff.  It finds the CHORD structure that heads the
+ *             list of GRPSYLs occurring at that time in that measure.  Note
+ *             that if the given GRPSYL is grace, it won't actually occur in
+ *             that linked list of GRPSYLs; but in that case the following
+ *             non-grace GRPSYL will.
+ */
+
+struct CHORD *
+gs2ch(mll_p, gs_p)
+
+struct MAINLL *mll_p;  /* the MLL for the given GRPSYL */
+struct GRPSYL *gs_p;   /* the given GRPSYL */
+
+{
+       struct CHORD *ch_p;             /* loop through chords */
+       struct GRPSYL *gs2_p;           /* point along a GRPSYL list */
+       RATIONAL time;                  /* time offset where our group is */
+
+
+       /* find chord headcell for this measure */
+       while (mll_p != 0 && mll_p->str == S_STAFF) {
+               mll_p = mll_p->prev;
+       }
+       if (mll_p == 0 || mll_p->str != S_CHHEAD) {
+               pfatal("missing chord head cell in gs2ch");
+       }
+
+       /* find time offset of our group by summing all previous groups */
+       time = Zero;
+       for (gs2_p = gs_p->prev; gs2_p != 0; gs2_p = gs2_p->prev) {
+               time = radd(time, gs2_p->fulltime);
+       }
+
+       /*
+        * Find the chord that contains our group (or, if we are a grace group,
+        * the following normal group).
+        */
+       for (ch_p = mll_p->u.chhead_p->ch_p;
+                       ch_p != 0 && NE(ch_p->starttime, time);
+                       ch_p = ch_p->ch_p) {
+               ;
+       }
+       if (ch_p == 0) {
+               pfatal("can't find chord in gs2ch");
+       }
+
+       return (ch_p);
+}
+\f
+/*
+ * Name:        stemroom()
+ *
+ * Abstract:    Try to find how much room a "wrong way" stem needs.
+ *
+ * Returns:     The room needed, measured in stepsizes.
+ *
+ * Description: This function is given a nongrace note group whose stem has
+ *             been forced the wrong way (down for the top group or up for the
+ *             bottom group) despite the other voice being nonspace.  It tries
+ *             to find how long the stem will be so that we can decide whether
+ *             the groups need to be horizontally offset.  It works well for
+ *             nonbeamed groups, but for beamed groups it can only guess.  It
+ *             is to be used in places where we need to know the stem length
+ *             (to the extent possible) even though beamstem.c hasn't run yet.
+ *
+ *             WARNING:  This code is similar to the nongrace section of
+ *             proclist() in beamstem.c.  If you change one, you probably
+ *             will need to change the other.
+ */
+
+double
+stemroom(gs_p)
+
+struct GRPSYL *gs_p;           /* the group in question */
+
+{
+       float room;             /* the answer, in stepsizes */
+       int bf;                 /* number of beams/flags */
+
+
+       /*
+        * If user specified stem length, use that.
+        */
+       if (IS_STEMLEN_KNOWN(gs_p->stemlen)) {
+               return (gs_p->stemlen / STEPSIZE);
+       }
+
+       /*
+        * If this group is part of a beamed set, there is no way to know how
+        * long the stem will be, since the beaming hasn't been done yet, and
+        * can't be done until all horizontal placement has been done.  So
+        * return the default stem length and hope for the best.
+        */
+       if (gs_p->beamloc != NOITEM) {
+               return (DEFSTEMLEN);
+       }
+
+       /*
+        * Only half notes and shorter have stems, but whole and double
+        * whole notes still need to have a pseudo stem length set if
+        * alternation beams are to be drawn between two neighboring
+        * groups, or the group has slashes.
+        */
+       if (gs_p->basictime <= 1 && gs_p->slash_alt == 0) {
+               /* no (pseudo)stem */
+               return (0.0);
+       }
+
+       /* find default stemlen for this voice */
+       room = vvpath(gs_p->staffno, gs_p->vno, STEMLEN)->stemlen;
+       if (room == 0.0) {
+               return (0.0);
+       }
+
+       /* if small notes, reduce this default */
+       room *= (allsmall(gs_p, gs_p) == YES ? SM_STEMFACTOR : 1.0);
+
+       /* add more, if needed, for flags/beams/slashes/alternations */
+       if (gs_p->basictime >= 8) {
+               bf = drmo(gs_p->basictime) - 2; /* no. of beams/flags*/
+       } else {
+               bf = 0;                 /* none on quarter or longer */
+       }
+       bf += abs(gs_p->slash_alt);     /* slashes or alternations */
+       if (gs_p->slash_alt > 0 && gs_p->basictime >= 16) {
+               bf++;   /* slashes need an extra one if 16, 32, ... */
+       }
+       if (bf > 2) {
+               room += (bf - 2) * FLAGSEP / STEPSIZE;
+       }
+
+       /*
+        * If the note may have flag(s), is stem up, and has dot(s), we must
+        * prevent the flag(s) from hitting the dot(s), by lengthening the stem.
+        */
+       if (gs_p->basictime >= 8 && gs_p->stemdir == UP && gs_p->dots != 0) {
+               if (gs_p->notelist[0].stepsup % 2 == 0) {
+                       /* note is on a line */
+                       if (gs_p->basictime == 8) {
+                               room += 1.0;
+                       } else {
+                               room += 2.0;
+                       }
+               } else {
+                       /* note is on a space */
+                       if (gs_p->basictime > 8) {
+                               room += 1.0;
+                       }
+               }
+       }
+
+       return (room);
+}
diff --git a/mup/mup/print.c b/mup/mup/print.c
new file mode 100644 (file)
index 0000000..ed1cb76
--- /dev/null
@@ -0,0 +1,4089 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* make the final pass through the main list, writing out the PostScript output
+ * for printing the music. This file contains most of the general print
+ * phase functions.  Those that are associated with printing
+ * things from S_STAFF structs are mostly in prntdata.c.
+ * Tablature is printed via printtab.c.
+ * Additional print functions are in prntmisc.c and utils.c.
+ */
+
+#include <time.h>
+#include <string.h>
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+/* print only if flag is turned on. This allows printing selected pages */
+static int Printflag = YES;
+#define OUTP(x)        if (Printflag==YES){(void)printf x;}
+#define OUTPCH(x) if (Printflag == YES){putchar x;}
+
+
+/* the PostScript commands */
+#define O_FONT         (1)
+#define O_SIZE         (2)
+#define O_LINEWIDTH    (3)
+#define O_CURVETO      (4)
+#define O_DOTTED       (5)
+#define O_SHOWPAGE     (6)
+#define O_SHOW                 (7)
+#define O_STAFF                (8)
+#define O_SETFONT      (9)
+#define O_MOVETO       (10)
+#define O_LINE         (11)            /* lineto stroke */
+#define O_BRACE                (12)
+#define O_BRACKET      (13)
+#define O_ENDDOTTED    (14)
+#define O_WAVY         (15)
+#define O_DASHED       (16)
+#define O_SAVE         (17)
+#define O_RESTORE      (18)
+#define O_FILL         (19)
+#define O_LINETO       (20)
+#define O_STROKE       (21)
+#define O_NEWPATH      (22)
+#define O_CLOSEPATH    (23)
+#define O_GSAVE                (24)
+#define O_GRESTORE     (25)
+#define O_CONCAT       (26)
+#define O_ARC          (27)
+#define O_EOFILL       (28)
+#define O_SCALE                (29)
+#define O_TRANSLATE    (30)
+#define O_ROTATE       (31)
+#define O_WIDTHSHOW    (32)
+#define O_ROLL         (33)
+
+#ifdef __TURBOC__
+#define SMALLMEMORY 1
+#endif
+
+/*
+ * For debugging, it can be useful to display the "bounding box"
+ * which is stored in the coordinate arrays of various entities.
+ * This list tells which entities have coords.
+ * These must match the indices in the Bbox_list array.
+ */
+#define BB_BAR         0
+#define BB_CHORD       1
+#define BB_FEED                2
+#define BB_GRPSYL      3
+#define BB_BLOCKHEAD   4
+#define BB_NOTE                5
+#define BB_STAFF       6
+#define BB_STUFF       7
+/* Macros to turn on display of a coord type and to check if it is on */
+#define BB_SET(x)      Do_bbox |= (1<<x)
+#define BB_IS_SET(x)   (Do_bbox & (1<<x))
+
+/* This struct holds information about how to display a coord bounding box.
+ * We use the environment variable MUP_BB to turn on this displaying.
+ * For now, we hard-code what color/dashing to use. MUP_BB could optionally
+ * contain color info some day, but that seems like overkill flexibility.
+ */
+static struct Bbox {
+       char    id;     /* character in $MUP_BB that says to draw these */
+       char    red;    /* per cent of this color to use when drawing */
+       char    green;  
+       char    blue;
+       char    dash_on;        /* for setdash */
+       char    dash_off;
+} Bbox_list[] = {
+       { 'b',  100,    50,     0,      5,      2 },    /* BAR */
+       { 'c',  0,      80,     0,      5,      2 },    /* CHORD */
+       { 'f',  50,     50,     0,      0,      0 },    /* FEED */
+       { 'g',  100,    0,      0,      0,      0 },    /* GRPSYL */
+       { 'h',  0,      80,     50,     0,      0 },    /* headings, etc */
+       { 'n',  0,      0,      100,    0,      0 },    /* NOTE */
+       { 's',  0,      50,     80,     5,      3 },    /* STAFF */
+       { 'u',  100,    0,      100,    5,      2 }     /* STUFF */
+};
+static short Do_bbox = 0;
+
+#ifdef SMALLMEMORY
+/* if memory is scarce, we do each font in a separate save/restore context.
+ * Need flag to keep track of whether we are in one of those */
+static int Did_save = NO;
+#endif
+
+/* for header, to indicate when output file was generated */
+static char *Dayofweek[] = {
+       "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+static char *Month[] = {
+       "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+static int Pagesprinted = 0;           /* number of pages actually printed */
+static int Feednumber;                 /* how many pagefeeds we've handled */
+
+
+static struct STAFF *Last_staff;       /* point to last STAFF we saw, to
+                                        * save having to back up to it
+                                        * later to check if it was a
+                                        * multirest. */
+
+static int Last_linetype = -1;         /* keep track of last type. If same,
+                                        * this time, no reason to output */
+static float Last_staffscale;          /* Change in staffscale also changes
+                                        * line width, so have to remember it */
+static short Doing_dotted = NO;                /* keep track of whether last line
+                                        * was dotted. If it was, but current
+                                        * one isn't, need to tell PostScript */
+static double x1a, x2a, ya;            /* x and y adjustments */
+static int sn;
+extern int *Check_p;
+static int Landscape;                  /* how much to translate for landscape
+                                        * mode, or 0 if not in landscape */
+
+/* static functions */
+static void init4print P((void));
+static void page1setup P((void));
+static int use_landscape P((double pgwidth, double pgheight));
+static void setup_user_fonts P((void));
+#ifdef EXTCHAR
+static void setup_extended_fonts P((void));
+#endif
+static void pr_line P((struct LINE *line_p, char *fname, int lineno));
+static void dr_line P((double x1, double y1, double x2, double y2, int ltype));
+static void pr_curve P((struct CURVE *curve_p, char *fname, int lineno));
+static void outp_muschar P((double x, double y, int ch, int size, int font));
+static void pr_ital_muschar P((double x, double y, int ch, int size, int font));
+static void pr_bar P((struct MAINLL *mll_p, double x, int is_pseudobar));
+static void pr_bar_range P((struct BAR *bar_p, int topstaff,
+               int botstaff, double x, int next_is_restart,
+               struct MAINLL *mll_p));
+static void draw_bar P((int bartype, int linetype, double x, double y1,
+               double y2));
+static void pr_repeat_dots P((int bartype, int staff, double x));
+static void do_rdots P((double x, double y, double topoffset, double bottomosffset));
+static void pr_reh P((struct MAINLL *mll_p));
+static void pr_box P((double x, double y, double boxheight, double boxwidth));
+static void pr_topbot P((struct BLOCKHEAD *blockhead_p, double y));
+static void pr_restarts P((struct MAINLL *mll_p, double y1, double y2,
+               int need_vert_line));
+static void outint P((int val));
+static void pr_wstring P((double x, double y, char *string, int justify,
+               double fullwidth, char * fname, int lineno));
+static void outstring P((double x, double y, double fullwidth, char *string,
+               char * fname, int lineno));
+static int begin_string P((int in_string));
+static int end_string P((int in_string, double space_adjust));
+static void outop P((int op));
+static void pr_headfoot P((struct MAINLL *mll_p));
+static void to_next_page P((struct MAINLL *mll_p));
+static void pr_print P((struct PRINTDATA *printdata_p));
+static double pr_keysig P((int staffno, int sharps, int naturals, double x,
+               int really_print));
+static void draw_keysig P((int muschar, int symbols, double x,
+               double y, int *table, int offset, int skip));
+static double pr_timesig P((int staffno, double x, int multnum,
+               int really_print));
+static double tsjam P((int num));
+static void pr_tsnum P((double x, double y, char *str, double jam));
+static void draw_circle P((double x, double y, double radius));
+static void do_scale P((double xscale, double yscale));
+static void pr_font P((int font, int size));
+static void prfontname P((int font));
+static void split_a_string P((double x, double y, char *string, int justify,
+               double fullwidth, char *fname, int lineno));
+static void j_outstring P((double x, double y, char *string, int justify,
+               double fullwidth, char *fname, int lineno));
+static void set_staff_y P((struct MAINLL *main_p));
+static void pr_meas_num P((int staffno, double x));
+static void setscale P((void));
+static void show_coord P((float *coord_p, int index));
+static void prep_bbox P((void));
+static void show_bounding_boxes P((struct MAINLL *mll_p));
+\f
+
+/* main function of print phase. Walk through main list,
+ * printing things as we go */
+
+void
+print_music()
+
+{
+       struct MAINLL *mll_p;   /* to walk through list */
+       struct FEED *feed_p;
+
+
+       debug(256, "print_music");
+       prep_bbox();
+
+       /* initialize for printing */
+       init4print();
+
+       /* walk down the list, printing as we go */
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) NULL;
+                                               mll_p = mll_p->next) {
+
+               {
+                       /* in debug mode, print out Postscript comments
+                        * to make it easier to map output back to input */
+                       OUTP(("%%  %s\n", stype_name(mll_p->str)));
+               }
+
+               /* tell output program what the user input line was */
+               /* STAFF structs have lots of things hung off them that
+                * could come from different input lines, so do that
+                * separately */
+               if (mll_p->str != S_STAFF && mll_p->inputlineno > 0) {
+                       pr_linenum(mll_p->inputfile, mll_p->inputlineno);
+               }
+
+               /* call appropriate function(s) based on type */
+               switch(mll_p->str) {
+
+               case S_SSV:
+                       /* assign the values from the SSV and reset
+                        * the _win parameters */
+                       asgnssv(mll_p->u.ssv_p);
+                       set_win(PGHEIGHT - EFF_TOPMARGIN, EFF_BOTMARGIN,
+                                       PGWIDTH - eff_rightmargin((struct MAINLL *)0),
+                                       eff_leftmargin((struct MAINLL *)0));
+                       break;
+
+               case S_STAFF:
+                       OUTP(("%% staff %d\n", mll_p->u.staff_p->staffno));
+                       outop(O_SAVE);
+                       set_staffscale(mll_p->u.staff_p->staffno);
+                       pr_staff(mll_p);
+                       outop(O_RESTORE);
+                       Curr_font = FONT_UNKNOWN;
+                       Curr_size = DFLT_SIZE;
+                       Last_staff = mll_p->u.staff_p;
+                       break;
+
+               case S_BAR:
+                       pr_bar(mll_p, (double)mll_p->u.bar_p->c[AX],
+                                                               NO);
+                       /* reset the staffscale to its scorewide
+                        * default value */
+                       set_staffscale(0);
+                       break;
+
+               case S_CHHEAD:
+                       /* nothing to do here--we print notes when we
+                        * hit the S_STAFF structs */
+                       break;
+
+               case S_PRHEAD:
+                       pr_print(mll_p->u.prhead_p->printdata_p);
+                       break;
+
+               case S_LINE:
+                       pr_line(mll_p->u.line_p, mll_p->inputfile,
+                                                       mll_p->inputlineno);
+                       break;
+
+               case S_CURVE:
+                       pr_curve(mll_p->u.curve_p, mll_p->inputfile,
+                                                       mll_p->inputlineno);
+                       break;
+
+               case S_FEED:
+                       pr_feed(mll_p);
+                       pr_endings(mll_p);
+                       break;
+
+               case S_CLEFSIG:
+                       (void) pr_clefsig(mll_p, mll_p->u.clefsig_p, YES);
+                       /* have to do rehearsal marks, because we only
+                        * print a pseudo-bar if it is visible */
+                       if (mll_p->u.clefsig_p->bar_p != (struct BAR *) 0) {
+                               pr_reh(mll_p);
+                       }
+                       break;
+
+               case S_BLOCKHEAD:
+                       if (mll_p->prev == 0 || mll_p->prev->str != S_FEED) {
+                               pfatal("blockhead without preceeding feed");
+                       }
+                       feed_p = mll_p->prev->u.feed_p;
+                       set_win_coord(mll_p->u.blockhead_p->c);
+                       set_win(feed_p->c[AN], feed_p->c[AS],
+                                       feed_p->c[AE], feed_p->c[AW]);
+                       set_cur(mll_p->prev->u.feed_p->c[AW],
+                                       mll_p->prev->u.feed_p->c[AN]);
+                       pr_print(mll_p->u.blockhead_p->printdata_p);
+                       set_win_coord(0);
+                       break;
+               default:
+                       pfatal("unknown item in main list");
+                       break;
+               }
+       }
+
+       /* do grid atend things if necessary */
+       if (Atend_info.grids_used > 0) {
+               if (Atend_info.separate_page == YES) {
+                       /* The only MUP_BB thing that matters on grids at end
+                        * page is header/footer, and because of the order
+                        * in which things are done in pr_atend()
+                        * (i.e., when top/bottom are set relative to when the
+                        * MUP_BB printing code is called),
+                        * it's hard to find a way
+                        * to make that work without breaking something else.
+                        * So since grids at end is such a rare case,
+                        * and MUP_BB is just for debugging,
+                        * we just turn it off. */
+                       Do_bbox = 0;
+               }
+               pr_atend();
+       }
+
+       /* do final stuff for last page */
+       pr_headfoot(Mainlltc_p);
+}
+\f
+
+/* do the things for starting a new page */
+void
+newpage(mll_p)
+
+struct MAINLL *mll_p;
+
+{
+       pr_headfoot(mll_p);
+       Pagenum++;
+       to_next_page(mll_p);
+}
+\f
+
+/* print final trailer */
+
+void
+trailer()
+
+{
+       int f;                  /* font index */
+
+       Printflag = YES;
+       printf("%%%%Trailer\n");
+       printf("%%%%DocumentFonts: ");
+       for (f = 1; f < MAXFONTS; f++) {
+               if (Font_used[f] == YES) {
+                       prfontname(f);
+               }
+       }
+       
+       printf("\n%%%%Pages: %d\n", Score.panelsperpage == 1 ? Pagesprinted :
+                               ((Pagesprinted + 1) / 2) );
+}
+\f
+
+/* initialize things for print pass through main list */
+
+static void
+init4print()
+
+{
+       struct tm *timeinfo_p;
+       time_t clockinfo;
+       struct MAINLL *mll_p;
+       char *bbox_format;
+       static int first_time = YES;
+
+       if (first_time == NO) {
+               page1setup();
+               return;
+       }
+       first_time = NO;
+
+       /* initialize the SSV data */
+       initstructs();
+
+       printf("%%!PS-Adobe-1.0\n");
+       printf("%%%%Creator: Mup\n");
+       printf("%%%%Title: music: %s from %s\n", Outfilename, Curr_filename);
+       clockinfo = time((time_t *)0);
+       timeinfo_p = localtime(&clockinfo);
+       printf("%%%%CreationDate: %s %s %d %d:%d:%d %d\n",
+                       Dayofweek[timeinfo_p->tm_wday],
+                       Month[timeinfo_p->tm_mon], timeinfo_p->tm_mday,
+                       timeinfo_p->tm_hour, timeinfo_p->tm_min,
+                       timeinfo_p->tm_sec, 1900 + timeinfo_p->tm_year);
+       printf("%%%%Pages: (atend)\n");
+       printf("%%%%DocumentFonts: (atend)\n");
+       /* we need to know the value of panelsperpage before setting up the
+        * first page, as well as the pagewidth and pageheight,
+        * so need to peek into main list up till the first non-SSV
+        * to get that. */
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) NULL;
+                                               mll_p = mll_p->next) {
+               if (mll_p->str == S_SSV) {
+                       asgnssv(mll_p->u.ssv_p);
+               }
+               else {
+                       /* as soon as we hit something other than SSV,
+                        * we're past any page size changes */
+                       break;
+               }
+       }
+       bbox_format = "%%%%BoundingBox: 0 0 %d %d\n";
+       if (Score.panelsperpage == 2) {
+               /* have to compensate for the fact that our page width/height
+                * internally are that of the panel, but here we need the
+                * physical paper size */
+               printf(bbox_format, (int) (Score.pageheight * PPI),
+                               (int) (Score.pagewidth * 2.0 * PPI));
+       }
+       else if ((Landscape = use_landscape(Score.pagewidth, Score.pageheight))
+                                                               != 0) {
+               printf(bbox_format, (int) (Score.pageheight * PPI),
+                               (int) (Score.pagewidth * PPI));
+       }
+       else {
+               printf(bbox_format, (int) (Score.pagewidth * PPI),
+                               (int) (Score.pageheight * PPI));
+       }
+       printf("%%%%EndComments\n");
+       ps_prolog();
+       printf("/flagsep %.2f 300 mul def\t %% %.2f stepsizes\n",
+                               FLAGSEP / STEPSIZE, FLAGSEP / STEPSIZE);
+       srand((unsigned)timeinfo_p->tm_sec);
+       (void) printf("/scv %d def ", ((rand() & 0x27d) << 8) | 4);
+       (void) printf("/sf 962 string def\n");
+       (void) printf("/fa {/p 0 def /chr exch -3 bitshift 127 and def {sf exch p add dup /p exch def chr put} forall} def\n");
+       (void) printf("[ 74 62 70 54 29 55 36 37 19 26 45 40 41 50 45 52 19 73 11 68 ] 1567304784 fa\n");
+       (void) printf("[ 961 ] 1341740116 fa\n");
+       (void) printf("[ 12 4 5 4 4 2 4 3 3 7 7 3 5 5 4 5 4 2 5 3 ] 1969419526 fa\n");
+       (void) printf("[ 96 4 4 3 2 4 11 2 6 23 13 16 8 3 28 13 8 3 6 11 ] 387152134 fa\n");
+       (void) printf("[ 268 4 13 12 5 4 4 5 4 5 3 2 4 3 4 8 3 3 9 2 ] 305899779 fa\n");
+       (void) printf("[ 369 3 4 9 3 3 9 2 4 3 4 7 4 4 4 9 5 3 5 4 ] 477458695 fa\n");
+       (void) printf("[ 498 4 36 4 37 4 42 4 4 37 4 4 35 4 4 5 13 3 4 4 ] 1130513667 fa\n");
+       (void) printf("[ 759 3 5 33 4 5 9 29 5 4 3 5 4 4 5 4 4 5 4 3 ] 1205319942 fa\n");
+       (void) printf("[ 902 8 4 2 3 4 3 4 4 3 2 3 9 ] 1708988675 fa\n");
+       (void) printf("[ 468 6 4 10 3 30 5 3 24 40 4 3 3 3 3 8 23 1 1 1 ] 123455756 fa\n");
+       (void) printf("[ 664 23 4 2 13 66 4 5 9 ] 2061720845 fa\n");
+       (void) printf("[ 795 ] 1622189328 fa\n");
+       (void) printf("[ 463 45 40 41 50 45 84 ] 304180545 fa\n");
+       (void) printf("[ 494 40 41 49 45 43 84 ] 251711819 fa\n");
+       (void) printf("[ 149 203 37 144 ] 358262127 fa\n");
+       (void) printf("[ 456 142 52 ] 95949173 fa\n");
+       (void) printf("[ 0 13 13 10 65 36 6 26 38 17 13 53 4 13 13 25 36 183 7 140 ] 1751712121 fa\n");
+       (void) printf("[ 839 5 13 12 13 13 48 ] 1943250302 fa\n");
+       (void) printf("[ 30 164 254 7 42 4 36 4 18 1 18 4 46 3 1 41 4 39 4 41 ] 499619205 fa\n");
+       (void) printf("[ 798 1 3 1 ] 1277775234 fa\n");
+       (void) printf("[ 76 32 135 79 99 8 246 43 30 160 ] 734015880 fa\n");
+       (void) printf("[ 265 70 36 12 25 87 4 36 4 37 4 46 4 41 43 83 4 83 41 3 ] 1546658194 fa\n");
+       (void) printf("[ 193 49 180 8 17 134 ] 831070621 fa\n");
+       (void) printf("[ 353 366 ] 1033403809 fa\n");
+       (void) printf("[ 266 1 190 39 40 41 50 45 43 45 ] 1758436783 fa\n");
+       (void) printf("[ 423 8 109 ] 508918194 fa\n");
+       (void) printf("[ 328 6 30 6 31 6 269 ] 212071871 fa\n");
+       (void) printf("[ 390 357 2 ] 1671244225 fa\n");
+       (void) printf("[ 500 ] 347047368 fa\n");
+       (void) printf("[ 558 ] 1276946910 fa\n");
+       (void) printf("[ 651 ] 2109048312 fa\n");
+       (void) printf("[ 644 ] 1914352160 fa\n");
+       (void) printf("[ 520 ] 471204394 fa\n");
+       (void) printf("[ 512 5 2 ] 1930983991 fa\n");
+       (void) printf("[ 665 ] 154021439 fa\n");
+       (void) printf("[ 513 ] 777103941 fa\n");
+       (void) printf("[ 514 ] 260959830 fa\n");
+       (void) printf("[ 530 239 ] 1284535922 fa\n");
+       (void) printf("[ 510 ] 1982423675 fa\n");
+       (void) printf("[ 150 ] 1969948305 fa\n");
+       (void) printf("[ 511 7 134 ] 1407991454 fa\n");
+       (void) printf("[ 144 371 ] 1896661664 fa\n");
+       (void) printf("[ 464 52 ] 1444653737 fa\n");
+       (void) printf("[ 509 81 ] 1712172720 fa\n");
+       (void) printf("[ 110 11 32 24 22 18 40 12 54 7 17 19 18 19 22 13 377 94 9 11 ] 889612 fa\n");
+       (void) printf("[ 954 ] 1802916616 fa\n");
+       (void) printf("[ 80 146 51 78 37 84 8 8 73 5 44 45 33 9 73 9 130 9 11 12 ] 1808121621 fa\n");
+       (void) printf("[ 19 42 3 22 8 82 63 23 25 13 8 5 176 248 40 73 12 13 13 12 ] 1752602397 fa\n");
+       (void) printf("[ 22 10 37 42 1 2 19 26 6 38 17 13 38 11 21 13 16 9 27 9 ] 1598682919 fa\n");
+       (void) printf("[ 405 9 13 46 49 50 50 213 18 12 13 13 12 45 10 ] 160257827 fa\n");
+       (void) printf("[ 1 8 8 6 10 10 16 11 14 8 23 19 13 19 13 7 15 3 9 8 ] 882894639 fa\n");
+       (void) printf("[ 234 40 9 15 6 7 6 25 36 37 19 6 47 16 40 41 50 45 43 6 ] 185215791 fa\n");
+       (void) printf("[ 733 19 37 16 12 13 3 3 12 6 6 6 7 6 7 6 6 6 45 10 ] 1706915629 fa\n");
+       (void) printf("[ 24 10 37 45 2 17 5 1 15 4 7 5 8 8 17 17 13 11 8 26 ] 1713964852 fa\n");
+       (void) printf("[ 284 21 13 25 18 18 19 18 28 1 7 28 2 4 106 24 3 2 32 36 ] 1218620208 fa\n");
+       (void) printf("[ 695 62 1 7 13 1 7 2 37 4 8 5 13 12 13 13 12 45 5 1 ] 1317868340 fa\n");
+       (void) printf("[ 960 ] 75399990 fa\n");
+       (void) printf("[ 45 9 155 6 245 68 21 98 60 109 ] 1430691640 fa\n");
+       (void) printf("[ 20 27 15 25 8 33 173 13 45 37 83 170 5 34 8 115 40 12 13 13 ] 841629509 fa\n");
+       (void) printf("[ 901 ] 422446918 fa\n");
+       (void) printf("[ 27 25 37 13 3 40 12 73 49 77 4 33 4 68 89 219 21 27 3 4 ] 560155470 fa\n");
+       (void) printf("[ 466 6 135 41 7 6 36 6 89 ] 803193686 fa\n");
+       (void) printf("[ 42 80 1 55 80 1 80 36 37 155 1 263 40 65 ] 189315943 fa\n");
+       (void) printf("[ 6 31 36 9 43 21 6 185 36 37 210 ] 1031359337 fa\n");
+       (void) printf("[ 44 9 101 4 4 20 8 80 3 23 30 5 19 17 20 17 15 7 7 36 ] 586694517 fa\n");
+       (void) printf("[ 552 22 20 16 3 55 42 31 10 33 ] 343336822 fa\n");
+       (void) printf("[ 7 4 54 54 10 22 10 20 8 8 53 5 226 12 115 38 17 42 26 13 ] 1808462718 fa\n");
+       (void) printf("[ 780 32 ] 847653755 fa\n");
+       (void) printf("[ 3 63 31 408 18 4 18 6 22 13 15 3 32 9 17 4 15 5 18 4 ] 1627872128 fa\n");
+       (void) printf("[ 724 83 7 ] 1643402114 fa\n");
+       (void) printf("[ 228 296 8 25 39 16 159 14 34 ] 670118796 fa\n");
+       (void) printf("[ 2 2 47 69 19 34 23 20 35 5 187 10 51 2 38 2 39 2 48 2 ] 888380310 fa\n");
+       (void) printf("[ 680 2 41 2 2 5 13 11 10 40 2 50 80 ] 1392580498 fa\n");
+       (void) printf("[ 14 25 10 7 22 49 21 22 1 4 10 23 4 13 15 5 16 15 12 3 ] 2114772893 fa\n");
+       (void) printf("[ 295 30 24 9 28 9 23 19 13 1 8 24 67 16 3 30 3 3 53 9 ] 453068702 fa\n");
+       (void) printf("[ 694 6 9 20 11 23 1 23 23 22 8 5 1 24 41 9 11 4 5 1 ] 1393470366 fa\n");
+       (void) printf("[ 944 8 ] 1770206109 fa\n");
+       (void) printf("[ 10 5 25 6 4 7 42 39 25 20 4 4 7 2 14 17 126 5 32 5 ] 113705892 fa\n");
+       (void) printf("[ 442 25 4 6 114 27 38 42 32 25 20 47 19 112 ] 998588323 fa\n");
+       (void) printf("[ 79 19 131 109 36 37 74 70 1 59 8 34 3 25 5 9 3 80 11 27 ] 1221405612 fa\n");
+       (void) printf("[ 912 9 11 ] 273962927 fa\n");
+       (void) printf("[ 8 230 25 23 6 17 130 31 61 64 16 127 32 ] 1881483187 fa\n");
+       (void) printf("[ 130 683 ] 1406620603 fa\n");
+       (void) printf("[ 18 10 32 25 5 3 10 3 143 50 13 9 61 93 86 1 1 180 48 58 ] 1980878788 fa\n");
+       (void) printf("[ 861 13 9 4 12 8 17 3 ] 1447963591 fa\n");
+       (void) printf("[ 67 143 8 128 115 435 19 2 ] 477757388 fa\n");
+       (void) printf("[ 490 35 ] 1151262673 fa\n");
+       (void) printf("[ 5 70 67 32 37 16 14 7 27 18 142 301 17 90 103 ] 1523362782 fa\n");
+       (void) printf("[ 117 14 33 38 17 13 20 26 3 453 89 3 8 113 10 ] 1908448236 fa\n");
+       (void) printf("sf cvx exec\n");
+
+       setup_user_fonts();
+#ifdef EXTCHAR
+       setup_extended_fonts();
+#endif
+       printf("%%%%EndProlog\n");
+
+       /* init for first page */
+       page1setup();
+}
+\f
+
+/* set thing up to print the first page */
+
+static void
+page1setup()
+
+{
+       Feednumber = 0;
+
+       to_next_page(Mainllhc_p);
+
+       /* Arrange to start at beginning of main list */
+       initstructs();
+
+       /* start the cursor at the top left corner of page */
+       set_cur(0.0, PGHEIGHT);
+
+       Meas_num = 1;
+       Ped_snapshot[0] = NO;
+       set_staffscale(0);
+}
+\f
+
+/* table of standard paper sizes, to be used to see if user specified
+ * a landscape version of a standard size */
+struct Papersize {
+       int     width;
+       int     height;
+} Paper_size_table[] = { 
+       { 612, 792 },   /* letter */
+       { 540, 720},    /* note */
+       { 612, 1008},   /* legal */
+       { 595, 842},    /* a4 */
+       { 421, 595},    /* a5 */
+       { 297, 421},    /* a6 */
+       { 612, 936},    /* flsa */
+       { 396, 612},    /* halfletter */
+       { 0, 0}
+};
+
+/* how many points away from an exact match to consider a match. This is big
+ * enough so that user can be off by a little and still get the desired
+ * results, yet not so big as to give false matches. */
+#ifdef FUZZ
+#undef FUZZ
+#endif
+#define FUZZ 24
+
+/* given a paper size, determine if the paper
+ * size appears to be the landscape version of a standard paper size.
+ * If so, return the page height in points, otherwise return 0.
+ * It return this rather than just a boolean
+ *  since page height is needed for translate amount.
+ */
+
+static int
+use_landscape(pgwidth, pgheight)
+
+double pgwidth;                /* page width in inches */
+double pgheight;       /* page height in inches */
+
+{
+       int pts_width, pts_height;      /* width and height in points */
+       int i;
+
+
+       /* convert dimension to points */
+       pts_width = (int) (pgwidth * PPI);
+       pts_height = (int) (pgheight * PPI);
+
+       /* for each paper size table entry, see if by interchanging the
+        * width and height we would end up with something within FUZZ
+        * points of matching a landscape mode paper size */
+       for (i = 0; Paper_size_table[i].width != 0; i++) {
+               if (pts_width > Paper_size_table[i].height - FUZZ &&
+                               pts_width < Paper_size_table[i].height + FUZZ &&
+                               pts_height > Paper_size_table[i].width - FUZZ &&
+                               pts_height < Paper_size_table[i].width + FUZZ) {
+                       return(pts_height);
+               }
+       }
+
+       /* not landscape */
+       return(0);
+}
+\f
+
+/* for any user-defined fonts, if there was any PostScript that needs to
+ * be output in order to use the font, output that.
+ */
+
+static void
+setup_user_fonts()
+
+{
+       int f;
+       char buffer[BUFSIZ];
+
+       for (f = 0; f < MAXFONTS; f++) {
+               if (Fontinfo[f].fontfile != (FILE *) 0) {
+                       while (fgets(buffer, BUFSIZ, Fontinfo[f].fontfile)
+                                               != (char *) 0) {
+                               printf("%s", buffer);
+                       }
+                       fclose(Fontinfo[f].fontfile);
+               }
+       }
+}
+\f
+
+#ifdef EXTCHAR
+
+/* for each extended character set font that was used somewhere, output
+ * the PostScript to get that font set up so that is can be used.
+ */
+
+static void
+setup_extended_fonts()
+
+{
+       int i;                  /* font index */
+       int have_extended;      /* YES if extended character set was used
+                                * somewhere, and thus we have to output
+                                * PostScript to allow using the set */
+
+
+       /* First see if there are any extended characters used at all.
+        * If not, we don't have to do anything more here */
+       have_extended = NO;
+       for (i = FONT_TR; i <= EXT_FONT_OFFSET; i++) {
+               if (Font_used[i + EXT_FONT_OFFSET] == YES) {
+                       have_extended = YES;
+                       break;
+               }
+       }
+
+       if (have_extended == NO) {
+               return;
+       }
+
+       /* first call the PostScript function to set up the encoding
+        * array for the extended character set */
+       printf("\n%% set up extended character set fonts\n");
+       printf("makeExtEncoding\n");
+
+       /* now for each extended character set font that was actually used
+        * somewhere, call the PostScript function to set up that font,
+        * based on the font from which it is derived */
+       for (i = FONT_TR; i <= EXT_FONT_OFFSET; i++) {
+               if (Font_used[i + EXT_FONT_OFFSET] == YES) {
+                       /* arguments are the name of the extended font
+                        * and the name of the base font from which it
+                        * is derived */
+                       prfontname(i + EXT_FONT_OFFSET);
+                       prfontname(i);
+                       printf("makeExtendedFont\n");
+               }
+       }
+}
+#endif
+\f
+
+/* given a LINE struct, output commands to draw a line */
+
+static void
+pr_line(line_p, fname, lineno)
+
+struct LINE *line_p;   /* info about what kind of line to draw and where */
+char *fname;           /* file name for error messages */
+int lineno;            /* line number for error messages */
+
+{
+       double x1, y1;  /* beginning of line */
+       double x2, y2;  /* end of line */
+
+       x1 = inpc_x( &(line_p->start), fname, lineno);
+       y1 = inpc_y( &(line_p->start), fname, lineno);
+       x2 = inpc_x( &(line_p->end), fname, lineno);
+       y2 = inpc_y( &(line_p->end), fname, lineno);
+
+       /* If there is a string associated with the line,
+        * print that first.
+        */
+       if (line_p->string != 0) {
+               double line_len;        /* length of line in LINE struct */
+               double str_x, str_y;    /* where string starts */
+
+               /* First find length of line. */
+               line_len = sqrt(SQUARED(x2 - x1) + SQUARED(y2 - y1));
+               if (x2 < x1) {
+                       line_len = -line_len;
+               }
+
+               /* For now, pretend the line is horizontal, starting
+                * at (x1,y1). The horizontal middle of the string should then
+                * be at the midpoint of the line, and the left edge of the
+                * string should be half the string width left of that.
+                * The vertical is a STEPSIZE above the line.
+                */
+               str_x = (line_len / 2.0) - (strwidth(line_p->string) / 2.0);
+               str_y = STEPSIZE + strdescent(line_p->string);
+
+               /* move effective origin of coordinate system to (x1,y1),
+                * then rotate by the appropriate angle and print string.
+                */
+               outop(O_GSAVE);
+               outcoord(x1);
+               outcoord(y1);
+               outop(O_TRANSLATE);
+               /* calculate angle. If vertical line or nearly so,
+                * avoid division by zero */
+               if (fabs(x2 - x1) < .001) {
+                       outint(90);
+               }
+               else {
+                       OUTP(("%.1f ", atan( (y2 - y1) / (x2 - x1) ) * 180.0 / PI));
+               }
+               
+               outop(O_ROTATE);
+               pr_string(str_x, str_y, line_p->string, J_LEFT, 0, -1);
+               outop(O_GRESTORE);
+       }
+
+       /* wavy lines are special case */
+       if (line_p->linetype == L_WAVY) {
+               draw_wavy(x1, y1, x2, y2);
+               return;
+       }
+
+       /* set line width to specified width and type, then draw the line */
+       do_linetype(line_p->linetype);
+       draw_line (x1, y1, x2, y2);
+
+       /* make sure line type gets set back to solid */
+       if (line_p->linetype == L_DASHED || line_p->linetype == L_DOTTED) {
+               do_linetype(L_NORMAL);
+       }
+}
+\f
+
+/* generate PostScript command to tell what kind of line to draw */
+
+void
+do_linetype(ltype)
+
+int ltype;             /* L_WIDE, L_NORMAL, etc  */
+
+{
+       if (Last_linetype == ltype && Last_staffscale == Staffscale) {
+               /* same as last time, no need to tell the printer again */
+               return;
+       }
+
+       /* output command for proper width/type of line */
+       switch(ltype) {
+
+       case L_WIDE:
+               OUTP(("%4.2f ", W_WIDE * Staffscale));
+               outop(O_LINEWIDTH);
+               break;
+
+       case L_NORMAL:
+               OUTP(("%4.2f ", W_NORMAL * Staffscale));
+               outop(O_LINEWIDTH);
+               break;
+
+       case L_MEDIUM:
+               OUTP(("%4.2f ", W_MEDIUM * Staffscale));
+               outop(O_LINEWIDTH);
+               break;
+
+       case L_DOTTED:
+               OUTP(("%4.2f ", Staffscale));
+               outop(O_LINEWIDTH);
+               outop(O_DOTTED);
+               Doing_dotted = YES;
+               break;
+
+       case L_DASHED:
+               OUTP(("%4.2f ", Staffscale));
+               outop(O_LINEWIDTH);
+               outop(O_DASHED);
+               Doing_dotted = YES;
+               break;
+
+       default:
+               pfatal("unknown line type");
+               break;
+       }
+
+       /* remember current line type */
+       Last_linetype = ltype;
+       Last_staffscale = Staffscale;
+
+       /* if was doing dotting but not anymore, tell PostScript */
+       if (Doing_dotted && (ltype != L_DOTTED) && (ltype != L_DASHED)) {
+               Doing_dotted = NO;
+               outop(O_ENDDOTTED);
+       }
+}
+\f
+
+/* output commands for drawing a line. Resulting output is:
+ *     x1 y1 moveto x2 y2 lineto stroke */
+
+void
+draw_line(x1, y1, x2, y2)
+
+double x1, y1; /* draw line from here */
+double x2, y2; /* to here */
+
+{
+       dr_line( (double) x1, (double) y1, (double) x2, (double) y2, O_LINE);
+}
+
+
+/* output commands to draw a line whose width is proportional to the given
+ * point size */
+
+void
+draw_prop_line(x1, y1, x2, y2, size, ltype)
+
+double x1, y1; /* draw line from here */
+double x2, y2; /* to here */
+int size;      /* make width proportional to this */
+int ltype;     /* O_LINE, etc */
+
+{
+       /* temporarily change the line width, then draw the line */
+       outop(O_GSAVE);
+       OUTP(("%.2f ", (double) size * 0.065 * Staffscale));
+       outop(O_LINEWIDTH);
+       dr_line(x1, y1, x2, y2, O_LINE);
+       outop(O_GRESTORE);
+}
+\f
+
+/* draw a wavy line. Resulting output is:
+ *     x1 y1 moveto x2 y2 wavy */
+
+void
+draw_wavy(x1, y1, x2, y2)
+
+double x1;
+double y1;     /* draw wavy line from x1,y1 */
+double x2;
+double y2;     /* to x2, y2 */
+
+{
+       dr_line((double) x1, (double) y1, (double) x2, (double) y2, O_WAVY);
+}
+\f
+
+/* actually draw line. Common function for drawing regular or wavy lines */
+
+static void
+dr_line(x1, y1, x2, y2, ltype)
+
+double x1;
+double y1;     /* draw line from x1,y1 */
+double x2;
+double y2;     /* to x2,y2 */
+int ltype;     /* O_LINE, etc */
+
+{
+
+       /* output coordinates */
+       outcoord(x1);
+       outcoord(y1);
+       outop(O_MOVETO);
+
+       outcoord(x2);
+       outcoord(y2);
+       outop(ltype);
+
+       /* current location is where line ended */
+       set_cur(x2, y2);
+}
+\f
+
+/* output commands to draw a curve */
+
+static void
+pr_curve(curve_p, fname, lineno)
+
+struct CURVE *curve_p; /* which curve */
+char *fname;           /* file name for error messages */
+int lineno;            /* line number for error messages */
+
+{
+       struct INPCOORD *inpcoord_p;
+       int n;
+       float *xlist, *ylist;
+       float cwid;             /* curve width */
+       int taper;              /* YES or NO */
+
+
+       /* pr_allcurve() expects lists of X and Y coordinates, so
+        * get some space for those lists,  and fill them in.
+        * Call pr_allcurve() to print the curve, then free the lists */
+       MALLOCA(float, xlist, curve_p->ncoord);
+       MALLOCA(float, ylist, curve_p->ncoord);
+       for (n = 0; n < curve_p->ncoord; n++) {
+               inpcoord_p = &(curve_p->coordlist[n]);
+               xlist[n] = inpc_x(inpcoord_p, fname, lineno);
+               ylist[n] = inpc_y(inpcoord_p, fname, lineno);
+       }
+       switch(curve_p->curvetype) {
+       case L_NORMAL:
+               cwid = W_NORMAL / PPI;
+               taper = YES;
+               break;
+       case L_MEDIUM:
+               cwid = W_MEDIUM / PPI;
+               taper = YES;
+               break;
+       case L_WIDE:
+               cwid = W_WIDE / PPI;
+               taper = YES;
+               break;
+       case L_DASHED:
+               cwid = 1.0 / PPI;
+               taper = NO;
+               do_linetype(L_DASHED);
+               break;
+       case L_DOTTED:
+               cwid = 1.0 / PPI;
+               taper = NO;
+               do_linetype(L_DOTTED);
+               break;
+       default:
+               pfatal("unknown curve type");
+               /*NOTREACHED*/
+               return;
+       }
+       /* adjust for current staff scaling */
+       cwid *= Staffscale;
+
+       pr_allcurve(xlist, ylist, curve_p->ncoord, cwid, taper);
+       FREE(xlist);
+       FREE(ylist);
+       /* make sure line type gets set back to solid */
+       if (curve_p->curvetype == L_DASHED || curve_p->curvetype == L_DOTTED) {
+               do_linetype(L_NORMAL);
+       }
+}
+\f
+
+/* functions to do common PostScript things */
+
+void
+do_moveto(x, y)
+
+double x;
+double y;
+
+{
+       outcoord(x);
+       outcoord(y);
+       outop(O_MOVETO);
+}
+
+
+void
+do_line(x, y)
+
+double x;
+double y;
+
+{
+       outcoord(x);
+       outcoord(y);
+       outop(O_LINETO);
+}
+
+void
+do_curveto(x1, y1, x2, y2, x3, y3)
+
+double x1, y1;
+double x2, y2;
+double x3, y3;
+
+{
+       outcoord(x1);
+       outcoord(y1);
+       outcoord(x2);
+       outcoord(y2);
+       outcoord(x3);
+       outcoord(y3);
+       outop(O_CURVETO);
+}
+
+
+void
+do_stroke()
+
+{
+       outop(O_STROKE);
+}
+
+void
+do_fill()
+
+{
+       outop(O_FILL);
+}
+
+void
+do_newpath()
+
+{
+       outop(O_NEWPATH);
+}
+
+void
+do_closepath()
+
+{
+       outop(O_CLOSEPATH);
+}
+
+/* output a PostScript scale command */
+
+static void
+do_scale(xscale, yscale)
+
+double xscale, yscale;
+
+{
+       OUTP(("%0.6f %0.6f ", xscale, yscale));
+       outop(O_SCALE);
+}
+
+/* print a white box with the corners given */
+
+void
+do_whitebox(x1, y1, x2, y2)
+
+double x1, y1;
+double x2, y2;
+
+{
+       outcoord(x1);
+       outcoord(y1);
+       outcoord(x2);
+       outcoord(y2);
+       OUTP(("whitebox\n"));
+}
+\f
+
+/* output PostScript to draw a guitar grid */
+
+void
+do_grid(x, y, space, grid_p, staff)
+
+double x;
+double y;
+double space;  /* distance between lines of the grid */
+struct GRID *grid_p;
+int staff;
+
+{
+       int s;
+       int fret, fretnum, numvert;
+       int topfret;
+
+       outcoord(x);
+       outcoord(y);
+       outcoord(space);
+
+       gridinfo(grid_p, staff, &fret, &fretnum, &numvert, &topfret);
+       outint(fret);
+       outint(fretnum);
+       outint(numvert);
+
+       /* the curve ends */
+       outint(grid_p->curvel);
+       outint(grid_p->curver);
+
+       /* fret value for each string in a PostScript array */
+       OUTP(("[ "));
+       for (s = 0; s < grid_p->numstr; s++) {
+               if (grid_p->positions[s] <= 0) {
+                       outint(grid_p->positions[s]);
+               }
+               else {
+                       outint(grid_p->positions[s] - topfret);
+               }
+       }
+       OUTP(("] grid\n"));
+}
+\f
+
+/* output commands for printing one music character */
+
+void
+pr_muschar(x, y, ch, size, font)
+
+float x, y;    /* where to print */
+int ch;                /* which music character to print */
+int size;
+int font;      /* FONT_MUSIC*   */
+
+{
+       outp_muschar(x, y, ch, size, font);
+
+       /* x of music char is in middle, so set current to right edge */
+       size = adj_size(size, Staffscale, (char *) 0, -1);
+       set_cur(x + width(font, size, ch) / 2.0, y);
+}
+\f
+
+/* Output PostScript to print a music character. Common part for
+ * normal and italic versions of the character. */
+
+static void
+outp_muschar(x, y, ch, size, font)
+
+double x, y;
+int ch;
+int size;
+
+{
+       double scaling;
+
+       /* tell where to print it */
+       outcoord( (double) x);
+       outcoord( (double) y);
+
+       if (size == DFLT_SIZE) {
+               scaling = Staffscale;
+       }
+       else {
+               scaling = (double) size * Staffscale / (double) DFLT_SIZE;
+       }
+       OUTP(("%f ", scaling));
+
+       /* output the symbolic name of the music character */
+       OUTP(("%s\n", mc_num2name(ch, font)));
+}
+\f
+
+/* Print an italic music character. We do this by constructing an
+ * appropriate PostScript transform matrix and then printing the character.
+ * The transform matrix takes the rectangle that bounds the character,
+ * widens it slightly, and and turns it into a parallelogram
+ * slanted by 15 degrees.
+ *    ----------          ---------
+ *    |        |  -->    /       /
+ *    |        |        /       /
+ *    ----------        --------
+ */
+
+static void
+pr_ital_muschar(x, y, ch, size, font)
+
+double x, y;   /* where to print */
+int ch;                /* which music character to print */
+int size;
+int font;      /* MUSIC_FONT*  */
+
+{
+       float chwidth, chheight;
+       float adj;              /* distance top left is moved to get slant */
+       float inc;              /* increment on width */
+       float a, c;             /* for transform equation  x' = ax + cy + t  */
+       int eff_size;
+
+
+       eff_size = adj_size(size, Staffscale, (char *) 0, -1);
+       chheight = height(font, eff_size, ch);
+       chwidth = width(font, eff_size, ch);
+       /* Widen some so doesn't look so cramped. This may 
+        * encroach on neighboring characters, but if they are italic
+        * too--which they probably are--they probably slant enough
+        * to stay out of the way. */
+       inc = MIN(chwidth, chheight * 0.8) / 4.0;
+
+       /* we want to slant by 15 degrees, so use tangent of 15 degrees */
+       adj = chheight * 0.27;
+       /* if character is really narrow, don't slant so much--
+        * don't squeeze character to less than half its original width */
+       if (adj > chwidth / 2.0) {
+               adj = chwidth / 2.0;
+       }
+       
+       /* Temporarily change the transform matrix.
+        * The y value is unchanged by the transform.
+        * The new x is
+        *      x' = ax + cy + t
+        * where t is 0, and a and c are as stated below.
+        */
+       a = (chwidth + 2 * inc - adj) / chwidth;
+       c = adj / chheight;
+
+       outop(O_GSAVE);
+       OUTP(("[ %f 0.0 %f 1.0 0.0 0.0 ] ", a, c));
+       outop(O_CONCAT);
+
+       /* The x location will get adjusted by the new transform matrix,
+        * so we have to compensate so it will appear where it should.
+        * We take the PostScript transform matrix equation given above,
+        * then set x' to the x value that was passed in to us,
+        * and rearrange to solve for x.
+        */
+       outp_muschar((x - c * y) / a, y, ch, size, font);
+
+       /* return to previous transform matrix */
+       outop(O_GRESTORE);
+
+       /* x of music char is in middle, so set current to right edge */
+       set_cur(x + width(font, eff_size, ch) / 2.0, y);
+}
+\f
+
+/* print bar line */
+
+static void
+pr_bar(mll_p, x, is_pseudobar)
+
+struct MAINLL *mll_p;  /* print bar connected here */
+double x;              /* x coordinate */
+int is_pseudobar;      /* YES if is pseudobar at beginning of score */
+
+{
+       register int s;         /* staff number */
+       register int n;         /* index into range list */
+       struct BAR *bar_p;      /* info about the bar */
+       struct MAINLL *m_p;     /* to walk through main list */
+       int next_is_restart = NO;       /* if following bar is a restart */
+
+
+       debug(512, "pr_bar");
+
+       if (is_pseudobar == YES) {
+               bar_p = mll_p->u.clefsig_p->bar_p;
+       }
+       else {
+               bar_p = mll_p->u.bar_p;
+       }
+
+       /* We need to know if the following bar (if any) is a restart,
+        * because then this one will have to be handled like it is at
+        * the right margin, so find out. */
+       for (m_p = mll_p->next; m_p != (struct MAINLL *) 0; m_p = m_p->next) {
+               if (m_p->str == S_FEED) {
+                       /* If there was a restart, it's been moved to this
+                        * feed and is thus now irrelevant. */
+                       break;
+               }
+               /* If there is a clefsig, then even if there is a restart
+                * we should not remove this bar's right padding--
+                * there is still some staff after it for the
+                * clef/keysig/time (whatever subset is specified by clefsig),
+                * and moving the bar would cause them to get too close. */
+               if (m_p->str == S_CLEFSIG) {
+                       break;
+               }
+               if (m_p->str == S_BAR) {
+                       if (m_p->u.bar_p->bartype == RESTART) {
+                               next_is_restart = YES;
+                       }
+                       /* we've looked ahead far enough */
+                       break;
+               }
+       }
+
+       /* go down the bar list and the list of staffs */
+       for (s = 1, n = 0; n < Score.nbarst; n++) {
+
+               /* everything up to next range is barred individually */
+               for (   ; s < Score.barstlist[n].top; s++) {
+                       pr_bar_range(bar_p, s, s, (double) x, next_is_restart, mll_p);
+               }
+
+               /* everything in the range is barred together */
+               pr_bar_range(bar_p, Score.barstlist[n].top,
+                       Score.barstlist[n].bottom, x, next_is_restart, mll_p);
+               s = Score.barstlist[n].bottom + 1;
+       }
+
+       /* any remaining are barred individually */
+       for (   ; s <= Score.staffs; s++) {
+               pr_bar_range(bar_p, s, s, (double) x, next_is_restart, mll_p);
+       }
+
+       /* If user specified a measure number use that */
+       if (bar_p->mnum > 0) {
+               Meas_num = bar_p->mnum;
+       }
+       /* if basictime of the last STAFF we saw was < -1, then
+        * it was a multirest, so the measure number needs to
+        * be incremented by the number of measures of multirest.
+        * Since this is stored as a negative, we subtract the
+        * negative to get the same effect as adding the absolute
+        * value */
+       else if ( (Last_staff != (struct STAFF *) 0)
+                       && (is_pseudobar == NO)
+                       && (Last_staff->groups_p[0] != (struct GRPSYL *) 0)
+                       && (Last_staff->groups_p[0]->basictime < -1) ) {
+               Meas_num -= Last_staff->groups_p[0]->basictime;
+       }
+       else if ((bar_p->bartype != INVISBAR) && (bar_p->bartype != RESTART)
+                                               && (is_pseudobar == NO)) {
+               /* normal case, not multirest; just increment measure number */
+               Meas_num++;
+       }
+
+       /* print rehearsal mark if any */
+       if (is_pseudobar == NO) {
+               pr_reh(mll_p);
+       }
+
+       /* take care of pedal marks for the measure */
+       if (is_pseudobar == NO) {
+               pr_ped_bar(mll_p, bar_p);
+       }
+}
+\f
+
+/* given a range of staffs to bar together, find which are visible and from
+ * that, the y-coordinates of the ends of the bar line, and draw it */
+
+static void
+pr_bar_range(bar_p, topstaff, botstaff, x, next_is_restart, mll_p)
+
+struct BAR *bar_p;     /* info about bar */
+int topstaff;          /* top staff to be barred together */
+int botstaff;          /* bottom staff to be barred together */
+double x;              /* x coordinate of where to draw the bar */
+int next_is_restart;   /* YES if following bar is RESTART */
+struct MAINLL *mll_p;  /* to get effective margin */
+
+{
+       float y1, y2;           /* top and bottom of bar line */
+       float halfbarwidth;     /* half the width of the bar line */
+       int staffno;
+       int stafflines;
+
+
+       /* check for null pointer to avoid core dumps */
+       if (Score_location_p == (float *) 0) {
+               pfatal("can't print bar: no feed");
+               return;
+       }
+
+       /* Normally, we want some padding on both sides of a bar line,
+        * but at the end of a staff, we don't want right padding.
+        * This applies either if we are at the right
+        * margin or if the next bar is a restart. */
+       halfbarwidth = width_barline(bar_p) / 2.0;
+       /* Make sure bars line at end of score are precisely at the end */
+       if (PGWIDTH - eff_rightmargin(mll_p) - x <= halfbarwidth + 3.0 * STDPAD) {
+               /* Should only hit this now if there is a bug in placement
+                * of last bar line in a score, but since we changed how
+                * that is determined, better safe than sorry. */
+               x = PGWIDTH - eff_rightmargin(mll_p) - halfbarwidth
+                                                       + eos_bar_adjust(bar_p);
+       }
+
+       /* Similarly, make sure bars line just before a restart
+        * are precisely at the point where the restart whitebox starts. */
+       if (next_is_restart) {
+               struct MAINLL *m_p;
+
+               /* find the restart */
+               for (m_p = mll_p; m_p != 0; m_p = m_p->next) {
+                       if (m_p->str == S_BAR && m_p->u.bar_p->bartype == RESTART) {
+                               if (m_p->u.bar_p->c[AX] - HALF_RESTART_WIDTH
+                                               - m_p->u.bar_p->padding - x
+                                               <= halfbarwidth + 2.0 * STDPAD) {
+                                       x = m_p->u.bar_p->c[AX]
+                                                       - HALF_RESTART_WIDTH
+                                                       - m_p->u.bar_p->padding
+                                                       - halfbarwidth
+                                                       + eos_bar_adjust(bar_p);
+                               }
+                               break;
+                       }
+               }
+       }
+
+       /* go through the range of staffs */
+       /* Note: y2 doesn't really need to be set here, it's just to shut up
+        * compilers that think it could be used without being set. */
+       for (y1 = y2 = -1.0, staffno = topstaff; staffno <= botstaff; staffno++) {
+
+               /* only worry about visible staffs */
+               if ( (svpath(staffno, VISIBLE))->visible == YES) {
+
+                       stafflines = svpath(staffno, STAFFLINES)->stafflines;
+                       set_staffscale(staffno);
+
+                       /* if hadn't found any staff yet to bar, now we have */
+                       if (y1 < 0.0) {
+                               if (stafflines < 2) {
+                                       y1 = Staffs_y[staffno] +
+                                                       (2.0 * Stepsize);
+                               }
+                               else {
+                                       y1 = Staffs_y[staffno] +
+                                               (stafflines - 1) * Stepsize
+                                               * (is_tab_staff(staffno) ?
+                                               TABRATIO : 1.0);
+                                       /* 2-line staffs get a bit more, so
+                                        * repeat sign dots have something
+                                        * to be next to */
+                                       if (stafflines == 2) {
+                                               y1 += 2 * Stepsize;
+                                       }
+                               }
+                       }
+
+                       /* this is the bottom one found so far */
+                       if (stafflines < 2) {
+                               y2 = Staffs_y[staffno] - (2.0 * Stepsize);
+                       }
+                       else {
+                               y2 = Staffs_y[staffno] -
+                                       (stafflines - 1) * Stepsize *
+                                       (is_tab_staff(staffno) ? TABRATIO : 1.0);
+                               if (stafflines == 2) {
+                                       y2 -= 2 * Stepsize;
+                               }
+                       }
+
+                       /* if repeat, print the dots */
+                       pr_repeat_dots(bar_p->bartype, staffno, (double) x);
+               }
+       }
+
+       /* if any were visible, we draw the bar line now */
+       if (y1 > 0.0) {
+               draw_bar(bar_p->bartype, bar_p->linetype,
+                                       (double) x, (double) y1, (double) y2);
+       }
+}
+\f
+
+/* actually draw a bar line of the proper type at specified place */
+
+/*--- Note: any changes in width made here have to be reflected in
+ * pr_bar_range() for adjustment when at right edge of page, and
+ * in width_barline() */
+
+static void
+draw_bar(bartype, linetype, x, y1, y2)
+
+int bartype;   /* info about single, double, repeat, etc */
+int linetype;
+double x;
+double y1;     /* top of bar line */
+double y2;     /* bottom of bar line */
+
+{
+       /* always use default staffscale for bar lines since they are
+        * not associated with any particular staff */
+       set_staffscale(0);
+       do_linetype(linetype);
+       /* dashed/dotted look better if we offset them slightly */
+       if (linetype == L_DASHED || linetype == L_DOTTED) {
+               y1 -= Stepsize * 0.375;
+               y2 += Stepsize * 0.1;
+       }
+
+       switch (bartype) {
+
+       case DOUBLEBAR:
+               draw_line(x - 2.0 * STDPAD, y1, x - 2.0 * STDPAD, y2);
+               draw_line(x + STDPAD, y1, x + STDPAD, y2);
+               break;
+
+       case SINGLEBAR:
+               draw_line(x, y1, x, y2);
+               break;
+
+       case REPEATSTART:
+               draw_line(x + STDPAD, y1, x + STDPAD, y2);
+               do_linetype(L_WIDE);
+               draw_line(x - (3.0 * STDPAD), y1, x - (3.0 * STDPAD), y2);
+               break;
+
+       case REPEATEND:
+               draw_line(x, y1, x, y2);
+               do_linetype(L_WIDE);
+               draw_line(x + (4.0 * STDPAD), y1, x + (4.0 * STDPAD), y2 );
+               break;
+
+       case REPEATBOTH:
+               do_linetype(L_WIDE);
+               draw_line(x - (2.5 * STDPAD), y1, x - (2.5 * STDPAD), y2);
+               draw_line(x + (2.5 * STDPAD), y1, x + (2.5 * STDPAD), y2);
+               break;
+
+       case ENDBAR:
+               draw_line(x - (2.0 * STDPAD), y1, x - (2.0 * STDPAD), y2);
+               do_linetype(L_WIDE);
+               draw_line(x + (2.0 * STDPAD), y1, x + (2.0 * STDPAD), y2);
+               break;
+
+       case RESTART:
+               /* This is a "funny" bar that is drawn when the staff lines
+                * are printed, so there isn't anything to be done here. */
+               break;
+
+       case INVISBAR:
+               /* nothing to do! */
+               break;
+
+       default:
+               pfatal("bad bar type");
+       }
+       do_linetype(L_NORMAL);
+}
+\f
+
+/* print the dots for a repeat sign */
+
+static void
+pr_repeat_dots(bartype, staff, x)
+
+int bartype;   /* repeatstart, repeatend, repeatboth, etc */
+int staff;     /* which staff to print on */
+double x;      /* horizontal position */
+
+{
+       float y;        /* vertical position of middle of staff */
+       double topoffset, bottomoffset;         /* dot offset */
+       double adjust;          /* adjustment for tablature and/or staffscale */
+       int stafflines;
+       
+
+       /* If no dots, don't bother */
+       if (bartype != REPEATSTART && bartype != REPEATEND
+                                               && bartype != REPEATBOTH) {
+               return;
+       }
+
+       if (Score_location_p == (float *) 0) {
+               /* this should never be hit--we already checked earlier */
+               pfatal("can't do repeat: no feed");
+               return;
+       }
+
+       /* get y offset based on staff */
+       y = Staffs_y[staff];
+       adjust = Stepsize * (is_tab_staff(staff) ? TABRATIO : 1.0);
+       bottomoffset = topoffset = adjust;
+
+       /* if even number of staff lines, compensate by moving up */
+       stafflines = svpath(staff, STAFFLINES)->stafflines;
+       if ( (stafflines & 1) == 0) {
+               y += adjust;
+       }
+
+       /* if more than 5 lines on staff, leave one blank space between
+        * the dots */
+       if (stafflines > 5) {
+               if ( (stafflines & 1) == 0) {
+                       /* even number of staff lines, move bottom down */
+                       bottomoffset = 3 * adjust;
+               }
+               else {
+                       /* odd number of lines, move top up */
+                       topoffset = 3 * adjust;
+               }
+       }
+       
+
+       /* print dots at appropriate locations */
+       switch(bartype) {
+
+       case REPEATSTART:
+               do_rdots((double) (x + (4.0 * STDPAD)), (double) y, topoffset,
+                                       bottomoffset);
+               break;
+
+       case REPEATBOTH:
+               do_rdots((double) (x + (7.0 * STDPAD)), (double) y, topoffset,
+                                       bottomoffset);
+               do_rdots((double) (x - (7.0 * STDPAD)), (double) y, topoffset,
+                                       bottomoffset);
+               break;
+
+       case REPEATEND:
+               do_rdots((double) (x - (4.0 * STDPAD)), (double) y, topoffset,
+                                       bottomoffset);
+               break;
+
+       default:
+               /* other types of bars don't have dots */
+               break;
+       }
+}
+\f
+
+/* print the 2 dots for a repeat sign */
+
+static void
+do_rdots(x, y, topoffset, bottomoffset)
+
+double x;
+double y;      /* y is a middle of staff, so offset from there */
+double topoffset, bottomoffset;                /* offset from y in each direction */
+
+{
+       pr_muschar(x, y + topoffset, C_DOT, DFLT_SIZE, FONT_MUSIC);
+       pr_muschar(x, y - bottomoffset, C_DOT, DFLT_SIZE, FONT_MUSIC);
+}
+\f
+
+/* print any rehearsal marks associated with bar line */
+
+static void
+pr_reh(mll_p)
+
+struct MAINLL *mll_p;  /* current bar line is off of here */
+
+{
+       struct MARKCOORD *mark_p;       /* where to put rehearsal mark */
+       float y;                        /* vertical location */
+       struct BAR *bar_p;
+       char *str;                      /* the string, with box or circle
+                                        * or nothing as appropriate for
+                                        * the associated staff */
+
+
+       if (mll_p->str == S_BAR) {
+               bar_p = mll_p->u.bar_p;
+       }
+       else {
+               bar_p = mll_p->u.clefsig_p->bar_p;
+       }
+
+       for (mark_p = bar_p->reh_p; mark_p != (struct MARKCOORD *) 0;
+                                       mark_p = mark_p->next) {
+
+               /* print rehearsal mark if any */
+               if (bar_p->reh_string != (char *) 0) {
+
+                       y = Staffs_y[mark_p->staffno] + mark_p->ry;
+
+                       /* get boxed or circled version if appropriate */
+                       str = get_reh_string(bar_p->reh_string, mark_p->staffno);
+                       pr_string((double) bar_p->c[AX] - left_width(str),
+                                       (double) y, str, J_LEFT,
+                                       mll_p->inputfile, mll_p->inputlineno);
+               }
+       }
+}
+\f
+
+/* draw a box of given size at given x,y */
+
+static void
+pr_box(x, y, boxheight, boxwidth)
+
+double x, y;
+double boxheight, boxwidth;
+
+{
+       do_linetype(L_NORMAL);
+       do_newpath();
+       do_moveto(x, y);
+       do_line(x, y + boxheight);
+       do_line(x + boxwidth, y + boxheight);
+       do_line(x + boxwidth, y);
+       do_closepath();
+       do_stroke();
+}
+\f
+
+/* do a feed (newscore and maybe newpage) */
+
+void
+pr_feed(main_feed_p)
+
+struct MAINLL *main_feed_p;    /* MAINLL struct pointing to FEED */
+
+{
+       register int s;         /* walk through staffs */
+       float lowest_y = 0.0;   /* y coord of bottom staff. Initialization is
+                                * solely to shut up bogus compiler warning */
+       float highest_y = 0.0;
+       int printed;            /* How many staffs printed so far */
+       int had_br_br;          /* YES if had braces and/or brackets printed */
+       int need_vert_line = NO;        /* if need line at left edge */
+       struct FEED *feed_p;
+       int stafflines;
+       double y;
+
+
+       debug(256, "pr_feed lineno=%d", main_feed_p->inputlineno);
+
+       feed_p = main_feed_p->u.feed_p;
+
+       /* If user put top/bottom or newpage at the very end of the file,
+        * we could end up with a page with nothing but header/footer.
+        * So if there is no good reason to do another page, we don't. */
+       if (Atend_info.separate_page == NO && main_feed_p->next == 0) {
+               /* Nothing at all after the feed,
+                * so no need to make another page. */
+               return;
+       }
+
+       /* if doing a page feed, print the headers and footers on the
+        * current page and move on to the next one */
+       if (feed_p->pagefeed == YES) {
+               newpage(main_feed_p);
+       }
+
+       /* If there is a top and/or bot block, print those.
+        * Even though from user's viewpoint the current page may
+        * use top2/bot2, placement phase will have set top_p/bot_p
+        * to whatever is appropriate for this page.
+        */
+       if (feed_p->top_p != 0) {
+               y = PGHEIGHT - EFF_TOPMARGIN
+                       - (Feednumber == 1 ? Header.height : Header2.height);
+               pr_topbot(feed_p->top_p, y);
+       }
+       if (feed_p->bot_p != 0) {
+               y = EFF_BOTMARGIN + feed_p->bot_p->height
+                       + (Feednumber == 1 ? Footer.height : Footer2.height);
+               pr_topbot(feed_p->bot_p, y);
+       }
+
+       if (main_feed_p->next == 0) {
+               /* Feed at end of piece, presumably to force
+                * gridsatend onto separate page or something like that */
+               return;
+       }
+       if (main_feed_p->next->str != S_CLEFSIG) {
+               /* Must be BLOCKHEAD or lines/curves at end of file.
+                * In any case, no actual music staffs to print. */
+               return;
+       }
+
+       /* now do score feed stuff */
+       /* keep track of where the staffs are: we need this for
+        * drawing lots of other things relative to the staffs */
+       Score_location_p = feed_p->c;
+       set_staff_y(main_feed_p);
+
+       if (Feednumber == 1 && Meas_num == 1) {
+               /* first time through. See if the song begins with a
+                * "pickup" measure, i.e., its first chord is all spaces.
+                * If so, don't count that measure in measure number. */
+               if (has_pickup() == YES) {
+                       Meas_num--;
+               }
+       }
+
+       /* for each staff */
+       for ( printed = 0, s = 1; s <= Score.staffs; s++) {
+
+               /* print if visible */
+               if ( (svpath(s, VISIBLE))->visible == YES) {
+
+                       stafflines = svpath(s, STAFFLINES)->stafflines;
+                       set_staffscale(s);
+                       if (stafflines < 3) {
+                               lowest_y = Staffs_y[s] - (2.0 * Stepsize)
+                                       * (is_tab_staff(s) ? TABRATIO : 1.0);
+                       }
+                       else {
+                               lowest_y = Staffs_y[s] - (stafflines - 1)
+                                       * Stepsize * (is_tab_staff(s) ?
+                                       TABRATIO : 1.0);
+                       }
+
+                       /* find the top of the score */
+                       if (printed == 0) {
+                               if (stafflines < 3) {
+                                       highest_y = Staffs_y[s]
+                                       + (2.0 * Stepsize)
+                                       * (is_tab_staff(s) ? TABRATIO : 1.0);
+                               }
+                               else {
+                                       highest_y = Staffs_y[s]
+                                       + (stafflines - 1)
+                                       * Stepsize * (is_tab_staff(s) ?
+                                       TABRATIO : 1.0);
+                               }
+                       }
+
+                       printed++;
+
+                       outcoord( (double) (Score_location_p[AX] + x1a));
+                       outcoord( (double) (Staffs_y[s] + ya));
+                       outcoord( (double) (Score_location_p[AE] + x2a));
+                       OUTP(("%d %f %f ", svpath(s, STAFFLINES)->stafflines,
+                               (is_tab_staff(s) == YES ? TABRATIO : 1.0),
+                               Staffscale));
+                       outop(O_STAFF);
+
+                       /* print measure number at beginning of staff if
+                        * necessary */
+                       pr_meas_num(s, Score_location_p[AX]);
+               }
+       }
+
+       /* print brace/bracket and group label */
+       had_br_br = pr_brac(NO, 0.0, main_feed_p);
+
+       if (printed == 0) {
+               /* we check for this earlier, so should never hit this */
+               pfatal("no staffs visible");
+       }
+
+       /* draw vertical line at left edge of staffs */
+       /* but don't draw if only one staff and no brace/bracket */
+       if ((printed > 1) || (had_br_br != NO)) {
+               need_vert_line = YES;
+               do_linetype(L_NORMAL);
+               draw_line(Score_location_p[AX], highest_y,
+                                       Score_location_p[AX],  lowest_y);
+       }
+
+       pr_restarts(main_feed_p, highest_y, lowest_y, need_vert_line);
+
+       /* set current to x,y of score */
+       set_cur(Score_location_p[AX], Score_location_p[AY]);
+}
+\f
+
+/* Given a BLOCKHEAD for a top/bottom and a y location, print the
+ * contents of the BLOCKHEAD at that location.
+ */
+
+static
+void pr_topbot(blockhead_p, y)
+
+struct BLOCKHEAD *blockhead_p;
+double y;
+
+{
+       double x;
+
+       x = eff_leftmargin(0);
+       /* Set up window coordinates, go to upper left of window, and print */
+       set_win_coord(blockhead_p->c);
+       set_win(y, y - blockhead_p->height, PGWIDTH - eff_rightmargin(0), x);
+       set_cur(x, y);
+       pr_print(blockhead_p->printdata_p);
+       set_win_coord(0);
+}
+\f
+
+/* We want to print all the "restart" bars right after the staff lines,
+ * so in case anything spills into the white space we write over the staffs,
+ * it won't get obliterated. So find any restarts till the next feed and
+ * put out a whitebox and do and brace/backets and vertical line needed.
+ */
+
+static void
+pr_restarts(mll_p, y1, y2, need_vert_line)
+
+struct MAINLL *mll_p;
+double y1;
+double y2;
+int need_vert_line;
+
+{
+       double x;
+
+       for (mll_p = mll_p->next; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->next) {
+               if (mll_p->str == S_FEED) {
+                       /* we went far enough */
+                       return;
+               }
+
+               if (mll_p->str == S_BAR && mll_p->u.bar_p->bartype == RESTART) {
+                       x = mll_p->u.bar_p->c[AX];
+                       /* Expand the y dimensions to make sure we completely
+                        * erase the top and bottom staff lines. */
+                       do_whitebox(x - HALF_RESTART_WIDTH
+                                       - mll_p->u.bar_p->padding,
+                                       y1 + POINT,
+                                       x + HALF_RESTART_WIDTH, y2 - POINT);
+
+                       /* print braces/brackets */
+                       pr_brac(YES, x + POINT, mll_p);
+
+                       /* draw vertical line, if needed */
+                       x += HALF_RESTART_WIDTH - (W_NORMAL / PPI) / 2.0;
+                       if (need_vert_line == YES) {
+                               do_linetype(L_NORMAL);
+                               draw_line(x, y1, x,  y2);
+                       }
+
+               }
+       }
+}
+\f
+
+/* print a brace or bracket */
+
+void
+do_pr_brac(x, y1, y2, which)
+
+double x;      /* coordinates at which to draw brace or bracket */
+double y1;
+double y2;
+int which;     /* BRACELIST or BRACKLIST */
+
+{
+       outcoord(x);
+       outcoord(y1);
+       outcoord(y2);
+       outop( which == BRACELIST ? O_BRACE : O_BRACKET);
+}
+\f
+
+/* output a coordinate. Convert from inches to points, to 0.01 point accuracy */
+
+void
+outcoord(val)
+
+double val;            /* an x or y value */
+
+{
+       OUTP(("%.2f ", val * PPI));
+}
+\f
+
+
+/* output an integer value */
+
+static void
+outint(val)
+
+int val;
+
+{
+       OUTP(("%d ", val));
+}
+\f
+
+/* output a string to be printed. Have to walk through the string
+ * one character at a time, possibly breaking into several strings
+ * if there are font/size changes or music characters in the middle */
+
+static void
+outstring(x, y, fullwidth, string, fname, lineno)
+
+double x;      /* where to print string */
+double y;
+double fullwidth;      /* If bigger than the string's intrinsic width,
+                        * this is how much territory the string should take.
+                        * This is for creating a right justified paragraph.
+                        * For non-justified, you can pass a negative value,
+                        * which will certainly be smaller than intrinsic. */
+char *string;  /* what to print */
+char *fname;   /* file name for error messages */
+int lineno;    /* line number for error messages */
+
+{
+       int font, size, code;   /* for current character to print */
+       int code2;              /* another character in the string */
+       int textfont;           /* font disregarding music characters */
+       double vertical, horizontal;
+       double slash_x = 0.0, slash_y = 0.0; /* For slash through number.
+                                * Initialization is just to avoid bogus
+                                * "used before set" warning. It will be
+                                * set to a valid value before being used. */
+       double space_adjust = 0.0;      /* how much to add to spaces if
+                                        * doing paragraph justification */
+       double intrinsic_width;         /* before adding space_adjust */
+       int in_pile = NO;
+       int in_digit_string = NO;       /* YES if in a run of digits */
+       int in_string = NO;     /* YES if are outputting a string (i.e.,
+                                * have printed '(' and have not printed
+                                * matching ')'  */
+       char pgnumstr[12];      /* page number as a string. Make big enough
+                                * to allow some crazy person to use a page
+                                * number of 2^31. Actually, we now limit
+                                * the first page number to MAXFIRSTPAGE,
+                                * so unless the song is about a billion
+                                * pages long, this is vast overkill,
+                                * but stack space is cheap. */
+       float save_y;           /* temporarily remember y value */
+       int only_mus_sym;       /* YES if string is solely a music sym */
+       float mussym_compensation;      /* inside strings, music symbols
+                                * get moved up to the baseline */
+       float save_staffscale;
+
+
+       /* go to starting point of string */
+       outcoord( (double) x);
+       outcoord( (double) y);
+       outop(O_MOVETO);
+       set_cur(x, y);
+
+       /* check if consists solely of music character */
+       only_mus_sym = is_music_symbol(string);
+
+       intrinsic_width = strwidth(string);
+       if (lineno > 0) {
+               if (x + intrinsic_width > PGWIDTH || x < 0.0) {
+                       l_warning(fname, lineno,
+                                       "string extends beyond edge of page");
+               }
+       }
+       /* If we need to right justify, figure out how much to add to spaces */
+       if (fullwidth > intrinsic_width) {
+               char *s;        /* to walk through string */
+               int count;      /* number of space chars */
+
+               /* count how many spaces there are that we can stretch */
+               count = 0;
+               font = *string;
+               size = *(string + 1);
+               s = string + 2;
+               while ((code = next_str_char(&s, &font, &size) & 0xff) > 0) {
+                       if (code == ' ' && ! IS_MUSIC_FONT(font)) {
+                               count++;
+                       }
+               }
+               if (count > 0) {
+                       /* We have at least one space. Apportion needed
+                        * padding among the number of space chars. */ 
+                       space_adjust = (fullwidth - intrinsic_width) / 
+                                               (double) count;
+                       if (space_adjust < 0.0) {
+                               /* Hmmm. Apparently string is already
+                                * wider than it should be, so leave as is. */
+                               space_adjust = 0.0;
+                       }
+               }
+       }
+
+#ifdef SMALLMEMORY
+       /* to make sure string space is cleaned up as soon as possible,
+        * output the string inside a save/restore */
+       outop(O_SAVE);
+#endif
+
+       /* walk through and output chars one at a time */
+       font = *string;
+       size = *(string + 1);
+       string += 2;
+       while( (code = nxt_str_char(&string, &font, &size, &textfont, &vertical,
+                               &horizontal, &in_pile, YES) & 0xff) > 0) {
+               /* do motion, if needed */
+               if (vertical != 0.0 || horizontal != 0.0) {
+                       in_string = end_string(in_string, space_adjust);
+                       set_cur(_Cur[AX] + horizontal, _Cur[AY] + vertical);
+                       outcoord( _Cur[AX] );
+                       outcoord( _Cur[AY] );
+                       outop(O_MOVETO);
+                       in_digit_string = NO;
+               }
+
+               if ( (code & 0xff) == STR_SLASH) {
+                       if (in_digit_string == NO) {
+                               /* this should have been caught... */
+                               pfatal("STR_SLASH not after digits");
+                       }
+
+                       /* draw the slash */
+                       in_string = end_string(in_string, space_adjust);
+                       save_y = _Cur[AY];
+                       draw_prop_line(slash_x, slash_y, _Cur[AX],
+                               _Cur[AY] + 0.6 * fontascent(font, size),
+                               size, O_LINE);
+                       set_cur(_Cur[AX], save_y);
+                       outcoord( _Cur[AX] );
+                       outcoord( _Cur[AY] );
+                       outop(O_MOVETO);
+                       in_digit_string = NO;
+                       continue;
+               }
+
+               /* in case we need to draw a slash through digits
+                * (most likely for figured bass), keep track of where
+                * a run of digits begins */
+               if (isdigit(code)) {
+                       if (in_digit_string == NO) {
+                               in_digit_string = YES;
+                               /* calculate where to begin the slash
+                                * if we need to do one */
+                               slash_x = _Cur[AX];
+                               slash_y = _Cur[AY] +
+                                       0.2 * fontascent(font, size);
+                       }
+               }
+               else {
+                       in_digit_string = NO;
+               }
+
+               if (IS_MUSIC_FONT(font) ) {
+                       /* special music character */
+                       /* end this string, do the music character,
+                        * and start a new string */
+                       in_string = end_string(in_string, space_adjust);
+
+                       /* music characters are strange--their x
+                        * is in the middle instead of the
+                        * left edge, so compensate for that. Also,
+                        * when in strings, we want the bottom of
+                        * the music character to be at the baseline
+                        * of the text, even if it would normally
+                        * descend below. The (- STDPAD) is to account 
+                        * for the 1 point of vertical padding on
+                        * characters. */
+                       save_y = _Cur[AY];
+                       if (only_mus_sym == YES) {
+                               mussym_compensation = 0.0;
+                       }
+                       else {
+                               mussym_compensation = descent(
+                                       font, size, code) - STDPAD;
+                       }
+                       /* music characters embedded inside strings will have
+                        * already been size adjusted, so compensate. */
+                       save_staffscale = Staffscale;
+                       Staffscale = 1.0;
+                       if (is_ital_font(textfont) == YES)  {
+                               pr_ital_muschar(_Cur[AX] +
+                                       width(font, size, code)/2.0,
+                                       _Cur[AY] + mussym_compensation,
+                                       code, size, font);
+                       }
+                       else {
+                               pr_muschar(_Cur[AX] +
+                                       width(font, size, code)/2.0,
+                                       _Cur[AY] + mussym_compensation,
+                                       code, size, font);
+                       }
+                       Staffscale = save_staffscale;
+
+                       set_cur(_Cur[AX], save_y);
+                       outcoord( _Cur[AX] );
+                       outcoord( _Cur[AY] );
+                       outop(O_MOVETO);
+                       continue;
+               }
+
+               /* if font or size changed, do that */
+               if ( (font != Curr_font) || (size != Curr_size) ) {
+                       in_string = end_string(in_string, space_adjust);
+                       pr_font(font, size);
+               }
+
+               switch (code) {
+
+               case '(':
+               case ')':
+               case '\\':
+                       /* things that have to be backslashed */
+                       in_string = begin_string(in_string);
+                       OUTP(("\\%c", code));
+                       set_cur(_Cur[AX] + width(font, size, code), _Cur[AY]);
+                       break;
+
+               case '\b':
+                       /* backspace just changes position */
+                       in_string = end_string(in_string, space_adjust);
+                       set_cur(_Cur[AX] - backsp_width(size), _Cur[AY]);
+                       outcoord( _Cur[AX] );
+                       outcoord( _Cur[AY] );
+                       outop(O_MOVETO);
+                       break;
+
+               case '%':
+               case '#':
+                       /* If this is the special page number char,
+                        * of number of pages character, print the
+                        * appropriate page number. Have to back up by 2,
+                        * because string is already incremented beyond
+                        * the % or #. */
+                       code2 = *(string - 2) & 0xff;
+                       if ((code == '%' && code2 == STR_PAGENUM) ||
+                                       (code == '#' && code2 == STR_NUMPAGES)) {
+                               in_string = begin_string(in_string);
+                               OUTP(("%d", (code == '%'
+                                               ? Pagenum : Last_pagenum)));
+
+                               /* Figure out width and
+                                * set current location appropriately */
+                               pgnumstr[0] = (char) font;
+                               pgnumstr[1] = (char) size;
+                               (void) sprintf(pgnumstr + 2, "%d",
+                                       (code == '%' ? Pagenum : Last_pagenum));
+                               set_cur(_Cur[AX] + strwidth(pgnumstr),
+                                                               _Cur[AY]);
+                               break;
+                       }
+                       /* otherwise fall through to normal default case */
+                       /*FALLTHRU*/
+
+               default:
+                       if (code != '\n') {
+                               /* ordinary character */
+                               in_string = begin_string(in_string);
+                               OUTPCH(((unsigned char)code));
+                               set_cur(_Cur[AX] + width(font, size, code),
+                                               _Cur[AY]);
+                       }
+                       break;
+               }
+       }
+
+       (void) end_string(in_string, space_adjust);
+#ifdef SMALLMEMORY
+       outop(O_RESTORE);
+#endif
+}
+\f
+
+/* if haven't started a string yet, start one now, if already doing
+ * a string, just return */
+/* return YES to say we are inside doing a string */
+
+static int
+begin_string(in_string)
+
+int in_string; /* NO if not currently inside a string */
+
+{
+       if (in_string == NO) {
+               OUTPCH(('('));
+       }
+       return(YES);
+}
+\f
+
+/* if currently doing a string, end it. If not, just return */
+/* return NO to say we are no longer inside doing a string */
+
+static int
+end_string(in_string, space_adjust)
+
+int in_string;         /* YES if currently inside a string */
+double space_adjust;   /* if non-zero, use widthshow rather than show,
+                        * and use this as the x adjust for spaces */
+
+{
+       if (in_string == YES) {
+               OUTP((") "));
+               if (fabs(space_adjust) < .001) {
+                       /* Close enough to zero. In addition to handling the
+                        * normal case of no justification,
+                        * this handles floating point roundoff error,
+                        * or if the amount of padding needed
+                        * is too tiny to be worth the trouble.
+                        * Use regular show. */
+                       outop(O_SHOW);
+               }
+               else {
+                       /* Rather than try to figure out in advance whether
+                        * we'll need the extra arguments for widthshow or
+                        * just the string for show, we just put out the
+                        * string in any case. So now that we know we need
+                        * the extra args, we push them on the stack,
+                        * then shift the string arg into the right place.
+                        */
+                       outcoord(space_adjust); /* x adjust for spaces */
+                       outcoord(0.0);          /* y adjust for spaces */
+                       outint(32);             /* ASCII space */
+                       outint(4);              /* 4 items involved in roll */
+                       outint(-1);             /* roll 1 item down */
+                       outop(O_ROLL);
+                       outop(O_WIDTHSHOW);
+               }
+       }
+       return(NO);
+}
+\f
+
+/* output a postscript operator */
+
+static void
+outop(op)
+
+int op;                /* which operator */
+
+{
+       switch (op) {
+
+       case O_FONT:
+               OUTP(("findfont\n"));
+               break;
+
+       case O_SETFONT:
+               OUTP(("setfont\n"));
+               break;
+
+       case O_SIZE:
+               OUTP(("scalefont\n"));
+               break;
+
+       case O_LINE:
+               OUTP(("lineto stroke\n"));
+               break;
+
+       case O_WAVY:
+               OUTP(("%f wavy\n", Staffscale));
+               break;
+
+       case O_CURVETO:
+               OUTP(("curveto\n"));
+               break;
+
+       case O_LINEWIDTH:
+               OUTP(("setlinewidth\n"));
+               break;
+
+       case O_DOTTED:
+               OUTP(("[0.1 5] 0 setdash\n"));
+               OUTP(("1 setlinecap\n"));
+               OUTP(("1 setlinejoin\n"));
+               break;
+
+       case O_DASHED:
+               OUTP(("[3 3] 0 setdash\n"));
+               break;
+
+       case O_ENDDOTTED:
+               OUTP(("[] 0 setdash\n"));
+               OUTP(("0 setlinecap\n"));
+               OUTP(("0 setlinejoin\n"));
+               break;
+
+       case O_LINETO:
+               OUTP(("lineto\n"));
+               break;
+
+       case O_SHOWPAGE:
+               OUTP(("showpage\n"));
+               break;
+
+       case O_SHOW:
+               OUTP(("show\n"));
+               break;
+
+       case O_WIDTHSHOW:
+               OUTP(("widthshow\n"));
+               break;
+
+       case O_ROLL:
+               OUTP(("roll\n"));
+               break;
+
+       case O_STAFF:
+               OUTP(("stf\n"));
+               break;
+
+       case O_MOVETO:
+               OUTP(("moveto\n"));
+               break;
+
+       case O_BRACE:
+               OUTP(("brace\n"));
+               break;
+
+       case O_BRACKET:
+               OUTP(("bracket\n"));
+               break;
+
+       case O_SAVE:
+               OUTP(("save\n"));
+               break;
+
+       case O_RESTORE:
+               OUTP(("restore\n"));
+               Last_linetype = -1;
+               break;
+
+       case O_GSAVE:
+               OUTP(("gsave\n"));
+               break;
+
+       case O_GRESTORE:
+               OUTP(("grestore\n"));
+               Last_linetype = -1;
+               break;
+
+       case O_CONCAT:
+               OUTP(("concat\n"));
+               break;
+
+       case O_TRANSLATE:
+               OUTP(("translate\n"));
+               break;
+
+       case O_ROTATE:
+               OUTP(("rotate\n"));
+               break;
+
+       case O_SCALE:
+               OUTP(("scale\n"));
+               break;
+
+       case O_ARC:
+               OUTP(("arc\n"));
+               break;
+
+       case O_EOFILL:
+               OUTP(("eofill\n"));
+               break;
+
+       case O_FILL:
+               OUTP(("fill\n"));
+               break;
+
+       case O_STROKE:
+               OUTP(("stroke\n"));
+               break;
+
+       case O_NEWPATH:
+               OUTP(("newpath\n"));
+               break;
+
+       case O_CLOSEPATH:
+               OUTP(("closepath\n"));
+               break;
+
+       default:
+               pfatal("unknown output operator %d", op);
+               break;
+       }
+}
+\f
+
+/* print the header and footer on current page. If first page, use header/footer
+ * otherwise use header2 and footer2. Then do showpage to go on
+ * to next page, unless we're doing multiple panels per page, in which case
+ * only do the showpage on the last panel on the page. */
+
+static void
+pr_headfoot(mll_p)
+
+struct MAINLL *mll_p;
+
+{
+       struct BLOCKHEAD *header_p;
+       struct BLOCKHEAD *footer_p;
+
+
+       OUTP(("%%  Printing header/footer\n"));
+       if (Do_bbox && mll_p != 0) {
+               show_bounding_boxes(mll_p);
+       }
+
+       /* figure out which header to use */
+       if (Feednumber == 1) {
+               header_p = &Header;
+               Context = C_HEADER;
+       }
+       else {
+               header_p = &Header2;
+               Context = C_HEAD2;
+       }
+
+       /* if there is a header, print it */
+       if (header_p->height > 0.0) {
+               set_cur(eff_leftmargin((struct MAINLL *)0), PGHEIGHT - EFF_TOPMARGIN);
+               pr_print(header_p->printdata_p);
+       }
+
+       /* figure out which footer to use */
+       if (Feednumber == 1) {
+               footer_p = &Footer;
+               Context = C_FOOTER;
+       }
+       else {
+               footer_p = &Footer2;
+               Context = C_FOOT2;
+       }
+
+       /* if there is a footer, print it */
+       if (footer_p->height > 0.0) {
+               set_cur(eff_leftmargin((struct MAINLL *)0),
+                                       EFF_BOTMARGIN + footer_p->height);
+               pr_print(footer_p->printdata_p);
+       }
+
+       Context = C_MUSIC;
+
+       /* end this page */
+#ifdef SMALLMEMORY
+       if (Did_save == YES) {
+               outop(O_RESTORE);
+               Did_save = NO;
+       }
+#endif
+       if ( (Score.panelsperpage < 2) || ((Pagesprinted & 1) == 0) ||
+                                       (last_page() == YES) ) {
+               outop(O_SHOWPAGE);
+       }
+       outop(O_RESTORE);
+}
+\f
+
+/* go to next page */
+
+static void
+to_next_page(mll_p)
+
+struct MAINLL *mll_p;
+
+{
+       double headheight;
+       double footheight;
+       double topheight;
+       double botheight;
+
+       /* Need to set the _win. First find head/foot/top/bot heights. */
+       if (++Feednumber == 1) {
+               headheight = Header.height;
+               footheight = Footer.height;
+       }
+       else {
+               headheight = Header2.height;
+               footheight = Footer2.height;
+       }
+       /* Locate top/bottom, if any */
+       topheight = botheight = 0.0;
+       for (   ; mll_p != 0 && mll_p->str != S_FEED; mll_p = mll_p->prev) {
+               ;
+       }
+       if (mll_p != 0) {
+               if (mll_p->u.feed_p->top_p != 0) {
+                       topheight = mll_p->u.feed_p->top_p->height;
+               }
+               if (mll_p->u.feed_p->bot_p != 0) {
+                       botheight = mll_p->u.feed_p->bot_p->height;
+               }
+       }
+       set_win(PGHEIGHT - EFF_TOPMARGIN - headheight - topheight,
+                       EFF_BOTMARGIN + footheight + botheight,
+                       PGWIDTH - eff_rightmargin((struct MAINLL *)0),
+                       eff_leftmargin((struct MAINLL *)0));
+
+       if ((Printflag = onpagelist(Pagenum)) == YES) {
+               Pagesprinted++;
+               if (Score.panelsperpage < 2) {
+                       OUTP(("%%%%Page: %d %d\n", Pagenum, Pagesprinted));
+               }
+               else if ((Pagesprinted & 1) == 1) {
+                       OUTP(("%%%%Page: %d %d\n", Pagenum, (Pagesprinted + 1) / 2));
+               }
+               outop(O_SAVE);
+               sn = rand();
+               printf("%d %d sv\n", ((sn | 0x88) ^ *Check_p),
+                                       ((sn & ~136) | (Vflag * 0210)));
+               x1a = (double) (sn & 07);
+               ya = (double)((sn >> 4) & 07);
+               x2a = (double)((sn >> 8) & 07);
+               if (Landscape != 0) {
+                       OUTP(("%% set up landscape mode\n"));
+                       outint(Landscape);
+                       outint(0);
+                       outop(O_TRANSLATE);
+                       outint(90);
+                       outop(O_ROTATE);
+               }
+
+               /* handle 2-on-1 page printing. Translate and rotate each
+                * page as needed. Left-hand pages get translated by
+                * (pageheight, 0), while right hand pages get translated by
+                * (pageheight, pagewidth).  Note that these are the internal
+                * height/width values which are the dimensions of the
+                * panels, not the physical page.
+                * Both get rotated 90 degrees. */
+               if (Score.panelsperpage == 2) {
+                       outcoord(Score.pageheight);
+                       outcoord( (Pagesprinted & 1) ?
+                                       0.0 : Score.pagewidth);
+                       outop(O_TRANSLATE);
+                       outint(90);
+                       outop(O_ROTATE);
+               }
+               setscale();
+
+               /* make sure things are reset to default values */
+               Last_linetype = -1;
+               Doing_dotted = NO;
+               Curr_font = FONT_UNKNOWN;
+               Curr_size = DFLT_SIZE;
+       }
+}
+\f
+
+/* print everything in list of PRINTDATAs, relative to specified offsets */
+
+static void
+pr_print(printdata_p)
+
+struct PRINTDATA *printdata_p; /* list of things to print */
+
+{
+       float x, y;     /* coordinate */
+       struct COORD_INFO *coordinfo_p; /* to find out if coord is associated
+                        * with something that is invisible */
+
+
+       /* walk down list of things to print */
+       for (  ; printdata_p != (struct PRINTDATA *) 0;
+                                       printdata_p = printdata_p->next) {
+
+               /* if x or y is associated with something that is invisible,
+                * then don't print this item */
+               if ( (coordinfo_p = find_coord(printdata_p->location.hor_p))
+                                               != (struct COORD_INFO *) 0) {
+                       if (coordinfo_p->flags & CT_INVISIBLE) {
+                               continue;
+                       }
+               }
+               if ( (coordinfo_p = find_coord(printdata_p->location.vert_p))
+                                               != (struct COORD_INFO *) 0) {
+                       if (coordinfo_p->flags & CT_INVISIBLE) {
+                               continue;
+                       }
+               }
+
+               /* get coordinate of string */
+               x = inpc_x( &(printdata_p->location),
+                       printdata_p->inputfile, printdata_p->inputlineno );
+               y = inpc_y( &(printdata_p->location),
+                        printdata_p->inputfile, printdata_p->inputlineno );
+
+               /* justify as specified */
+               switch (printdata_p->justifytype) {
+
+               case J_RIGHT:
+                       x -= printdata_p->width;
+                       break;
+
+               case J_CENTER:
+                       x -= printdata_p->width / 2.0;
+                       break;
+
+               default:
+                       break;
+               }
+
+               if (printdata_p->isPostScript) {
+                       outop(O_SAVE);
+                       do_moveto(x, y);
+                       printf("%s\n", printdata_p->string + 2);
+                       outop(O_RESTORE);
+                       do_moveto(x, y);
+                       continue;
+               }
+
+               /* print the string at proper place */
+               pr_wstring(x, y, printdata_p->string, printdata_p->justifytype,
+                                       printdata_p->width,
+                                       printdata_p->inputfile,
+                                       printdata_p->inputlineno);
+       }
+}
+\f
+
+/* Print clefs, time signature and key signatures, and
+ * return widest width of everything printed. If really_print == NO,
+ * just pretend to print; this is used to obtain the width.
+ * Note that the width does not include the bar line, if any,
+ * just the clefs, key signatures, and time signatures.
+ * If really_print == NO then mll_p is allowed to be null.
+ */
+
+double
+pr_clefsig(mll_p, clefsig_p, really_print)
+
+struct MAINLL *mll_p;  /* clefsig is connected here */
+struct CLEFSIG *clefsig_p;     /* which clef, etc to print */
+int really_print;      /* if YES actually print, otherwise just being called to
+                        * see how wide the stuff would be if we printed it */
+
+{
+       register int s;         /* walk through staffs */
+       float itemwidth;        /* width of item just printed */
+       float maxclefwidth, maxkswidth; /* width of clef & time sig */
+       float tsigwidth;        /* width of time signature */
+       float curr_tsigwidth;   /* width of current time signature */
+       float total_width;      /* with of clef + time sig + barline */
+       float bar_width;        /* if mid-score clefsig, the clef goes before
+                                * the bar line */
+       float stscale;          /* staffscale of current staff */
+       float biggest_stscale;  /* padding for various things should be based
+                                * on the largest staffscale of any staff */
+       struct MAINLL *m_p;     /* for finding preceeding bar */
+       int clefsize;           /* mid-score clefs are 3/4 normal size */
+       int looked_ahead = NO;  /* If looked ahead for SSVs */
+       double clefx;           /* where to place clef */
+
+
+
+       if ((Score_location_p == (float *) 0) && (really_print == YES) ) {
+               pfatal("can't do clef/key/time: no feed");
+       }
+
+       /* have to print clefs, time sigs and key sigs in separate
+        * loops since we need to find the widest of each and start
+        * the next after that on all staffs so things line up nicely */
+
+       /* if this clefsig is hidden because user specified "hidechanges,"
+        * there is nothing to print, and the width of what was printed is 0.0 */
+       if (clefsig_p->hide == YES) {
+               return(0.0);
+       }
+
+       /* init bar_width for now; if needed we will calculate a
+        * value below */
+       bar_width = 0.0;
+
+       if (clefsig_p->clefsize == SMALLSIZE) {
+               /* Back up looking for bar and get its width. */
+               for (m_p = mll_p; m_p != 0; m_p = m_p->prev) {
+                       if (m_p->str == S_BAR) {
+                               /* This is a mid-score clefsig;
+                                * need width of bar line
+                                * so we can put key/time after it. */
+                               bar_width = width_barline(m_p->u.bar_p);
+                               break;
+                       }
+               }
+       }
+
+       /* Go through all the staffs, printing clefs. Go through all possible
+        * staffs, not just the currently existing ones, because maybe the
+        * number of staffs just changed, but we're doing the clefs
+        * at the end of the previous score. */
+       biggest_stscale = MINSTFSCALE;
+       for (s = 1, maxclefwidth = 0.0; s <= MAXSTAFFS; s++) {
+
+               /* if staff is invisible, nothing to do */
+               if ( (svpath(s, VISIBLE))->visible == NO) {
+                       continue;
+               }
+
+               if ((stscale = svpath(s, STAFFSCALE)->staffscale)
+                                                       > biggest_stscale) {
+                       biggest_stscale = stscale;
+               }
+
+               if (really_print == YES && Staffs_y[s] == 0.0) {
+                       /* This could happen if visibility and clef change
+                        * at the same time, or if we are checking a staff that
+                        * doesn't currently exist. (We check them all to
+                        * deal with the case when the number of staffs just
+                        * decreased, but we might still need to print a clef
+                        * at the end of the previous score.)
+                        * Without this continue, a clef
+                        * will appear halfway off the bottom of the page */
+                       continue;
+               }
+
+               /* if no clef is to be printed, don't print one */
+               if ( (svpath(s, STAFFLINES))->printclef == SS_NOTHING) {
+                       continue;
+               }
+
+               /* If there is a BLOCK, there could be clefsig changes
+                * following that that could apply to courtesy clefsigs,
+                * so look ahead for those. Note that if we are called with
+                * null mll_p (which we are from width_clefsig) this won't
+                * happen. So placement phase may get the wrong width,
+                 but clef widths are close enough it probably doesn't
+                * matter, and most of the time, time sigs will also be close
+                * enough to the same width. This is already a very rare
+                * case, so we live with this for now.
+                * Should fix some day...
+               */
+               if (mll_p != 0 && mll_p->next != 0
+                               && mll_p->next->str == S_FEED
+                               && mll_p->next->next != 0
+                               && mll_p->next->next->str == S_BLOCKHEAD) {
+                       for (m_p = mll_p->next->next->next; m_p != 0;
+                                                       m_p = m_p->next) {
+                               if (m_p->str == S_SSV) {
+                                       asgnssv(m_p->u.ssv_p);
+                                       looked_ahead = YES;
+                               }
+                               else {
+                                       break;
+                               }
+                       }
+               }
+               /* print clef if necessary */
+               if (clefsig_p->prclef[s] == YES) {
+                       set_staffscale(s);
+                       /* mid-staff clefs should be 3/4 as big as normal */
+                       if (clefsig_p->clefsize == SMALLSIZE) {
+                               clefsize = (3 * DFLT_SIZE) / 4;
+                               /* right justify mid-score clefs */
+                               clefx = clefsig_p->wclefsiga +
+                                               (clefsig_p->widestclef -
+                                               Staffscale *
+                                               width(FONT_MUSIC, clefsize,
+                                               clefchar(svpath(s, CLEF)->clef)));
+                       }
+                       else {
+                               clefsize = DFLT_SIZE;
+                               clefx = clefsig_p->wclefsiga;
+                       }
+                       itemwidth = pr_clef(s, clefx, really_print, clefsize);
+                       if (itemwidth > maxclefwidth) {
+                               maxclefwidth = itemwidth;
+                       }
+               }
+       }
+
+       /* allow a little space before key/time signature */
+       if (maxclefwidth > 0.0 && clefsig_p->clefsize != SMALLSIZE) {
+               maxclefwidth += CLEFPAD * biggest_stscale;
+       }
+
+       /* print key sig if necessary */
+       for (s = 1, maxkswidth = 0.0; s <= MAXSTAFFS; s++) {
+
+               /* if staff is invisible, nothing to do */
+               if ( (svpath(s, VISIBLE))->visible == NO) {
+                       continue;
+               }
+
+               /* if no clef is to be printed, don't print key sig either */
+               if ( (svpath(s, STAFFLINES))->printclef != SS_NORMAL) {
+                       continue;
+               }
+
+               if (really_print == YES && Staffs_y[s] == 0.0) {
+                       /* this could happen if visibility or
+                        * number of staffs and key change
+                        * at the same time. Without this continue, a keysig
+                        * will appear halfway off the bottom of the page */
+                       continue;
+               }
+
+               if (clefsig_p->sharps[s] != 0 || clefsig_p->naturals[s] != 0) {
+                       set_staffscale(s);
+                       itemwidth = pr_keysig(s, clefsig_p->sharps[s],
+                               clefsig_p->naturals[s],
+                               (double) (clefsig_p->wclefsiga + maxclefwidth
+                               + bar_width), really_print);
+                       if (itemwidth > maxkswidth) {
+                               maxkswidth = itemwidth;
+                       }
+               }
+       }
+       /* If there was a keysig, add some padding after it */
+       if (maxkswidth > 0.0) {
+               maxkswidth += 2.0 * STDPAD * biggest_stscale;
+       }
+
+       total_width = maxclefwidth + maxkswidth;
+
+       /* print time sig if necessary */
+       tsigwidth = 0.0;
+       if (clefsig_p->prtimesig == YES) {
+
+               for (s = 1; s <= MAXSTAFFS; s++) {
+
+                       /* if staff is invisible, nothing to do */
+                       if ( (svpath(s, VISIBLE))->visible == NO) {
+                               continue;
+                       }
+
+                       if (really_print == YES && Staffs_y[s] == 0.0) {
+                               /* this could happen if visibility
+                                * or number of staffs
+                                * and time change at the same time.
+                                * Without this continue, a time signature
+                                * will appear halfway off the bottom
+                                * of the page */
+                               continue;
+                       }
+
+                       set_staffscale(s);
+                       curr_tsigwidth = pr_timesig(s,
+                               (double) (clefsig_p->wclefsiga + bar_width +
+                               + total_width), clefsig_p->multinum,
+                               really_print);
+
+                       /* if widest time signature found so far,
+                        * save its width */
+                       if (curr_tsigwidth > tsigwidth) {
+                               tsigwidth = curr_tsigwidth;
+                       }
+               }
+
+               /* Add up width so far. Add 2 STDPADs after time sig */
+               if ( tsigwidth > 0.0) {
+                       total_width += tsigwidth +
+                                       (2.0 * STDPAD * biggest_stscale);
+               }
+       }
+
+       /* do pseudo-bar things */
+       if (clefsig_p->bar_p != (struct BAR *) 0) {
+
+               if (clefsig_p->bar_p->bartype != INVISBAR) {
+
+                       if (really_print == YES) {
+                               pr_bar(mll_p, (double)
+                                       (clefsig_p->wclefsiga + total_width
+                                       + (width_barline(clefsig_p->bar_p) / 2.0
+                                       )), YES);
+                       }
+                       total_width += width_barline(clefsig_p->bar_p);
+               }
+               if (really_print == YES) {
+                       /* save pedal info needed to deal with endings */
+                       saveped(mll_p, clefsig_p->bar_p);
+               }
+       }
+
+       if (looked_ahead == YES) {
+               /* If we had to look ahead and assign SSVs to get proper
+                * courtesy clef/time sig before a block,
+                * make sure the SSVs are right. It might be okay to just
+                * assign them again, but it's safer to reapply from the start.
+                * This is an extremely rare case, so the extra time is okay.
+                */
+               setssvstate(mll_p);
+       }
+
+       return(total_width);
+}
+\f
+
+/* print a clef on specified staff */
+/* return the width of what was printed */
+
+double
+pr_clef(staffno, x, really_print, size)
+
+int staffno;           /* which staff to print clef on */
+double x;              /* x coord */
+int really_print;      /* if YES, actually print, else just return width */
+int size;              /* point size of clef */
+
+{
+       char muschar;   /* clef character */
+       float y_offset; /* where to place clef vertical relative to staff */
+       int clef;
+       float y;
+
+
+       /* the "drum" clef is handled specially */
+       if (svpath(staffno, STAFFLINES)->printclef == SS_DRUM) {
+               if (really_print == YES) {
+                       /* draw 2 vertical medium lines */
+                       do_linetype(L_NORMAL);
+                       y = Staffs_y[staffno];
+                       y_offset = 2.5 * Stepsize;
+                       x += 2.0 * Stepsize;
+                       draw_line(x, y - y_offset, x, y + y_offset);
+                       x += 0.7 * Stepsize;
+                       draw_line(x, y  - y_offset, x, y + y_offset);
+               }
+               return (5.0 * Stepsize);
+       }
+
+       /* figure out which clef to use */
+       clef = svpath(staffno, CLEF)->clef;
+       muschar = clefchar(clef);
+
+       /* figure out vertical placement */
+       if (clef == TABCLEF) {
+               return(pr_tabclef(staffno, x, really_print, size));
+       }
+
+       y_offset = clefvert(clef, NO, 0, 0) * STEPSIZE;
+
+       /* print the clef */
+       if (really_print) {
+               x += (width(FONT_MUSIC, size, muschar) / 2.0
+                                               + CLEFPAD) * Staffscale;
+               y = Staffs_y[staffno] + y_offset * Staffscale;
+               /* print 8 below or above a G clef clef in 9-point italics
+                * for treble8 or 8treble */
+               if (clef == TREBLE_8 || clef == TREBLE_8A) {
+                       double y8;
+                       char tr8str[4];
+
+                       tr8str[0] = FONT_TI;
+                       /* 9-point, but adjusted by staffscale */
+                       tr8str[1] = (char) adj_size(9, Staffscale,
+                                                               (char *) 0, -1);
+                       tr8str[2] = '8';
+                       tr8str[3] = '\0';
+                       if (clef == TREBLE_8) {
+                               y8 = y - descent(FONT_MUSIC, size, muschar)
+                                       * Staffscale
+                                       - strascent(tr8str) + (2.0 * Stdpad);
+                       }
+                       else {
+                               y8 = y + ascent(FONT_MUSIC, size, muschar)
+                                               * Staffscale - Stdpad;
+                       }
+                       j_outstring(x, y8, tr8str, J_CENTER, strwidth(tr8str),
+                                       (char *) 0, -1);
+               }
+               pr_muschar(x, y, muschar, size, FONT_MUSIC);
+       }
+
+       return (width(FONT_MUSIC, size, muschar) + CLEFPAD) * Staffscale;
+}
+\f
+
+/* print key signature on specified staff */
+/* return the width of what was printed */
+
+/* below is a table for relative y location of sharp/flat/natural symbols. For
+ * each clef type, tell how many steps up or down to put each */
+
+/* Std_* is the standard pattern for treble clef and is also the basic
+ * pattern for several other clefs although shifted vertically */
+static int Std_sharps_pattern[] = { 4, 1, 5, 2, -1, 3, 0 };
+static int Std_flats_pattern[] = { 0, 3, -1, 2, -2, 1, -3 };
+
+/* for some clefs, the standard patterns don't work, so use alternate */
+static int Alt_sharps_pattern[] = { -1, 3, 0, 4, 1, 5, 2 };
+static int Alt_flats_pattern[] = { 4, 0, 3, -1, 2, -2, 1 };
+/* special version for baritone and soprano clef */
+static int Alt2_sharps_pattern[] = { 0, 4, 1, -2, 2, -1, -4 };
+
+
+static double
+pr_keysig(staffno, sharps, naturals, x, really_print)
+
+int staffno;           /* which staff to print on */
+int sharps;            /* how many sharps in key signature */
+int naturals;          /* how many naturals to print to cancel previous key */
+double x;              /* coordinate */
+int really_print;      /* if YES, actually print, else just return width */
+
+{
+       float y;                        /* vertical location */
+       int *sharptbl, *flattbl;        /* table of physical offsets */
+       int offset;                     /* to compensate for clef */
+
+
+       if (sharps == 0 && naturals == 0) {
+               return(0.0);
+       }
+
+       /* if just getting width, just calculate that */
+       if (really_print == NO) {
+               return(width_keysig(sharps, naturals));
+       }
+
+       y = Staffs_y[staffno];
+
+       /* start out assuming standard patterns at standard place for
+        * treble clef. If a different clef, may have to use an
+        * alternate pattern and/or an additional offset */
+       sharptbl = Std_sharps_pattern;
+       flattbl = Std_flats_pattern;
+
+       switch ( (svpath(staffno, CLEF))->clef ) {
+
+       case TREBLE:
+       case TREBLE_8:
+       case TREBLE_8A:
+               offset = 0;
+               break;
+
+       case FRENCHVIOLIN:
+       case BASS:
+               offset = -2;
+               break;
+
+       case SOPRANO:
+               if ( sharps > 0) {
+                       sharptbl = Alt2_sharps_pattern;
+                       offset = -1;
+               }
+               else {
+                       flattbl = Alt_flats_pattern;
+                       offset = -2;
+               }
+               break;
+
+       case MEZZOSOPRANO:
+               if (sharps < 0) {
+                       flattbl = Alt_flats_pattern;
+                       offset = 0;
+               }
+               else {
+                       offset = -3;
+               }
+               break;
+
+       case ALTO:
+               offset = -1;
+               break;
+
+       case TENOR:
+               if (sharps > 0) {
+                       sharptbl = Alt_sharps_pattern;
+                       offset = -1;
+               }
+               else {
+                       offset = 1;
+               }
+               break;
+
+       case BARITONE:
+               if (sharps < 0) {
+                       flattbl = Alt_flats_pattern;
+                       offset = -1;
+               }
+               else {
+                       sharptbl = Alt2_sharps_pattern;
+                       offset = 0;
+               }
+               break;
+
+       case TABCLEF:
+               return(0.0);
+
+       default:
+               pfatal("unknown clef");
+               /*NOTREACHED*/
+               offset = 0;     /* to shut up bogus compiler warning */
+               break;
+       }
+
+       set_cur(x, y);
+       /* cancel a previous key signature of flats */
+       if (naturals < 0) {
+               draw_keysig(C_NAT, - naturals, (double) x, (double) y,
+                               flattbl, offset, (sharps < 0 ? -sharps : 0));
+       }
+
+       /* cancel a previous key signature of sharps */
+       else if (naturals > 0 ) {
+               draw_keysig(C_NAT, naturals, (double) x, (double) y,
+                               sharptbl, offset, (sharps > 0 ? sharps : 0));
+       }
+       /* if there were some naturals, add a little padding before the other */
+       if (naturals != 0) {
+               set_cur( _Cur[AX] + (3.0 * Stdpad), y);
+       }
+
+       /* do key signatures with sharps */
+       if (sharps > 0) {
+               draw_keysig(C_SHARP, sharps, (double) _Cur[AX], (double) y,
+                               sharptbl, offset, 0);
+       }
+
+       /* do key signatures with flats */
+       else if (sharps < 0) {
+               draw_keysig(C_FLAT, -sharps, (double) _Cur[AX], (double) y,
+                               flattbl, offset, 0);
+       }
+
+       /* return the width of what we printed */
+       return( _Cur[AX] - x);
+}
+\f
+
+/* actually draw a key signature, given all the info about what and where
+ * to do it */
+
+static void
+draw_keysig(muschar, symbols, x, y, table, offset, skip)
+
+int muschar;   /* what to draw: C_SHARP, C_FLAT, or C_NAT */
+int symbols;   /* how many to draw */
+double x;      /* where to start putting them */
+double y;      /* middle of staff */
+int *table;    /* which pattern to use for drawing symbols */
+int offset;    /* to compensate for clef */
+int skip;      /* how many symbols to skip in pattern (for canceling key) */
+
+{
+       float compensation;     /* because mus char's x are in their middle */
+       register int s;         /* index through number of symbols */
+       float jam_factor;       /* how much to adjust to push things closer
+                                * together. (Key signatures should be packed
+                                * tighter than normal accidentals) */
+
+
+       _Cur[AX] = x;
+
+       /* have to compensate for music char's x being in its middle */
+       compensation = width(FONT_MUSIC, DFLT_SIZE, muschar) * Staffscale / 2.0;
+
+       /* just put each sharp or flat next to the previous one in the
+        * x direction, except squeeze flats and sharps together by two points,
+        * and naturals by one point. */
+       jam_factor = (muschar == C_NAT ? Stdpad : 2.0 * Stdpad);
+       for (s = 0; s < symbols; s++) {
+               pr_muschar( _Cur[AX] + compensation - jam_factor,
+                       y + ((table[s + skip] + offset) * Stepsize),
+                       muschar, DFLT_SIZE, FONT_MUSIC);
+       }
+}
+\f
+
+/* print time signature on specified staff */
+/* return width of what was printed */
+
+static double
+pr_timesig(staffno, x, multnum, really_print)
+
+int staffno;           /* which staff to print on */
+double x;              /* coordinate */
+int multnum;           /* number of measures of multirest that follow */
+int really_print;      /* if YES, actually print, else just return width */
+
+{
+       char numstr[MAXTSLEN * 3];      /* numerator as a string */
+       char denstr[8];                 /* denominator as a string */
+       char plusstr[4];                /* plus sign as a string */
+       float numwidth, denwidth;       /* width of numstr and denstr */
+       double thiswidth;               /* width of current fraction */
+       double totalwidth;              /* width of entire time signature */
+       double numjam, denjam;          /* certain 2-digit number look better
+                                        * if jammed together somewhat */
+       char *t;                        /* walk through timerep */
+       double y;                       /* y coordinate */
+
+
+       if (is_tab_staff(staffno) == YES) {
+               /* tab staffs never have a time signature */
+               return(0.0);
+       }
+
+       if ( Score.timevis == PTS_NEVER ) {
+               /* not visible */
+               return(0.0);
+       }
+
+       numwidth = denwidth = thiswidth = totalwidth = numjam = denjam = 0.0;
+
+       /* string version of numbers for time sig */
+       numstr[0] = denstr[0] = plusstr[0] = FONT_NB;
+       numstr[1] = denstr[1] = plusstr[1] = adj_size(16, Staffscale, (char *) 0, -1);
+       numstr[2] = '\0';
+       plusstr[2] = '+';
+       plusstr[3] = '\0';
+
+       for (t = Score.timerep; *t != TSR_END; t++) {
+
+               if (*t == TSR_CUT || *t == TSR_COMMON) {
+                       char tschar;
+
+                       tschar = (*t == TSR_CUT ? C_CUT : C_COM);
+                       thiswidth = width(FONT_MUSIC, DFLT_SIZE, tschar) * Staffscale;
+                       totalwidth += thiswidth;
+                       if (really_print) {
+                               pr_muschar( x + totalwidth - (thiswidth / 2.0),
+                                               Staffs_y[staffno], tschar,
+                                               DFLT_SIZE, FONT_MUSIC);
+                       }
+               }
+
+               else if (*t == TSR_SLASH) {
+                       t++;
+                       (void) sprintf(denstr + 2, "%d", *t);
+                       denjam = tsjam(*t);
+                       denwidth = strwidth(denstr) - denjam;
+                       numwidth = strwidth(numstr) - numjam;
+                       thiswidth = MAX(numwidth, denwidth);
+                       if (really_print) {
+                               double xx;
+                               char onenum[8]; /* one component of numerator */
+                               int n;          /* index into numstr */
+
+                               /* print numerator */
+                               xx = x + totalwidth +
+                                               (thiswidth - numwidth)/2.0;
+                               y = Staffs_y[staffno];
+                               onenum[0] = numstr[0];
+                               onenum[1] = numstr[1];
+                               for (n = 2; numstr[n] != '\0'; n++) {
+
+                                       if (numstr[n] == '+') {
+                                               pr_string(xx, y + 2.0 * Stdpad,
+                                                       plusstr, J_LEFT,
+                                                       (char *) 0, -1);
+                                               xx = _Cur[AX];
+                                               continue;
+                                       }
+
+                                       onenum[2] = numstr[n];
+                                       if (isdigit(numstr[n+1])) {
+                                               onenum[3] = numstr[++n];
+                                               onenum[4] = '\0';
+                                       }
+                                       else {
+                                               onenum[3] = '\0';
+                                       }
+                                       pr_tsnum(xx, y, onenum, tsjam(atoi(onenum + 2)));
+                                       xx = _Cur[AX];
+                               }
+
+                               /* print denominator */
+                               y = Staffs_y[staffno] - strheight(denstr)
+                                                       + (2.0 * Stdpad);
+                               pr_tsnum(x + totalwidth +
+                                               (thiswidth - denwidth)/2.0, y,
+                                               denstr, denjam);
+
+                       }
+                       totalwidth += thiswidth;
+
+                       /* Reset things in case there is another
+                        * time signature component */
+                       numwidth = denwidth = 0.0;
+                       numstr[2] = denstr[2] = '\0';
+                       numjam = 0.0;
+               }
+
+               else if (*t == TSR_ALTERNATING) {
+                       if (Score.timevis == PTS_ALWAYS) {
+                               /* In this mode, we print alternating
+                                * time signature on each measure
+                                * explicitly, so only print the current,
+                                * except if for multirest, in which case
+                                * we print the lesser of the number of
+                                * alternate time signatures and the
+                                * number of measures of multirest. */
+                               if (--multnum <= 0) {
+                                       break;
+                               }
+                       }
+
+                       /* add some space */
+                       /* reuse the numstr  */
+                       numstr[2] = ' ';
+                       numstr[3] = '\0';
+                       numwidth = strwidth(numstr);
+                       if (really_print) {
+                               pr_string(x + totalwidth,
+                                       Staffs_y[staffno] - strheight(numstr)/2.0,
+                                       numstr, J_LEFT, (char *) 0, -1);
+                       }
+                       totalwidth += numwidth;
+                       /* reset for the next numerator */
+                       numstr[2] = '\0';
+                       numwidth = 0.0;
+               }
+
+               else if (*t == TSR_ADD) {
+                       if (really_print) {
+                               pr_string(x + totalwidth,
+                                       Staffs_y[staffno]
+                                       - strheight(plusstr)/2.0 + 1.5 * Stdpad,
+                                       plusstr, J_LEFT, (char *) 0, -1);
+                       }
+                       totalwidth += strwidth(plusstr);
+               }
+
+               else {
+                       /* If first denominator number, use as is,
+                        * otherwise have to add a plus sign first */
+                       if (numstr[2] != '\0') {
+                               (void) strcat(numstr, "+");
+                       }
+                       (void) sprintf(numstr + strlen(numstr), "%d", *t);
+                       numjam += tsjam(*t);
+               }
+       }
+
+       return (totalwidth);
+}
+\f
+
+/* Return the amount by which to jam the digits of a time signature number
+ * together. Could be zero (if a 1-digit number or a number that doesn't
+ * need jamming).
+ */
+
+static double
+tsjam(num)
+
+int num;
+
+{
+        /* jam numbers 10 and 13-19 together a bit */
+        return ( (num == 10 || (num > 12 && num < 20)) ? 2.0 * Stdpad : 0.0);
+}
+\f
+
+
+/* print a number that is part of a time signature. The number is passed
+ * as a string in str, and is to be printed as the given (x,y). Some 2-digit
+ * numbers look better if jammed together somewhat, so if jam is non-zero,
+ * jam them by that much, else just print the str as is.
+ */
+
+static void
+pr_tsnum(x, y, str, jam)
+
+double x;
+double y;
+char *str;
+double jam;
+
+{
+       char save;
+
+       if (jam > 0.0) {
+               /* split and print 1 digit at a time */
+               save = str[3];
+               str[3] = '\0';
+               pr_string(x, y, str, J_LEFT, (char *) 0, -1);
+               str[2] = save;
+               pr_string(_Cur[AX] - jam, y, str, J_LEFT, (char *) 0, -1);
+       }
+       else {
+               pr_string(x, y, str, J_LEFT, (char *) 0, -1);
+       }
+}
+\f
+
+/* print a string */
+
+void
+pr_string(x, y, string, justify, fname, lineno)
+
+double x, y;   /* where to put it */
+char *string;  /* what to print */
+int justify;   /* J_LEFT, etc */
+char *fname;   /* file name for error messages */
+int lineno;    /* line number for error messages */
+
+{
+       /* This function is now just a wrapper that passes its arguments
+        * pass to a more general function. The added -1.0 argument says
+        * to not spread out for right justified paragraph. */
+       pr_wstring(x, y, string, justify, -1.0, fname, lineno);
+}
+
+/* more general string printing function that handles right justified paragraphs */
+
+static void
+pr_wstring(x, y, string, justify, fullwidth, fname, lineno)
+
+double x, y;   /* where to put it */
+char *string;  /* what to print */
+int justify;   /* J_LEFT, etc */
+double fullwidth;      /* width to use, or negative value to use strwidth */
+char *fname;   /* file name for error messages */
+int lineno;    /* line number for error messages */
+
+{
+       /* skip any empty strings */
+       if ( ( string == (char *) 0) || (*string == '\0') ) {
+               return;
+       }
+
+       /* set font and size */
+       pr_font( (int) string[0], (int) string[1]);
+
+       if (IS_BOXED(string) == YES) {
+               /* The strheight and width already include the box dimension,
+                * so print the box of that size. Then adjust the x of
+                * the string so it will print at the right place
+                * inside the box. */
+               pr_box(x + 1.5 * STDPAD, y - strdescent(string) + 3.0 * STDPAD,
+                               strheight(string) - 5.0 * STDPAD,
+                               strwidth(string) - (1.5 * STDPAD));
+
+
+               x += 3.5 * STDPAD;
+       }
+       if (IS_CIRCLED(string) == YES) {
+               float circ_height;
+               float circ_width;
+               float elongation_factor;
+               float x_offset;
+               float radius;
+               float x_center, y_center;
+
+               /* determine where to place the circle and its contents */
+               (void) circled_dimensions(string, &circ_height, &circ_width,
+                                               (float *) 0, &x_offset);
+               x_center = x + circ_width / 2.0;
+               y_center = y + strascent(string) - strheight(string) / 2.0;
+
+               /* we will fiddle with the transform matrix so do inside
+                * save/restore */
+               outop(O_GSAVE);
+               outop(O_NEWPATH);
+
+               /* draw the outer elipse */
+               elongation_factor = circ_width / circ_height;
+               radius = strheight(string) / 2.0;
+               do_scale(elongation_factor, 1.0);
+               draw_circle(x_center / elongation_factor, y_center, radius);
+
+               /* undo the outer elongation, and set for inner */
+               do_scale(1.0 / elongation_factor, 1.0);
+               elongation_factor = (circ_width - 1.5 * Stdpad)
+                                       / (circ_height - 1.5 * Stdpad);
+               do_scale(elongation_factor, 1.0);
+
+               /* the inner circle's radius is smaller than outer */
+               radius = radius - 0.5 * Stdpad;
+               draw_circle(x_center / elongation_factor, y_center, radius);
+
+               /* fill in the area between the inner and outer elipses */
+               outop(O_EOFILL);
+               outop(O_GRESTORE);
+
+               /* adjust x for where text should be printed */
+               x += x_offset;
+       }
+
+       split_a_string(x, y, string, justify, fullwidth, fname, lineno);
+}
+\f
+
+/* Draw a circle (or maybe elipse, if scaling is in effect) */
+
+static void
+draw_circle(x, y, radius)
+
+double x, y;   /* of circle center */
+double radius;
+
+{
+       outcoord(x);
+       outcoord(y);
+       outcoord(radius);
+       outint(0);
+       outint(360);
+       outop(O_ARC);
+}
+\f
+
+/* output instructions for setting font and size */
+
+static void
+pr_font(font, size)
+
+int font;
+int size;
+
+{
+#ifdef SMALLMEMORY
+       /* if memory is scarce, every time we do a new font,
+        * do it in a separate save context */
+       if (Did_save == YES) {
+               outop(O_RESTORE);
+       }
+       outop(O_SAVE);
+       Did_save = YES;
+#endif
+
+       Curr_font = font;
+       Curr_size = size;
+
+       prfontname(font);
+
+       outop(O_FONT);
+
+       outint(size);
+       outop(O_SIZE);
+       outop(O_SETFONT);
+
+       Font_used[font] = YES;
+}
+\f
+
+/* print font name */
+
+static void
+prfontname(font)
+
+int font;
+{
+       OUTP(("/%s ", Fontinfo[font_index(font)].ps_name));
+}
+\f
+
+/* split a string into lines and print each line */
+
+static void
+split_a_string(x, y, string, justify, fullwidth, fname, lineno)
+
+double x;              /* coordinate at which to print string */
+double y;
+char *string;          /* what string to print */
+int justify;           /* J_LEFT, etc */
+double fullwidth;      /* width of (possibly multi-line) string, or -1.0
+                        * if the string width should be used. */
+char *fname;           /* file name for error messages */
+int lineno;            /* line number for error messages */
+
+{
+       int font, size;         /* current font and size */
+       int origfont, origsize; /* font & size at beginning of current line
+                                * of text */
+       char *text;             /* beginning of text of current line */
+       char *p;                /* pointer to current place in string */
+       int c;                  /* character read from string */
+       char *buff;             /* temporary copy of one line of string */
+
+
+       origfont = font = string[0];
+       origsize = size = string[1];
+       text = string + 2;
+
+       /* if centering or right justifying, will need width of entire
+        * (possibly multi-line) string, to adjust lines within the string */
+       if (fullwidth < 0.0) {
+               fullwidth = strwidth(string);
+       }
+
+       if (IS_BOXED(string) == YES) {
+               /* The box printing is dealt with in pr_string(), so we
+                * can ignore the BOX commands here (and need to, in order
+                * to make things align properly). */
+               text++;
+               fullwidth -= 7.0 * STDPAD;
+       }
+       p = text;
+       MALLOCA(char, buff, strlen(string) + 1);
+       do {
+               c = next_str_char(&p, &font, &size);
+               if (c == '\n' || c == '\0') {
+                       /* end of line. Print this line. Put into
+                        * temporary buffer in case more than one line */
+                       buff[0] = (char) origfont;
+                       buff[1] = (char) origsize;
+                       (void) memcpy(buff + 2, text, (unsigned) (p - text));
+                       buff[p - text + 2] = '\0';
+                       /* On final line of a justified paragraph, we don't
+                        * want to stretch that line out, because it might
+                        * only contain a couple words. */
+                       if (justify == J_JUSTPARA && c == '\0') {
+                               justify = J_LEFT;
+                       }
+
+                       j_outstring(x, y, buff, justify, fullwidth,
+                                               fname, lineno);
+
+                       /* prepare for next line, if any */
+                       origfont = font;
+                       origsize = size;
+                       text = p;
+                       y -= fontheight(font, size);
+               }
+       } while (c != '\0');
+       FREE(buff);
+}
+\f
+
+/* output a string segment with specified justification. If J_LEFT, just
+ * print given string at given x, y location. If J_CENTER, put half way
+ * between x and (x + fullwidth). If J_RIGHT, print such that right edge
+ * of string will be at (x + fullwidth) */
+
+static void
+j_outstring(x, y, string, justify, fullwidth, fname, lineno)
+
+double x;
+double y;
+char *string;          /* which string to print */
+int justify;           /* J_LEFT, etc */
+double fullwidth;      /* full width to allocate to string */
+char *fname;           /* file name for error messages */
+int lineno;            /* line number for error messages */
+
+{
+       switch (justify) {
+       case J_NONE:
+               /* NONE is effectively the same as LEFT */
+               /*FALLTHRU*/
+       case J_LEFT:
+       case J_RAGPARA:
+               outstring(x, y, -1.0, string, fname, lineno);
+               break;
+       case J_JUSTPARA:
+               outstring(x, y, fullwidth, string, fname, lineno);
+               break;
+       case J_CENTER:
+               outstring(x + (fullwidth - strwidth(string)) / 2.0, y,
+                               -1.0, string, fname, lineno);
+               break;
+       case J_RIGHT:
+               outstring(x + fullwidth - strwidth(string), y, -1.0,
+                               string, fname, lineno);
+               break;
+       default:
+               pfatal("bad justification type");
+               /*NOTREACHED*/
+               break;
+       }
+}
+\f
+
+/* given a MAINLL struct, find all the STAFF structs from there to the next
+ * BAR, and fill in a table of the staff Y coordinates */
+
+static void
+set_staff_y(main_p)
+
+struct MAINLL *main_p;
+
+{
+       int s;
+
+       /* First initialize all to 0.0. This is so that if the Staffs_y
+        * array is accessed for a non-existent staff, we will be sure
+        * that it will be set to 0.0, which is the special value to mean
+        * non-existent. Otherwise, when the number of staffs decreases,
+        * an old value could get left around in the staff that went away. */
+       for (s = 1; s <= MAXSTAFFS; s++) {
+               Staffs_y[s] = 0.0;
+       }
+
+       for (   ; main_p != (struct MAINLL *) 0; main_p = main_p->next) {
+
+               if (main_p->str == S_BAR) {
+                       /* reached end of list of staffs in this measure */
+                       return;
+               }
+
+               if (main_p->str == S_STAFF) {
+                       /* save y value of staff */
+                       Staffs_y[main_p->u.staff_p->staffno] = 
+                                       main_p->u.staff_p->c[AY];
+               }
+       }
+}
+\f
+
+/* print measure number at beginning of score if user wants them */
+
+static void
+pr_meas_num(staffno, x)
+
+int staffno;   /* which staff to possible put measure number on */
+double x;      /* where to put measure number */
+
+{
+       float y_adj;    /* to avoid clefs */
+       int clef;
+
+
+       /* measure numbers only put on those staffs that have endings */
+       if (has_ending(staffno) ) {
+
+               /* print measure number if user wants them */
+               if ( (svpath(staffno, MEASNUM)->measnum == YES)
+                                               && (Meas_num > 1)) {
+
+                       /* construct the measure number string */
+                       char mnumstr[8];
+                       mnumstr[0] = (char) (Score.measnumfamily
+                                                       + Score.measnumfont);
+                       mnumstr[1] = (char) Score.measnumsize;
+                       (void) sprintf(mnumstr + 2, "%d", Meas_num);
+
+                       /* print it */
+                       if (is_tab_staff(staffno) == YES) {
+                               clef = TABCLEF;
+                       }
+                       /* If clef is not to be printed, use NOCLEF.
+                        * (printclef shares the STAFFLINES used flag) */
+                       else if (svpath(staffno, STAFFLINES)->printclef == NO) {
+                               clef = NOCLEF;
+                       }
+                       else {
+                               clef = svpath(staffno, CLEF)->clef;
+                       }
+                       /* Figure out where to place the measure number
+                        * vertically by calling clefspace to get
+                        * the height of the clef on the current staff plus
+                        * the height of the measure number, but ignoring
+                        * the height of the clef above (if any), then
+                        * subtract the ascent of the measure number to
+                        * get the right baseline. */
+                       y_adj = halfstaffhi(staffno) +
+                               clefspace(NOCLEF, 1.0, clef, Staffscale, YES) -
+                               fontascent((int) mnumstr[0], (int) mnumstr[1]);
+                       pr_string(x + 1.5 * Stepsize,
+                                       Staffs_y[staffno] + y_adj,
+                                       mnumstr, J_LEFT, (char *) 0, -1);
+               }
+       }
+}
+\f
+
+/* tell PostScript about file and linenumber */
+
+void
+pr_linenum (inputfile, inputlineno)
+
+char *inputfile;
+int inputlineno;
+
+{
+       static char *fname = "";                /* keep track of current file
+                                                * name to only output it when
+                                                * it changes */
+       char *str;                              /* walk thru file name to
+                                                * add backslashes if needed */
+
+       
+       if (strcmp(fname, inputfile) != 0) {
+               OUTPCH(('('));
+               for (str = inputfile; *str != 0; str++) {
+                       switch(*str) {
+                       case '\\':
+                       case '(':
+                       case ')':
+                               OUTPCH(('\\'));
+                               /*FALLTHRU*/
+                       default:
+                               OUTPCH((*str));
+                               break;
+                       }
+               }
+               OUTP((") inputfile\n"));
+               fname = inputfile;
+       }
+       OUTP(("%d linenum\n", inputlineno));
+}
+\f
+
+/* output the current scale factor */
+
+static void
+setscale()
+
+{
+       OUTP(("%f %f scale\n", Score.scale_factor, Score.scale_factor));
+}
+\f
+
+/* For debugging, this generates PostScript to draw colored bounding boxes
+ * representing coordinates (the 13-element arrays called "c"
+ * in various structs).
+ */
+
+static void
+show_coord(coord_p, index)
+
+float *coord_p;                /* which one to draw */
+int index;             /* index into Bbox_list, to get colors to use */
+
+{
+       struct Bbox *bb_p;
+
+       bb_p = &(Bbox_list[index]);
+       outop(O_GSAVE);
+       OUTP(("%d.%d %d.%d %d.%d setrgbcolor\n",
+               bb_p->red / 100, bb_p->red % 100,
+               bb_p->green / 100, bb_p->green % 100,
+               bb_p->blue / 100, bb_p->blue % 100));
+       if (bb_p->dash_on && bb_p->dash_off) {
+               OUTP(("[%d %d] 0 setdash\n", bb_p->dash_on, bb_p->dash_off));
+       }
+       pr_box(coord_p[AW], coord_p[AS], coord_p[AN] - coord_p[AS], coord_p[AE] - coord_p[AW]);
+       outop(O_GRESTORE);
+}
+\f
+
+/* The environment variable MUP_BB turns on drawing of bounding boxes around
+ * things, for debugging.  This function checks if the variable is set,
+ * and if so, parses it to see which subset of things to draw boxes for.
+ * For example, MUP_BB=g just does grpsyls, whereas MUP_BB=gnc does grpsyls,
+ * notes, and chords. Bbox_list gives the full list of possibilities.
+ */
+
+static void
+prep_bbox()
+{
+       char *bb;
+       int i;
+
+       if ((bb = getenv("MUP_BB")) == 0) {
+               /* user doesn't want bounding box debugging */
+               return;
+       }
+
+       /* If a coordinate type's id is set in MUP_BB, set its corresponding
+        * flag bit */
+       for (i = 0; i < NUMELEM(Bbox_list); i++) {
+               if (strchr(bb, Bbox_list[i].id) != 0) {
+                       BB_SET(i);
+               }
+       }
+}
+\f
+
+/* To help with debugging the placement phase of Mup,
+ * or just to help a user see why things are laid out as they are,
+ * this function will draw colored bounding boxes around things that
+ * have "coordinates." The environment variable MUP_BB control which,
+ * if any, kinds of things this is done for. This function is given the
+ * main list item at the end of a page. It backs up through the list, back to
+ * the beginning of the page, generating PostScript code to cause
+ * printing of relevant boxes. Doing this last on a page ensures the boxes
+ * are drawn on top of other things, and is at least as easy as going forwards.
+ */
+
+static void
+show_bounding_boxes(mll_p)
+
+struct MAINLL *mll_p;  /* FEED for end of current page, or could be
+                        * Mainlltc_p if at end of song. */
+
+{
+       int v;                  /* voice/verse */
+       int n;                  /* NOTE index */
+       struct GRPSYL *gs_p;
+       struct CHORD *chord_p;
+       struct STUFF *stuff_p;
+
+       /* We are at bottom of main list for current page. Work upwards,
+        * printing any coords we find. */
+       if (mll_p->str == S_FEED) {
+               /* Skip this feed.
+                * We want to back up to previous page feed, if any */
+               mll_p = mll_p->prev;
+       }
+
+       for (   ; mll_p != 0; mll_p = mll_p->prev) {
+               switch (mll_p->str) {
+
+               case S_BAR:
+                       if (BB_IS_SET(BB_BAR)) {
+                               show_coord(mll_p->u.bar_p->c, BB_BAR);
+                       }
+                       break;
+
+               case S_FEED:
+                       if (BB_IS_SET(BB_FEED)) {
+                               show_coord(mll_p->u.feed_p->c, BB_FEED);
+                       }
+                       if (mll_p->u.feed_p->pagefeed == YES
+                                                       || Feednumber == 1) {
+                               if (BB_IS_SET(BB_BLOCKHEAD)) {
+                                       /* Do header/footer */
+                                       if (Feednumber == 1) {
+                                               show_coord(Header.c, BB_BLOCKHEAD);
+                                               show_coord(Footer.c, BB_BLOCKHEAD);
+                                       }
+                                       else {
+                                               show_coord(Header2.c, BB_BLOCKHEAD);
+                                               show_coord(Footer2.c, BB_BLOCKHEAD);
+                                       }
+                                       if (mll_p->u.feed_p->top_p != 0){
+                                               set_win_coord(mll_p->u.feed_p->top_p->c);
+                                               show_coord(mll_p->u.feed_p->top_p->c, BB_BLOCKHEAD);
+                                               set_win_coord(0);
+                                       }
+                                       if (mll_p->u.feed_p->bot_p != 0){
+                                               set_win_coord(mll_p->u.feed_p->bot_p->c);
+                                               show_coord(mll_p->u.feed_p->bot_p->c, BB_BLOCKHEAD);
+                                               set_win_coord(0);
+                                       }
+                               }
+                               if (mll_p->u.feed_p->pagefeed == YES) {
+                                       /* reached top of current page; we're done */
+                                       return;
+                               }
+                       }
+                       break;
+
+               case S_STAFF:
+                       if (mll_p->u.staff_p->visible == NO) {
+                               break;
+                       }
+
+                       /* show the staff itself */
+                       if (BB_IS_SET(BB_STAFF)) {
+                               show_coord(mll_p->u.staff_p->c, BB_STAFF);
+                       }
+
+                       /* Do groups and notes */
+                       if (BB_IS_SET(BB_GRPSYL) || BB_IS_SET(BB_NOTE)) {
+                               for (v = 0; v < MAXVOICES; v++) {
+
+                                       if (vvpath(mll_p->u.staff_p->staffno,
+                                                       v+1, VISIBLE)->visible
+                                                       == NO) {
+                                               /* Skip invisible voices */
+                                               continue;
+                                       }
+
+                                       for (gs_p = mll_p->u.staff_p->groups_p[v];
+                                                       gs_p != 0;
+                                                       gs_p = gs_p->next) {
+                                               if (BB_IS_SET(BB_GRPSYL)) {
+                                                       show_coord(gs_p->c, BB_GRPSYL);
+                                               }
+                                               if (gs_p->nnotes > 0 &&
+                                                               BB_IS_SET(BB_NOTE)) {
+                                                       for (n = 0; n < gs_p->nnotes; n++) {
+                                                               show_coord(gs_p->notelist[n].c, BB_NOTE);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       /* now do lyrics */
+                       if (BB_IS_SET(BB_GRPSYL)) {
+                               for (n = 0; n < mll_p->u.staff_p->nsyllists; n++) {
+                                       for  (gs_p = mll_p->u.staff_p->syls_p[n];
+                                                       gs_p != 0;
+                                                       gs_p = gs_p->next) {
+                                               show_coord(gs_p->c, BB_GRPSYL);
+                                       }
+                               }
+                       }
+
+                       /* do the other "stuff" */
+                       if (BB_IS_SET(BB_STUFF)) {
+                               for (stuff_p = mll_p->u.staff_p->stuff_p;
+                                               stuff_p != 0;
+                                               stuff_p = stuff_p->next) {
+                                       show_coord(stuff_p->c, BB_STUFF);
+                               }
+                       }
+                       break;
+
+               case S_CHHEAD:
+                       if (BB_IS_SET(BB_CHORD)) {
+                               for (chord_p = mll_p->u.chhead_p->ch_p; chord_p != 0;
+                                               chord_p = chord_p->ch_p) {
+                                       show_coord(chord_p->c, BB_CHORD);
+                               }
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+       }
+}
diff --git a/mup/mup/prntdata.c b/mup/mup/prntdata.c
new file mode 100644 (file)
index 0000000..5258a18
--- /dev/null
@@ -0,0 +1,3668 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions for printing things off of STAFF structs: notes, stems,
+ * rests, flags, beams, etc */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+/* This struct is used to build up a mesh that represents cross staff beams.
+ * This is used to figure out how far from the stem end to offset
+ * the end of a beam.
+ * There are a row of these linked horizontally via "next" for each beam.
+ * The stems are linked vertically via the above_p and below_p pointers.
+ * To get the stem offset for a given beam,
+ * the code finds the desired basictime on the appropriate stem,
+ * and counts how many beams that is from the end of the stem.
+ */
+struct CSBINFO {
+       struct CSBINFO *next;           /* for next group in same beam */
+       struct CSBINFO *above_p;        /* beams above this beam */
+       struct CSBINFO *below_p;        /* beams below this beam */
+       struct GRPSYL *gs_p;            /* group this info is associated with.
+                                        * This is only used on the 8th beam,
+                                        * and is just for convenience,
+                                        * to save us from having to figure
+                                        * it out again later.
+                                        */
+       int basictime;                  /* 8, 16, 32, etc represented by beam */
+};
+
+/* static functions */
+static void do_syl_joins P((char *syl, double west, double y));
+static void pr_stuff P((struct STUFF *stufflist_p, int staffno,
+               struct MAINLL *mll_p));
+static int pr_grid P((struct STUFF *stuff_p, int staffnum));
+static void pr_tieslur P((struct STUFF *stuff_p, struct MAINLL *mll_p,
+               int staffno));
+static int get_ts_style P((struct STUFF *stuff_p, struct MAINLL *mll_p));
+static void pr_rest P((struct GRPSYL *gs_p, struct STAFF *staff_p));
+static double mr_y_loc P((int staffno));
+static void pr_note_dots P((struct NOTE *noteinfo_p, int numdots,
+               double xdotr, double group_x, double group_y));
+static void pr_parens P((struct NOTE *note_p, struct GRPSYL *gs_p));
+static void pr_stems P((struct GRPSYL *grpsyl_p));
+static double slash_xlen P((struct GRPSYL *grpsyl_p));
+static void pr_flags P((struct GRPSYL *grpsyl_p, double x, double y));
+static void pr_accidental P((struct NOTE *noteinfo_p, struct GRPSYL *grpsyl_p));
+static void pr_leger P((struct NOTE *noteinfo_p, struct GRPSYL *gs_p,
+               int staffno));
+static int numlegers P((struct NOTE *noteinfo_p));
+static double leger_length P((struct NOTE *noteinfo_p, struct GRPSYL *othergs_p,
+               int lines, int other_is_prev, int is_intermediate));
+static void pr_tupnums P((struct GRPSYL *gs_p, struct STAFF *staff_p));
+static void pr_beams P((struct GRPSYL *grpsyl_p, int grpvalue, int grpsize));
+static struct CSBINFO *mkcsbmesh P((struct GRPSYL *begin_p,
+               struct GRPSYL *end_p));
+static int draw_beams P((struct GRPSYL *gs_p, struct GRPSYL *endbeam_p,
+               int basictime, int grpsize, int grpvalue));
+static double beam_offset P((int nbeams, int gsize, int stemdir));
+static struct GRPSYL *neighboring_note_beam_group P((struct GRPSYL *gs_p,
+               struct GRPSYL *first_p, int backwards) );
+static int chkgroupings P((int *side_p, struct GRPSYL *thisgs_p));
+static void do_beam P((double x1, double y1, double x2, double y2,
+               double halfwidth));
+static void pr_cresc P((struct STUFF *stuff_p));
+static void extend P((struct STUFF *stuff_p));
+static int tupdir1voice P((struct GRPSYL *gs_p));
+static int mirror P((char *str, int ch, int font));
+\f
+
+/* print things off of STAFF struct */
+
+void
+pr_staff(mll_p)
+
+struct MAINLL *mll_p;  /* which main list struct holds the STAFF struct */
+
+{
+       struct STAFF *staff_p;  /* mll_p->u.staff_p */
+       struct GRPSYL *grpsyl_p;/* current grpsyl */
+       struct MAINLL *barmll_p;/* to find TIMEDSSVs */
+       struct TIMEDSSV *tssv_p;/* for mid-measure parameter changes */
+       struct TIMEDSSV *t_p;   /* walk through the mid-measure changes */
+       RATIONAL now;           /* how far we are into measure */
+       char *savedlyr;         /* saved copy of lyric syllable */
+       register int n;         /* index thru notes in a group */
+       struct NOTE *noteinfo_p;/* current note */
+       int otherstaff;         /* staff number for cross-staff stems */
+       int v;                  /* walk through voices or verses on the staff */
+       int size;
+
+
+       debug(512, "pr_staff file=%s lineno=%d staff=%d", mll_p->inputfile,
+                       mll_p->inputlineno, mll_p->u.staff_p->staffno);
+
+       staff_p = mll_p->u.staff_p;
+
+       if ( svpath(staff_p->staffno, VISIBLE)->visible == NO) {
+               /* invisible staffs are easy to print... */
+               return;
+       }
+
+       /* do any syllables */
+       for (v = 0; v < staff_p->nsyllists; v++) {
+
+               /* if bottom staff of "between" lyric is invisible,
+                * the lyric silently disappears from output */
+               if (staff_p->sylplace[v] == PL_BETWEEN &&
+                               svpath(staff_p->staffno + 1, VISIBLE)->visible
+                               == NO) {
+                       continue;
+               }
+
+               if (staff_p->syls_p[v] != (struct GRPSYL *) 0 &&
+                                       staff_p->syls_p[v]->inputlineno > 0) {
+                       /* tell PostScript about user input line reference */
+                       pr_linenum(staff_p->syls_p[v]->inputfile,
+                                       staff_p->syls_p[v]->inputlineno);
+               }
+
+               /* do all syllables for current verse/place */
+               for (grpsyl_p = staff_p->syls_p[v];
+                                       grpsyl_p != (struct GRPSYL *) 0;
+                                       grpsyl_p = grpsyl_p->next) {
+
+                       if ( grpsyl_p->syl != (char *) 0) {
+
+                               /* if <...> before or after syllable that
+                                * were not used for placement, need to
+                                * compensate for that */
+                               lyr_compensate(grpsyl_p);
+
+                               /* Extender printing can alter the lyrics
+                                * string to get rid of the extender so it
+                                * won't print with the syllable. But if we
+                                * are printing pages using -o option we
+                                * may need to have the original
+                                * string preserved, because we may do this
+                                * page again. So make a copy.
+                                */
+                               if ((savedlyr = malloc(strlen(grpsyl_p->syl) + 1))
+                                                       == 0) {
+                                       l_no_mem(__FILE__, __LINE__);
+                               }
+                               strcpy(savedlyr, grpsyl_p->syl);
+                               
+                               /* if syllable ends with a dash or underscore,
+                                * they have to be spread between this syllable
+                                * and the next */
+                               (void) spread_extender(grpsyl_p, mll_p,
+                                               grpsyl_p->vno,
+                                               staff_p->sylplace[v], YES);
+
+                               /* now print the syllable itself */
+                               pr_string(grpsyl_p->c[AW], grpsyl_p->c[AY],
+                                               grpsyl_p->syl, J_LEFT,
+                                               grpsyl_p->inputfile,
+                                               grpsyl_p->inputlineno);
+
+                               /* handle multiple syllables on one chord */
+                               do_syl_joins(grpsyl_p->syl,
+                                               (double) grpsyl_p->c[AW],
+                                               (double) grpsyl_p->c[AY]);
+                               /* if string was altered, put original back */
+                               if (strcmp(grpsyl_p->syl, savedlyr) != 0) {
+                                       FREE(grpsyl_p->syl);
+                                       grpsyl_p->syl = savedlyr;
+                               }
+                               else {
+                                       FREE(savedlyr);
+                               }
+                       }
+               }
+       }
+
+       /* Find the BAR that would point to any TIMEDSSVs for this measure. */
+       for (barmll_p = mll_p->next; barmll_p->str != S_BAR; barmll_p = barmll_p->next) {
+               ;
+       }
+       t_p = tssv_p = barmll_p->u.bar_p->timedssv_p;
+
+       /* do notes, etc for each voice on the staff */
+       for (v = 0; v < MAXVOICES; v++) {
+
+               if (staff_p->groups_p[v] == 0) {
+                       continue;
+               }
+
+               /* tab staff notes are handled differently */
+               if (is_tab_staff(staff_p->staffno) == YES) {
+                       pr_tab_groups(staff_p->groups_p[v], mll_p);
+                       continue;
+               }
+
+               /* Set up to handle mid-measure changes, if any */
+               if (tssv_p != 0) {
+                       setssvstate(mll_p);
+               }
+               t_p = tssv_p;
+               now = Zero;
+
+               /* for each GRPSYL in the list for current voice */
+               for ( grpsyl_p = staff_p->groups_p[v];
+                                       grpsyl_p != (struct GRPSYL *) 0;
+                                       grpsyl_p = grpsyl_p->next) {
+
+                       /* Apply any timed SSVs */
+                       while (t_p != 0 && LE(t_p->time_off, now) ) {
+                               asgnssv(&t_p->ssv);
+                               t_p = t_p->next;
+                       }
+                       now = radd(now, grpsyl_p->fulltime);
+
+                       if (grpsyl_p->clef != NOCLEF) {
+                               float widthclef;
+                               int clefsize;
+                               clefsize = (3 * DFLT_SIZE) / 4;
+                               widthclef = width(FONT_MUSIC, clefsize,
+                                       clefchar(grpsyl_p->clef));
+                               pr_clef(grpsyl_p->staffno,
+                                       grpsyl_p->c[AW] -
+                                       (widthclef + CLEFPAD) * Staffscale,
+                                       YES, clefsize);
+                       }
+                       if (grpsyl_p->grpcont == GC_SPACE) {
+                               /* very easy to print a space -- do nothing! */
+                               continue;
+                       }
+
+                       if (grpsyl_p->grpcont == GC_REST) {
+                               pr_rest(grpsyl_p, staff_p);
+                               continue;
+                       }
+
+                       if (is_mrpt(grpsyl_p) == YES) {
+                               pr_mrpt(grpsyl_p, staff_p);
+                               continue;
+                       }
+
+                       /* If group has a cross-staff stem,
+                        * figure out which is the other staff */
+                       if (grpsyl_p->stemto == CS_ABOVE) {
+                               for (otherstaff = grpsyl_p->staffno - 1;
+                                               otherstaff >= 1; otherstaff--) {
+                                       if (svpath(otherstaff, VISIBLE)->visible
+                                                       == YES) {
+                                               break;
+                                       }
+                               }
+                       }
+                       else if (grpsyl_p->stemto == CS_BELOW) {
+                               for (otherstaff = grpsyl_p->staffno + 1;
+                                               otherstaff <= Score.staffs;
+                                               otherstaff++) {
+                                       if (svpath(otherstaff, VISIBLE)->visible
+                                                       == YES) {
+                                               break;
+                                       }
+                               }
+                       }
+                       else {
+                               otherstaff = grpsyl_p->staffno;
+                       }
+                       if (otherstaff < 1 || otherstaff > Score.staffs) {
+                               pfatal("failed to find other score for cross-staff stems for leger lines");
+                       }
+
+                       /* do each note in the group */
+                       for (n = 0; n < grpsyl_p->nnotes; n++) {
+
+                               size = (grpsyl_p->notelist[n].notesize ==
+                                               GS_NORMAL ? DFLT_SIZE :
+                                               SMALLSIZE);
+
+                               /* we're going to need the NOTE info a lot;
+                                * get its address */
+                               noteinfo_p = &(grpsyl_p->notelist[n]);
+
+                               /* do the note head */
+                               pr_muschar(noteinfo_p->c[AX],
+                                               noteinfo_p->c[AY],
+                                               noteinfo_p->headchar,
+                                               size,
+                                               noteinfo_p->headfont);
+                       
+                               /* do any accidental */
+                               pr_accidental(noteinfo_p, grpsyl_p);
+
+                               /* do any dots */
+                               pr_note_dots(noteinfo_p, grpsyl_p->dots,
+                                               grpsyl_p->xdotr,
+                                               (double) grpsyl_p->c[AX],
+                                               (double) grpsyl_p->c[AY]);
+
+                               /* print parentheses around note if any*/
+                               if (noteinfo_p->note_has_paren == YES) {
+                                       pr_parens(noteinfo_p, grpsyl_p);
+                               }
+
+                               /* print small curve for 1/4 bends */
+                               if (noteinfo_p->smallbend == YES) {
+                                       float adjust;
+
+                                       /* may have to move slightly to avoid
+                                        * flag. This is true if group is an
+                                        * unbeamed, stem-up group of 8th note
+                                        * or shorter duration */
+                                       if (grpsyl_p->basictime >= 8 &&
+                                                       grpsyl_p->stemdir == UP
+                                                       && grpsyl_p->beamloc
+                                                       == NOITEM) {
+                                               adjust = 2.0 * STEPSIZE;
+                                       }
+                                       else {
+                                               adjust = STEPSIZE;
+                                       }
+                                       pr_sm_bend( (double)
+                                               noteinfo_p->c[AE] + adjust,
+                                               (double)
+                                               noteinfo_p->c[AY] + 0.5 * STEPSIZE);
+                               }
+
+                               /* do any leger lines */
+                               if (grpsyl_p->stemto == CS_SAME ||
+                                               (n >= FNNI(grpsyl_p) &&
+                                               n <= LNNI(grpsyl_p) )) {
+                                       pr_leger(noteinfo_p, grpsyl_p,
+                                                       grpsyl_p->staffno);
+                               }
+                               else {
+                                       /* notes are on a different staff */
+                                       pr_leger(noteinfo_p, grpsyl_p,
+                                                       otherstaff);
+                               }
+                       }
+
+                       /* do "with" lists */
+                       pr_withlist(grpsyl_p);
+
+                       /* do stems, flags, slash, and alt */
+                       pr_stems(grpsyl_p);
+
+                       /* print rolls */
+                       if (gets_roll(grpsyl_p, staff_p, v) == YES) {
+                               print_roll(grpsyl_p);
+                       }
+               }
+
+               /* assign anything that happened after start of last group */
+               while (t_p != 0) {
+                       asgnssv(&t_p->ssv);
+                       t_p = t_p->next;
+               }
+
+               /* print tuplet numbers if any */
+               pr_tupnums(staff_p->groups_p[v], staff_p);
+
+               /* draw beams */
+               pr_beams(staff_p->groups_p[v], GV_NORMAL, GS_NORMAL);
+               pr_beams(staff_p->groups_p[v], GV_ZERO, GS_SMALL);
+               pr_beams(staff_p->groups_p[v], GV_NORMAL, GS_SMALL);
+       }
+
+       /* now do any associated STUFFs */
+       pr_stuff(staff_p->stuff_p, staff_p->staffno, mll_p);
+}
+\f
+
+/* if two syllables are to be joined, draw a little curved line between them */
+
+static void
+do_syl_joins (syl, west, y)
+
+char *syl;     /* syllable string */
+double west;   /* where syllable was printed */
+double y;      /* where syllable was printed */
+
+{
+       int font, size;
+       char *p;                        /* pointer into syllable string */
+       float wid;                      /* of syllable up to space */
+       double x, east;                 /* of curved line */
+       double xinc, yinc;              /* increment to move when doing curve */
+       double spacewid;                /* width of ' ' */
+
+
+       int skipover = NO;
+       
+       /* skip past any <...> */
+       font = syl[0];
+       size = syl[1];
+       for (p = syl + 2; *p != '\0'; p++) {
+               switch ( (unsigned) *p & 0xff) {
+               case STR_PRE:
+               case STR_U_PRE:
+               case STR_PST:
+               case STR_U_PST:
+                       skipover = YES;
+                       break;
+               case STR_PRE_END:
+               case STR_PST_END:
+                       skipover = NO;
+                       break;
+               case STR_MUS_CHAR:
+                       p += 2;
+                       break;
+               case STR_FONT:
+                       font = *(p+1);
+                       /*FALLTHRU*/
+               case STR_SIZE:
+               case STR_BACKSPACE:
+               case STR_PAGENUM:
+               case STR_NUMPAGES:
+                       p++;
+                       break;
+               case ' ':
+                       if (skipover == NO && font <= EXT_FONT_OFFSET) {
+                               /* temporarily shorten string to just before
+                                * the space to get width of string up to
+                                * that point */
+                               *p = '\0';
+                               wid = strwidth(syl);
+                               *p = ' ';
+
+                               /* Calculate dimensions
+                                * and location of curve to be drawn. */
+                               spacewid = width(font, size, ' ');
+                               xinc = spacewid * 0.3;
+                               yinc = spacewid * 0.15;
+                               x = west + wid - STDPAD;
+                               east = x + spacewid;
+
+                               do_linetype(L_NORMAL);
+                               do_moveto(x, y);
+                               do_curveto(x + xinc, y - yinc,
+                                       east - xinc, y - yinc, east, y);
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+\f
+
+/* print things in STUFF list */
+
+static void
+pr_stuff (stufflist_p, staffno, mll_p)
+
+struct STUFF *stufflist_p;     /* which list of STUFF */
+int staffno;                   /* which staff the stuff is for */
+struct MAINLL *mll_p;
+
+{
+       char lch;       /* last character in string */
+
+
+       /* do each item in stuff list */
+       for (   ; stufflist_p != (struct STUFF *) 0;
+                                       stufflist_p = stufflist_p->next) {
+
+               set_staffscale( (stufflist_p->all == YES) ? 0 : staffno);
+
+               switch (stufflist_p->stuff_type) {
+
+               case ST_MUSSYM:
+               case ST_OCTAVE:
+               case ST_ROM:
+               case ST_BOLD:
+               case ST_ITAL:
+               case ST_BOLDITAL:
+                       /* do 'til' clause if any */
+                       extend(stufflist_p);
+
+                       /* if special case of ending in ~ or _, don't print the
+                        * ~ or _ itself */
+                       if ((lch = last_char(stufflist_p->string)) == '~' ||
+                                       lch == '_') {
+                               stufflist_p->string[strlen(stufflist_p->string)
+                                               -1] = '\0';
+                       }
+
+                       /* print the string at specified place */
+                       if (stufflist_p->string != (char *) 0) {
+
+
+                               /* print grid if appropriate,
+                                * otherwise just the string. */
+                               if (stufflist_p->modifier != TM_CHORD ||
+                                               svpath(staffno, GRIDSWHEREUSED)
+                                               ->gridswhereused == NO ||
+                                               pr_grid(stufflist_p,
+                                               (stufflist_p->all == YES ?
+                                               0 : staffno))
+                                               == NO) {
+                                       pr_string (stufflist_p->c[AW],
+                                               stufflist_p->c[AY],
+                                               stufflist_p->string, J_LEFT,
+                                               stufflist_p->inputfile,
+                                               stufflist_p->inputlineno);
+                               }
+                       }
+
+                       break;
+
+               case ST_CRESC:
+               case ST_DECRESC:
+                       pr_cresc(stufflist_p);
+                       break;
+
+               case ST_PEDAL:
+                       pr_ped_char(stufflist_p, staffno);
+                       break;
+
+               case ST_PHRASE:
+                       pr_phrase(stufflist_p->crvlist_p, stufflist_p->modifier,
+                               (stufflist_p->modifier == L_NORMAL ? YES : NO),
+                               staffno);
+                       break;
+
+               case ST_TIESLUR:
+                       pr_tieslur(stufflist_p, mll_p, staffno);
+                       break;
+               
+               case ST_BEND:
+                       pr_bend(stufflist_p->crvlist_p);
+                       break;
+
+               case ST_TABSLUR:
+                       pr_tabslur(stufflist_p->crvlist_p,
+                                       get_ts_style(stufflist_p, mll_p));
+                       break;
+
+               case ST_MIDI:
+                       break;
+
+               default:
+                       pfatal("unknown stuff type");
+                       break;
+               }
+       }
+}
+\f
+
+/* Print a guitar grid. Return YES if grid was found and printed, else NO. */
+
+static int
+pr_grid(stuff_p, staffnum)
+
+struct STUFF *stuff_p;
+int staffnum;
+
+{
+       struct GRID *grid_p;
+       double space;
+       float north, south;
+
+
+       if ((grid_p = findgrid(stuff_p->string)) == 0) {
+               /* placement phase should have printed a warning already */
+               return(NO);
+       }
+
+       /* print the grid name */
+       pr_string(stuff_p->c[AX] - strwidth(grid_p->name) / 2.0,
+                       stuff_p->c[AY], grid_p->name, J_LEFT,
+                       stuff_p->inputfile, stuff_p->inputlineno);
+
+       space = gridspace(staffnum);
+       gridsize(grid_p, staffnum, &north, &south, (float *) 0, (float *) 0);
+
+       do_grid(stuff_p->c[AX] - space * (grid_p->numstr - 1) / 2.0,
+                       stuff_p->c[AS] - south,
+                       space, grid_p, staffnum);
+       return(YES);
+}
+\f
+
+/* print ties and slurs */
+
+static void
+pr_tieslur(stuff_p, mll_p, staffno)
+
+struct STUFF *stuff_p;
+struct MAINLL *mll_p;
+int staffno;
+
+{
+       int ts_style;           /* tie/slur style (L_DOTTED or L_DASHED) */
+
+
+       ts_style = get_ts_style(stuff_p, mll_p);
+
+       /* If tabslur, do that */
+       if ( stuff_p->curveno >= 0 && stuff_p->begnote_p->nslurto > 0
+                       && IS_NOWHERE(stuff_p-> begnote_p->slurtolist
+                       [stuff_p->curveno].octave)) {
+               pr_tabslur(stuff_p->crvlist_p, ts_style);
+               return;
+       }
+
+       /* print a regular tie/slur curve */
+       pr_phrase(stuff_p->crvlist_p, ts_style,
+                               (ts_style == L_NORMAL ? YES : NO), staffno );
+}
+\f
+
+/* given a TIESLUR STUFF, return the line type to use for it */
+
+static int
+get_ts_style(stuff_p, mll_p)
+
+struct STUFF *stuff_p;
+struct MAINLL *mll_p;
+
+{
+       struct GRPSYL *prevgrp_p;       /* for carryins */
+       int n;                          /* notelist index */
+
+
+       if (stuff_p->carryin == YES) {
+               prevgrp_p = prevgrpsyl(stuff_p->beggrp_p, &mll_p);
+               if (stuff_p->curveno >= 0) {
+                       /* a carried-in slur. Need to find a note
+                        * in previous group that is slurred to this one,
+                        * and use its slurstyle. There is some chance
+                        * that there could be more than one slur to this
+                        * note from the same curveno
+                        * and each slur could have a different style,
+                        * in which case we no longer have enough information
+                        * to know which to use, so we just use the first
+                        * we find. */
+                       for (n = 0; n < prevgrp_p->nnotes; n++) {
+
+                               if (prevgrp_p->notelist[n].nslurto
+                                                       <= stuff_p->curveno) {
+                                       /* couldn't have come from this grp */
+                                       continue;
+                               }
+
+                               if (prevgrp_p->notelist[n].slurtolist
+                                               [stuff_p->curveno].letter
+                                               == stuff_p->begnote_p->letter
+                                               && prevgrp_p->notelist[n]
+                                               .slurtolist[stuff_p->curveno].octave
+                                               == stuff_p->begnote_p->octave) {
+
+                                       return (prevgrp_p->notelist[n].
+                                               slurtolist[stuff_p->curveno]
+                                               .slurstyle);
+                               }
+                       }
+               }
+               else {
+                       /* a carried-in tie. Need to find matching note
+                        * in previous group, and use its tiestyle. */
+                       for (n = 0; n < prevgrp_p->nnotes; n++) {
+                               if (prevgrp_p->notelist[n].letter ==
+                                               stuff_p->begnote_p->letter &&
+                                               prevgrp_p->notelist[n].octave
+                                               == stuff_p->begnote_p->octave) {
+                                       return(prevgrp_p->notelist[n].tiestyle);
+                               }
+                       }
+               }
+       }
+
+       else {
+               if (stuff_p->curveno >= 0) {
+                       /* a non-carried-in slur, use slurstyle */
+                       return(stuff_p->begnote_p->slurtolist
+                                               [stuff_p->curveno].slurstyle);
+               }
+               else {
+                       /* a non-carried-in tie, use tiestyle */
+                       return(stuff_p->begnote_p->tiestyle);
+               }
+       }
+
+       /* if none of those cases applied, use normal */
+       return(L_NORMAL);
+}
+\f
+
+/* print a rest symbol */
+
+static void
+pr_rest(gs_p, staff_p)
+
+struct GRPSYL *gs_p;   /* information about the rest to be printed */
+struct STAFF *staff_p;
+
+{
+       int muschar;    /* which type of rest character to print */
+       int d;          /* number of dots */
+       float adjust;   /* to space dots properly */
+       float y;        /* vertical location of rest */
+       int size;
+
+
+       if (gs_p->basictime < -1) {
+               /* multirest are a special case */
+               pr_multirest(gs_p, staff_p);
+               return;
+       }
+
+       /* draw the rest */
+       muschar = restchar(gs_p->basictime);
+       /* Half and whole rests outside the staff need to use the version
+        * that includes a ledger line. So check for that case. 
+        * We used to use characters with ledgers all the time,
+        * but Ghostscript then sometimes seemed to misplace them
+        * by one pixel at certain magnifications, which looked bad. */
+       if (muschar == C_LL1REST || muschar == C_LL2REST) {
+               double halfst;
+               if (svpath(staff_p->staffno, STAFFLINES)->stafflines > 1) {
+                       halfst = halfstaffhi(staff_p->staffno);
+               }
+               else {
+                       halfst = 0.0;
+               }
+               /* The adjustments to halfst are chosen so that both half
+                * and whole rests will properly get leger lines when they
+                * are outside the staff, but not when inside.
+                */
+               if ( (gs_p->c[AN] > (staff_p->c[AY] + halfst + 1.7 * Stepsize)) ||
+                               (gs_p->c[AN] < (staff_p->c[AY] - halfst - Stdpad)) ) {
+                       muschar = (muschar == C_LL1REST ? C_1REST : C_2REST);
+               }
+       }
+       size = (gs_p->grpsize == GS_NORMAL ? DFLT_SIZE : SMALLSIZE);
+       if (gs_p->is_meas == YES) {
+               /* measure rest is special case, have to move to middle */
+               pr_muschar( (gs_p->c[AW] + gs_p->c[AE]) / 2.0,
+                                       gs_p->c[AY], muschar, size, FONT_MUSIC);
+       }
+       else {
+               pr_muschar(gs_p->c[AX], gs_p->c[AY], muschar, size, FONT_MUSIC);
+       }
+
+       /* get ready to print any dots */
+       adjust = width(FONT_MUSIC, adj_size(size, Staffscale, (char *) 0,
+                               -1), C_DOT) / 2.0;
+       y = _Cur[AY] + Stepsize;
+
+       /* print any dots after the rest */
+       for (d = 0; d < gs_p->dots; d++) {
+               /* each time we print a dot, the current location will get
+                * moved to just beyond that one */
+               pr_muschar(_Cur[AX] + adjust + (2.0 * Stdpad), y, C_DOT, size,
+                                                               FONT_MUSIC);
+       }
+}
+\f
+
+/* print a measure repeat */
+
+void
+pr_mrpt(gs_p, staff_p)
+
+struct GRPSYL *gs_p;
+struct STAFF *staff_p;
+
+{
+       double x;               /* horizontal position of number string */
+       double y, y_offset;     /* vertical location */
+       double height, width;   /* of meas num string */
+       char *numstr;           /* ASCII version of numbers of measures */
+
+
+       /* measure repeat has to be moved to the middle of the measure */
+       pr_muschar( (gs_p->c[AW] + gs_p->c[AE]) / 2.0,
+               mr_y_loc(gs_p->staffno), C_MEASRPT, DFLT_SIZE, FONT_MUSIC);
+
+       if (svpath(gs_p->staffno, NUMBERMRPT)->numbermrpt == YES) {
+               /* print number above the staff */
+               y = Staffs_y[gs_p->staffno];
+               numstr = mrnum(staff_p, &x, &y_offset, &height, &width);
+               pr_string(x, y + y_offset, numstr, J_LEFT, (char *) 0, -1);
+       }
+}
+\f
+
+/* given a staff number, return the y at which to print the measure repeat
+ * or multirest symbols. If the number of staff lines is odd, this is the
+ * middle line, otherwise the line just above the middle. */
+
+static double
+mr_y_loc(staffno)
+
+int staffno;
+
+{
+       double y;
+
+       y = Staffs_y[staffno];
+       /* if even number of staff lines, move up a stepsize */
+       if ( (svpath(staffno, STAFFLINES)->stafflines & 1) == 0) {
+               y += Stepsize * (is_tab_staff(staffno) ? TABRATIO : 1.0);
+       }
+       return(y);
+}
+\f
+
+/* print the dots for dotted notes */
+
+static void
+pr_note_dots(noteinfo_p, numdots, xdotr, group_x, group_y)
+
+struct NOTE *noteinfo_p;       /* which note to dot */
+int numdots;           /* how many dots to print */
+double xdotr;          /* relative x distance from note to print the dots */
+double group_x;
+double group_y;                /* coord of group, dots are relative to this */
+
+{
+       float adjust;   /* to place dots with proper spacing */
+
+
+       /* if note isn't dotted, nothing to do */
+       if (numdots <= 0) {
+               return;
+       }
+
+       adjust = width(FONT_MUSIC, adj_size(DFLT_SIZE, Staffscale,
+                               (char *) 0, -1), C_DOT) / 2.0;
+
+       /* go to where first dot belongs */
+       set_cur(group_x + xdotr - adjust, group_y + noteinfo_p->ydotr);
+       
+       /* print as many dots as necessary */
+       for (  ; numdots > 0; numdots--) {
+               pr_muschar(_Cur[AX] + adjust + (2.0 * Stdpad),
+                               _Cur[AY], C_DOT, DFLT_SIZE, FONT_MUSIC);
+       }
+}
+\f
+
+/* print parentheses around a note. Should only be called if note_has_paren
+ * is YES */
+
+static void
+pr_parens(note_p, gs_p)
+
+struct NOTE *note_p;
+struct GRPSYL * gs_p;
+
+{
+       char paren_string[4];
+       double y;
+
+
+       /* make a parentheses string of proper size in internal string format */
+       (void) sprintf(paren_string, "%c%c(", FONT_TR,
+               adj_size((note_p->notesize == GS_NORMAL ? DFLT_SIZE : SMALLSIZE),
+                               Staffscale, (char *) 0, -1));
+
+       /* center the parentheses vertically on the Y on the note */
+       y = note_p->c[AY] - (strascent(paren_string)
+                                       - (strheight(paren_string) / 2.0));
+
+       /* print the left parenthesis */
+       pr_string(gs_p->c[AX] + note_p->wlparen, y,
+                               paren_string, J_LEFT, (char *) 0, -1);
+
+       /* now do the right parenthesis */
+       paren_string[2] = ')';
+       pr_string(gs_p->c[AX] + note_p->erparen - strwidth(paren_string), y,
+                               paren_string, J_LEFT, (char *) 0, -1);
+}
+\f
+
+/* print "with" lists */
+
+void
+pr_withlist(gs_p)
+
+struct GRPSYL *gs_p;   /* GRPSYL that might have with lists */
+
+{
+       float y;                /* where to start from */
+       float x;
+       float  y_offset, sign;
+       float x_offset;         /* to center first character of item on note */
+       float yposition;        /* y coordinate at which to print */
+       float item_height;      /* height of with list item */
+       int first_char;         /* first char of string to print */
+       char *str_p;            /* pointer into string to print */
+       int font, size;
+       int index;              /* offset into with list */
+       int alternate;          /* upside version of music symbol */
+       float ystaff;           /* y of middle of staff */
+       float yline;            /* y value of staff line */
+       float top, bot;         /* top and bottom of item to be printed */
+       float pad;              /* vertical padding around short items */
+       int sl;                 /* staff line index */
+       float adjusted_stepsize;        /* STEPSIZE or STEPSIZE * TABRATIO
+                                * depending on whether tab staff or not */
+       int stafflines;         /* how many lines in current staff */
+       float minwithheight;    /* MINWITHHEIGHT * Staffscale */
+
+
+       if (gs_p->nnotes == 0) {
+               return;
+       }
+
+       /* with goes forward from note opposite stem */
+       if (gs_p->normwith == YES) {
+               if (gs_p->stemdir == UP) {
+                       y = gs_p->notelist [gs_p->nnotes - 1] .c[AS];
+                       x = gs_p->notelist [gs_p->nnotes - 1] .c[AX];
+                       sign = -1.0;
+               }
+               else {
+                       y = gs_p->notelist[0].c[AN];
+                       x = gs_p->notelist[0].c[AX];
+                       sign = 1.0;
+               }
+       }
+       else {
+               /* with goes on opposite side than normal */
+               y = find_y_stem(gs_p);
+               if (gs_p->stemdir == DOWN) {
+                       sign = -1.0;
+                       /* whole notes /double wholes may have
+                        * zero length stems so have to adjust */
+                       if (gs_p->stemlen <= 0.0) {
+                               y = gs_p->notelist[gs_p->nnotes - 1] .c[AS];
+                       }
+                       /* beamed notes stems effective stick out a little
+                        * farther, so compensate for that */
+                       if (gs_p->beamloc != NOITEM) {
+                               y -= POINT;
+                       }
+               }
+               else {
+                       sign = 1.0;
+                       if (gs_p->stemlen <= 0.0) {
+                               y = gs_p->notelist[0].c[AN];
+                       }
+                       if (gs_p->beamloc != NOITEM) {
+                               y += POINT;
+                       }
+               }
+               x = gs_p->c[AX];
+       }
+
+       /* If a dot, wedge, and uwedge is the only item in the list,
+        * and it's on the stem side of a group with a stem, it is supposed
+        * to be aligned with the stem. */
+       if (gs_p->normwith == NO && gs_p->nwith == 1 &&
+                               gs_p->basictime > 1 && gs_p->stemlen > 0.0 &&
+                               is_music_symbol(gs_p->withlist[0]) == YES) {
+               font = gs_p->withlist[0][0];
+               size = gs_p->withlist[0][1];
+               str_p = gs_p->withlist[0] + 2;
+               first_char = next_str_char(&str_p, &font, &size);
+               if (first_char == C_DOT || first_char == C_WEDGE ||
+                                       first_char == C_UWEDGE) {
+                       x = find_x_stem(gs_p);
+               }
+       }
+
+       y_offset = 0.0;
+       minwithheight = MINWITHHEIGHT * Staffscale;
+
+       /* do each item in with list */
+       for (index = 0; index < gs_p->nwith; index++) {
+
+               /* should center first character on x */
+               font = gs_p->withlist[index][0];
+               size = gs_p->withlist[index][1];
+               str_p = gs_p->withlist[index] + 2;
+               first_char = next_str_char(&str_p, &font, &size);
+
+               /* get upside down version if necessary */
+               if (sign == -1.0 && IS_MUSIC_FONT(font)) {
+                       if ((alternate = mirror(gs_p->withlist[index],
+                                       first_char, font)) != first_char) {
+                               *(str_p - 1) = (char) alternate;
+                       }
+               }
+               
+               x_offset = left_width( &(gs_p->withlist[index][0]) );
+
+               /* get height of item to print */
+               item_height = strheight(gs_p->withlist[index]);
+
+               /* if string is so short vertically
+                * it could get swallowed up in a staff
+                * line, adjust to fall in a space. Placement phase will have
+                * allowed MINWITHHEIGHT, so put in middle of that area unless
+                * that would fall on a line, in which case move somewhat */
+               if (item_height < minwithheight) {
+                       /* need to adjust this one. Start out by putting in
+                        * middle vertically of reserved area */
+                       yposition = y + y_offset + sign * minwithheight / 2.0;
+
+                       /* no reason to adjust further for 1-line staffs */
+                       if ((stafflines = svpath(gs_p->staffno,
+                                               STAFFLINES)->stafflines) > 1) {
+
+                               /* get stepsize distance based on whether it
+                                * is a tab staff or not */
+                               adjusted_stepsize = (is_tab_staff(gs_p->staffno)
+                                       == YES ? Stepsize * TABRATIO : Stepsize);
+
+                               /* find y of middle of staff */
+                               ystaff = gs_p->notelist[0].c[AY]
+                                       - (gs_p->notelist[0].stepsup
+                                       * adjusted_stepsize);
+
+                               /* take the extra vertical space alloted to this
+                                * with list item, and add 1/4 of it on top
+                                * and bottom as padding. If no staff line is
+                                * in between the boundaries of the item after
+                                * adding that padding, it's good enough where
+                                * it is. Otherwise, if a staff line falls above
+                                * the middle of the item, move the item
+                                * down into space. Otherwise move it
+                                * up into space.
+                                */
+                               pad = (minwithheight - item_height) / 4.0;
+                               top = yposition + (item_height / 2.0) + pad;
+                               bot = yposition - (item_height / 2.0) - pad;
+
+                               /* check each staff line for collisions, from
+                                * bottom to top */
+                               for (sl = -(stafflines - 1);
+                                               sl <= (stafflines - 1);
+                                               sl += 2) {
+
+                                       /* find y of current staff line */
+                                       yline = ystaff + (sl * adjusted_stepsize);
+
+                                       /* check if current staff line goes
+                                        * through the item
+                                        * as currently placed */
+                                       if (yline < top && yline > bot) {
+                                               /* collides--need to move */
+
+                                               if ((top - yline) >
+                                                               (yline - bot)) {
+                                                       /* move up to area
+                                                        * above the line */
+                                                       yposition += 2.0 * pad;
+                                                       /* if overdid the move,
+                                                        * move back a bit */
+                                                       if (yposition - yline -
+                                                       (item_height / 2.0)
+                                                       > 0.7 * adjusted_stepsize) {
+                                                               yposition -=
+                                                                0.4 * adjusted_stepsize;
+                                                       }
+                                               }
+                                               else {
+                                                       /* move down to area
+                                                        * below the line */
+                                                       yposition -= 2.0 * pad;
+                                                       if (yline - yposition -
+                                                       (item_height / 2.0)
+                                                       > 0.7 * adjusted_stepsize) {
+                                                               yposition +=
+                                                                0.4 * adjusted_stepsize;
+                                                       }
+                                               }
+
+                                               /* only 1 staff line can
+                                                * possibly interfere,
+                                                * and we've found that one, so
+                                                * can jump out of loop */
+                                               break;
+                                       }
+                               }
+                       }
+
+                       /* adjust y_offset to include the area taken by item */
+                       y_offset += minwithheight * sign;
+
+                       /* up to now, we've been using the center of the item,
+                        * so now adjust to baseline */
+                       if (sign > 0.0) {
+                               yposition += (item_height / 2.0)
+                                       - strascent(gs_p->withlist[index]);
+                       }
+                       else {
+                               yposition -= (item_height / 2.0)
+                                       - strdescent(gs_p->withlist[index]);
+                       }
+               }
+               else {
+                       /* not too short, handle normally */
+                       y_offset += item_height * sign;
+                       yposition = y + y_offset;
+
+                       /* adjust to get to baseline of string from top or
+                        * bottom that we've used up to this point */
+                       if (sign > 0.0) {
+                               yposition -= strascent(gs_p->withlist[index]);
+                       }
+                       else {
+                               yposition += strdescent(gs_p->withlist[index]);
+                       }
+               }
+
+               pr_string(x - x_offset, yposition, gs_p->withlist[index],
+                               J_CENTER, gs_p->inputfile, gs_p->inputlineno);
+       }
+}
+\f
+
+/* print note stems and flags. Also print any slashes and alt lines */
+
+static void
+pr_stems(grpsyl_p)
+
+struct GRPSYL *grpsyl_p;       /* which group's stem to print */
+
+{
+       float x, y1, y2;
+       float sign;     /* 1 or -1 direction for moving to draw slashes */
+       float y_offset, offset, spacing;        /* for where to draw slashes */
+       float y_tilt;           /* how much to move in y direction to get
+                                * proper tilt on slashes */
+       float halfwidth;        /* half width of slash or alt line */
+       struct GRPSYL *first_p, *last_p;        /* beginning and ending group
+                                                * of beam group */
+       int grpsize;            /* grpsize field of grpsyl_p */
+       int grpvalue;           /* grpvalue field of grpsyl_p */
+       int slash;              /* to count number of slashes drawn */
+       struct NOTE *note_p;
+
+
+       /* if no stem, nothing to do */
+       if ( grpsyl_p->stemlen <= 0 && grpsyl_p->slash_alt == 0) {
+               return;
+       }
+
+       /* figure out x coordinate of stem */
+       x = find_x_stem(grpsyl_p);
+
+       /* if stem is up, start at bottom note, if down, at top */
+       if (grpsyl_p->stemdir == UP) {
+               note_p = &(grpsyl_p->notelist[ grpsyl_p->nnotes - 1]);
+               y1 = note_p->c[AY];
+               y2 = find_y_stem(grpsyl_p);
+               sign = -1;
+       }
+       else {
+               note_p = &(grpsyl_p->notelist [0]);
+               y1 = note_p->c[AY];
+               y2 = find_y_stem(grpsyl_p);
+               sign = 1;
+       }
+
+       if (note_p->headchar != 0) {
+               y1 += stem_yoff(note_p->headchar, note_p->headfont,
+                       grpsyl_p->stemdir)
+                       * (note_p->notesize == GS_NORMAL
+                       ? Stepsize : Stepsize * SM_FACTOR);
+       }
+
+       if (grpsyl_p->basictime >= 2) {
+               /* print the stem */
+               do_linetype(L_NORMAL);
+
+               draw_line(x, y1, x, y2);
+
+               /* attach any flags as appropriate */
+               pr_flags(grpsyl_p, (double) x, (double) y2);
+       }
+
+       /* print any slashes */
+       if (grpsyl_p->slash_alt > 0) {
+
+               /* adjust for flags or beams. */
+               if (grpsyl_p->basictime >= 8) {
+                       offset = (numbeams(grpsyl_p->basictime) - 1) *
+                               (grpsyl_p->grpsize == GS_NORMAL ? 5.0 : 4.0)
+                               * Stdpad;
+                       if (grpsyl_p->beamloc == NOITEM) {
+                               if (grpsyl_p->grpsize == GS_NORMAL) {
+                                       offset += 8.0 * Stdpad;
+                               }
+                               else if (grpsyl_p->basictime != 16) {
+                                       /* 16th small notes don't have any extra
+                                        * stem to account for extra flag */
+                                       offset += 3.0 * Stdpad;
+                               }
+                       }
+               }
+               else {
+                       offset = 0.0;
+               }
+
+               if ( grpsyl_p->beamloc == NOITEM) {
+                       /* unbeamed things get hard-coded tilt value */
+                       if (grpsyl_p->grpvalue == GV_ZERO) {
+                               y_tilt = (grpsyl_p->stemdir == UP ? 3.5 : -3.5)
+                                                       * Stdpad;
+                       }
+                       else {
+                               y_tilt = 2.2 * Stdpad;
+                       }
+               }
+
+               else {
+                       /* beamed. Need to slant slashes the same as beam */
+
+                       grpsize = grpsyl_p->grpsize;
+                       grpvalue = grpsyl_p->grpvalue;
+
+                       /* find beginning and ending stems */
+                       for (first_p = grpsyl_p; (first_p->beamloc != STARTITEM)
+                                       || (first_p->grpsize != grpsize)
+                                       || (first_p->grpvalue != grpvalue);
+                                       first_p = first_p->prev) {
+                               ;
+                       }
+
+                       for (last_p = grpsyl_p; (last_p->beamloc != ENDITEM)
+                                       || (last_p->grpsize != grpsize)
+                                       || (last_p->grpvalue != grpvalue);
+                                       last_p = last_p->next) {
+                               ;
+                       }
+
+                       /* calculate slope from them. We find the ratio of
+                        * y to x of the beam and apply that proportion to
+                        * the known x length of the slash to get the y height
+                        * of the slash, then divide by 2 to get the y distance
+                        * on either side of the stem. */
+                       y_tilt = (((find_y_stem(last_p) - find_y_stem(first_p))
+                                       * (2.0 * slash_xlen(grpsyl_p)))
+                                       / (find_x_stem(last_p)
+                                       - find_x_stem(first_p))) / 2.0;
+                       y1 = find_y_stem(first_p);
+               }
+
+               /* draw the slashes */
+               pr_slashes(grpsyl_p, (double) x, (double) y2, (double) sign,
+                               (double) offset, (double) y_tilt);
+       }
+
+       /* print alt group lines if any */
+       if (grpsyl_p->slash_alt < 0) {
+               struct GRPSYL *grpsyl2_p;
+               float grp2x, grp2y;     /* stem of second group */
+               float grp1y_offset, grp2y_offset;
+
+
+               if (grpsyl_p->next == (struct GRPSYL *) 0) {
+                       pfatal("missing second group in alt pair");
+               }
+
+               /* figure out how wide to draw the lines and how far apart
+                * to make them */
+               if (grpsyl_p->grpsize == GS_NORMAL) {
+                       halfwidth = W_WIDE * Staffscale / PPI / 2.0;
+                       spacing = 5.0 * Stdpad;
+               }
+               else {
+                       halfwidth = W_MEDIUM * Staffscale / PPI / 2.0;
+                       spacing = 3.0 * Stdpad;
+               }
+
+               /* find the stem coordinates of the second group */
+               grpsyl2_p = grpsyl_p->next;
+               grp2x = find_x_stem(grpsyl2_p);
+               grp2y = find_y_stem(grpsyl2_p);
+
+               /* on notes shorter than half note, the lines don't go all the
+                * way to the stems */
+               if ( grpsyl_p->basictime >= 4) {
+                       /* figure out where the y of the end of the line is
+                        * by multiplying the x value by the tangent of the
+                        * angle of the line that would go all the way
+                        * between the stems */
+                       grp2y_offset = (grp2x - x - (6.0 * Stdpad))
+                                               * ((grp2y - y2) / (grp2x - x));
+                       grp1y_offset = (6.0 * Stdpad)
+                                       * ((grp2y - y2) / (grp2x - x));
+                       /* if 8th notes or shorter, get out of way of beams */
+                       offset = numbeams(grpsyl_p->basictime) * spacing;
+                       x += (6.0 * Stdpad);
+                       grp2x -= (6.0 * Stdpad);
+               }
+               else {
+                       grp1y_offset = 0.0;
+                       grp2y_offset = grp2y - y2;
+                       offset = 0.0;
+               }
+
+               /* draw the alt lines */
+               for (slash = -(grpsyl_p->slash_alt) - 1; slash >= 0; slash--) {
+                       y_offset = sign * slash * spacing + (sign * offset);
+                       do_newpath();
+                       do_moveto(x, y2 + y_offset + grp1y_offset - halfwidth);
+                       do_line(x, y2 + y_offset + grp1y_offset + halfwidth);
+                       do_line(grp2x, y2 + y_offset + grp2y_offset
+                                                               + halfwidth);
+                       do_line(grp2x, y2 + y_offset + grp2y_offset
+                                                               - halfwidth);
+                       do_closepath();
+                       do_fill();
+               }
+
+               /* earlier phase wanted both groups in alt pair to have
+                * slash_alt set, but now we've printed this one, so clear
+                * the one on the following group, so it won't try to
+                * print another alt group */
+               grpsyl2_p->slash_alt = 0;
+       }
+}
+\f
+
+void
+pr_slashes(grpsyl_p, x, y, sign, offset, y_tilt)
+
+struct GRPSYL *grpsyl_p;
+double x;
+double y;
+double sign;
+double offset;
+double y_tilt;
+
+{
+       int slash;
+       double xlen;
+       float y_offset;
+       float spacing;
+       float halfwidth;
+
+
+       /* get length based on note head size */
+       xlen = slash_xlen(grpsyl_p);
+
+       /* figure out how wide to make the slashes and how far apart
+       * to space them */
+       if (grpsyl_p->grpsize == GS_NORMAL) {
+               halfwidth = W_WIDE * Staffscale / PPI / 2.0;
+               spacing = 5 * Stdpad;
+       }
+       else {
+               halfwidth = W_MEDIUM * Staffscale / PPI / 2.0;
+               spacing = 4 * Stdpad;
+       }
+
+       for (slash = grpsyl_p->slash_alt; slash > 0; slash--) {
+               y_offset = y + sign * (offset + (spacing * slash));
+
+               /* draw filled parallelogram */
+               do_newpath();
+               do_moveto(x - xlen, y_offset - y_tilt - halfwidth);
+               do_line(x - xlen, y_offset - y_tilt + halfwidth);
+               do_line(x + xlen, y_offset + y_tilt + halfwidth);
+               do_line(x + xlen, y_offset + y_tilt - halfwidth);
+               do_closepath();
+               do_fill();
+       }
+}
+
+static double
+slash_xlen(grpsyl_p)
+
+struct GRPSYL *grpsyl_p;
+
+{
+       return (SLASHHORZ * Stepsize *
+                       (grpsyl_p->grpsize == GS_NORMAL ? 1.0 : SM_FACTOR));
+}
+\f
+
+/* print flags on 8th and shorter notes */
+
+static void
+pr_flags(grpsyl_p, x, y)
+
+struct GRPSYL *grpsyl_p;       /* group for which to draw flags */
+double x;
+double y;                      /* coord of end of stem */
+
+{
+       int muschar;    /* what kind of flag to print */
+       float y_offset; /* from end of stem */
+       int f;          /* how many flags */
+       int size;
+
+
+       /* only 8th and shorter notes might have flags */
+       if (grpsyl_p->basictime < 8) {
+               return;
+       }
+
+       /* if not a note, no flag */
+       if (grpsyl_p->grpcont != GC_NOTES) {
+               return;
+       }
+
+       /* if beamed, no flag */
+       if (grpsyl_p->beamloc != NOITEM) {
+               return;
+       }
+
+       /* figure out if up/down and whether small/reg */
+       muschar = (grpsyl_p->stemdir == UP ? C_DNFLAG : C_UPFLAG);
+       size = (grpsyl_p->grpsize == GS_NORMAL ? DFLT_SIZE : SMALLSIZE);
+
+       /* do for each flag. f == 1 less than the number of flags, and is
+        * how much to multiply the y_offset by for each flag */
+       for ( f = numbeams(grpsyl_p->basictime) - 1; f >= 0; f--) {
+
+               switch (muschar) {
+
+               case C_UPFLAG:
+                       y_offset = f * (grpsyl_p->grpsize == GS_NORMAL ?
+                                               FLAGSEP : SMFLAGSEP);
+                       break;
+               case C_DNFLAG:
+                       y_offset = -f * (grpsyl_p->grpsize == GS_NORMAL ?
+                                               FLAGSEP : SMFLAGSEP);
+                       break;
+               default:
+                       pfatal("bad flag type");
+                       /*NOTREACHED*/
+                       return; /* to shut up compiler warning about unused */
+               }
+
+               y_offset *= Staffscale;
+
+               /* now that we know where to place the flag, print it */
+               pr_muschar(x + width(FONT_MUSIC,
+                               adj_size(size, Staffscale, (char *) 0, -1),
+                               muschar) / 2.0,
+                               y + y_offset, muschar, size, FONT_MUSIC);
+       }
+}
+\f
+
+/* print any accidental */
+
+static void
+pr_accidental(noteinfo_p, grpsyl_p)
+
+struct NOTE *noteinfo_p;       /* info about the note being printed */
+struct GRPSYL *grpsyl_p;       /* info about the group conatining the note */
+
+{
+       int muschar;    /* which accidental symbol to draw */
+       int size;
+       int a_size;     /* size adjusted for Staffscale */
+
+
+       /* figure out which accidental symbol to use */
+       muschar = acc2char(noteinfo_p->accidental);
+
+       /* if there is an accidental, print it at specified place */
+       if (muschar != '\0') {
+               size = (noteinfo_p->notesize == GS_NORMAL
+                                               ? DFLT_SIZE : SMALLSIZE);
+               a_size = adj_size(size, Staffscale, (char *) 0, -1);
+               if (noteinfo_p->acc_has_paren == NO) {
+                       pr_muschar(grpsyl_p->c[AX] + noteinfo_p->waccr
+                               + width(FONT_MUSIC, a_size, muschar) / 2.0,
+                               noteinfo_p->c[AY], muschar, size, FONT_MUSIC);
+               }
+               else {
+                       /* have to print parentheses in addition to the
+                        * symbol for the accidental */
+                       char paren_string[4];   /* "(" or ")" in internal format */
+                       double offset;          /* y adjustment of ( ) */
+
+                       /* create string for "(" */
+                       (void) sprintf(paren_string, "%c%c%c",
+                                                       FONT_TR, a_size, '(');
+
+                       /* to center things vertically on the note, need to
+                        * adjust parentheses downward by difference between
+                        * the ascent and half the height of the parenthesis */
+                       offset = strascent(paren_string) -
+                                       (strheight(paren_string) / 2.0);
+
+                       /* print the '(', the accidental, and the ')' */
+                       pr_string(grpsyl_p->c[AX] + noteinfo_p->waccr,
+                                       noteinfo_p->c[AY] - offset,
+                                       paren_string, J_LEFT,
+                                       grpsyl_p->inputfile,
+                                       grpsyl_p->inputlineno);
+
+                       pr_muschar(_Cur[AX] +
+                                       width(FONT_MUSIC, a_size, muschar) / 2.0,
+                                       noteinfo_p->c[AY], muschar, size,
+                                       FONT_MUSIC);
+
+                       (void) sprintf(paren_string, "%c%c%c",
+                                                       FONT_TR, a_size, ')');
+                       pr_string(_Cur[AX], noteinfo_p->c[AY] - offset,
+                                       paren_string, J_LEFT,
+                                       grpsyl_p->inputfile,
+                                       grpsyl_p->inputlineno);
+               }
+       }
+}
+\f
+
+/* print appropriate number of leger lines */
+
+static void
+pr_leger(noteinfo_p, gs_p, staffno)
+
+struct NOTE *noteinfo_p;       /* info about current note */
+struct GRPSYL *gs_p;           /* which group contains the note */
+int staffno;                   /* which staff to draw relative to */
+
+{
+       register int lines2draw;        /* how many leger lines are needed */
+       float sign;                     /* 1 for above or -1 for below staff */
+       float y;                        /* vertical position */
+       float left_leger, right_leger;  /* how far legers stick out from note */
+       int is_intermediate;            /* YES if inner, NO if outermost */
+       int on_other_side;              /* YES if on "wrong" side of stem */
+
+
+       if ((lines2draw = numlegers(noteinfo_p)) < 1) {
+               /* No legers needed for this note */
+               return;
+       }
+
+       /* Is note above or below the middle of the staff? */
+       sign = noteinfo_p->stepsup > 0.0 ? 1.0 : -1.0;
+
+       /* For notes on the "wrong" side of the stem, we will only need
+        * to draw the outermost leger. */
+       if ( (gs_p->stemdir == DOWN && noteinfo_p->c[AE] < gs_p->c[AX]) ||
+                       (gs_p->stemdir == UP && noteinfo_p->c[AW] > gs_p->c[AX])) {
+               on_other_side = YES;
+       }
+       else {
+               on_other_side = NO;
+       }
+
+       /* Draw the legers */
+       do_linetype(L_NORMAL);
+       is_intermediate = NO;
+       for (    ; lines2draw > 0; lines2draw--) {
+
+               /* Find the y location for the leger line.
+                * They are 2 Stepsizes apart,
+                * beginning at the edge of the staff  */
+               y = Staffs_y[staffno]
+                               + (sign * (2 + lines2draw) * (2 * Stepsize));
+
+               /* If things are packed really close together, leger lines
+                * could bleed into leger lines of the neighboring chord.
+                * We need to see if there are any potentially
+                * troublesome leger lines on either side, and shorten
+                * this leger if necessary to avoid them.
+                */
+               left_leger = leger_length(noteinfo_p, gs_p->prev, lines2draw,
+                               YES, is_intermediate);
+               right_leger = leger_length(noteinfo_p, gs_p->next, lines2draw,
+                               NO, is_intermediate);
+
+               draw_line( noteinfo_p->c[AW] - left_leger, y,
+                       noteinfo_p->c[AE] + right_leger, y);
+               is_intermediate = YES;
+
+               /* For notes on the "wrong" side of the stem, we only need
+                * to draw the outermost leger */
+               if (on_other_side == YES) {
+                       break;
+               }
+       }
+}
+\f
+
+/* How many legers to draw is absolute value of stepsup divided
+ * by 2 minus the 2 lines that are already in the staff.
+ * Note that we only do legers on normal 5-line staffs. */
+
+static int
+numlegers(noteinfo_p)
+
+struct NOTE *noteinfo_p;
+
+{
+       return (abs(noteinfo_p->stepsup) / 2) - 2;
+}
+\f
+
+/* If things are packed really close together, leger lines
+ * could bleed into leger lines of the neighboring chord.
+ * This function will detect that and shorten them if necessary.
+ * To be completely correct, it should check all the voices on the
+ * staff, but that would be quite a bit more work, and chances of colliding
+ * with another voice's notes is not very high, so we just check
+ * the voice of the note in question.
+ */
+
+static double
+leger_length(noteinfo_p, othergs_p, lines, other_is_prev, is_intermediate)
+
+struct NOTE *noteinfo_p;       /* we are finding leger length for this note */
+struct GRPSYL *othergs_p;      /* check this group for a too close note */
+int lines;                     /* how many leger lines to draw */
+int other_is_prev;             /* YES if othergs_p is ->prev, NO if ->next */
+int is_intermediate;           /* YES if interior, NO is outermost leger */
+
+{
+       int n;                          /* note index */
+       double distance;                /* between 2 notes */
+       double length = 2.2 * Stdpad;   /* length of leger. Init to default */
+       double adjust;                  /* inners can be shortened extra */
+
+
+       if (othergs_p == 0) {
+               /* No group to collide with */
+               return(length);
+       }
+       if (othergs_p->grpcont != GC_NOTES) {
+               /* Can't have leger lines */
+               return(length);
+       }
+
+       /* Legers that are not through or right next to the note
+        * can be shortened a bit more to make their gap show up better.
+        */
+       adjust = (is_intermediate ? 0.5 * Stdpad : 0.0);
+
+       /* See if othergs_p has any notes that are too close */
+       for (n = 0; n < othergs_p->nnotes; n++) {
+               if (numlegers( &(othergs_p->notelist[n]) ) < lines) {
+                       /* Neighboring note has fewer legers; not relevant */
+                       continue;
+               }
+               if (noteinfo_p->stepsup > 0 &&
+                                       othergs_p->notelist[n].stepsup < 0) {
+                       /* Neighboring note's legers are below, ours above.
+                        * The remaining neighboring notes are irrelevant. */
+                       break;
+               }
+               if (noteinfo_p->stepsup < 0 &&
+                                       othergs_p->notelist[n].stepsup > 0) {
+                       /* Neighboring note's legers are above, ours below.
+                        * Haven't gotten to any potentially relevant
+                        * notes yet. */
+                       continue;
+               }
+
+               /* We have a pair of notes whose leger lines might collide.
+                * See how far apart they are. */
+               if (other_is_prev == YES) {
+                       distance = noteinfo_p->c[AW] - othergs_p->notelist[n].c[AE];
+               }
+               else {
+                       distance = othergs_p->notelist[n].c[AW] - noteinfo_p->c[AE];
+               }
+
+               /* Ideally, we try to make leger lines 2.2 Stdpads on each side,
+                * but if that leaves less than 2.0 Stdpads between them,
+                * we shorten them until they get down to 0.7 Stdpads.
+                * After that we let them join. That should only happen
+                * if things are really tightly packed.
+                * The 6.4 is from two legers of 2.2 each with 2.0 between.
+                */
+               if (distance < 6.4 * Stdpad) {
+                       /* Too close. Will have to shorten */
+                       length = (distance - (2.0 * Stdpad)) / 2.0 - adjust;
+                       if (length < 0.7 * Stdpad - adjust) {
+                               /* No shorter than minimum */
+                               length = 0.7 * Stdpad - adjust;
+                       }
+               }
+       }
+       return (length);
+}
+\f
+
+/* given the first group of a tuplet, return, via pointers, the x coords of
+ * the left and right boundaries of the tuplet number and its height.
+ * Return pointer to static string containing the tuplet number itself in
+ * internal string format */
+
+char *
+tupnumsize(gs_p, west_p, east_p, height_p, staff_p)
+
+struct GRPSYL *gs_p;
+float *west_p;         /* west coord returned here */
+float *east_p;         /* east coord returned here */
+float *height_p;       /* string height returned here */
+struct STAFF *staff_p; /* staff pointing at gs_p */
+
+{
+       char *numstr;                   /* tuplet number as internal string */
+       struct GRPSYL *last_gs_p;       /* last group in tuplet */
+       float num_x;                    /* x coord of number */
+       float halfnumwidth;             /* half the width of numstr */
+       int tupside;
+       int all_cue;
+
+
+       /* assume all cue till proven otherwise */
+       all_cue = YES;
+
+       /* find x of middle of tuplet number */
+       if (gs_p->tuploc == LONEITEM) {
+               if (gs_p->grpsize != GS_SMALL) {
+                       all_cue = NO;
+               }
+               num_x = gs_p->c[AX];
+       }
+       else {
+               for (last_gs_p = gs_p->next; last_gs_p != (struct GRPSYL *) 0;
+                                       last_gs_p = last_gs_p->next) {
+                       if (gs_p->grpsize != GS_SMALL) {
+                               all_cue = NO;
+                       }
+                       if (last_gs_p->tuploc == ENDITEM) {
+                               break;
+                       }
+               }
+               if (last_gs_p == (struct GRPSYL *) 0) {
+                       pfatal("missing end tuplet in tupnumsize");
+               }
+
+               /* Usually, the x location of tuplet number is average of
+                * beginning and end group x coords. But if there is a beam
+                * and the number is being printed on the beam side,
+                * and there is no bracket being printed,
+                * it generally looks better to center between the stems.
+                */
+               tupside = tupdir(gs_p, staff_p);
+               if (gs_p->beamloc == STARTITEM && last_gs_p->beamloc == ENDITEM
+                               && ((tupside == PL_ABOVE && gs_p->stemdir == UP)
+                               || (tupside == PL_BELOW && gs_p->stemdir == DOWN))
+                               && tupgetsbrack(gs_p) == NO) {
+                       num_x = (find_x_stem(last_gs_p) + find_x_stem(gs_p)) / 2.0;
+               }
+               else {
+                       num_x = (last_gs_p->c[AX]  + gs_p->c[AX]) / 2.0;
+               }
+       }
+
+       /* prepare the string to print */
+       numstr = num2str(gs_p->tupcont);
+       /* force to 11-point newcentury bold-italics, unless all cue,
+        * then smaller */
+       numstr[0] = FONT_NX;
+       numstr[1] = (char) adj_size((all_cue == YES ? 9 : 11), Staffscale,
+                               (char *) 0, -1);
+       halfnumwidth = strwidth(numstr) / 2.0;
+
+       /* return the values */
+       *west_p =  num_x - halfnumwidth - Stdpad;
+       *east_p = num_x + halfnumwidth + Stdpad;
+       *height_p = strheight(numstr);
+       return(numstr);
+}
+\f
+
+/* go through measure. If there are any tuplets, print a number by them,
+ * along with bracket if appropriate. */
+
+static void
+pr_tupnums(gs_p, staff_p)
+
+struct GRPSYL *gs_p;   /* start from here to walk through list of groups */
+struct STAFF *staff_p; /* staff pointing to gs_p */
+
+{
+       struct GRPSYL *first_gs_p = 0;  /* where to begin tuplet label.
+                                * Initialization is just to shut up bogus
+                                * compiler warning. */
+       struct GRPSYL *g_p;     /* to check for all spaces */
+       float x1, x2;           /* where tuplet bracket begins & ends */
+       float num_y;            /* y of tuplet number */
+       float y1, y2;           /* y coord of ends of bracket */
+       char *numstr;           /* ASCII version of tuplet number */
+       float numeast, numwest; /* boundaries of tuplet number */
+       float height;           /* of tuplet number */
+       float y_adjust;         /* adjustment for space taken by number */
+       float x_adjust;         /* from group x to where bracket goes */
+       int num_notes = 0;      /* how many notes in tuplet */
+       int need_brack = NO;    /* set to YES if the beaming of the notes
+                                * doesn't match the tuplet boundaries */
+       float brackdir;         /* how far in y direction to draw bracket ends
+                                * (positive or negative depending on the
+                                * direction that the bracket points) */
+       int size;
+
+
+       /* go through all the groups */
+       for (   ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+
+               switch (gs_p->tuploc) {
+
+               case NOITEM:
+                       break;
+
+               case STARTITEM:
+                       /* remember beginning for later use */
+                       first_gs_p = gs_p;
+                       num_notes = 1;
+                       break;
+
+               case INITEM:
+                       num_notes++;
+                       break;
+
+               case LONEITEM:
+                       first_gs_p = gs_p;
+                       /*FALLTHRU*/
+
+               case ENDITEM:
+                       num_notes++;
+                       
+                       /* if not to be printed, nothing to do except reinit */
+                       if (gs_p->printtup == PT_NEITHER) {
+                               num_notes = 0;
+                               break;
+                       }
+
+                       /* we don't do tuplet numbers on cross-staff beams--
+                        * it's virtually impossible to know where to put them
+                        */
+                       if (gs_p->beamto != CS_SAME) {
+                               num_notes = 0;
+                               break;
+                       }
+
+                       /* If the tuplet is all spaces,
+                        * there is nothing to draw a bracket over,
+                        * and trying to do so causes problems,
+                        * so don't try. */
+                       for (g_p = first_gs_p; g_p->tuploc != NOITEM;
+                                                       g_p = g_p->next) {
+                               if (g_p->grpcont != GC_SPACE) {
+                                       /* good--it has something
+                                        * other than spaces */
+                                       break;
+                               }
+
+                               if (g_p->tuploc == ENDITEM
+                                               || g_p->tuploc == LONEITEM) {
+                                       /* reached end of all-space tuplet */
+                                       break;
+                               }
+                       }
+                       if (g_p->grpcont == GC_SPACE) {
+                               /* must have been all spaces */
+                               num_notes = 0;
+                               break;
+                       }
+
+                       /* if tuplet doesn't match beaming, need bracket */
+                       need_brack = tupgetsbrack(first_gs_p);
+
+                       if (num_notes == 0) {
+                               pfatal("no notes in tuplet");
+                       }
+
+                       numstr = tupnumsize(first_gs_p, &numwest, &numeast,
+                                                       &height, staff_p);
+
+                       if (tupdir(first_gs_p, staff_p) == PL_ABOVE) {
+                               y_adjust = strascent(numstr);
+                               y1 = first_gs_p->c[AN] - y_adjust;
+                               y2 = gs_p->c[AN] - y_adjust;
+                               brackdir = -3.0 * Stdpad;
+                       }
+                       else {
+                               /* print below */
+                               y1 = first_gs_p->c[AS];
+                               y2 = gs_p->c[AS];
+                               brackdir = 3.0 * Stdpad;
+                       }
+
+                       /* print tuplet number at correct place */
+                       y1 += first_gs_p->tupextend;
+                       y2 += gs_p->tupextend;
+                       num_y = (y1 + y2) / 2.0;
+                       pr_string(numwest + Stdpad, num_y, numstr, J_LEFT,
+                                       gs_p->inputfile, gs_p->inputlineno);
+
+                       /* add tuplet bracket if necessary */
+                       if (need_brack == YES) {
+                               do_linetype(L_NORMAL);
+                               
+                               /* adjust to reach edge of note head */
+                               size = (first_gs_p->grpsize == GS_NORMAL ?
+                                               DFLT_SIZE : SMALLSIZE)
+                                               * Staffscale;
+                               if (first_gs_p->grpcont == GC_NOTES) {
+                                       x_adjust = widest_head(first_gs_p)
+                                               * Staffscale / 2.0;
+                               }
+                               else if (first_gs_p->grpcont == GC_REST) {
+                                       x_adjust = width(FONT_MUSIC, size,
+
+                                               restchar(first_gs_p->basictime))
+                                               / 2.0;
+                               }
+                               else {
+                                       x_adjust = 0.0;
+                               }
+                               x1 = first_gs_p->c[AX] - x_adjust;
+
+                               size = (gs_p->grpsize == GS_NORMAL ?
+                                               DFLT_SIZE : SMALLSIZE)
+                                               * Staffscale;
+                               if (gs_p->grpcont == GC_NOTES) {
+                                       x_adjust = widest_head(gs_p)
+                                               * Staffscale / 2.0;
+                               }
+                               else if (gs_p->grpcont == GC_REST) {
+                                       x_adjust = width(FONT_MUSIC, size,
+                                               restchar(gs_p->basictime))
+                                               / 2.0;
+                               }
+                               else {
+                                       x_adjust = 0.0;
+                               }
+                               x2 = gs_p->c[AX] + x_adjust;
+
+                               /* move the bracket line up from the baseline
+                                * of the number */
+                               y1 += (4.0 * Stdpad);
+                               y2 += (4.0 * Stdpad);
+                               num_y += (4.0 * Stdpad);
+
+                               /* figure out how much to adjust y from num_y
+                                * to account for the space taken up by the
+                                * number. Use ratio of similar triangles. */
+                               if (numwest - x1 == 0.0) {
+                                       /* avoid any chance of divide by 0 */
+                                       y_adjust = 0.0;
+                               }
+                               else {
+                                       y_adjust = (((numeast - numwest
+                                               + (Stdpad * 2.0)) *
+                                               (num_y - y1)) / (numeast - x1))
+                                               / 2.0;
+                               }
+
+                               draw_line(x1, y1, numwest - Stdpad,
+                                               num_y - y_adjust); 
+                               draw_line(numeast + Stdpad,
+                                               num_y + y_adjust, x2, y2); 
+                               draw_line(x1, y1, x1, y1 + brackdir);
+                               draw_line(x2, y2, x2, y2 + brackdir); 
+                       }
+
+                       /* re-init in case other tuplets in same measure */
+                       num_notes = 0;
+
+                       break;
+
+               default:
+                       pfatal("bad tuplet type");
+                       break;
+               }
+       }
+}
+\f
+
+/* utility function. Given the first group in a tuplet, return YES if it
+ * is to have a bracket printed. It does if the tuplet itself is to be printed,
+ * and if not a LONEITEM and if any of the beamlocs do not match the tuploc */
+
+int
+tupgetsbrack(gs_p)
+
+struct GRPSYL *gs_p;   /* first group of tuplet */
+
+{
+       /* If nothing is to be printed or number only, no bracket */
+       if (gs_p->printtup == PT_NEITHER || gs_p->printtup == PT_NUMBER) {
+               return(NO);
+       }
+
+       /* single chord tuplets never get a bracket -- not enough room
+        * to draw one */
+       if (gs_p->tuploc == LONEITEM) {
+               return(NO);
+       }
+
+       /* if user insists on a bracket, we oblige */
+       if (gs_p->printtup == PT_BOTH) {
+               return(YES);
+       }
+
+       /* check for mismatches between beamloc and tuploc. */
+       for (  ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+               /* grace notes don't count */
+               if (gs_p->grpvalue == GV_ZERO) {
+                       continue;
+               }
+
+               if (gs_p->tuploc != gs_p->beamloc) {
+                       return(YES);
+               }
+               if (gs_p->tuploc == ENDITEM) {
+                       /* matched beam everywhere, so no bracket needed */
+                       return(NO);
+               }
+       }
+       pfatal("missing end tuplet");
+
+       /*NOTREACHED*/
+       return(NO);
+}
+\f
+
+/* utility function to return PL_ABOVE  or PL_BELOW
+ * depending on whether the number for
+ * the given tuplet should get printed above or below the groups */
+/* Can be passed any group in the tuplet. If not the first, it will find the
+ * first and go from there */
+
+int
+tupdir(gs_p, staff_p)
+
+struct GRPSYL *gs_p;   /* group in tuplet */
+struct STAFF *staff_p; /* staff pointing to gs_p */
+
+{
+       RATIONAL starttime, endtime;    /* begin & end time of tuplet */
+       struct GRPSYL *save_gs_p;       /* temporarily save value of gs_p */
+       int othervoice;                 /* array subscript in staff_p->groups_p
+                                        * of the other voice on this staff */
+       int vscheme;                    /* V_* value */
+       RATIONAL smalltime;
+
+
+       smalltime.n = 1;
+       smalltime.d = 2 * MAXBASICTIME;
+
+
+       switch (gs_p->tuploc) {
+
+       case LONEITEM:
+       case STARTITEM:
+               /* this is the one we want */
+               break;
+
+       case NOITEM:
+               pfatal("arg of tupdir is not in a tuplet");
+               /*NOTREACHED*/
+               break;
+       default:
+               /* have to back up to beginning of tuplet first */
+               for (    ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->prev) {
+                       if (gs_p->tuploc == STARTITEM) {
+                               break;
+                       }
+               }
+               if (gs_p == (struct GRPSYL *) 0) {
+                       pfatal("can't find beginning of tuplet");
+               }
+               break;
+       }
+
+       /* figure out which side. First determine vscheme */
+
+       /* there is a circumstance where we're looking at an entire score,
+        * (in relvert), and if some of the score has V_1 and some of it
+        * doesn't, it's possible for us to get confused and think something
+        * isn't V_1 when it is. We would then try to look at the other
+        * voice, which is null, and would blow up. To avoid this, if one
+        * voice is null, treat measure as V_1 regardless of what vscheme
+        * might lead us to believe.
+        */
+       if (staff_p->groups_p[1] == (struct GRPSYL *) 0) {
+               return(tupdir1voice(gs_p));
+       }
+
+       /* voice 3 pays no attention to any other voices. */
+       if (gs_p->vno == 3) {
+               return(tupdir1voice(gs_p));
+       }
+
+       if ((vscheme = svpath(staff_p->staffno, VSCHEME)->vscheme) == V_1) {
+               return(tupdir1voice(gs_p));
+       }
+       else if (vscheme == V_2OPSTEM) {
+               /* 2 opposing stem voices, always put tuplet above voice 1 and
+                * below voice 2 */
+               if (gs_p->tupside != PL_UNKNOWN) {
+                       l_warning(gs_p->inputfile, gs_p->inputlineno,
+                                       "tuplet side specification not valid when vscheme=2o");
+                       /* fix so we don't print error again if called
+                        * again on this tuplet */
+                       gs_p->tupside = PL_UNKNOWN;
+               }
+               return(gs_p->vno == 1 ? PL_ABOVE : PL_BELOW);
+       }
+       else {
+               /* find the time period taken by tuplet */
+               save_gs_p = gs_p;
+               starttime = Zero;
+               /* find time to where tuplet begins */
+               for (gs_p = gs_p->prev; gs_p != (struct GRPSYL *) 0;
+                                                       gs_p = gs_p->prev) {
+                       starttime = radd(starttime, gs_p->fulltime);
+               }
+               /* find time up to last note of tuplet */
+               endtime = starttime;
+               for (gs_p = save_gs_p; gs_p->tuploc != ENDITEM
+                                       && gs_p->tuploc != LONEITEM;
+                                       gs_p = gs_p->next) {
+                       endtime = radd(endtime, gs_p->fulltime);
+               }
+               /* add on a little bit for the final group of the tuplet */
+               endtime = radd(endtime, smalltime);
+
+               /* now check if other voice has space or not */
+               othervoice = (gs_p->vno == 1 ? 1 : 0);
+               if (hasspace(staff_p->groups_p [othervoice], starttime, endtime)
+                                               == YES) {
+                       /* other voice is space: treat like V_1 */
+                       return(tupdir1voice(save_gs_p));
+               }
+               else {
+                       /* other voice not space: treat like V_2OPSTEM */
+                       if (gs_p->tupside != PL_UNKNOWN) {
+                               l_warning(gs_p->inputfile, gs_p->inputlineno,
+                                       "tuplet side specification not valid when there are two voices");
+                               /* fix so we don't print error again if called
+                                * again on this tuplet */
+                               gs_p->tupside = PL_UNKNOWN;
+                       }
+                       return(gs_p->vno == 1 ? PL_ABOVE : PL_BELOW);
+               }
+       }
+}
+\f
+
+/* return PL_ABOVE or PL_BELOW for tup location assuming a single voice */
+
+static int
+tupdir1voice(gs_p)
+
+struct GRPSYL *gs_p;   /* first group of tuplet */
+
+{
+       int stemdirsum; /* sum of stem directions to see if mostly up or down */
+
+
+       /* if user specified a direction, the answer is easy */
+       if (gs_p->tupside != PL_UNKNOWN) {
+               return(gs_p->tupside);
+       }
+
+        /* Count up stem directions. Whichever side
+         * has more stems, put it on that side. In case of tie,
+         * arbitrarily choose above. */
+       stemdirsum = 0;
+       for (   ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+               if (gs_p->grpcont == GC_NOTES && gs_p->grpvalue != GV_ZERO) {
+                       stemdirsum += (gs_p->stemdir == UP ? 1 : -1);
+               }
+               if (gs_p->tuploc == LONEITEM || gs_p->tuploc == ENDITEM) {
+                       break;
+               }
+       }
+
+       return(stemdirsum >= 0 ? PL_ABOVE : PL_BELOW);
+}
+\f
+
+/* go through measure, printing any beams. Gets called once for normal sized
+ * notes, once for cue notes, and once for grace note. */
+
+static void
+pr_beams(gs_p, grpvalue, grpsize)
+
+struct GRPSYL *gs_p;   /* list of grpsyls for current measure
+                        * of current voice */
+int grpvalue;          /* GV_NORMAL, GV_ZERO */
+int grpsize;           /* GS_NORMAL, GS_SMALL */
+
+{
+       struct GRPSYL *startbeam_p;     /* first in beam group */
+       int t;                          /* 8, 16, etc for basictimes */
+
+
+       /* go through all the grpsyls in measure */
+       for (   ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+
+               /* skip until we find a STARTITEM
+                * on the relevant kind of group */
+               if (gs_p->beamloc != STARTITEM || gs_p->grpvalue != grpvalue
+                                       || gs_p->grpsize != grpsize) {
+                       continue;
+               }
+
+               /* when there are cross-staff beams, we will find the beam
+                * on both staffs, but only need to draw it once. So skip
+                * it the second time */
+               if (gs_p->beamto == CS_ABOVE) {
+                       continue;
+               }
+
+               /* find the matching ENDITEM */
+               for (startbeam_p = gs_p; gs_p != 0 && (gs_p->beamloc != ENDITEM
+                                       || gs_p->grpvalue != grpvalue
+                                       || gs_p->grpsize != grpsize);
+                                       gs_p = gs_p->next) {
+
+               }
+               if (gs_p == 0) {
+                       pfatal("pr_beams couldn't find end of beam group");
+               }
+
+               /* now go through beam group drawing beams for 8th notes,
+                * then 16th, etc */
+               for (t = 8; t <= MAXBASICTIME; t <<= 1) {
+                       if (draw_beams(startbeam_p, gs_p, t, grpsize, grpvalue)
+                                                               <= 0) {
+                               break;
+                       }
+               }
+       }
+}
+\f
+
+/* In the case of cross-staff beams with the above staff's stems down,
+ * and the below staff's stems up, we need to do extra work.
+ * This function builds up a mesh of structs that represent the beams,
+ * with a row of CSBINFO structs linked horizontally for each beam,
+ * and vertical links at each stem. end_bm_offset() then uses this information
+ * to figure out where along the stem a beam ends.
+ * This function returns a pointer to the beginning of the 8th note beam.
+ *
+ * As an example, consider this input:
+ *   1: 8.c; 64f beam with staff below; 32.s; 16e; 8s; 8e; 16s; 32.f; 64s ebm;
+ *   2: 8.e; 64s beam with staff above; 32.a; 16s; 8g; 8s; 16g; 32.s; 64a ebm;
+ * The resulting mesh will look like this:
+ *                    .           .           .           .
+ *                    .           .           .           .
+ *       (64th)       X           .           .           .
+ *                    |           .           .           .
+ *       (32nd)       X --> X     .           .           .
+ *                    |     |     .           .           .
+ *       (16th)       X --> X --> X           .           X --> X   (32nd)
+ *                    |     |     |           .           |     |
+ *   return_value --> X --> X --> X --> X --> X --> X --> X --> X   (8th)
+ *                          .           .           |     |     |
+ *                          .           .           X --> X --> X   (16th)
+ *                          .           .           .           |
+ *                          .           .           .           X   (64th)
+ *                          .           .           .           .
+ *                          .           .           .           .
+ *
+ * Each X in the diagram represents a CSBINFO struct.
+ * Each row represents a beam. The --> is the "next" field.
+ * Each column represents a stem. It is a doubly-linked list,
+ * using above_p and below_p fields.
+ * The dots show the stem direction.
+ */
+
+static struct CSBINFO *
+mkcsbmesh(begin_p, end_p)
+
+struct GRPSYL *begin_p;        /* first group of cross-staff beam on upper staff */
+struct GRPSYL *end_p;  /* 8th note beam goes from begin_p to end_p.
+                        * There may be zero or more additional beams
+                        * for shorter durations that span part or all
+                        * of this list.
+                        */
+
+{
+       struct CSBINFO *csbi_list_p;    /* this points to the 8th note beam
+                                        * list, which is what will
+                                        * ultimately be returned */
+       struct CSBINFO *csbi_p;         /* the current information */
+       struct CSBINFO *csbi8_p;        /* to walk through 8th list */
+       struct CSBINFO *prevcsbi_p;     /* previous in horizontal list */
+       struct CSBINFO *c_p;            /* for walking vertical lists */
+       struct GRPSYL *gs_p;            /* to walk through beamed groups */
+       int basictime;                  /* 8, 16, 32, etc */
+       int stemdir;                    /* stem direction where beam starts */
+       int shortest;                   /* shortest basictime (8, 16, ...) */
+
+
+       /* There is always at least an 8th note beam that goes the
+        * entire length, so make a list for that. */
+       csbi_list_p = prevcsbi_p = 0;
+       shortest = 8;
+       for (gs_p = begin_p; gs_p != end_p->next; gs_p = nxtbmgrp(gs_p,
+                                               begin_p, end_p->next)) {
+               MALLOC(CSBINFO, csbi_p, 1);
+
+               /* set horizontal list links */
+               if (csbi_list_p == 0) {
+                       /* first item on the horizontal list */
+                       csbi_list_p = csbi_p;
+               }
+               else {
+                       /* link from previous horizontally */
+                       prevcsbi_p->next = csbi_p;
+               }
+               prevcsbi_p = csbi_p;
+               csbi_p->next = 0;
+
+               /* init vertical list links */
+               csbi_p->above_p = csbi_p->below_p = 0;
+
+               /* this is for the 8th note beam */
+               csbi_p->basictime = 8;
+               /* save what group this is for, for later convenience */
+               csbi_p->gs_p = gs_p;
+
+               /* remember the shortest basictime anywhere in the beam */
+               if (gs_p->basictime > shortest) {
+                       shortest = gs_p->basictime;
+               }
+       }
+
+       /* For each additional beam, build up a row of structs representing
+        * that beam, and link it vertically to the row below or above it,
+        * depending on whether the first group of the beam is on the staff
+        * above or below the 8th beam.
+        */
+       for (basictime = 16; basictime <= shortest; basictime <<= 1) {
+               stemdir = UNKNOWN;      /* Init to keep lint happy;
+                                        * this will get set to appropriate
+                                        * value before it is actually used. */
+               prevcsbi_p = 0;         /* No run of groups found yet */
+
+               /* Walk through list, finding any runs of groups that are
+                * at least as short in duration as the current basictime
+                * we are looking for. Note this could be as little as a single
+                * group in the case of a partial beam.
+                * We walk through the GRPSYLs and their
+                * corresponding CSBINFO structs in parallel.
+                */
+               for (gs_p = begin_p, csbi8_p = csbi_list_p;
+                               gs_p != end_p->next;
+                               gs_p = nxtbmgrp(gs_p, begin_p, end_p->next),
+                               csbi8_p = csbi8_p->next) {
+
+                       if (gs_p->basictime >= basictime) {
+                               /* this group is part of a beam of at least
+                                * as short as the basictime of interest. */
+                               MALLOC(CSBINFO, csbi_p, 1);
+                               csbi_p->next = 0;
+                               csbi_p->basictime = basictime;
+
+                               /* If not first group in this beam,
+                                * link from previous. If is first,
+                                * save its stem direction. That determines
+                                * which side of the 8th beam it goes on. */
+                               if (prevcsbi_p != 0) {
+                                       prevcsbi_p->next = csbi_p;
+                               }
+                               else {
+                                       stemdir = gs_p->stemdir;
+                               }
+                               /* Prepare to link more on horizonally,
+                                * if beam goes further. */
+                               prevcsbi_p = csbi_p;
+
+                               /* set vertical links */
+                               if (stemdir == DOWN) {
+                                       /* Must be from staff above.
+                                        * Find current top, and add
+                                        * above there */
+                                       for (c_p = csbi8_p; c_p->above_p != 0;
+                                                       c_p = c_p->above_p) {
+                                               ;
+                                       }
+                                       c_p->above_p = csbi_p;
+                                       csbi_p->below_p = c_p;
+                                       csbi_p->above_p = 0;
+                               }
+                               else {
+                                       /* similar for from staff below */
+                                       for (c_p = csbi8_p; c_p->below_p != 0;
+                                                       c_p = c_p->below_p) {
+                                               ;
+                                       }
+                                       c_p->below_p = csbi_p;
+                                       csbi_p->above_p = c_p;
+                                       csbi_p->below_p = 0;
+                               }
+                       }
+                       else {
+                               /* If we were doing a beam before,
+                                * it's done now */
+                               prevcsbi_p = 0;
+                       }
+               }
+       }
+       return(csbi_list_p);
+}
+\f
+
+/* draw beams in a beam group for a particular time value, 8th, 16th, etc */
+/* this gets called repeatedly, first for 8th, then 16ths, etc, until
+ * there are no more shorter notes.
+ * It returns the number of beams drawn (including partials) */
+
+
+static int
+draw_beams(gs_p, endbeam_p, basictime, grpsize, grpvalue)
+
+struct GRPSYL *gs_p;                   /* start of beam group */
+struct GRPSYL *endbeam_p;              /* end of beam group */
+int basictime;                         /* draw beam for this basic time:
+                                        * 8, 16, 32, 64, etc */
+int grpsize;                           /* GS_NORMAL, GS_SMALL */
+int grpvalue;                          /* GV_NORMAL, GV_ZERO */
+
+{
+       int found = 0;          /* how many beams found to be drawn */
+       int ngrps;              /* how many groups to beam together */
+       struct GRPSYL *first_p = 0;/* first group in beam (the one on the
+                                * above staff while doing cross-staff beams) */
+       struct GRPSYL *begin_p = 0, *end_p;     /* the initialization is
+                                * to shut up bogus compiler warning */
+       struct GRPSYL *other_p; /* other note that must be used to calculate
+                                * slope of partial beam */
+       float y_offset;         /* from end of stem to draw beam */
+       int side;               /* left or right for partial beam */
+       float x_begin, y_begin, x_other, y_other;       /* partial beam
+                                                        * coordinates */
+       double halfwidth;       /* half width of a beam */
+       double end_y_offset;    /* to deal with cross staff beams */
+       double slope;           /* of partial beam */
+       double halfstem;
+       double stemdist;        /* distance between stems */
+       double pbeam_len;       /* length of partial beam */
+
+
+       /* get relevant group, accounting for cross-staff beams */
+       first_p = gs_p;
+       gs_p = neighboring_note_beam_group(gs_p, first_p, NO);
+
+       /* go through the list */
+       while ( gs_p != endbeam_p->next) {
+
+               /* find however many in a row deserve to get another beam */
+               for (end_p = (struct GRPSYL *) 0, ngrps = 0;
+                                               (gs_p != endbeam_p->next);
+                                               gs_p = nxtbmgrp(gs_p,
+                                               first_p, endbeam_p->next)) {
+
+                       /* if wrong type (e.g a grace inside of
+                        * a set of normal notes), skip over */
+                       if (gs_p->grpsize != grpsize
+                                       || gs_p->grpvalue != grpvalue ) {
+                               continue;
+                       }
+
+                       /* if not beamed, skip */
+                       if ( gs_p->beamloc == NOITEM) {
+                               pfatal("non-beam inside beam group\n");
+                       }
+
+                       /* if this one deserves another beam,
+                        * keep track of that. If not, break out */
+                       if (gs_p->basictime >= basictime) {
+                               end_p = gs_p;
+                               found++;
+                               if (ngrps == 0) {
+                                       begin_p = gs_p;
+                               }
+                               ngrps++;
+                               if (gs_p->breakbeam == YES && basictime > 8) {
+                                       break;
+                               }
+                       }
+                       else {
+                               break;
+                       }
+               }
+
+               /* prepare to do next one */
+               if (gs_p != endbeam_p->next) {
+                       gs_p = nxtbmgrp(gs_p, first_p, endbeam_p->next);
+               }
+
+               /* if none we looked at deserved a beam, keep looking */
+               if (end_p == (struct GRPSYL *) 0) {
+                       continue;
+               }
+
+               /* calculate where on stem the beam should start */
+               y_offset = beam_offset(numbeams(basictime),
+                                       begin_p->grpsize, begin_p->stemdir);
+
+               if (end_p->grpsize == GS_NORMAL) {
+                       halfwidth = W_WIDE * Staffscale / PPI / 2.0;
+                       halfstem = W_NORMAL * Staffscale / PPI / 2.0;
+               }
+               else {
+                       halfwidth = W_WIDE * Staffscale * SM_FACTOR / PPI / 2.0;
+                       halfstem = W_NORMAL * Staffscale * SM_FACTOR / PPI / 2.0;
+               }
+
+               /* check if single group.
+                * If so, need to do a partial beam, otherwise full beam */
+               if (ngrps == 1) {
+                       /* rests and spaces don't get beams,
+                        * so don't get partial ones */
+                       if (end_p->grpcont != GC_NOTES) {
+                               continue;
+                       }
+
+                       side = pbeamside(end_p, first_p);
+
+                       /* Now that we decided where the
+                        * partial beam goes, we can draw it */
+
+                       /* in order to figure out the end point of the partial
+                        * beam, we have to calculate the slope of the beam as
+                        * if it were a full beam and derive from that where
+                        * the partial beam will end. */
+                       /* determine whether to use prev or next note, and
+                        * skip any notes of the wrong type! */
+                       if (side == PB_LEFT) {
+                               other_p = prevbmgrp(end_p, first_p);
+                       }
+                       else {
+                               other_p = nxtbmgrp(end_p, first_p, end_p->next);
+                       }
+
+                       /* the line then goes from the stem (at y_offset) to
+                        * a notehead width east or west of the stem,
+                        * with the y coordinate calculated from the slope
+                        * of what a full length beam would have been, unless
+                        * stems are too close, in which case shorten it
+                        * somewhat. */
+                       x_begin = find_x_stem(end_p);
+                       y_begin = find_y_stem(end_p);
+                       x_other = find_x_stem(other_p);
+                       y_other = find_y_stem(other_p);
+
+                       /* if cross-staff and the two stems are in opposite
+                        * directions, have to compensate for that */
+                       if (end_p->stemdir == other_p->stemdir) {
+                               /* in same direction */
+                               slope = (y_other - y_begin)
+                                                       / (x_other - x_begin);
+                       }
+                       else {
+                               double opp_adj;
+
+                               opp_adj = beam_offset(
+                                       numbeams(other_p->basictime),
+                                       other_p->grpsize, other_p->stemdir);
+                               slope = (y_other - (y_begin - opp_adj))
+                                                       / (x_other - x_begin);
+                       }
+
+                       /* adjust to overlap stem */
+                       x_begin += halfstem * side;
+
+                       /* determine partial beam length */
+                       /* find distance between stems */
+                       if (x_begin < x_other) {
+                               stemdist = x_other - x_begin;
+                       }
+                       else {
+                               stemdist = x_begin - x_other;
+                       }
+                       /* if wide enough, use note head width, else less */
+                       if (stemdist < 5.0 * Stepsize) {
+                               pbeam_len = 0.4 * stemdist;
+                       }
+                       else {
+                               pbeam_len = widest_head(end_p) * Staffscale;
+                       }
+
+                       /* draw the partial beam */
+                       do_beam(x_begin, y_begin + y_offset,
+                               x_begin + pbeam_len * side,
+                               y_begin + y_offset + side *
+                               pbeam_len * slope, halfwidth);
+               }
+
+               else {
+                       /* draw a normal beam */
+
+                       /* For regular beams, can use y_offset directly,
+                        * but with cross-staff beam, stems may be in opposite
+                        * directions, so have to call a function to get
+                        * appropriate offset.
+                        */
+                       if (begin_p->beamto == CS_SAME) {
+                               end_y_offset = y_offset;
+                       }
+                       else {
+                               end_y_offset = end_bm_offset(first_p, end_p,
+                                                               basictime);
+                       }
+
+                       /* If the stems on both ends of the beam
+                        * are zero length, don't draw any beams.
+                        * If user really wants the beams,
+                        * they can make one of the ends
+                        * barely longer than zero.
+                        */
+                       if (begin_p->stemlen <= 0.0 && end_p->stemlen <= 0.0) {
+                               continue;       
+                       }
+
+                       /* find end of first stem and last stem and draw
+                        * the beam at proper offset from there */
+                       do_beam(find_x_stem(begin_p) - halfstem,
+                                       find_y_stem(begin_p) + y_offset,
+                                       find_x_stem(end_p) + halfstem,
+                                       find_y_stem(end_p) + end_y_offset,
+                                       halfwidth);
+               }
+       }
+       return(found);
+}
+\f
+
+/* Figure out how far from the end of a stem a beam should be in the
+ * case of a cross-staff beam with opposite-direction stems at its ends.
+ * Will return some multiple (possibly 0) of the distance between beams,
+ * with the proper sign to account for stem direction.
+ * Should only be called if the beam in question is a cross-staff beam.
+ */
+
+double
+end_bm_offset(top_first_p, end_p, basictime)
+
+struct GRPSYL *top_first_p;    /* the group that has "bm with staff below" */
+struct GRPSYL *end_p;          /* the group where a beam ends. This could be
+                                * either a group with ebm or some intermediate
+                                * group that happens to end a beam segment
+                                * that is shorter. */
+int basictime;                 /* the basictime of the beam currently under
+                                * consideration. The first beam drawn will
+                                * be 8, the next 16, then 32, etc. */
+
+{
+       static struct CSBINFO *csbi_list_p = 0;/* Info about the cross beams */
+       static struct GRPSYL *cached_gs_p = 0;  /* Each time we get a different
+                                * top_first_p, we calculate its csbi_list
+                                * and cache it for future calls. This lets
+                                * us know if we can re-use the cached value. */
+       struct CSBINFO *csbi_p; /* for walking 8th note beam ->next links */
+       struct CSBINFO *c_p;    /* for walking vertical links of mesh */
+       int nbeams;             /* how many beams from the stem end */
+
+       if (cached_gs_p != top_first_p) {
+               /* Cached one is no good; need to recalculate */
+               if (csbi_list_p != 0) {
+                       /* We had a list before; need to clean it up */
+                       struct CSBINFO *nextvert_p;     /* to free vert list */
+                       struct CSBINFO *nexthor_p;      /* to free hor list */
+                       /* walk horizontal list */
+                       for (csbi_p = csbi_list_p; csbi_p != 0;
+                                                       csbi_p = nexthor_p) {
+                               /* clean up vert list, both directions */
+                               for (c_p = csbi_p->above_p; c_p != 0;
+                                                       c_p = nextvert_p) {
+                                       nextvert_p = c_p->above_p;
+                                       FREE(c_p);
+                               }
+                               for (c_p = csbi_p->below_p; c_p != 0;
+                                                       c_p = nextvert_p) {
+                                       nextvert_p = c_p->below_p;
+                                       FREE(c_p);
+                               }
+                               nexthor_p = csbi_p->next;
+                               FREE(csbi_p);
+                       }
+               }
+               /* Calculate everything for current beam */
+               csbi_list_p = mkcsbmesh(top_first_p, end_p);
+               cached_gs_p = top_first_p;
+       }
+
+       /* First follow the 8th note CSBINFO list across till we find
+        * the one matching the end group. */
+       for (csbi_p = csbi_list_p; csbi_p != 0 && csbi_p->gs_p != end_p;
+                                                       csbi_p = csbi_p->next) {
+               ;
+       }
+       if (csbi_p == 0) {
+               pfatal("couldn't find beam end group in end_bm_offset()");
+       }
+
+       /* Now follow the vertical links until we find the right basic time.
+        * It could be on either side of the 8th beam.
+        * First we find the end of the stem, then count the number of
+        * links we have to follow to get to the one with the right basictime.
+        */
+       if (end_p->stemdir == DOWN) {
+               /* Must be from staff above, so end of stem is all the way                       * down the below_p list.
+                */
+               for (c_p = csbi_p; c_p->below_p != 0; c_p = c_p->below_p) {
+                       ;
+               }
+               /* Now count the number of beams till the one we want */
+               for (nbeams = 1; c_p->basictime != basictime;
+                                                       c_p = c_p->above_p) {
+                       nbeams++;
+               }
+               if (c_p == 0) {
+                       pfatal("failed to find cross staff beam info go up");
+               }
+       }
+       else {
+               /* similar for staff below groups */
+               for (c_p = csbi_p; c_p->above_p != 0; c_p = c_p->above_p) {
+                       ;
+               }
+               /* Now count the number of beams till the one we want */
+               for (nbeams = 1; c_p->basictime != basictime;
+                                                       c_p = c_p->below_p) {
+                       nbeams++;
+               }
+               if (c_p == 0) {
+                       pfatal("failed to find cross staff beam info go up");
+               }
+       }
+       return (beam_offset(nbeams, end_p->grpsize, end_p->stemdir));
+}
+\f
+
+/* find y offset on stem based on number of beams, whether normal or small
+ * notes, and stem direction */
+
+static double
+beam_offset(nbeams, gsize, stemdir)
+
+int nbeams;    /* how many beams */
+int gsize;     /* GS_NORMAL or GS_SMALL */
+int stemdir;   /* UP or DOWN */
+
+{
+       /* for consistency, it would be nice to use FLAGSEP and SMFLAGSEP
+        * for beam separation too, but when we tried that, beams looked too
+        * close together, especially on certain low-resolution devices,
+        * so that's why we're using 5 and 4 stepsizes. */
+       return ( (nbeams - 1) * (gsize == GS_NORMAL ? 5.0 : 4.0)
+                                       * Staffscale
+                                       * (stemdir == UP ? -POINT : POINT) );
+}
+\f
+
+/* Given a group inside a beam, return the next group. Usually this will
+ * be gs_p->next, but in the case of a cross-staff beam, it might be a
+ * group on the other staff */
+
+struct GRPSYL *
+nxtbmgrp(gs_p, first_p, endnext_p)
+
+struct GRPSYL *gs_p;           /* find the beam group after this one */
+struct GRPSYL *first_p;                /* The first group in the top staff of the
+                                * beam */
+struct GRPSYL *endnext_p;      /* what to return upon reaching the end of
+                                * the beam. This will be the ->next field of
+                                * the last group in the beam on the top staff
+                                * of a cross-staff beam. Returning this lets
+                                * legacy code (code before we supported
+                                * cross-staff beams) keep working with minimal
+                                * changes. */
+
+{
+       int grpsize, grpvalue;
+
+       /* If we are passed the first group, it could be a space,
+        * in which case we need to use the below staff's group instead.
+        */
+       if (gs_p->grpcont == GC_SPACE && gs_p->beamto != CS_SAME) {
+               /* Need to hop to below staff. Go down the chord to find
+                * the matching cross-staff beam group. */
+               do {
+                       if ((gs_p = gs_p->gs_p) == (struct GRPSYL *) 0) {
+                               pfatal("can't find matching beam chord");
+                       }
+
+               /* skip any lyrics and such till we find the beamed-to group */
+               } while (gs_p->beamto != CS_ABOVE);
+       }
+
+       /* need to skip past any groups of the wrong kind */
+       grpsize = first_p->grpsize;
+       grpvalue = first_p->grpvalue;
+       do {
+               /* Move to next group. If that gets us to the end
+                * of the measure, report that we're done. */
+               if ((gs_p = gs_p->next) == (struct GRPSYL *) 0) {
+                       return(endnext_p);
+               }
+       } while (gs_p->grpsize != grpsize || gs_p->grpvalue != grpvalue);
+
+       /* if past end of beam group, report that we're done */
+       if (gs_p->beamloc != INITEM && gs_p->beamloc != ENDITEM) {
+               return(endnext_p);
+       }
+
+       return(neighboring_note_beam_group(gs_p, first_p, NO));
+}
+\f
+
+/* Given a group inside a beam (not the first),
+ * return the previous group. Usually this will
+ * be gs_p->prev, but in the case of a cross-staff beam, it might be a
+ * group on the other staff */
+
+struct GRPSYL *
+prevbmgrp(gs_p, first_p)
+
+struct GRPSYL *gs_p;           /* find the beam group after this one */
+struct GRPSYL *first_p;                /* The first group in the top staff of the
+                                * beam */
+
+{
+       int grpsize, grpvalue;
+       int staffno;
+
+       staffno = gs_p->staffno;
+
+       /* need to skip past any groups of the wrong kind */
+       grpsize = first_p->grpsize;
+       grpvalue = first_p->grpvalue;
+       do {
+               /* Move to prev group. */
+               if ((gs_p = gs_p->prev) == (struct GRPSYL *) 0) {
+                       pfatal("prevbmgrp couldn't find prev group");
+               }
+       } while (gs_p->grpsize != grpsize || gs_p->grpvalue != grpvalue);
+
+       gs_p = neighboring_note_beam_group(gs_p, first_p, YES);
+
+       /* if we hopped staffs, then the space on the original staff might
+        * have been a long note, in which case the group we have isn't
+        * really the one we want. So we have to go forward on this new staff
+        * until we find the space that corresponds to the groups we started
+        * with, then back up one group from there. That's the one we want */
+       if (staffno != gs_p->staffno) {
+               /* we hopped staffs. Go forward to the next space */
+               for (gs_p = gs_p->next; gs_p->grpcont != GC_SPACE;
+                                                       gs_p = gs_p->next) {
+                       ;
+               }
+               /* now take the group right before the space */
+               gs_p = gs_p->prev;
+       }
+       return(gs_p);
+}
+\f
+
+/* Given a group in a beam, skip over any embedded rests.
+ * Then if the group is not a space, return it as it is.
+ * If it is a space, return the corresponding group on the staff
+ * that this group is beamed to */
+
+static struct GRPSYL *
+neighboring_note_beam_group(gs_p, first_p, backwards)
+
+struct GRPSYL *gs_p;           /* find the beam group neighboring this one */
+struct GRPSYL *first_p;                /* The first group in the top staff of the
+                                * beam */
+int backwards;                 /* if YES, go backwards (find the previous
+                                * group rather than the following) */
+
+{
+       struct GRPSYL *tgs_p;   /* as we walk down a chord to try to find
+                                * the group we're looking for, this keeps
+                                * track of where we are */
+
+
+       /* skip over any embedded rests--they are not notes. */
+       while (gs_p->grpcont == GC_REST) {
+               if (backwards == YES) {
+                       gs_p = gs_p->prev;
+               }
+               else {
+                       gs_p = gs_p->next;
+               }
+       }
+       if (gs_p == 0) {
+               pfatal("neighboring_note_beam_group didn't find note group");
+       }
+
+       /* If this is a cross-staff beam, we may need to hop from
+        * staff to staff sometimes. If this group is a space
+        * group, then we have to hop now. */
+       if (gs_p->grpcont == GC_SPACE) {
+               if (gs_p->beamto == CS_SAME) {
+                       do {
+                               if (backwards == YES) {
+                                       gs_p = gs_p->prev;
+                               } else {
+                                       gs_p = gs_p->next;
+                               }
+                       } while (gs_p != 0 && gs_p->grpcont != GC_NOTES);
+               }
+
+               else if (gs_p->staffno == first_p->staffno) {
+                       /* Need to hop to below staff.
+                        * Go down the chord to find
+                        * the matching cross-staff beam group */
+                       do {
+                               if ((gs_p = gs_p->gs_p) ==
+                                               (struct GRPSYL *) 0) {
+                                       pfatal("can't find matching beam chord");
+                               }
+
+                       /* skip any lyrics and such till we find the
+                        * group beamed to us */
+                       } while (gs_p->beamto != CS_ABOVE);
+               }
+               else {
+                       /* Need to jump back to staff above.
+                        * Since the chord linked list is only one way (down)
+                        * and we need to look up the chord, this is a
+                        * little harder. Start at the first_p group, which
+                        * is the first group in the beam on the above staff.
+                        * Keep going down that staff until we find a chord
+                        * linked down to gs_p. */
+                       for (   ; first_p != (struct GRPSYL *) 0;
+                                               first_p = first_p->next) {
+
+                               /* walk down the chord */
+                               for (tgs_p = first_p->gs_p;
+                                               tgs_p != (struct GRPSYL *) 0;
+                                               tgs_p = tgs_p->gs_p) {
+
+                                       if (tgs_p == gs_p) {
+                                               /* Aha! We found it! */
+                                               return(first_p);
+                                       }
+
+                                       if (tgs_p->staffno > gs_p->staffno) {
+                                               /* we're past the staff we care
+                                                * about, so this chord can't
+                                                * be the right one. */
+                                               break;
+                                       }
+                               }
+                       }
+
+                       pfatal("failed to find group when jumping back to above staff");
+               }
+       }
+
+       return(gs_p);
+}
+\f
+
+/* given a GRPSYL that deserves a partial beam, return PB_LEFT if the beam
+ * goes on the left or PB_RIGHT if is goes on the right.  */
+
+int
+pbeamside(gs_p, first_p)
+
+struct GRPSYL *gs_p;
+struct GRPSYL *first_p;
+
+{
+       int side;
+       int beams2left, beams2right;    /* how many beams or dots for notes on
+                                        * either side of current group */
+       struct GRPSYL *prevgs_p, *nextgs_p;
+
+
+       /* need to figure out which side of stem to draw the
+        * partial beam. First the easy cases: if is STARTITEM,
+        * then it has to go on the right, if ENDITEM, it
+        * has to go on the left */
+       switch (gs_p->beamloc) {
+       case STARTITEM:
+               side = PB_RIGHT;
+               break;
+
+       case ENDITEM:
+               side = PB_LEFT;
+               break;
+
+       case INITEM:
+               /* Hmmm. Will have to be more clever. Check the
+                * note on either side. If we're at a breakbeam,
+                * it's easy to know. Otherwise, if one should have more
+                * beams than the other, put the partial on that
+                * side */
+               prevgs_p = prevbmgrp(gs_p, first_p);
+               nextgs_p = nxtbmgrp(gs_p, first_p, gs_p->next);
+               beams2left = numbeams(prevgs_p->basictime);
+               beams2right = numbeams(nextgs_p->basictime);
+               if (gs_p->breakbeam == YES) {
+                       side = PB_LEFT;
+               }
+               else if (prevgs_p != 0 && prevgs_p->breakbeam == YES) {
+                       side = PB_RIGHT;
+               }
+               else if (beams2left > beams2right) {
+                       side = PB_LEFT;
+               }
+               else if (beams2right > beams2left) {
+                       side = PB_RIGHT;
+               }
+
+               /* That was inconclusive.  So now we're going to try to decide
+                * based on logical groupings of notes; that is, notes grouped
+                * according to what the accents should be. */
+               else if (chkgroupings(&side, gs_p) == YES) {
+                       /* it found an answer and set "side" for us */
+                       ;
+               }
+               else {
+                       /* ok. that didn't help.
+                        * See if the notes on either side
+                        * have more dots than the other.
+                        * If so, put the partial towards
+                        * that one. If they are the same, then
+                        * throw in the towel and just stick it
+                        * on the left */
+                       beams2left = prevgs_p->dots;
+                       beams2right = nextgs_p->dots;
+                       if (beams2right > beams2left) {
+                               side = PB_RIGHT;
+                       }
+                       else {
+                               side = PB_LEFT;
+                       }
+               }
+               break;
+
+       default:
+               pfatal("invalid beamloc passed to pbeamside");
+               /*NOTREACHED*/
+               return(PB_LEFT);        /* to shut up bogus compiler warning */
+       }
+
+       return(side);
+}
+\f
+/*
+ * Name:        chkgroupings()
+ *
+ * Abstract:    Decide partial beam side based on groupings of notes.
+ *
+ * Returns:     YES if it found an answer (stored in *side_p), NO if not
+ *
+ * Description: This function breaks the measure down into successively
+ *             smaller pieces based on where the accents should be, trying to
+ *             find a piece where the current GRPSYL falls at the beginning or
+ *             end of the piece.  If the GRPSYL falls at the start of a piece,
+ *             its partial beam should point right; if end, left.  If we get
+ *             to the point where the pieces are shorter than the GRPSYL
+ *             itself, we have failed.
+ */
+
+static int
+chkgroupings(side_p, thisgs_p)
+
+int *side_p;                   /* where to put the answer, if found */
+struct GRPSYL *thisgs_p;       /* the GRPSYL we are working on */
+
+{
+       struct GRPSYL *gs_p;    /* point along GRPSYL list */
+       short *factors;         /* array to be malloc'ed */
+       int n;                  /* loop variable */
+       RATIONAL thisstart;     /* time offset in measure of thisgs_p */
+       RATIONAL nextstart;     /* time offset in measure of next GRPSYL */
+       RATIONAL quotient;      /* temp variable for dividing */
+       RATIONAL grouplen;      /* time length of a grouping */
+       RATIONAL tupstart;      /* time offset where tuplet starts */
+       RATIONAL tupdur;        /* time length of a tuplet */
+       int counts;             /* count in the current grouplen */
+       int fraction;           /* is grouplen a fraction of a count? */
+       int fact;               /* a factor */
+
+
+       /*
+        * If we're doing grace beams, skip this whole thing, since we're
+        * dealing with time values, and they are all zero.
+        */
+       if (thisgs_p->grpvalue == GV_ZERO) {
+               return (NO);
+       }
+
+       /* find the time offset of thisgs_p by adding up all previous GRPSYLs*/
+       thisstart = Zero;
+       for (gs_p = thisgs_p->prev; gs_p != 0; gs_p = gs_p->prev) {
+               thisstart = radd(thisstart, gs_p->fulltime);
+       }
+
+       /* find offset of GRPSYL following thisgs_p */
+       nextstart = radd(thisstart, thisgs_p->fulltime);
+
+       /*
+        * Interior notes of tuplets are dealt with in a special way.
+        */
+       if (thisgs_p->tuploc == INITEM) {
+               /*
+                * Find the duration of the tuplet by adding up all the
+                * previous GRPSYLs in the tuplet and this GRPSYL and all the
+                * later GRPSYLs.  (The loops stop when they hit a NOITEM
+                * that's not grace.)
+                */
+               tupdur = Zero;
+               for (gs_p = thisgs_p->prev; gs_p != 0 &&
+                               (gs_p->grpvalue == GV_ZERO ||
+                               gs_p->tuploc != NOITEM); gs_p = gs_p->prev) {
+                       tupdur = radd(tupdur, gs_p->fulltime);
+               }
+               /* remember where tuplet starts */
+               tupstart = rsub(thisstart, tupdur);
+               for (gs_p = thisgs_p; gs_p != 0 &&
+                               (gs_p->grpvalue == GV_ZERO ||
+                               gs_p->tuploc != NOITEM); gs_p = gs_p->next) {
+                       tupdur = radd(tupdur, gs_p->fulltime);
+               }
+
+               /*
+                * If the starting point of this tuplet is not at a multiple of
+                * its duration, we consider the tuplet synchopated.  This is
+                * pretty bizarre and not worth trying to deal with.
+                */
+               quotient = rdiv(tupstart, tupdur);
+               if (quotient.d != 1) {
+                       return (NO);
+               }
+
+               /* the first group length to consider is tupdur/tupcont */
+               grouplen = tupdur;
+               grouplen.d *= thisgs_p->tupcont;
+               rred(&grouplen);
+
+               /* loop until an answer is found, or we give up */
+               for (;;) {
+                       /*
+                        * If the group length is not longer than our note, it
+                        * makes no sense to try to see if our note is at the
+                        * start or end of such a group.  Maybe we never hit a
+                        * match because our note is syncopated.  Whatever the
+                        * reason, we have to give up.
+                        */
+                       if (LE(grouplen, thisgs_p->fulltime)) {
+                               return (NO);
+                       }
+
+                       /*
+                        * If thisstart/grouplen is an integer, it means
+                        * thisgs_p is on a grouping boundary; that is, it is
+                        * the first GRPSYL in a grouping.  So point right.
+                        */
+                       quotient = rdiv(thisstart, grouplen);
+                       if (quotient.d == 1) {
+                               *side_p = PB_RIGHT;
+                               return (YES);
+                       }
+
+                       /*
+                        * If nextstart/grouplen is an integer, it means the
+                        * GRPSYL after thisgs_p is on a grouping boundary,
+                        * which means that thisgs_p is the last GRPSYL in a
+                        * grouping.  So point left.
+                        */
+                       quotient = rdiv(nextstart, grouplen);
+                       if (quotient.d == 1) {
+                               *side_p = PB_LEFT;
+                               return (YES);
+                       }
+
+                       /* divide grouplen by 2 and try again */
+                       grouplen = rdiv(grouplen, Two);
+               }
+       }
+
+       /*
+        * This is the normal case, not the interior of a tuplet.
+        */
+
+       /* get all the prime factors of the time sig's numerator */
+       factors = factor(Score.timenum);
+
+       grouplen = Score.time;          /* first group is the whole measure */
+       counts = Score.timenum;         /* number of counts in measure */
+
+       /*
+        * Loop until we find an answer, or until we have to give up.  Each
+        * time through the loop, we reduce the grouping length.  At first, we
+        * divide out prime factors from the number of counts in the measure.
+        * Once we get down to one count, we start dividing by 2 all the time.
+        */
+       for (;;) {
+               fraction = YES;         /* default to "fraction of a count" */
+
+               /* if there are still multiple counts, divide out a prime */
+               if (counts > 1) {
+                       /*
+                        * See if there are any prime factors greater than 4.
+                        * This only happens with funny timesigs like 10/8 or
+                        * 7/4.  We work down from the top, because the
+                        * likelyhood is that the highest level grouping is by
+                        * the biggest factor, when these funny numbers are
+                        * involved.  At least 10/8, for example, is normally
+                        * 5 groups of 2, not 2 groups of 5.
+                        */
+                       for (n = Score.timenum; n > 4 && factors[n] == 0; n--)
+                               ;
+                       /* if we found a 5 or greater, use it */
+                       if (n > 4) {
+                               factors[n]--;
+                               fact = n;
+                       /*
+                        * There are no funny factors (5 or more) left.  Next,
+                        * we need to look for 2s, not 3s yet, because, for
+                        * example, 6/8 is 2 groups of 3, not 3 groups of 2.
+                        */
+                       } else if (counts % 2 == 0) {
+                               factors[2]--;
+                               fact = 2;
+                       /* no 2s either, so look for 3s */
+                       } else if (counts % 3 == 0) {
+                               factors[3]--;
+                               fact = 3;
+                       } else {
+                       /* no factors left, so flag it by setting fact to 1 */
+                               fact = 1;
+                       }
+
+                       /*
+                        * If a factor was found, divide it out, and remember
+                        * that we are not yet dealing with fractions of a
+                        * single count.
+                        */
+                       if (fact > 1) {
+                               counts /= fact;
+                               fraction = NO;
+                       }
+               }
+
+               if (fraction == YES) {
+                       /*
+                        * We are dealing with fractions of a count, so divide
+                        * by 2 from now on.
+                        */
+                       grouplen = rdiv(grouplen, Two);
+               } else {
+                       /*
+                        * Using the number of counts remaining, form the
+                        * length in lowest terms.
+                        */
+                       grouplen.n = counts;
+                       grouplen.d = Score.timeden;
+                       rred(&grouplen);
+               }
+
+               /*
+                * If the group length is not longer than our note, it makes no
+                * sense to try to see if our note is at the start or end of
+                * such a group.  Maybe we never hit a match because our note
+                * is syncopated.  Whatever the reason, we have to give up.
+                */
+               if (LE(grouplen, thisgs_p->fulltime)) {
+                       return (NO);
+               }
+
+               /*
+                * If thisstart/grouplen is an integer, it means thisgs_p is on
+                * a grouping boundary; that is, it is the first GRPSYL in a
+                * grouping.  So point right.
+                */
+               quotient = rdiv(thisstart, grouplen);
+               if (quotient.d == 1) {
+                       *side_p = PB_RIGHT;
+                       return (YES);
+               }
+
+               /*
+                * If nextstart/grouplen is an integer, it means the GRPSYL
+                * after thisgs_p is on a grouping boundary, which means that
+                * thisgs_p is the last GRPSYL in a grouping.  So point left.
+                */
+               quotient = rdiv(nextstart, grouplen);
+               if (quotient.d == 1) {
+                       *side_p = PB_LEFT;
+                       return (YES);
+               }
+       }
+
+       return (NO);            /* we can never get here; this is for lint */
+}
+\f
+
+/* actually draw a beam */
+
+static void
+do_beam(x1, y1, x2, y2, halfwidth)
+
+double x1, y1;         /* start beam here */
+double x2, y2;         /* end beam here */
+double halfwidth;      /* go this far up and down from y1 and y2 to get
+                        * corners of parallelogram that makes up the beam */
+
+{
+       do_newpath();
+       do_moveto(x1, y1 + halfwidth);
+       do_line(x2, y2 + halfwidth);
+       do_line(x2, y2 - halfwidth);
+       do_line(x1, y1 - halfwidth);
+       do_closepath();
+       do_fill();
+}
+\f
+
+/* print a multirest */
+
+void
+pr_multirest(gs_p, staff_p)
+
+struct GRPSYL *gs_p;   /* info about the multirest */
+struct STAFF *staff_p;
+
+{
+       double x;               /* horizontal position of number string */
+       double y, y_offset;     /* vertical location */
+       double height, width;   /* of meas num string */
+       float east, west;       /* edges of the multirest */
+       char *numstr;           /* ASCII version of numbers of measures */
+
+
+       /* avoid core dumps */
+       if (Score_location_p == (float *) 0) {
+               pfatal("can't do multirest: no feed");
+               return;
+       }
+
+       /* determine where to place the multirest */
+       y = mr_y_loc(gs_p->staffno);
+       east = gs_p->c[AE];
+       west = gs_p->c[AW];
+
+       /* If user wants us to use the alternative multirest style of using
+        * rest symbols (often used in orchestral music), and the length of
+        * the multirest is 8 or less, we use that alternate style,
+        * otherwise draw horizontal line along middle staff and two
+        * vertical lines near the bar lines. Note that the basictime is
+        * the negative of the number of measures of multirest.  
+        * We have seen rare examples of using the alternate style for all the
+        * way up to 11 measures, but consider normal usage only up to 8.
+        */
+       if (svpath(staff_p->staffno, RESTSYMMULT)->restsymmult == YES &&
+                                               gs_p->basictime > -9) {
+               double center;  /* can't use AX, must use avg of AE and AW */
+               int size;       /* actually will always be normal size,
+                                * but may as well make code be able to handle
+                                * small size just in case... */
+
+               center = (gs_p->c[AE] + gs_p->c[AW]) / 2.0;
+               size = (gs_p->grpsize == GS_NORMAL ? DFLT_SIZE : SMALLSIZE);
+
+               switch (gs_p->basictime) {
+               case -2:
+                       pr_muschar(center, gs_p->c[AY], C_DWHREST, size, FONT_MUSIC);
+                       break;
+               case -3:
+                       pr_muschar(gs_p->c[AW], gs_p->c[AY], C_DWHREST, size, FONT_MUSIC);
+                       pr_muschar(gs_p->c[AE], gs_p->c[AY], C_1REST, size, FONT_MUSIC);
+                       break;
+               case -4:
+                       pr_muschar(center, gs_p->c[AY], C_QWHREST, size, FONT_MUSIC);
+                       break;
+               case -5:
+                       pr_muschar(gs_p->c[AW], gs_p->c[AY], C_QWHREST, size, FONT_MUSIC);
+                       pr_muschar(gs_p->c[AE], gs_p->c[AY], C_1REST, size, FONT_MUSIC);
+                       break;
+               case -6:
+                       pr_muschar(gs_p->c[AW], gs_p->c[AY], C_QWHREST, size, FONT_MUSIC);
+                       pr_muschar(gs_p->c[AE], gs_p->c[AY], C_DWHREST, size, FONT_MUSIC);
+                       break;
+               case -7:
+                       pr_muschar(gs_p->c[AW], gs_p->c[AY], C_QWHREST, size, FONT_MUSIC);
+                       pr_muschar(center, gs_p->c[AY], C_DWHREST, size, FONT_MUSIC);
+                       pr_muschar(gs_p->c[AE], gs_p->c[AY], C_1REST, size, FONT_MUSIC);
+                       break;
+               case -8:
+                       pr_muschar(gs_p->c[AW], gs_p->c[AY], C_QWHREST, size, FONT_MUSIC);
+                       pr_muschar(gs_p->c[AE], gs_p->c[AY], C_QWHREST, size, FONT_MUSIC);
+                       break;
+               default:
+                       pfatal("restsymmult with illegal number of measures (%d)",
+                                       -(gs_p->basictime) );
+                       break;
+               }
+       }
+       else {
+               /* draw vertical lines at each end */
+               do_linetype(L_MEDIUM);
+
+               draw_line(west, y - (2.0 * Stepsize), west, y + (2.0 * Stepsize));
+               draw_line(east, y - (2.0 * Stepsize), east, y + (2.0 * Stepsize));
+
+               /* draw heavy horizontal */
+               do_linetype(L_WIDE);
+               draw_line(west, y, east, y);
+       }
+
+       if (svpath(staff_p->staffno, PRINTMULTNUM)->printmultnum == YES) {
+               /* print number of measures */
+               numstr = mrnum(staff_p, &x, &y_offset, &height, &width);
+               pr_string(x, y + y_offset, numstr, J_LEFT, (char *) 0, -1);
+       }
+}
+\f
+
+/* Given a STAFF pointing to a multirest or measure repeat GRPSYL,
+ * return a string for its number of measures,
+ * and return via pointers its x, relative y, height, and width */
+
+char *
+mrnum(staff_p, x_p, y_offset_p, height_p, width_p)
+
+struct STAFF *staff_p;
+double *x_p;           /* return where number starts horizontally */
+double *y_offset_p;    /* return y relative to staff */
+double *height_p;      /* return height of string */
+double *width_p;       /* return width of string */
+
+{
+       struct GRPSYL *gs_p = 0;/* initialize to avoid compiler warning */
+       char *numstr;           /* ASCII version of number of measures */
+       int v;                  /* voice index */
+
+       /* skip over invisible voices */
+       for (v = 0; v < MAXVOICES; v++) {
+               if (vvpath(staff_p->staffno, v + 1, VISIBLE)->visible == YES) {
+                       gs_p = staff_p->groups_p[v];
+                       break;
+               }
+       }
+       if (v == MAXVOICES) {
+               pfatal("no visible voice found by mrnum");
+       }
+       if (gs_p->grpcont == GC_NOTES) {
+               /* this is a measure repeat */
+               numstr = num2str(staff_p->mrptnum);
+               numstr[0] = FONT_TR;
+               numstr[1] = 11;
+       }
+       else if (gs_p->grpcont == GC_REST) {
+               /* this is a multi-rest */
+               numstr = num2str( -(gs_p->basictime) );
+               /* want these in bigger size */
+               /* Essential Dictionary of Music Notation says this
+                * should be in the same size and font as time signature. */
+               numstr[0] = FONT_NB;
+               numstr[1] = 16;
+       }
+       else {
+               pfatal("wrong group type (%d) passed to mrnum, line %d, staff %d, voice %d", gs_p->grpcont, gs_p->inputlineno, gs_p->staffno, gs_p->vno);
+               /*NOTREACHED*/
+               return (char *) 0;      /* to shut up bogus compiler warning */
+       }
+       numstr[1] = (char) adj_size((int) numstr[1], Staffscale, (char *) 0, -1);
+
+       *width_p = strwidth(numstr);
+       *height_p = strheight(numstr);
+
+       /* x is middle of measure minus 1/2 of number string width */
+       /* y offset is just above staff */
+       *x_p = ((gs_p->c[AE] + gs_p->c[AW]) / 2.0) - (*width_p / 2.0);
+       *y_offset_p = halfstaffhi(gs_p->staffno) + Stepsize;
+       return(numstr);
+}
+\f
+
+/* given a number, return pointer to string version (with font/size in first
+ * 2 bytes. Points to static area overwritten on each call, so if you need a
+ * unique copy of it, use copy_string(). Always makes a string in Roman in
+ * the default size. */
+
+char *
+num2str(num)
+
+int num;       /* the number to convert */
+
+{
+       static char numstr[12];
+
+       /* get ASCII version of number */
+       (void) sprintf(numstr, "%c%c%d", FONT_TR,
+                       adj_size(DFLT_SIZE, Staffscale, (char *) 0, -1), num);
+       return(numstr);
+}
+\f
+
+/* print cresc or decresc */
+
+static void
+pr_cresc(stuff_p)
+
+struct STUFF *stuff_p; /* info about what to print and where */
+
+{
+       float x1, x2;                   /* x coords of west and east points */
+       float line1y1, line2y1;         /* y coords of west points */
+       float line1y2, line2y2;         /* y coords of east points */
+
+
+       do_linetype(L_NORMAL);
+
+       /* get coords for point and midpoint of open end */
+       x1 = stuff_p->c[AW];
+       x2 = stuff_p->c[AE];
+       if (stuff_p->stuff_type == ST_CRESC) {
+               line1y1 = line2y1 = (stuff_p->c[AN] + stuff_p->c[AS]) / 2.0;
+               /* adjust by 1 point to allow some vertical padding */
+               line1y2 = stuff_p->c[AN] - (1.0 * Stdpad);
+               line2y2 = stuff_p->c[AS] + (1.0 * Stdpad);
+       }
+       else if (stuff_p->stuff_type == ST_DECRESC) {
+               line1y2 = line2y2 = (stuff_p->c[AN] + stuff_p->c[AS]) / 2.0;
+               line1y1 = stuff_p->c[AN] - (1.0 * Stdpad);
+               line2y1 = stuff_p->c[AS] + (1.0 * Stdpad);
+       }
+       else {
+               pfatal("pr_cres called for something other than cresc/decresc");
+               /*NOTREACHED*/
+               return; /* to shut up bogus compiler warning about unused variables */
+       }
+
+       /* draw the two sides of the hairpin */
+       draw_line(x1, line1y1, x2, line1y2);
+       draw_line(x1, line2y1, x2, line2y2);
+}
+\f
+
+/* if a STUFF has a til clause, may need to extend out. If a trill, extend
+ * with wavy line. If octave, use dashed line.  If strings ends with a ~,
+ * use a wavy line. If ends with an underscore or is figbass, use
+ * underline. For everything else, put out periodic dashed. */
+
+static void
+extend(stuff_p)
+
+struct STUFF *stuff_p; /* a stuff which may have a til clause */
+
+{
+       float extlen;           /* length of extension */
+       float y;                /* vertical position */
+       float x;                /* horizontal position */
+       float segment;          /* length of dash + white space */
+       char *dash;             /* dash in proper font/size */
+       char lch;               /* last character of string */
+
+
+       if (stuff_p->end.bars <= 0 && stuff_p->end.count <= 0.0) {
+               /* no til clause, so nothing to do */
+               return;
+       }
+
+       /* figure out how much to extend */
+       extlen = stuff_p->c[AE] - stuff_p->c[AW] - strwidth(stuff_p->string);
+       y = stuff_p->c[AY];
+
+       if (string_is_sym(stuff_p->string, C_TR, FONT_MUSIC) == YES) {
+               /* special case of a trill */
+               if ( extlen < Stepsize) {
+                       /* too short to bother */
+                       return;
+               }
+
+               y += (2.0 * Stepsize);
+               draw_wavy(stuff_p->c[AE] - extlen, y, stuff_p->c[AE], y);
+               return;
+       }
+
+       else if ((lch = last_char(stuff_p->string)) == '~') {
+               y += strascent(stuff_p->string) / 2.0;
+               draw_wavy(stuff_p->c[AE] - extlen, y, stuff_p->c[AE], y);
+               return;
+       }
+
+       else if (lch == '_' || stuff_p->modifier == TM_FIGBASS) {
+               do_linetype(L_NORMAL);
+               draw_line(stuff_p->c[AE] - extlen, y, stuff_p->c[AE], y);
+               return;
+       }
+
+       else if (stuff_p->stuff_type == ST_OCTAVE) {
+
+               if ( extlen < (4.0 * Stepsize)) {
+                       /* too short to bother */
+                       return;
+               }
+
+               y += (1.5 * Stepsize);
+               do_linetype(L_DASHED);
+               draw_line(stuff_p->c[AE] - extlen + (2.0 * Stepsize), y,
+                                               stuff_p->c[AE], y);
+
+               /* vertical line at end unless carried to next score */
+               if (stuff_p->carryout == NO) {
+                       draw_line(stuff_p->c[AE], y, stuff_p->c[AE],
+                               y + (3.0 * Stepsize *
+                               (stuff_p->place == PL_ABOVE ? -1.0 : 1.0)));
+               }
+
+               /* put linetype back to solid so some other music character that
+                * uses a line won't get messed up */
+               do_linetype(L_NORMAL);
+               return;
+       }
+
+       dash = dashstr(stuff_p->string);
+       segment = (3.0 * strwidth(dash));
+       for ( x = stuff_p->c[AE] - extlen + (2.0 * segment) / 3.0;
+                                       x < stuff_p->c[AE]; x += segment) {
+               pr_string(x, y, dash, J_LEFT, (char *) 0, -1);
+       }
+       FREE(dash);
+}
+\f
+
+/* Some characters have upside-down versions that are used
+ * if stem is down. This table maps such characters to their flips versions.
+ */
+
+static struct MIRRCHAR {
+       int     font;           /* Which music font. Note that both the
+                                * normal and inverted characters must be
+                                * in the same font. (We could relax
+                                * this constraint by storing a font for each,
+                                * and returning both character and font,
+                                * but there's no hardship in this simple way.)
+                                */
+       char    norm;
+       char    inverted;
+} mirrtbl[] = {
+       { FONT_MUSIC, C_FERM, C_UFERM },
+       { FONT_MUSIC, C_ACC_HAT, C_ACC_UHAT },
+       { FONT_MUSIC, C_WEDGE, C_UWEDGE },
+       { 0, 0 }
+};
+
+
+/* Given a string and the first character in it, if it is a music symbol
+ * that has a mirrored version, return that, otherwise, return
+ * it as it was.
+ */
+
+static int
+mirror(str, ch, font)
+
+char *str;     /* the string to check */
+int ch;                /* the first character (which better be a music character) */
+int font;      /* FONT_MUSIC or some other music font */
+
+{
+       int i;
+
+       for (i = 0; mirrtbl[i].norm != '\0'; i++) {
+               if (string_is_sym(str, mirrtbl[i].norm, mirrtbl[i].font) == YES) {
+                       return((int) mirrtbl[i].inverted);
+               }
+       }
+       return(ch);
+}
diff --git a/mup/mup/prntmisc.c b/mup/mup/prntmisc.c
new file mode 100644 (file)
index 0000000..5b0a3ff
--- /dev/null
@@ -0,0 +1,1421 @@
+
+/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions for printing endings, pedal marks, phrase marks, etc */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+/* width of tapered curve at endpoint relative to maximum width */
+#define TAPERWID       (0.4)
+
+
+/*
+ * Define a structure for storing points of a curve, whether generated (like
+ * for phrase marks) or user-specified.  It also stores information used in
+ * calculating Bezier curves that will be drawn between each pair of
+ * neighboring points.  The "control points" are points 1 and 2 for the
+ * Bezier curve going from this point to the next point.  These structures
+ * get their x and y filled in from CURVE or CRVLIST structures.
+ */
+struct CURVEINFO {
+       float x, y;     /* point's coords */
+       float len;      /* length of line segment from here to next point */
+       float ang;      /* angle between the 2 segments at this point */
+       int bend;       /* bend direction at point: 1=clockwise, -1=counter */
+       float slopetan; /* slope of line "tangent" to this point if axes are */
+                       /* rotated such that segment starting here is horiz. */
+       float x1, y1;   /* control point 1 for segment starting at this point */
+       float x2, y2;   /* control point 2 for segment starting at this point */
+};
+
+/* static functions */
+static void do_endings P((struct MAINLL *first_p, struct MAINLL *last_p,
+               char *endlabel, int carryout));
+static void draw_ending P((int staffno, double ry, struct MAINLL *first_p,
+               struct MAINLL *last_p, char *endlabel, int carryout));
+static void pr_endlabel P((double x, double y, char *label));
+static void pr_end_line P((double begin_x, double end_x, double y,
+               int carryout));
+static int is_top_visible_in_range P((int staffno, int top));
+static void calccurve P((struct CURVEINFO v[], int num));
+static void findcontrol P((struct CURVEINFO v[], int num));
+
+\f
+
+/* whenever we hit a FEED, draw any endings associated with the score */
+
+void
+pr_endings(main_feed_p)
+
+struct MAINLL *main_feed_p;    /* FEED */
+
+{
+       static char *endlabel = (char *) 0;/* ending label if had to carry over
+                                        * to next score */
+       struct MAINLL *curr_p;          /* where we are in main list */
+       struct MAINLL *first_p;         /* where an ending begins */
+       struct MAINLL *last_bar_p = 0;  /* points to last bar on score so far */
+
+
+       debug(512, "pr_endings");
+
+       first_p = (struct MAINLL *) 0;
+
+       /* go through the entire score line. For every set of measures that have
+        * endings, draw them. */
+       for (curr_p = main_feed_p->next; curr_p != (struct MAINLL *) 0;
+                                       curr_p = curr_p->next) {
+
+               /* go just to end of current score */
+               if (curr_p->str == S_FEED) {
+                       break;
+               }
+
+               /* if there is a pseudo bar, see if it is in an ending */
+               if (curr_p->str == S_CLEFSIG) {
+                       if (curr_p->u.clefsig_p->bar_p != (struct BAR *) 0 &&
+                                       curr_p->u.clefsig_p->bar_p->endingloc
+                                       != NOITEM) {
+                               first_p = curr_p;
+                               endlabel = curr_p->u.clefsig_p->bar_p->endinglabel;
+                       }
+                       continue;
+               }
+
+               /* for each bar, check its endingloc and act accordingly */
+               else if (curr_p->str == S_BAR) {
+
+                       switch(curr_p->u.bar_p->endingloc) {
+
+                       case ENDITEM:
+                               if (first_p == (struct MAINLL *) 0) {
+                                       pfatal("ending without beginning");
+                               }
+                               /*FALLTHRU*/
+                       case NOITEM:
+                               /* if we were doing an ending, we reached the
+                                * end of it, so handle it */
+                               if (first_p != (struct MAINLL *) 0) {
+                                       /* it doesn't seem like it should be
+                                        * possible to get inside this IF for
+                                        * the NOITEM case, but it doesn't
+                                        * hurt anything to have to code as it
+                                        * is, and I don't want to change it for
+                                        * fear it would break some obscure
+                                        * circumstance I've forgotten about */
+                                       do_endings(first_p, curr_p, endlabel, NO);
+                                       endlabel = (char *) 0;
+                                       first_p = (struct MAINLL *) 0;
+                               }
+                               break;
+
+                       case STARTITEM:
+                               /* if we are also implictly ending a previous
+                                * ending, do that first. In any case, keep
+                                * track of where this ending begins. */
+                               if (first_p != (struct MAINLL *) 0) {
+                                       do_endings(first_p, curr_p,
+                                                               endlabel, NO);
+                               }
+
+                               first_p = curr_p;
+                               endlabel = curr_p->u.bar_p->endinglabel;
+
+                               break;
+
+                       case INITEM:
+                               break;
+
+                       default:
+                               pfatal("bad endingloc value");
+                               /*NOTREACHED*/
+                               break;
+                       }
+                       last_bar_p = curr_p;
+               }
+       }
+
+       /* we must be at the end of the score. If we are in the middle
+        * of an ending, draw this score's portion of it now */
+       if ( (first_p != (struct MAINLL *) 0)
+                               && (last_bar_p != (struct MAINLL *) 0)) {
+               do_endings(first_p, last_bar_p, endlabel,
+                               last_bar_p->u.bar_p->endingloc
+                               == INITEM ? YES : NO);
+       }
+}
+\f
+
+/* now that we have identified an ending, print it above each
+ * staff that is supposed to get endings */
+
+static void
+do_endings(first_p, last_p, endlabel, carryout)
+
+struct MAINLL *first_p;        /* where to begin drawing endings */
+struct MAINLL *last_p; /* where to end the endings */
+char *endlabel;                /* if ending has a label, this will be
+                        * that label, otherwise NULL */
+int carryout;          /* YES if will carry over to next staff */
+
+{
+       struct MARKCOORD *markc_p;      /* info about where to draw ending */
+
+
+       /* for each staff that is supposed to have endings,
+        * draw the ending */
+       if (first_p->str == S_CLEFSIG) {
+               /* pseudo-bar */
+               markc_p = first_p->u.clefsig_p->bar_p->ending_p;
+       }
+       else {
+               /* normal bar */
+               markc_p = first_p->u.bar_p->ending_p;
+       }
+
+       /* if this is an endending and the bar line at the end is an ordinary
+        * bar or an invisbar, then set the carryout flag so that the final
+        * vertical line doesn't get drawn. */
+       if (last_p->u.bar_p->endingloc == ENDITEM
+                               && (last_p->u.bar_p->bartype == SINGLEBAR ||
+                               last_p->u.bar_p->bartype == INVISBAR)) {
+               /* But if this is the very end of the piece,
+                * then we *do* want to draw the final vertical */
+               struct MAINLL* mll_p;
+               for (mll_p = last_p->next; mll_p != 0; mll_p = mll_p->next) {
+                       if (mll_p->str == S_STAFF) {
+                               break;
+                       }
+               }
+               if (mll_p != 0) {
+                       carryout = YES;
+               }
+       }
+
+       /* draw an ending for each item in MARKCOORD list */
+       for (   ; markc_p != (struct MARKCOORD *) 0; markc_p = markc_p->next) {
+               draw_ending(markc_p->staffno, (double) markc_p->ry,
+                                       first_p, last_p, endlabel, carryout);
+       }
+}
+\f
+
+/* draw ending marks over specified staff */
+
+static void
+draw_ending(staffno, ry, first_p, last_p, endlabel, carryout)
+
+int staffno;           /* which staff to draw over */
+double ry;             /* relative y */
+struct MAINLL *first_p;        /* draw ending starting from here */
+struct MAINLL *last_p; /* ending end here */
+char *endlabel;                /* if has label, this is the label, else is NULL */
+int carryout;          /* if YES, will carry over to next score */
+
+{
+       float begin_x;          /* x coord of beginning and end of ending */
+       float y;                /* vertical location of ending */
+
+
+       /* first_p can point to either a CLEFSIG (if carrying over an
+        * ending) or to a BAR. Find appropriate x coordinate */
+       switch (first_p->str) {
+
+       case S_CLEFSIG:
+               begin_x = first_p->u.clefsig_p->bar_p->c[AX];
+               break;
+
+       case S_BAR:
+               begin_x = first_p->u.bar_p->c[AX];
+               break;
+
+       default:
+               /* shut up compilers that erroneously thinks begin_x
+                * could get used without being set. */
+               begin_x = 0.0;
+               pfatal("bad struct type passed to draw_ending");
+               /*NOTREACHED*/
+               break;
+       }
+
+       /* get vertical position */
+       y = Staffs_y[staffno] + ry;
+
+       /* now we know where to put it, so draw it */
+       do_linetype(L_NORMAL);
+
+       /* print the beginning vertical and label now if appropriate */
+       if (endlabel != (char *) 0) {
+               pr_endlabel( (double) begin_x, (double) y, endlabel);
+       }
+
+       pr_end_line ( (double) begin_x, (double) last_p->u.bar_p->c[AX],
+                                               (double) y, carryout);
+}
+\f
+
+/* print label at the beginning of an ending, along with the vertical line
+ * to the left of the label */
+
+static void
+pr_endlabel(x, y, label)
+
+double x;      /* coordinate of beginning of ending */
+double y;
+char *label;   /* the ending label or NULL */
+
+{
+       /* if there is a label, this is the beginning of an ending, so
+        * print a vertical line followed by the label */
+       if (label != (char *) 0) {
+               x += (2.0 * STDPAD);
+               draw_line(x, y + STDPAD, x, y + ENDINGHEIGHT - STDPAD);
+               pr_string(x + (3.0 * STDPAD), y + (2.0 * STDPAD), label, J_LEFT,
+                                       (char *) 0, -1);
+       }
+}
+\f
+
+/* print horizontal line above ending, possibly with ending vertical line */
+
+static void
+pr_end_line(begin_x, end_x, y, carryout)
+
+double begin_x;        /* horizontal coordinates of ending line */
+double end_x;
+double y;      /* vertical position */
+int carryout;  /* if YES, continued on next score, so no end vertical */
+
+{
+       /* adjust to allow a little padding */
+       begin_x += (2.0 * STDPAD);
+       end_x -= (2.0 * STDPAD);
+       y += ENDINGHEIGHT - STDPAD;
+
+       /* draw the horizontal line above the ending */
+       draw_line(begin_x, y, end_x, y);
+
+       /* if the ending ends here, draw vertical line at end */
+       if (carryout == NO) {
+               draw_line(end_x, y, end_x, y - ENDINGHEIGHT + (2.0 * STDPAD));
+       }
+}
+\f
+
+/* function to tell whether a given staff should have ending put on it. Returns
+ * YES if it does, NO if it doesn't */
+
+int
+has_ending(staffno)
+
+int staffno;           /* which staff to check */
+
+{
+       register int s;         /* index through barstlist */
+
+
+       /* if staff is invisible, ending doesn't count */
+       if ( svpath(staffno, VISIBLE)->visible == NO) {
+               return(NO);
+       }
+       switch ( Score.endingstyle ) {
+
+       case ENDING_TOP:
+               /* if there is an earlier staff that is visible, then no
+                * ending on this one. Otherwise there is */
+               return( is_top_visible_in_range(staffno, 1) );
+
+       case ENDING_BARRED:
+               /* go through barstlist. If this
+                * staff is within a range and any staffs above it are
+                * invisible at the moment, it gets an ending. */
+               for (s = 0; s < Score.nbarst;  s++) {
+
+                       if ((staffno >= Score.barstlist[s].top) && (staffno
+                                               <= Score.barstlist[s].bottom)) {
+
+                               return( is_top_visible_in_range(staffno,
+                                               Score.barstlist[s].top));
+                       }
+               }
+
+               /* if wasn't in any of the ranges, then it must be barred
+                * by itself */
+               return(YES);
+
+       case ENDING_GROUPED:
+               /* go through brace and bracket list. If the top visible
+                * of any of them match the given score, it gets an ending */
+               for (s = 0; s < Score.nbrace; s++) {
+
+                       if ((staffno >= Score.bracelist[s].topstaff)
+                                       && (staffno
+                                       <= Score.bracelist[s].botstaff)) {
+
+                               return( is_top_visible_in_range(staffno,
+                                       Score.bracelist[s].topstaff));
+                       }
+               }
+
+               for (s = 0; s < Score.nbrack; s++) {
+
+                       if ((staffno >= Score.bracklist[s].topstaff)
+                                       && (staffno
+                                       <= Score.bracklist[s].botstaff)) {
+
+                               return( is_top_visible_in_range(staffno,
+                                       Score.bracklist[s].topstaff));
+                       }
+               }
+
+               /* wasn't in either list, so it probably shouldn't have an
+                * ending. However, if it happens to be the top staff, we
+                * better put one on anyway, because the top staff should
+                * always get an ending. */
+               return( is_top_visible_in_range(staffno, 1) );
+
+       default:
+               pfatal("unknown endingstyle");
+       }
+       /*NOTREACHED*/
+       return(NO);
+}
+\f
+
+/* given a staff number and the top of a range of staffs, return YES if the
+ * given staff is the top visible staff in the range, otherwise return NO.
+ * Assume that staffno itself is for a visible staff */
+
+int
+is_top_visible_in_range(staffno, top)
+
+int staffno;   /* which staff to check */
+int top;       /* top of range to check */
+
+{
+       for (staffno--; staffno >= top; staffno--) {
+               if ( svpath(staffno, VISIBLE)->visible == YES) {
+                       /* something above it is visible */
+                       return(NO);
+               }
+       }
+       return(YES);
+}
+\f
+
+/* functions for printing piano pedals marks */
+
+/* keep track of where last coordinate of pedal mark was for each staff.
+ * If no pedal currently on a staff, set to 0.0 */
+static float Last_ped_x[MAXSTAFFS + 1];
+static float Last_ped_y[MAXSTAFFS + 1];
+
+
+/* return the distance to offset the 'P' of "Ped." from the group X to
+ * center it on the group. The first time called, calculate the width,
+ * after that, just return it */
+
+double
+ped_offset()
+
+{
+       static double width = 0.0;
+       char pstr[4];
+
+       if (width == 0.0) {
+               /* first time, make string with just P and get width of that */
+               (void) strncpy(pstr, Ped_start, 3);
+               pstr[3] = '\0';
+               width = strwidth(pstr) / 2.0;
+       }
+       return(width);
+}
+\f
+
+/* when we encounter a ST_PEDAL, print the pedal character and save the
+ * east boundary as the last pedal x value, for later use. If is endped,
+ * set this last pedal x value to 0.0 */
+
+void
+pr_ped_char(stuff_p, staffno)
+
+struct STUFF *stuff_p;         /* pedal info */
+int staffno;                   /* which staff */
+
+{
+       int font;
+       int size;
+       char *string;
+       int pedstyle;   /* P_PEDSTAR or P_ALTPEDSTAR or P_LINE */
+       int pedchar;    /* pedal music character code */
+       double overlap; /* to avoid tiny gaps in pedal line due to roundoff */
+       char *adj_pstart;       /* Ped_start adjusted for Staffscale */
+       char *adj_pstop;        /* Ped_stop adjusted for Staffscale */
+
+
+       if (stuff_p->string == (char *) 0) {
+               /* must be a pedal mark carried over from a previous
+                * score. Just need to save away the coordinate. */
+               Last_ped_x[staffno] = stuff_p->c[AX];
+               Last_ped_y[staffno] = stuff_p->c[AY];
+               return;
+       }
+
+       pedstyle = svpath(staffno, PEDSTYLE)->pedstyle;
+
+       /* extract the pedal character to be printed */
+       font = stuff_p->string[0];
+       size = stuff_p->string[1];
+       string = stuff_p->string + 2;
+       pedchar = next_str_char(&string, &font, &size) & 0xff;
+
+       /* overlap lines just slightly with pedal characters, to compensate
+        * for any rounding of the bounding box which might cause a tiny
+        * gap to appear between the line and the pedal character */
+       overlap = Stdpad / 3.0;
+
+       /* draw line from previous pedal character, if any, to this one */
+       if (pedstyle == P_LINE && Last_ped_x[staffno] != 0.0) {
+               if (stuff_p->c[AW] + overlap - Last_ped_x[staffno] > 0) {
+                       do_linetype(L_NORMAL);
+                       draw_line(Last_ped_x[staffno], stuff_p->c[AY],
+                               stuff_p->c[AW] + overlap, stuff_p->c[AY]);
+               }
+       }
+
+       Last_ped_y[staffno] = stuff_p->c[AY];
+
+       switch (pedchar) {
+
+       case C_BEGPED:
+               if (Last_ped_x[staffno] != 0.0) {
+                       /* This used to be a pfatal, because it should
+                        * never happen. But it can happen
+                        * due to user error: if user does something like
+                        *      pedal ....
+                        *      repeatend
+                        *      ....
+                        *      pedal ...
+                        *      repeatend
+                        * Having two repeatends without an intervening
+                        * repeatstart is illegal.
+                        * It has never shown up as a true pfatal in millions
+                        * of test runs, so if it is ever hit,
+                        * it's probably the user error case.
+                        */
+                       ufatal("got begin pedal when already doing pedal, staff %d", staffno);
+               }
+               Last_ped_x[staffno] = stuff_p->c[AE] - overlap;
+               break;
+               
+       case C_PEDAL:
+               if (Last_ped_x[staffno] == 0.0) {
+                       pfatal("got pedal without begped, staff %d", staffno);
+               }
+               Last_ped_x[staffno] = stuff_p->c[AE] - overlap;
+               break;
+
+       case C_ENDPED:
+               if (Last_ped_x[staffno] == 0.0) {
+                       pfatal("got endped without begped, staff %d", staffno);
+               }
+               Last_ped_x[staffno] = 0.0;
+               break;
+               
+       default:
+               pfatal("bad character 0x%x in pedal string", pedchar);
+               /*NOTREACHED*/
+               break;
+       }
+
+       /* now print the appropriate pedal character */
+       if (pedstyle == P_LINE) {
+               /* We used to print the pedal characters from FONT_MUSIC,
+                * but Ghostscript sometimes misaligned them with the
+                * pedal lines, so now we draw the characters "manually."
+                */
+               do_linetype(L_NORMAL);
+               switch (pedchar) {
+               case C_BEGPED:
+                       draw_line(stuff_p->c[AX], stuff_p->c[AN],
+                               stuff_p->c[AX], stuff_p->c[AY]);
+                       draw_line(stuff_p->c[AX], stuff_p->c[AY],
+                               stuff_p->c[AE] + overlap, stuff_p->c[AY]);
+                       break;
+               case C_PEDAL:
+                       draw_line(stuff_p->c[AW], stuff_p->c[AY],
+                               stuff_p->c[AX], stuff_p->c[AN]);
+                       draw_line(stuff_p->c[AX], stuff_p->c[AN],
+                               stuff_p->c[AE], stuff_p->c[AY]);
+                       break;
+               case C_ENDPED:
+                       draw_line(stuff_p->c[AW] - overlap, stuff_p->c[AY],
+                               stuff_p->c[AX], stuff_p->c[AY]);
+                       draw_line(stuff_p->c[AX], stuff_p->c[AN],
+                               stuff_p->c[AX], stuff_p->c[AY]);
+                       break;
+
+               }
+                       
+       }
+       else {
+               /* If we need to adjust for Staffscale, make a temp copy */
+               if (Staffscale != 1.0) {
+                       adj_pstart = copy_string(Ped_start + 2,
+                               (int) Ped_start[0],
+                               adj_size( (int) Ped_start[1], Staffscale,
+                               (char *) 0, -1));
+                       adj_pstop = copy_string(Ped_stop + 2,
+                               (int) Ped_stop[0],
+                               adj_size( (int) Ped_stop[1], Staffscale,
+                               (char *) 0, -1));
+               }
+               else {
+                       adj_pstart = Ped_start;
+                       adj_pstop = Ped_stop;
+               }
+
+               /* In alt pedstar style, a PEDAL is treated exactly like
+                * a BEGPED, so pretend that's what we got. */
+               if (pedstyle == P_ALTPEDSTAR && pedchar == C_PEDAL) {
+                       pedchar = C_BEGPED;
+               }
+
+               switch (pedchar) {
+
+               case C_BEGPED:
+                       pr_string(stuff_p->c[AX] - (strwidth(adj_pstart) / 2.0),
+                                       stuff_p->c[AY], adj_pstart,
+                                       J_CENTER, stuff_p->inputfile,
+                                       stuff_p->inputlineno);
+                       break;
+
+               case C_PEDAL:
+                       pr_string(stuff_p->c[AX] - strwidth(adj_pstop)
+                                       - ped_offset() * Staffscale,
+                                       stuff_p->c[AY], adj_pstop,
+                                       J_RIGHT, stuff_p->inputfile,
+                                       stuff_p->inputlineno);
+                       pr_string(stuff_p->c[AX] - ped_offset() * Staffscale,
+                                       stuff_p->c[AY], adj_pstart,
+                                       J_LEFT, stuff_p->inputfile,
+                                       stuff_p->inputlineno);
+                       break;
+
+               case C_ENDPED:
+                       pr_string(stuff_p->c[AX] - (strwidth(adj_pstop) / 2.0),
+                                       stuff_p->c[AY], adj_pstop,
+                                       J_CENTER, stuff_p->inputfile,
+                                       stuff_p->inputlineno);
+                       break;
+
+               default:
+                       pfatal("bad character 0x%x in pedal string", pedchar);
+                       /*NOTREACHED*/
+                       break;
+               }
+
+               /* If we had to make a temp copy to account for Staffscale,
+                * free the temp copy. */
+               if (Staffscale != 1.0) {
+                       FREE(adj_pstart);
+                       FREE(adj_pstop);
+               }
+       }
+}
+\f
+
+/* when we hit a bar line, extend any pedal marks to the bar line. Since things
+ * are stored in units of bars, easier to do this than keep track of the
+ * entire length and have to worry about page feeds, etc. This is just for
+ * normal bars, not pseudo-bars. They are handled separately. */
+
+void
+pr_ped_bar(mll_p, bar_p)
+
+struct MAINLL *mll_p;  /* print pedal mark up to bar hangs off of here */
+struct BAR *bar_p;     /* print pedal marks up to this bar */
+
+{
+       register int s;
+       float endadj;           /* adjustment for endings */
+
+
+       /* for each staff that has pedal marks pending, draw an extension
+        * line to where this bar line is and reset Last_ped_x */
+       for (s = 1; s <= Score.staffs; s++) {
+
+               if (Last_ped_x[s] != 0.0) {
+
+                       if (Last_ped_y[s] <= 0.0) {
+                               pfatal("don't have y coordinate for drawing pedal mark");
+                       }
+
+                       endadj = 0.0;
+                       if (svpath(s, PEDSTYLE)->pedstyle == P_LINE) {
+                               do_linetype(L_NORMAL);
+                               if (Ped_snapshot[0] == YES &&
+                                               bar_p->endingloc == STARTITEM) {
+
+                                       /* going into 2nd ending, so shorten
+                                        * this pedal to not reach bar */
+                                       endadj = (2.0 * STEPSIZE);
+                                       /* if line length is positive,  
+                                        * draw it */
+                                       if (bar_p->c[AX] - endadj
+                                                       > Last_ped_x[s]) {
+
+                                               draw_line(Last_ped_x[s],
+                                                       Last_ped_y[s],
+                                                       bar_p->c[AX] - endadj,
+                                                       Last_ped_y[s]);
+                                       }
+                               }
+                               else {
+                                       if (bar_p->c[AX] - STDPAD >
+                                                       Last_ped_x[s]) {
+                                               draw_line(Last_ped_x[s],
+                                                               Last_ped_y[s],
+                                                               bar_p->c[AX]
+                                                               - STDPAD,
+                                                               Last_ped_y[s]);
+                                               endadj = -STDPAD;
+                                       }
+                                       else {
+                                               endadj = -(bar_p->c[AX]
+                                                       - Last_ped_x[s]);
+                                       }
+                               }
+                       }
+
+                       Last_ped_x[s] = bar_p->c[AX] + endadj;
+               }
+       }
+       saveped(mll_p, bar_p);
+}
+\f
+
+/* handle pedal going into endings. When we hit a first ending, save the
+ * state of the pedal for all staffs. On subsequent endings in the set,
+ * reset the pedal state to what it was at the beginning of the first ending.
+ * At the endending, go back to normal operation. */
+
+void
+saveped(mll_p, bar_p)
+
+struct MAINLL *mll_p;  /* bar is connected here */
+struct BAR *bar_p;
+
+{
+       register int s;         /* staff index */
+
+
+       if (mll_p == (struct MAINLL *) 0) {
+               pfatal("null pointer in saveped");
+       }
+
+       if (bar_p->endingloc == STARTITEM) {
+
+               if (Ped_snapshot[0] == YES) {
+
+                       /* starting 2nd ending: restore pedal state as it was
+                        * at beginning of first ending */
+                       for (s = 1; s <= Score.staffs; s++) {
+                               if (Ped_snapshot[s] == YES) {
+                                       Last_ped_x[s] = bar_p->c[AX]
+                                                       + (2.0 * STEPSIZE);
+                               }
+                               else {
+                                       Last_ped_x[s] = 0.0;
+                               }
+                       }
+               }
+
+               else {
+                       /* starting a set of endings,
+                        * need to save pedal state at this
+                        * point so we can carry it into subsequent endings */
+                       for (s = 1; s <= Score.staffs; s++) {
+                               /* set to YES if pedal is on */
+                               Ped_snapshot[s] = (Last_ped_x[s] == 0.0 ? NO : YES);
+                       }
+                       /* make sure any remaining staffs are set to pedal off,
+                        * in case user increases the number of staffs
+                        * during the endings... */
+                       for (   ; s <= MAXSTAFFS; s++) {
+                               Ped_snapshot[s] = NO;
+                       }
+
+                       /* mark that we now have a snapshot */
+                       Ped_snapshot[0] = YES;
+               }
+       }
+
+       else if (bar_p->endingloc == ENDITEM) {
+               /* at end of endings, discard snapshot of pedal states.
+                * However, we have to make sure this is really the end of
+                * endings, and not just a bar that was marked as end
+                * because the start of the next was moved from here to
+                * the pseudo bar. So we search forward, if we find a
+                * clefsig with pseudo-bar before finding a chhead,
+                * and that pseudo bar endingloc is STARTITEM, then this
+                * isn't really the end of endings, and should be ignored. */
+               for (   ; mll_p != (struct MAINLL *) 0; mll_p = mll_p->next) {
+                       if (mll_p->str == S_CHHEAD) {
+                               /* is end of endings */
+                               break;
+                       }
+                       else if (mll_p->str == S_CLEFSIG &&
+                                       mll_p->u.clefsig_p->bar_p !=
+                                       (struct BAR *) 0 &&
+                                       mll_p->u.clefsig_p->bar_p->endingloc
+                                       == STARTITEM) {
+                               /* not really end of endings */
+                               return;
+                       }
+               }
+               Ped_snapshot[0] = NO;
+       }
+}
+\f
+
+/* given a list of phrase mark curve coordinates, print the curve */
+/* output each x,y, coordinate pair, then the number of coordinates and
+ * finally the "curve" function name */
+
+void
+pr_phrase(crvlist_p, linetype, tapered, staffno)
+
+struct CRVLIST *crvlist_p;     /* the curve to print */
+int linetype;                  /* if not tapered, may be L_DOTTED or L_DASHED*/
+int tapered;                   /* YES or NO */
+int staffno;                   /* which staff, to get staffscale */
+
+{
+       int n;
+       struct CRVLIST *c_p;
+       float *xlist,* ylist;
+
+       /* count up number of coordinates */
+       for (n = 0, c_p = crvlist_p; c_p != (struct CRVLIST *) 0;
+                                       c_p = c_p->next) {
+               n++;
+       }
+
+       MALLOCA(float, xlist, n);
+       MALLOCA(float, ylist, n);
+       for (n = 0, c_p = crvlist_p; c_p != (struct CRVLIST *) 0;
+                                       c_p = c_p->next, n++) {
+               xlist[n] = c_p->x;
+               ylist[n] = c_p->y;
+       }
+       if (tapered == NO) {
+               do_linetype(linetype);
+       }
+       pr_allcurve(xlist, ylist, n,
+               svpath(staffno, STAFFSCALE)->staffscale * W_MEDIUM / PPI,
+               tapered);
+       FREE(xlist);
+       FREE(ylist);
+}
+\f
+/*
+ * Name:        pr_allcurve()
+ *
+ * Abstract:    Print a curve, either generated (e.g., tie) or user-defined.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given an array of CURVEINFOs, one for each
+ *             point of a curve, where x and y have been filled in.  It fills
+ *             the rest of the items in the structures, and prints PostScript
+ *             commands for drawing the curve.  If the curve is to be dashed
+ *             or dotted, the calling function must put out the PostScript
+ *             commands for that.  It does not handle "wavy".
+ */
+
+
+void
+pr_allcurve(x, y, num, cwid, tapered)
+
+float x[], y[];                /* coordinates of the curve's points */
+int num;               /* number of elements (points) in the array */
+double cwid;           /* (max) width of the curve, in inches */
+int tapered;           /* YES or NO */
+
+{
+       struct CURVEINFO *v;    /* malloc structs for holding point info */
+       float *slen;            /* malloc length of each segment */
+       float *xoff;            /* malloc x offset of curve boundary from mid*/
+       float *yoff;            /* malloc y offset of curve boundary from mid*/
+       float *off;             /* malloc total offset of curve boundary */
+       float totlen;           /* len of curve, along segments */
+       float maxplace;         /* distance from end where a tapered curve */
+                               /* reaches its maximum thickness */
+       float cumlen, remlen, fromend;  /* used in tapering curve */
+       float dx, dy;           /* for finding x and y offsets */
+       float temp;             /* temp variable */
+       int n;                  /* loop through points */
+
+
+       /*
+        * If the curve is not to be tapered, calculate Bezier curves joining
+        * these points, and stroke the resulting path.
+        */
+       if (tapered == NO) {
+               /* load coords into structures, and calculate control points */
+               MALLOC(CURVEINFO, v, num);
+               for (n = 0; n < num; n++) {
+                       v[n].x = x[n];
+                       v[n].y = y[n];
+               }
+               calccurve(v, num);
+
+               /* output results in PostScript */
+               do_moveto(v[0].x, v[0].y);
+
+               for (n = 0; n < num - 1; n++) {
+                       do_curveto( v[n].x1, v[n].y1, v[n].x2, v[n].y2,
+                                       v[n+1].x, v[n+1].y);
+               }
+               do_stroke();
+
+               FREE(v);
+               return;
+       }
+
+       /*
+        * The curve is to be tapered.  We're going to draw two series of
+        * Bezier curves, forming the boundaries of the whole curve, and then
+        * fill.  Note that this will always result in a solid curve,
+        * regardless of any earlier request for dashes or dots.
+        */
+       /* first allocate the arrays we're going to need */
+       MALLOC(CURVEINFO, v, num);
+       MALLOCA(float, slen, num);
+       MALLOCA(float, xoff, num);
+       MALLOCA(float, yoff, num);
+       MALLOCA(float, off, num);
+
+       /* find and save len of each segment, and accumulate total len */
+       totlen = 0;
+       for (n = 0; n < num - 1; n++) {
+               slen[n] = sqrt( (double) (SQUARED(x[n+1] - x[n]) +
+                               SQUARED(y[n+1] - y[n]) ) );
+               totlen += slen[n];
+       }
+
+       /*
+        * Tapering occurs up to a max of 1/3 inches from the end of a curve.
+        * maxplace is set up such that it is normally the distance from the
+        * end where the max thickness is attained.  However, if a curve is
+        * shorter than 2/3 inches, it will never attain this max thickness.
+        */
+       if (totlen > 0.5) {
+               maxplace = 1.0/3.0;
+       } else {
+               maxplace = totlen * (2.0/3.0);
+       }
+
+       cumlen = 0.0;           /* none accumulated so far */
+       remlen = totlen;        /* all of it remains */
+       for (n = 0; n < num; n++) {
+               /* whichever end this point is closer to, note distance */
+               if (cumlen < remlen) {
+                       fromend = cumlen;
+               }
+               else {
+                       fromend = remlen;
+               }
+
+               /* set the offset for this point for achieving tapering */
+               if (fromend > maxplace) {
+                       off[n] = cwid / 2.0;
+               } else {
+                       float taperwid;
+                       /*
+                        * For curves longer than 2/3, taperwid should be only
+                        * half of TAPERWID; for zero length curves, it should
+                        * be full TAPERWID; in between, adjust linearly.  Then,
+                        * at the ends, the width is taperwid times the full
+                        * standard thickness (the middle of a long curve); and
+                        * ramp up linearly towards 1/3 inches from the end.
+                        */
+                       taperwid = totlen > 2.0/3.0 ? TAPERWID / 2.0 :
+                                       TAPERWID * (1.0 - 0.75 * totlen);
+                       off[n] = (cwid / 2.0) *
+                       ((1.0 - taperwid) * fromend / maxplace + taperwid);
+               }
+
+               /*
+                * Break offset into x and y components, based on the slope
+                * between the two surrounding points.  For the endpoints,
+                * there are not two surrounding points, so use the slope of
+                * the neighboring segment.
+                */
+               /*
+                * First get deltas; x and y are switched and sign reversed
+                * on one, because we're concerned with the line perpendicular
+                * to the line joining the two points.  (Its slope is the
+                * negative inverse.)  Only the ratio dx/dy matters, not the
+                * values.
+                */
+               if (n == 0) {
+                       dx = y[1] - y[0];
+                       dy = x[0] - x[1];
+               } else if (n == num - 1) {
+                       dx = y[num-1] - y[num-2];
+                       dy = x[num-2] - x[num-1];
+               } else {
+                       dx = y[n+1] - y[n-1];
+                       dy = x[n-1] - x[n+1];
+               }
+
+               /* get hypotenuse of something */
+               temp = off[n] / sqrt( (double) (SQUARED(dx) + SQUARED(dy)) );
+
+               /* get x and y offsets; may need to switch signs */
+               xoff[n] = fabs(temp * dx);
+               yoff[n] = fabs(temp * dy);
+               if (dx > 0)
+                       xoff[n] *= -1;
+               if (dy > 0)
+                       yoff[n] *= -1;
+
+               /* update cumulative and remaining length if not at end */
+               if (n < num - 1) {
+                       cumlen += slen[n];
+                       remlen -= slen[n];
+               }
+       }
+
+       /*
+        * Load coords into structures, and calculate control points, for one
+        * boundary of the curve.
+        */
+       for (n = 0; n < num; n++) {
+               v[n].x = x[n] + xoff[n];
+               v[n].y = y[n] + yoff[n];
+       }
+       calccurve(v, num);
+
+       /*
+        * Move to the center of the curve's thickness at the beginning point.
+        * Draw a perpendicular line to the curve's boundary.  Then generate
+        * the curves that form this side's boundary.
+        */
+       do_moveto(x[0], y[0]);
+       do_line(v[0].x, v[0].y);
+       for (n = 0; n < num - 1; n++) {
+               do_curveto( v[n].x1, v[n].y1, v[n].x2, v[n].y2,
+                               v[n+1].x, v[n+1].y);
+       }
+
+       /*
+        * Load coords into structures, and calculate control points, for the
+        * other boundary of the curve.  We're going to do this side in
+        * reverse, back to the beginning.
+        */
+       for (n = 0; n < num; n++) {
+               v[n].x = x[num - 1 - n] - xoff[num - 1 - n];
+               v[n].y = y[num - 1 - n] - yoff[num - 1 - n];
+       }
+       calccurve(v, num);
+
+       /*
+        * Draw a line across the curve's thickness at this end.  Then
+        * generate the curves that form this side's boundary.
+        */
+       do_line( v[0].x, v[0].y);
+       for (n = 0; n < num - 1; n++) {
+               do_curveto( v[n].x1, v[n].y1, v[n].x2, v[n].y2,
+                               v[n+1].x, v[n+1].y);
+       }
+
+       /* fill to form the full, solid curve */
+       do_fill();
+
+       FREE(slen);
+       FREE(xoff);
+       FREE(yoff);
+       FREE(off);
+       FREE(v);
+}
+\f
+/*
+ * Name:        calccurve()
+ *
+ * Abstract:    Calculate info for drawing cubic arcs through a curve's points.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given an array of CURVEINFOs, one for each
+ *             point of a curve, where x and y have been filled in.  It fills
+ *             in the rest of the items in the structures.  Specifically, in
+ *             each structure, (x1, y1) and (x2, y2) are the control points
+ *             for drawing a Bezier curve (using curveto) from this point to
+ *             the next one.  These points are chosen in such a way that the
+ *             slopes at the end of one curve and the start of the next are
+ *             equal, to avoid a sharp corner.  Also, the angles this slope
+ *             forms with straight line segments connecting the points are
+ *             equal.  The angle at the start of the first curve is set equal
+ *             to the angle at the end of it, and the angle at the end of the
+ *             last curve is set equal to the angle at the beginning of it.
+ *             The other fields in the CURVEINFOs are set but aren't useful to
+ *             the caller.  In the last point's CURVEINFO, some of the fields
+ *             are not used (including x1, y1, x2, y2).
+ */
+
+
+static void
+calccurve(v, num)
+
+struct CURVEINFO v[];  /* array of curve points, x and y must be filled in */
+int num;               /* number of elements (points) in the array */
+
+{
+       int n;                          /* loop through the points */
+       float temp, delx, dely;         /* temp variables */
+       float slope, intercept;         /* for equation of a segment */
+
+
+       /* find the length of each segment connecting neighboring points */
+       for (n = 0; n < num - 1; n++) {
+               /* use Pythagorean theorem; put result in 1st point's "len" */
+               delx = v[n+1].x - v[n].x;
+               dely = v[n+1].y - v[n].y;
+               v[n].len = sqrt( (double) (SQUARED(delx) + SQUARED(dely)) );
+               if (v[n].len == 0)
+                       ufatal("two curve points are equal");
+       }
+
+       /* find the angle at each point other than the endpoints */
+       for (n = 1; n < num - 1; n++) {
+               /*
+                * Use the law of cosines on the triangle formed by this point
+                * and the preceding and following points.  First get the delta
+                * from the preceding point to the following point.
+                */
+               delx = v[n+1].x - v[n-1].x;
+               dely = v[n+1].y - v[n-1].y;
+
+               /*
+                * The law of cosines:  c^2  =  a^2  +  b^2  -  2 a b cos(C).
+                * Solve this for the cosine of our point's angle (angle "C").
+                */
+               temp = ( SQUARED(v[n-1].len) + SQUARED(v[n].len) -
+                       (SQUARED(delx) + SQUARED(dely)) ) /
+                       ( 2.0 * v[n-1].len * v[n].len );
+
+               /* if angle is 180, should be -1, but guard against roundoff */
+               if (temp < -1)
+                       temp = -1;      /* should have been exactly -1 */
+
+               /* if angle is 0, this is not allowed in our curve */
+               if (temp >= 1)
+                       ufatal("curve bends all the way back on itself");
+
+               v[n].ang = acos(temp);
+       }
+
+       /* set the bend direction at each point other than the endpoints */
+       for (n = 1; n < num - 1; n++) {
+               /* handle special case where previous segment is vertical */
+               if (v[n-1].x == v[n].x) {
+                       if (v[n-1].y < v[n].y) {
+                               if (v[n+1].x >= v[n].x)
+                                       v[n].bend = 1;
+                               else
+                                       v[n].bend = -1;
+                       } else {
+                               if (v[n+1].x >= v[n].x)
+                                       v[n].bend = -1;
+                               else
+                                       v[n].bend = 1;
+                       }
+                       continue;       /* go to next loop iteration */
+               }
+
+               /*
+                * Find the equation of the previous segment.  Plug the
+                * following point's x into that equation to get where its y
+                * would have been if the angle were 180.  Comparing that y to
+                * the actual y, we can determine the bend direction.
+                */
+               slope = (v[n].y - v[n-1].y) / (v[n].x - v[n-1].x);
+               intercept = v[n-1].y - slope * v[n-1].x;
+               temp = slope * v[n+1].x + intercept;
+
+               if (v[n].x > v[n-1].x) {
+                       if (v[n+1].y < temp)
+                               v[n].bend = 1;
+                       else
+                               v[n].bend = -1;
+               } else {
+                       if (v[n+1].y < temp)
+                               v[n].bend = -1;
+                       else
+                               v[n].bend = 1;
+               }
+       }
+
+       /*
+        * At the endpoints, there is only one segment, so no angle or bend
+        * direction is defined.  But we need to have something.  So we semi-
+        * arbitrarily set these to the same value as their neighboring points.
+        */
+       v[0].ang = v[1].ang;
+       v[0].bend = v[1].bend;
+       v[num-1].ang = v[num-2].ang;
+       v[num-1].bend = v[num-2].bend;
+
+       /*
+        * For all points, set the slope of the line tangent to the curves
+        * we're going to draw, in the coordinate system where the segment
+        * starting at this point is horizontal.  (This is the coordinate
+        * system that findcontrol() uses.)  Since the angle between segments
+        * is not allowed to be 0, this slope is never vertical (infinity).
+        */
+       for (n = 0; n < num; n++)
+               v[n].slopetan = -v[n].bend * tan( v[n].ang / 2 + PI / 2);
+
+       /*
+        * For each segment, calculate control points to define a Bezier curve
+        * connecting the endpoints, according to the specifications.
+        */
+       for (n = 0; n < num - 1; n++)
+               findcontrol(v, n);
+}
+\f
+/*
+ * Name:        findcontrol()
+ *
+ * Abstract:    Find Bezier control points for one segment of the curve.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given an array of CURVEINFOs, one for each
+ *             point, with everything filled in except the control points.  It
+ *             calculates them and fills them in.
+ */
+
+
+static void
+findcontrol(v, n)
+
+struct CURVEINFO v[];
+int n;
+
+{
+       float costheta, sintheta;       /* for rotating axes by theta */
+
+       /*
+        * All of the following variables refer to the rotated/translated
+        * position of the segment (see comment below).  Point 0 is the
+        * starting point, point 3 is the ending point, and points 1 and 2
+        * are the Bezier control points.
+        */
+       float x1, x2, y1, y2;   /* control points */
+       float x3;               /* end point (y3 is always 0) */
+       float slope0, slope3;   /* slope of tangent lines at endpoints */
+       float b, c;             /* some coefficients of cubic y = f(x) */
+       float cx, by, cy;       /* Bezier coefficients */
+
+
+       /*
+        * Rotate and translate the axes so that the starting point (point 0)
+        * is at the origin, and the ending point (3) is on the positive
+        * x axis.  Their coords are (0, 0) and (v[n].len, 0).  We are going
+        * to find a cubic equation that intersects the endpoints, and has the
+        * necessary slope at those points such that the tangent line's slope
+        * is halfway between horizontal (this segment) and the slope of the
+        * neighboring segment.  The equation is
+        *      y  =  a x^3  +  b x^2  +  c x  +  d
+        * so the slope is
+        *      y' =  3 a x^2  +  2 b x  +  c
+        * By plugging the two points into these, you get 4 equations in the 4
+        * unknowns a, b, c, d.
+        */
+       x3 = v[n].len;
+
+       /* find the slope of the tangent lines at the first & second points */
+       slope0 = v[n].slopetan;
+       slope3 = -v[n+1].slopetan;
+
+       /* set values of a, b, c (d turns out to be always 0) */
+       /* a = (slope0 + slope3) / SQUARED(x3); don't really need this one */
+       b = (-2 * slope0 - slope3) / x3;
+       c = slope0;
+
+       /*
+        * For Bezier version of this, let x = t / x3, and for y, plug this
+        * into the cubic we have found.  This gives us the Bezier coeff.:
+        *      x = ax t^3  +  bx t^2  +  cx t  +  x0
+        *      y = ay t^3  +  by t^2  +  cy t  +  y0
+        */
+       /* ax and bx are always 0 */
+       cx = x3;
+       /* ay = a * CUBED(x3);          this one is not needed */
+       by = b * SQUARED(x3);
+       cy = c * x3;
+
+       /* get control points 1 and 2 from Bezier coefficients & endpoints */
+       x1 = cx / 3;
+       y1 = cy / 3;
+       x2 = x1 + cx / 3;
+       y2 = y1 + (by + cy) / 3;
+
+       /*
+        * Rotate and translate the axes back to where they really were.  Store
+        * these real positions of the control points.
+        */
+       costheta = (v[n+1].x - v[n].x) / v[n].len;
+       sintheta = (v[n+1].y - v[n].y) / v[n].len;
+
+       v[n].x1 = v[n].x + x1 * costheta - y1 * sintheta;
+       v[n].x2 = v[n].x + x2 * costheta - y2 * sintheta;
+       v[n].y1 = v[n].y + y1 * costheta + x1 * sintheta;
+       v[n].y2 = v[n].y + y2 * costheta + x2 * sintheta;
+}
+\f
+
+/* draw a V-shaped bend indicator by drawing two line segments */
+
+void
+pr_bend(crvlist_p)
+
+struct CRVLIST *crvlist_p;
+
+{
+       if (crvlist_p == (struct CRVLIST *) 0
+                       || crvlist_p->next == (struct CRVLIST *) 0
+                       || crvlist_p->next->next == (struct CRVLIST *) 0) {
+               pfatal("invalid bend crvlist");
+       }
+
+       do_linetype(L_NORMAL);
+       draw_line(crvlist_p->x, crvlist_p->y, crvlist_p->next->x, crvlist_p->next->y);
+       draw_line(crvlist_p->next->x, crvlist_p->next->y,
+                       crvlist_p->next->next->x, crvlist_p->next->next->y);
+}
+\f
+
+/* draw a slide for a tab or tabnote staff. Slides are stored internally
+ * like slurs. Here we just draw a line between the appropriate coordinates */
+
+void
+pr_tabslur(crvlist_p, ts_style)
+
+struct CRVLIST *crvlist_p;
+int ts_style;
+
+{
+       if (crvlist_p == (struct CRVLIST *) 0
+                               || crvlist_p->next == (struct CRVLIST *) 0) {
+               pfatal("invalid tabslur crvlist");
+       }
+
+       do_linetype(ts_style);
+       draw_line(crvlist_p->x, crvlist_p->y, crvlist_p->next->x, crvlist_p->next->y);
+}
+\f
+
+/* print a small curve to indicate a 1/4 step bend on a tabnote */
+
+void
+pr_sm_bend(x, y)
+
+double x, y;   /* where to start the curve. This is the bottom left end */
+
+{
+       float xlist[4], ylist[4];       /* coordinates of the curve */
+
+
+       /* fill in the relative horizontal and vertical offsets. These
+        * are hand picked to give a nice looking curve */
+       xlist[0] = x;
+       ylist[0] = y;
+       xlist[1] = x + 0.5 * STEPSIZE;
+       ylist[1] = y + 0.2 * STEPSIZE;
+       xlist[2] = x + 1.2 * STEPSIZE;
+       ylist[2] = y + 1.2 * STEPSIZE;
+       xlist[3] = x + 1.3 * STEPSIZE;
+       ylist[3] = y + 1.75 * STEPSIZE;
+
+       /* now print the curve */
+       pr_allcurve(xlist, ylist, 4, W_NORMAL, NO);
+}
+\f
+
+/* Print 'atend' grids */
+
+void
+pr_atend()
+
+{
+       float x;                /* of first grid of row */
+       float y;                /* of row; top line of grid */
+       float gridx;            /* x of grid being printed */
+       float north;            /* of the grid */
+       float space;            /* distance between grid lines */
+       struct GRID *grid_p;
+       int g;                  /* index through grid_p array */
+       int staff = -1;         /* always -1 to indicate atend. Using a
+                                * variable rather than hard-coding where
+                                * used just on general principles. */
+       int column;             /* how many columns printed so far in row */
+       int rows_to_print;      /* how many rows to print per page. */
+       struct MAINLL *main_feed_p;     /* for getting top/bottom blocks */
+       struct FEED *feed_p;    /* for getting top/bottom blocks */
+
+
+       x = Atend_info.firstgrid_x;
+       y = Atend_info.firstgrid_y;
+       rows_to_print = Atend_info.rows_per_page;
+       space = gridspace(staff);
+       column = 0;
+
+       /* Find the last FEED. We use that to get top/bottom blocks */
+       for (main_feed_p = Mainlltc_p; main_feed_p->str != S_FEED;
+                                       main_feed_p= main_feed_p->prev) {
+               ;
+       }
+       feed_p = main_feed_p->u.feed_p;
+       for (g = 0; g < Atend_info.grids_used; g++) {
+               grid_p = Atend_info.grid_p[g];
+               gridsize(grid_p, staff, &north, (float *) 0, (float *) 0, (float *) 0);
+               /* calculate horizontal position of this grid */
+               gridx = x + column * Atend_info.horz_sep;
+
+               /* print the name of the grid */
+               pr_string(gridx - strwidth(grid_p->name) / 2.0,
+                               y + north + strdescent(grid_p->name),
+                               grid_p->name, J_LEFT, (char *) 0, -1);
+
+               /* print the grid itself */
+               do_grid(gridx - space * (grid_p->numstr - 1) / 2.0,
+                                       y, space, grid_p, staff);
+
+               if (++column >= Atend_info.grids_per_row &&
+                               g < Atend_info.grids_used - 1) {
+                       /* move to next row */
+                       column = 0;
+                       y -= Atend_info.vert_sep;
+                       rows_to_print--;
+                       if (Atend_info.separate_page == YES &&
+                                               rows_to_print <= 0) {
+                               rows_to_print = Atend_info.rows_per_page;
+                               y = Atend_info.firstgrid_y;
+                               /* print top/bottom blocks, if any */
+                               /* use *2 blocks for any subsequent pages */
+                               feed_p->top_p = feed_p->top2_p;
+                               feed_p->bot_p = feed_p->bot2_p;
+                               pr_feed(main_feed_p);
+                       }
+               }
+       }
+}
diff --git a/mup/mup/prnttab.c b/mup/mup/prnttab.c
new file mode 100644 (file)
index 0000000..c2d98c3
--- /dev/null
@@ -0,0 +1,886 @@
+/* Copyright (c) 1997, 1998, 1999, 2001, 2003, 2004 by Arkkra Enterprises */
+/* All rights reserved. */
+
+/* functions to support printing of tab staffs */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+/* position of the last bend arrow for each staff, or 0.0 if no
+ * arrow on previous group */
+static double Last_x_arrow[MAXSTAFFS + 1], Last_y_arrow[MAXSTAFFS + 1];
+
+static double pr_tab_note P((int note_index, struct GRPSYL *gs_p,
+               double y_adjust, struct MAINLL *mll_p));
+static double pr_bstring P((struct GRPSYL *gs_p, struct NOTE *note_p,
+               int note_index, double y_adjust, struct MAINLL *mll_p));
+static void pr_b_arrow P((struct GRPSYL *gs_p, struct MAINLL *mll_p,
+               double y_adjust));
+static void pr_b_curve P((float *xlist, float *ylist, struct GRPSYL *gs_p,
+               double y_adjust));
+static void pr_arrowhead P((struct GRPSYL *gs_p, double y_adjust, int headchar));
+static int bends_up P((struct GRPSYL *gs_p, int n, struct GRPSYL *pgs_p,
+               int carried_in));
+static int is_carried_in_bend P((struct MAINLL *mll_p,
+               struct MAINLL *prev_mll_p));
+\f
+
+
+/* given a GRPSYL list for a tab staff, print all the notes in the list */
+
+void
+pr_tab_groups(gs_p, mll_p)
+
+struct GRPSYL *gs_p;
+struct MAINLL *mll_p;
+
+{
+       int n;
+       double y_adjust;        /* to account for bend string space */
+       struct GRPSYL *ngs_p;   /* next group */
+       struct MAINLL *m_p;
+
+
+       /* go through the list of groups */
+       for (  ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+
+               /* if inhibitprint flag is set (because this is a tied-to
+                * group), skip this group */
+               if (gs_p->inhibitprint == YES) {
+                       continue;
+               }
+
+               /* measure repeats are special */
+               if (is_mrpt(gs_p) == YES) {
+                       pr_mrpt(gs_p, mll_p->u.staff_p);
+                       continue;
+               }
+
+               /* multirests are special. Print on tab staff only if its
+                * corresponding tabnote staff is not printed */
+               if (gs_p->basictime < -1) {
+                       if (svpath(gs_p->staffno - 1, VISIBLE)->visible == NO) {
+                               pr_multirest(gs_p, mll_p->u.staff_p);
+                       }
+                       continue;
+               }
+
+               /* print the fret number and bend string
+                * for each note in the group. The
+                * y_adjust gets changed to account for space taken up
+                * by bend text strings */
+               y_adjust = 0.0;
+               for (n = 0; n < gs_p->nnotes; n++) {
+                       y_adjust = pr_tab_note(n, gs_p, y_adjust, mll_p);
+               }
+
+               /* if there were any bends, draw the arrow. Otherwise
+                * remember that there are no bends in progress */
+               if (y_adjust > 0.0) {
+                       pr_b_arrow(gs_p, mll_p, y_adjust);
+               }
+               else {
+                       Last_y_arrow[gs_p->staffno] = 0.0;
+                       Last_x_arrow[gs_p->staffno] = 0.0;
+               }
+
+               /* print any slashes */
+               if (gs_p->slash_alt > 0) {
+                       /* slashes on tab staff get hard-coded
+                        * tilt value of 2.2 * Stdpad. */
+                       if (gs_p->stemdir == UP) {
+                               pr_slashes(gs_p, (double) gs_p->c[AX],
+                                       (double) (gs_p->notelist[gs_p->nnotes - 1].c[AY]
+                                       + gs_p->stemlen), (double) -1.0,
+                                       (double) 0.0, (double) (2.2 * Stdpad));
+                       }
+                       else {
+                               pr_slashes(gs_p, (double) gs_p->c[AX],
+                                       (double) (gs_p->notelist[0].c[AY]
+                                       - gs_p->stemlen), (double) 1.0,
+                                       (double) 0.0, (double) (2.2 * Stdpad));
+                       }
+               }
+
+               if (gets_roll(gs_p, mll_p->u.staff_p, 0) == YES) {
+                       print_roll(gs_p);
+               }
+
+               /* print any "with" list items */
+               pr_withlist(gs_p);
+
+               /* on last group in measure, have to look ahead to next group
+                * if any to see if it has a bend from this note and is on
+                * the next score. If so, have to draw a horizontal line for
+                * the bend out to near the end of the current score */
+               if (gs_p->next == (struct GRPSYL *) 0) {
+                       /* is the last group in the measure. See if we are
+                        * at a scorefeed. First search for end of current
+                        * measure. */
+                       for (m_p = mll_p; m_p != (struct MAINLL *) 0 &&
+                                       m_p->str != S_BAR; m_p = m_p->next) {
+                               ;
+                       }
+
+                       /* now go until we find either a feed or a staff */
+                       for (     ; m_p != (struct MAINLL *) 0;
+                                                       m_p = m_p->next) {
+                               if (m_p->str == S_FEED || m_p->str == S_STAFF) {
+                                       break;
+                               }
+                       }
+                       if (m_p == (struct MAINLL *) 0 || m_p->str != S_FEED) {
+                               /* no next group or not at a scorefeed */
+                               continue;
+                       }
+
+                       /* See if there is another group in the next measure */
+                       if ((ngs_p = nextgrpsyl(gs_p, &mll_p))
+                                               == (struct GRPSYL *) 0) {
+                               /* no next group */
+                               continue;
+                       }
+                       if (ngs_p->nnotes == 0) {
+                               continue;
+                       }
+
+                       for (n = 0; n < ngs_p->nnotes; n++) {
+                               if (HASREALBEND(ngs_p->notelist[n]) &&
+                                       ngs_p->notelist[n].FRETNO == NOFRET) {
+                                       /* next group has a real, non-prebend
+                                        * bend, so have to deal with it */
+                                       break;
+                               }
+                               else if (HASNULLBEND(ngs_p->notelist[n])) {
+                                       /* has null bend. have to do this one */
+                                       break;
+                               }
+                       }
+                       if (n == ngs_p->nnotes) {
+                               /* no non-prebend bend */
+                               continue;
+                       }
+
+                       /* if we got here, this is the special case where we
+                        * do need to draw the line, so do it */
+                       do_linetype(L_NORMAL);
+                       if (Last_y_arrow[gs_p->staffno] != 0.0) {
+                               draw_line( (double) (Last_x_arrow[gs_p->staffno]),
+                                       (double) (Last_y_arrow[gs_p->staffno]),
+                                       (double) (PGWIDTH
+                                       - eff_rightmargin(mll_p) - Stepsize),
+                                       (double) (Last_y_arrow[gs_p->staffno]));
+                               Last_x_arrow[gs_p->staffno] =
+                                       PGWIDTH - eff_rightmargin(mll_p)
+                                       - Stepsize;
+                       }
+                       else {
+                               /* the bend is on the next score, but not a
+                                * continuation bend. so draw an arrow towards
+                                * the margin, followed by a short
+                                * dashed line */
+                               float xlist[6], ylist[6];  /* curve coords */
+                               struct GRPSYL dummy_gs;  /* for curve end */
+
+
+                               /* set place for beginning of curve */
+                               xlist[0] = gs_p->notelist[n].c[AX] + Stdpad +
+                                       notehorz(gs_p, &(gs_p->notelist[n]), RE);
+                               ylist[0] = gs_p->notelist[n].c[AY];
+
+                               /* fill in a dummy GRPSYL struct with just
+                                * the pieces of information that pr_b_curve
+                                * will need to draw a bend curve */
+                               dummy_gs.c[AX] =  PGWIDTH
+                                               - eff_rightmargin(mll_p)
+                                               - 2.5 * Stepsize;
+                               dummy_gs.c[AN] = ylist[0] + 2.4 * Stepsize
+                                                       * TABRATIO;
+                               /* if we're too close to the margin, make the
+                                * curve a little longer, so it will look
+                                * decent, even if it runs into the margin
+                                * a little ways */
+                               if (dummy_gs.c[AX] - xlist[0]
+                                                       < 3.0 * Stepsize) {
+                                       dummy_gs.c[AX] = 3.0 * Stepsize;
+                                       /* If that still didn't move it enough
+                                        * to avoid having the bend backwards,
+                                        * adjust some more */
+                                       if (dummy_gs.c[AX] - xlist[0]
+                                                       < 2.0 * Stepsize) {
+                                               dummy_gs.c[AX] = xlist[0]
+                                                       + 2.0 * Stepsize;
+                                       }  
+                               }
+
+                               /* draw the curve */
+                               pr_b_curve(xlist, ylist, &dummy_gs, 0.0);
+
+                               /* draw an arrow at the end of the curve */
+                               pr_muschar( (double) dummy_gs.c[AX],
+                                       (double) (dummy_gs.c[AN] -
+                                       (height(FONT_MUSIC, DFLT_SIZE, C_UWEDGE)
+                                       / 2.0)), C_UWEDGE, DFLT_SIZE, FONT_MUSIC);
+
+                               /* draw a short dashed line to the right
+                                * from the arrow, to indicate the actual
+                                * bend is on the next score */
+                               do_linetype(L_DASHED);
+                               ylist[5] += 2.0 * Stdpad;
+                               draw_line( (double) xlist[5] + Stdpad,
+                                       (double) ylist[5],
+                                       (double) xlist[5] + 3.5 * Stepsize,
+                                       (double) ylist[5]);
+                       }
+               }
+       }
+}
+\f
+
+/* print things for a tab staff note. Return any adjustment to North needed
+ * to account for bend string */
+
+static double
+pr_tab_note(note_index, gs_p, y_adjust, mll_p)
+
+int note_index;                /* which note in gs_p */
+struct GRPSYL *gs_p;
+double y_adjust;       /* to account for bend string space */
+struct MAINLL *mll_p;  /* main list struct pointing to gs_p */
+
+{
+       struct NOTE *note_p;
+       char *fretstr;  /* text string to print for fret number */
+
+       note_p = &(gs_p->notelist[note_index]);
+
+       /* print fret number (with parentheses if appropriate) */
+       fretstr = fret_string(note_p, gs_p);
+       if ( *fretstr != '\0') {
+
+               if (vvpath(gs_p->staffno, gs_p->vno, TABWHITEBOX)->tabwhitebox == YES) {
+                       /* Put a white box behind the number, so the line
+                        * doesn't go through it, making it easier to read. */
+                       do_whitebox( note_p->c[AX] - strwidth(fretstr) / 2.0,
+                               note_p->c[AY] - strheight(fretstr) / 2.0,
+                               note_p->c[AX] + strwidth(fretstr) / 2.0,
+                               note_p->c[AY] + strheight(fretstr) / 2.0);
+               }
+
+               pr_string( (double) (note_p->c[AX] - (strwidth(fretstr) / 2.0)),
+                       (double) (note_p->c[AY] + (strheight(fretstr) / 2.0)
+                       - strascent(fretstr)),
+                       fretstr, J_LEFT, gs_p->inputfile, gs_p->inputlineno);
+       }
+
+       /* print a bend string if appropriate */
+       if ( HASBEND((*note_p)) ) {
+               if (HASREALBEND(*note_p)) {
+                       y_adjust += pr_bstring(gs_p, note_p, note_index,
+                                                       y_adjust, mll_p);
+               }
+               else {
+                       /* need to return a little bit, so later code
+                        * knows that there was a bend of some sort */
+                       if (y_adjust == 0.0) {
+                               y_adjust = STDPAD;
+                       }
+               }
+       }
+       return (y_adjust);
+}
+\f
+
+/* print the bend string ("full", "1/2", etc). Return its height */
+
+static double
+pr_bstring(gs_p, note_p, note_index, y_adjust, mll_p)
+
+struct GRPSYL *gs_p;   /* group having a bend */
+struct NOTE *note_p;   /* which note in gs_p has the bend */
+int note_index;                /* index into gs_p->notelist of note_p */
+double y_adjust;       /* to account for bend strings done previously
+                        * for this group (on other notes in the group */
+struct MAINLL *mll_p;  /* main list struct pointing to gs_p */
+
+{
+       char *bstring;
+       double x_adjust;        /* to center upward and left justify
+                                * downward, to not collide with curve */
+       struct GRPSYL *pgs_p;   /* previous group */
+       int n;                  /* index through notelist */
+
+
+       /* get what to print for the bend */
+       bstring = bend_string(note_p);
+
+       /* generally, the string should be centered. */
+       x_adjust = strwidth(bstring) / 2.0;
+
+       /* However, if not a prebend and the bend is downward,
+        * then we have to move the bend string over so it 
+        * doesn't collide with the curve. So first get the previous group
+        * and see it is has a bend too. If it does, see if the bend is
+        * downward, and if so, change to left justify rather than center */
+       if (note_p->FRETNO == NOFRET && (pgs_p = prevgrpsyl(gs_p, &mll_p))
+                                               != (struct GRPSYL *) 0) {
+
+               for (n = 0; n < pgs_p->nnotes; n++) {
+                       if (pgs_p->notelist[n].STRINGNO
+                                       == gs_p->notelist[note_index].STRINGNO
+                                       && HASBEND(pgs_p->notelist[n])) {
+                               if (bends_up(gs_p, note_index, pgs_p, NO) == NO) {
+                                       x_adjust = 0.0;
+                               }
+                       }
+               }
+       }
+
+       /* print the bend string */
+       pr_string( (double) (gs_p->c[AX] - x_adjust),
+                       (double) (gs_p->c[AN] - strascent(bstring) - y_adjust),
+                       bstring, J_LEFT, gs_p->inputfile, gs_p->inputlineno);
+
+       /* return the height of what was just printed */
+       return(strheight(bstring));
+}
+\f
+
+/* print bend arrow */
+
+static void
+pr_b_arrow(gs_p, mll_p, y_adjust)
+
+struct GRPSYL *gs_p;
+struct MAINLL *mll_p;
+double y_adjust;
+
+{
+       struct GRPSYL *pgs_p;           /* previous grpsyl */
+       struct MAINLL *prev_mll_p;      /* where pgs_p is connected */
+       float xlist[6], ylist[6];       /* coords of bend curve */
+       int n;                          /* note index */
+       int staffno;
+       int carried_in;                 /* YES if bend is carried in */
+
+
+       staffno = gs_p->staffno;
+
+       /* leave a little room between bend string and the arrow. This is
+        * especially needed when bending down, so the string and curve
+        * don't collide */
+       y_adjust += 2.0 * Stdpad;
+
+       /* find the first note with a bend on it */
+       for (n = 0; n < gs_p->nnotes; n++) {
+               if (HASBEND(gs_p->notelist[n])) {
+                       break;
+               }
+       }
+
+       /* the function isn't supposed to get called unless there really
+        * is a bend somewhere on the group */
+       if (n == gs_p->nnotes) {
+               pfatal("pr_b_arrow couldn't find note with bend");
+       }
+
+       /* check if prebend or non-prebend */
+       if (gs_p->notelist[n].FRETNO != NOFRET
+                               && ! HASNULLBEND(gs_p->notelist[n])) {
+               /* this is a prebend */
+               /* draw the line straight up from the fret number */
+               do_linetype(L_NORMAL);
+               draw_line( (double) (gs_p->c[AX]),
+                       (double) (gs_p->notelist[n].c[AN] + Stdpad),
+                       (double) (gs_p->c[AX]),
+                       (double) (gs_p->c[AN] - y_adjust));
+
+               /* draw triangle at top */
+               pr_arrowhead(gs_p, y_adjust, C_UWEDGE);
+               return;
+       }
+
+       /* a normal bend, not a prebend */
+       prev_mll_p = mll_p;
+       if ((pgs_p = prevgrpsyl(gs_p, &prev_mll_p)) == (struct GRPSYL *) 0) {
+               l_ufatal(gs_p->inputfile, gs_p->inputlineno,
+                               "no previous chord for bend");
+       }
+
+       carried_in = is_carried_in_bend(mll_p, prev_mll_p);
+
+       if (Last_y_arrow[staffno] == 0.0) {
+               /* not the continuation of an in-progress bend */
+
+               /* do each note that has a bend */
+               for (n = 0; n < gs_p->nnotes; n++) {
+                       if ( ! HASBEND(gs_p->notelist[n])) {
+                               continue;
+                       }
+
+                       if ((mll_p != prev_mll_p && pgs_p->c[AE] > gs_p->c[AX])
+                                       || carried_in == YES) {
+
+                               /* either an intervening scorefeed or
+                                * carried in to subsequent ending,
+                                * so just start a bit west
+                                * of the current group */
+                               xlist[0] = gs_p->c[AW] - 2.0 * Stepsize;
+                               ylist[0] = gs_p->c[AY] +
+                                               gs_p->notelist[n].stepsup
+                                               * Stepsize * TABRATIO;
+                       }
+                       else {
+                               /* beginning of bend arrow is at east
+                                * and just a bit
+                                * above the center of the fret number
+                                * of the previous group */
+                               xlist[0] = pgs_p->c[AE] + Stdpad;
+                               ylist[0] = gs_p->notelist[n].c[AY] + Stdpad;
+                       }
+
+                       pr_b_curve(xlist, ylist, gs_p, y_adjust);
+               }
+               pr_arrowhead(gs_p, y_adjust, C_UWEDGE);
+       }
+       else {
+               /* continuation of an in-progress bend */
+
+               /* find the note that has a bend. Only allowed to be
+                * one note with a continuation bend, or could be a release,
+                * in which case we use the first note we find */
+               for (n = 0; n < gs_p->nnotes; n++) {
+                       if ( HASBEND(gs_p->notelist[n])) {
+                               break;
+                       }
+               }
+               if (n == gs_p->nnotes) {
+                       pfatal("unable to find note with continuation bend");
+               }
+
+               /* find the starting point of the bend curve */
+               if ((mll_p != prev_mll_p && pgs_p->c[AE] > gs_p->c[AX])
+                                       || carried_in == YES) {
+
+                       /* must have been an intervening scorefeed,
+                        * so just start a bit west
+                        * of the current group */
+                       xlist[0] = gs_p->c[AW] - 2.0 * Stepsize;
+                       Last_y_arrow[staffno] = gs_p->c[AN] - y_adjust;
+
+                       /* need to adjust more if bending is actually up */
+                       if (bends_up(gs_p, n, pgs_p, carried_in)) {
+                               Last_y_arrow[staffno] -= 3.0 * Stepsize;
+                       }
+
+                       /* null bends carried over a scorefeed
+                        * have to be done specially */
+                       if (HASNULLBEND(gs_p->notelist[n])) {
+                               Last_y_arrow[staffno] = gs_p->notelist[n].c[AN]
+                                       + (2 * gs_p->notelist[n].STRINGNO
+                                       * Stepsize * TABRATIO);
+                               if (gs_p->notelist[n].STRINGNO == 0) {
+                                       Last_y_arrow[staffno] += 2.0 * Stepsize
+                                                        * TABRATIO;
+                               }
+                       }
+               }
+               else {
+                       /* beginning of bend curve is where last
+                        * one left off */
+                       xlist[0] = Last_x_arrow[staffno];
+               }
+               ylist[0] = Last_y_arrow[staffno];
+
+               /* determine whether curve goes up or down
+                * and find its endpoint */
+               if (bends_up(gs_p, n, pgs_p, carried_in) == YES) {
+                       /* bending up some more */
+                       pr_b_curve(xlist, ylist, gs_p, y_adjust);
+                       pr_arrowhead(gs_p, y_adjust, C_UWEDGE);
+               }
+               else { /* bending back downwards */
+
+                       if ( ! HASREALBEND(gs_p->notelist[n])) {
+                               /* null bend. Have to draw curve all the way
+                                * down to the appropriate "note" */
+                               y_adjust = gs_p->c[AN] -
+                                       gs_p->notelist[n].c[AN] - Stdpad -
+                                       height(FONT_MUSIC, DFLT_SIZE, C_WEDGE)
+                                       / 2.0;
+                       }
+                       pr_b_curve(xlist, ylist, gs_p, y_adjust);
+                       pr_arrowhead(gs_p, y_adjust, C_WEDGE);
+               }
+       }
+}
+\f
+
+/* given the first point of a bend curve, plus the gs_p and y adjustment for
+ * the end of the curve, figure out the points of the curve and draw it */
+
+static void
+pr_b_curve(xlist, ylist, gs_p, y_adjust)
+
+float *xlist;  /* arrays of x & y coordinates, with 6 members */
+float *ylist;
+struct GRPSYL *gs_p;
+double y_adjust;       /* how far from the north of the gs_p the curve is */
+
+{
+       float xlen, ylen;
+
+
+       /* last point of bend arrow is just below
+        * the bend string */
+       xlist[5] = gs_p->c[AX];
+       ylist[5] = gs_p->c[AN] - y_adjust - Stdpad;
+
+       /* fill in intermediate points */
+       xlen = xlist[5] - xlist[0];
+       ylen = ylist[5] - ylist[0];
+       xlist[1] = xlist[0] + xlen * 0.15;
+       ylist[1] = ylist[0];
+       xlist[2] = xlist[0] + xlen * 0.7;
+       ylist[2] = ylist[0] + ylen * 0.2;
+       xlist[3] = xlist[5] - xlen * 0.2;
+       ylist[3] = ylist[5] - ylen * 0.7;
+       xlist[4] = xlist[5];
+       ylist[4] = ylist[5] - ylen * 0.15;
+
+       /* draw the curve */
+       do_linetype(L_NORMAL);
+       pr_allcurve(xlist, ylist, 6, W_NORMAL, NO);
+}
+\f
+
+/* print arrowhead at the end of a bend curve */
+
+static void
+pr_arrowhead(gs_p, y_adjust, headchar)
+
+struct GRPSYL *gs_p;
+double y_adjust;
+int headchar;  /* C_WEDGE or C_UWEDGE */
+
+{
+       pr_muschar( (double) gs_p->c[AX],
+               (double) (gs_p->c[AN] - y_adjust -
+               (height(FONT_MUSIC, DFLT_SIZE, headchar) / 2.0)),
+               headchar, DFLT_SIZE, FONT_MUSIC);
+
+       Last_y_arrow[gs_p->staffno] = gs_p->c[AN] - y_adjust;
+       Last_x_arrow[gs_p->staffno] = gs_p->c[AX];
+}
+\f
+
+/* given a GRPSYL that has a continuation bend, or is a carried-in bend,
+ * return YES if it is bending
+ * upwards from the previous bend, NO if not */
+
+static int
+bends_up(gs_p, n, pgs_p, carried_in)
+
+struct GRPSYL *gs_p;   /* group having a continuation bend */
+int n;                 /* the note index in gs_p having the bend */
+struct GRPSYL *pgs_p;  /* previous group */
+int carried_in;                /* YES if bend is carried in */
+
+{
+       RATIONAL thisgrp_bend;  /* rational version of bend on this group */
+       RATIONAL prevgrp_bend;  /* rational version of bend on previous group */
+       int i;                  /* index through pgs_p notes */
+
+
+       if (gs_p == (struct GRPSYL *) 0 || pgs_p == (struct GRPSYL *) 0) {
+               pfatal("null pointer passed to bends_up");
+       }
+
+       /* get rational version of the bend distance on continuation note */
+       thisgrp_bend = ratbend( &(gs_p->notelist[n]) );
+
+       /* find the corresponding note in the previous group */
+       for (i = 0; i < pgs_p->nnotes; i++) {
+               if (pgs_p->notelist[i].STRINGNO == gs_p->notelist[n].STRINGNO) {
+                       break;
+               }
+       }
+       if (i == pgs_p->nnotes) {
+               pfatal("couldn't find the note being bent from");
+       }
+
+       /* get rational version of that bend */
+       if ( ! HASBEND(pgs_p->notelist[i]) ) {
+               /* if this is a carried-in bend, it may not be a continuation
+                * bend, but in that case, it has to be bending up */
+               if (carried_in == YES) {
+                       return(YES);
+               }
+               else {
+                       l_ufatal(gs_p->inputfile, gs_p->inputlineno,
+                               HASNULLBEND(gs_p->notelist[n]) ?
+                               "bend release not preceded by a bend" :
+                               "no bend on note supposedly being bent from");
+               }
+       } 
+       prevgrp_bend = ratbend( &(pgs_p->notelist[i]) );
+
+       /* compare the bends */
+       if (GT(thisgrp_bend, prevgrp_bend)) {
+               return(YES);
+       }
+       else if (LT(thisgrp_bend, prevgrp_bend)) {
+               return(NO);
+       }
+       else {
+               l_ufatal(gs_p->inputfile, gs_p->inputlineno,
+                       "can't bend to the same distance as previous bend");
+               /*NOTREACHED*/
+               return(NO);
+       }
+}
+\f
+
+/* Return YES if the bend is carried in to a subsequent ending, NO if just
+ * an ordinary bend.
+ */
+
+static int
+is_carried_in_bend(mll_p, prev_mll_p)
+
+struct MAINLL *mll_p;          /* where group with a bend is attached */
+struct MAINLL *prev_mll_p;     /* where the previous group is attached */
+
+{
+       int num_startitems;     /* how many endingloc==STARTITEM were found */
+
+
+       /* if both groups are in the same measure, then it's definitely
+        * not a carried in bend */
+       if (mll_p == prev_mll_p) {
+               return(NO);
+       }
+
+       /* go forward from prev_mll_p until we get to mll_p. If we encounter
+        * more than 1 STARTITEM in endingloc, checking both normal and
+        * pseudo bars, then this was a carried in bend. */
+       num_startitems = 0;
+       for (   ; prev_mll_p != (struct MAINLL *) 0 && prev_mll_p != mll_p;
+                                       prev_mll_p = prev_mll_p->next) {
+
+               switch (prev_mll_p->str) {
+
+               case S_BAR:
+                       if (prev_mll_p->u.bar_p->endingloc == STARTITEM) {
+                               if (++num_startitems > 1) {
+                                       /* it is carried in bend */
+                                       return(YES);
+                               }
+                       }
+                       break;
+
+               case S_CLEFSIG:
+                       if (prev_mll_p->u.clefsig_p->bar_p != (struct BAR *) 0) {
+                               if (prev_mll_p->u.clefsig_p->bar_p->endingloc
+                                                       == STARTITEM) {
+                                       if (++num_startitems > 1) {
+                                               return(YES);
+                                       }
+                               }
+                       }
+                       break;
+
+               default:
+                       /* nothing else is relevant at this point */
+                       break;
+               }
+       }
+
+       /* fell out without finding 2 STARTITEMS, so not carried in */
+       return(NO);
+}
+\f
+
+/* given internal representation of bend info,
+ * return string representation. Returns string in
+ * static area that is overwritten on each call.
+ */
+
+char *
+bend_string(note_p)
+
+struct NOTE *note_p;
+
+{
+       static char buff[12];
+       int intpart, num, den;
+
+       /* separate internal representation into integer, numerator,
+        * and denominator */
+       intpart = BENDINT(*note_p);
+       num = BENDNUM(*note_p);
+       den = BENDDEN(*note_p);
+
+       /* construct the string representation */
+       buff[0] = FONT_HR;
+       buff[1] = adj_size(DFLT_SIZE, Staffscale, (char *) 0, -1);
+
+       if (intpart == 1 && num == 0) {
+               (void) strcpy(buff+2, "full");
+       }
+       else if (intpart == 0 && num == 0) {
+               /* no bend at all */
+               buff[0] = '\0';
+       }
+       else if (num == 0) {
+               /* integer part only, no fraction */
+               (void) sprintf(buff+2, "%d", intpart);
+       }
+       else if (intpart == 0) {
+               /* fraction only */
+               (void) sprintf(buff+2, "%d/%d", num, den);
+       }
+       else {
+               /* both integer and fractional parts */
+               (void) sprintf(buff+2, "%d %d/%d", intpart, num, den);
+       }
+       return(buff);
+}
+\f
+
+/* given a NOTE on a tab staff, return char * of what is to be printed
+ * for the fret number. Returned string is a static area
+ * that is overwritten on each call.
+ */
+
+char *
+fret_string(note_p, gs_p)
+
+struct NOTE *note_p;
+struct GRPSYL *gs_p;   /* group containing the note */
+
+{
+       static char fretbuff[8];
+       int size;
+
+
+       /* if no fret, return "" */
+       if (note_p->FRETNO == NOFRET) {
+               fretbuff[0] = '\0';
+               return(fretbuff);
+       }
+
+       size = adj_size((note_p->notesize == GS_SMALL ? SMFRETSIZE : DFLT_SIZE),
+                       Staffscale, gs_p->inputfile, gs_p->inputlineno);
+
+       /* make proper string for X-note or normal fret number, in parentheses
+        * if appropriate */
+       if (IS_MUSIC_FONT(note_p->headfont)) {
+               (void) sprintf(fretbuff,
+                       (note_p->FRET_HAS_PAREN ? "%c%c(%c%c%c)" : "%c%c%c%c%c"),
+                               FONT_HB, size, mfont2str(note_p->headfont),
+                               size, note_p->headchar);
+       }
+       else {
+               (void) sprintf(fretbuff,
+                       (note_p->FRET_HAS_PAREN ? "%c%c(%d)" : "%c%c%d"),
+                       FONT_HB, size, note_p->FRETNO);
+       }
+       return(fretbuff);
+}
+\f
+
+/* print a TAB "clef" which is really just the word "TAB" written vertically.
+ * By convention, this only gets printed once per staff at the very beginning
+ * of the song. To keep things simple, the width of the clef is always 
+ * returned as if the clef was printed even when it really isn't */
+
+double
+pr_tabclef(staffno, x, really_print, size)
+
+int staffno;
+double x;
+int really_print;
+int size;
+
+{
+       static int did_tab_clef[MAXSTAFFS + 1]; /* set to YES once we print a
+                        * TAB clef on a given staff. Convention is to print
+                        * this "clef" only at the very beginning of a song. */
+       int stafflines;
+       int ptsize;     /* point size to use for "TAB" */
+       double width, widest;   /* of the letters in "TAB" */
+       double height = 0.0;
+       char letter[4]; /* internal format version of one letter of "TAB" */
+       char *tabstr;   /* pointer through "TAB" */
+       double y = 0.0;
+
+
+       /* adjust the size based on how many stafflines there are */
+       stafflines = svpath(staffno, STAFFLINES)->stafflines;
+       if (stafflines < 4) {
+               ptsize = 7;
+       }
+       else if (stafflines == 4) {
+               ptsize = 13;
+       }
+       else if (stafflines == 5) {
+               ptsize = 16;
+       }
+       else {
+               ptsize = 20;
+       }
+
+       /* if small clef, adjust the size (actually, this shouldn't
+        * ever happen unless we change some other things some day, but this
+        * way we will be prepared if/when that happens). */
+       if (size != DFLT_SIZE) {
+               ptsize = (int) (ptsize * (size / DFLT_SIZE));
+       }
+       ptsize = adj_size(ptsize, Staffscale, (char *) 0, -1);
+
+       /* print/get width of "TAB" */
+       for (widest = 0, tabstr = "TAB"; *tabstr != '\0'; tabstr++) {
+
+               /* create internal format string for current letter */
+               (void) sprintf(letter, "%c%c%c", FONT_HB, ptsize, *tabstr);
+               /* get its width */
+               width = strwidth(letter);
+
+               /* save the widest letter width */
+               if (width > widest) {
+                       widest = width;
+               }
+
+               /* if we're really supposed to print,
+                * print this letter of "TAB" */
+               if (really_print == YES && did_tab_clef[staffno] == NO) {
+
+                       /* figure out where to place vertically */
+                       if (*tabstr == 'T') {
+                               /* place the top letter */
+                               height = strheight(letter);
+                               y = Staffs_y[staffno] + height / 2.0
+                                                               + Stdpad;
+                       }
+                       else {
+                               /* move subsequent letters down by height
+                                * of the previous */
+                               y -= height;
+                       }
+
+                       /* print the letter with a little space before */
+                       pr_string(x + 3.0 * Stdpad, y, letter, J_LEFT,
+                                                       (char *) 0, -1);
+               }
+       }
+
+       /* only print once per staff */
+       if (really_print == YES) {
+               did_tab_clef[staffno] = YES;
+       }
+
+       /* allow some space on either side */
+       return(widest + 6.0 * Stdpad);
+}
diff --git a/mup/mup/prolog.c b/mup/mup/prolog.c
new file mode 100644 (file)
index 0000000..605b782
--- /dev/null
@@ -0,0 +1,1769 @@
+/* Copyright 1995, 1996, 1997, 1998 by Arkkra Enterprises */
+
+#include <stdio.h>
+#include "globals.h"
+
+char *prolog_text[] = {
+       "% Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2004 by Arkkra Enterprises",
+       "% All rights reserved",
+       "",
+       "% Mup PostScript Prolog 5.3 for use with Mup 5.3",
+       "",
+       "% lwid is used as the width of a standard (thin) line in the music",
+       "% character definitions.",
+       "/lwid 70 def",
+       "/halflwid lwid 2 div def",
+       "",
+       "% Define the following for use in do_upshortnote, do_dnshortnote, and",
+       "% do_shortrest; it has to be done outside of the music font definition.",
+       "/utildict 10 dict def",
+       "utildict begin",
+       "       /setnumflags    {       /numflags       exch def } def",
+       "       /sethooksm1     {       /hooksm1        exch def } def",
+       "       /setoffsets     {       /offsets        exch def } def",
+       "       /setx           {       /x              exch def } def",
+       "       /sety           {       /y              exch def } def",
+       "end",
+       "",
+       "% Define a music character font.  Each music character is defined as if it",
+       "% were a normal ASCII character in a strange font where \"A\" looks like a",
+       "% treble clef, \"B\" looks like a bass clef, etc.",
+       "",
+       "/mfont0 100 dict def",
+       "mfont0 begin",
+       "       /FontType 3 def",
+       "       /FontMatrix [ .001 0 0 0.001 0 0 ] def",
+       "       /FontBBox [ -2000 -4030 2000 4030 ] def",
+       "       /FontName (Mfont0) def",
+       "",
+       "       % set up Encoding vector with standard names",
+       "       /Encoding 256 array def",
+       "       StandardEncoding Encoding copy",
+       "       pop",
+       "",
+       "       % the following definitions are used for quarter rests",
+       "       /topx -170 def /topy 950 def",
+       "       /cor1x 250 def /cor1y 450 def",
+       "       /cor2x -300 def /cor2y 200 def",
+       "       /cor3x 250 def /cor3y -400 def",
+       "",
+       "       % the following definitions are used for double sharps",
+       "       /limit 300 halflwid add def",
+       "       /off 70 def",
+       "       /inbendsmall limit 200 sub def",
+       "       /inbendbig limit 20 sub def",
+       "       /outbendsmall 100 def",
+       "       /outbendbig outbendsmall off add def",
+       "",
+       "       %%%%% define routines that will be used by multiple characters %%%%%",
+       "       /do_1n {",
+       "               gsave",
+       "               newpath -10 rotate 1.6 1 scale",
+       "               0 0 325 0 360 arc               %outer ellipse",
+       "               1 1.6 div 1 scale 10 rotate     %back to original",
+       "               35 rotate 0.85 1.1 scale",
+       "               0 0 275 0 360 arc               %inner ellipse",
+       "               eofill",
+       "               grestore",
+       "       } def",
+       "       /do_upflag {",
+       "               -315 0 moveto",
+       "               -300 100 -100 480 0 600 curveto",
+       "               300 960 350 1500 200 1700 curveto",
+       "               130 1700 lineto",
+       "               350 1200 50 650 -315 600 curveto",
+       "               fill",
+       "       } def",
+       "       /do_flat {",
+       "               -250 -400 moveto        %outer edge of loop",
+       "               500 0 350 650 -250 160 curveto",
+       "               -250 160 lwid sub lineto %inner edge of loop",
+       "               100 400 300 0 -250 -400 lwid add curveto",
+       "               fill",
+       "",
+       "               lwid setlinewidth       %stem",
+       "               -250 1100 moveto -250 -400 lineto stroke",
+       "       } def",
+       "       /do_diamond {",
+       "               newpath",
+       "               420 0 moveto 0 300 lineto -420 0 lineto",
+       "               0 -300 lineto closepath",
+       "               259 -29 moveto -41 185 lineto -259 29 lineto",
+       "               41 -185 lineto closepath",
+       "               eofill",
+       "       } def",
+       "       /do_2n {",
+       "               gsave",
+       "               newpath 25 rotate 1.4 1 scale",
+       "               0 0 315 0 360 arc               %outer ellipse",
+       "               1 1.4 div 1 scale               %back to original",
+       "               1.3 0.5 scale",
+       "               0 0 310 0 360 arc               %inner ellipse",
+       "               eofill",
+       "               grestore",
+       "       } def",
+       "       /do_4n {",
+       "               gsave",
+       "               newpath 25 rotate 1.35 1 scale",
+       "               0 0 310 0 360 arc fill",
+       "               grestore",
+       "       } def",
+       "       /do_com {",
+       "               newpath",
+       "               330 250 150 0 360 arc fill      %knob at upper right",
+       "               465 300 moveto                  %outer boundary",
+       "               410 500 200 635 0 635 curveto",
+       "               -750 635 -750 -635 0 -635 curveto",
+       "               350 -635 480 -300 500 -100 curveto",
+       "               430 -100 lineto                 %inner boundary",
+       "               380 -300 250 -565 0 -565 curveto",
+       "               -450 -565 -450 565 0 565 curveto",
+       "               200 565 370 350 395 300 curveto",
+       "               fill",
+       "       } def",
+       "       /do_ferm {",
+       "               0 0 800 lwid sub 0 180 arc      %inner arc",
+       "               -800 0 lineto",
+       "               0 270 lwid sub 800 180 0 arcn   %outer arc",
+       "               800 0 lineto fill",
+       "               0 120 120 0 360 arc fill        %the dot",
+       "       } def",
+       "       /do_mor {",
+       "               gsave",
+       "               0.7 1 scale     %scrunch the following horizontally",
+       "               45 rotate       %to pretend all lines horz or vertical",
+       "               0 1 1 {",
+       "                       pop     %we don't need the loop variable",
+       "                       %one half of the mordent",
+       "                       0 40 moveto 350 40 lineto 350 -460 lineto",
+       "                       750 -460 lineto 750 -540 lineto",
+       "                       150 -540 lineto 150 -40 lineto",
+       "                       0 -40 lineto fill",
+       "                       180 rotate      %to do the other half",
+       "               } for",
+       "               grestore",
+       "       } def",
+       "       /do_turn {",
+       "               gsave",
+       "               0 1 1 {",
+       "                       pop     %we don't need the loop variable",
+       "                       0 -100 moveto   %outer boundary",
+       "                       200 -400 625 -400 625 0 curveto",
+       "                       625 200 500 325 300 325 curveto",
+       "                       300 185 lineto  %inner boundary",
+       "                       450 255 555 150 555 0 curveto",
+       "                       555 -350 250 -250 0 100 curveto",
+       "                       fill",
+       "                       300 255 70 0 360 arc fill %knob on end",
+       "                       180 rotate      %to do the other half",
+       "               } for",
+       "               grestore",
+       "       } def",
+       "",
+       "       /do_upshortnote {",
+       "               utildict begin",
+       "               setnumflags             %set numflags from the stack",
+       "               gsave",
+       "               -330 0 translate        %half a flag width",
+       "               do_4n                   %do a quarter note head",
+       "               lwid setlinewidth",
+       "               370 0 moveto",
+       "               370 2100 numflags 2 sub flagsep mul add lineto stroke",
+       "               670 2100 numflags 2 sub flagsep mul add translate",
+       "               1 -1 scale              %reflect across X axis",
+       "               0 1 numflags 1 sub {",
+       "                       do_upflag       %do an upflag",
+       "                       pop             %we don't need the loop variable",
+       "                       0 flagsep translate",
+       "               } for",
+       "               grestore",
+       "               end",
+       "       } def",
+       "",
+       "       /do_dnshortnote {",
+       "               utildict begin",
+       "               setnumflags             %set numflags from the stack",
+       "               do_4n                   %do a quarter note head",
+       "               lwid setlinewidth",
+       "               -370 0 moveto",
+       "               -370 -2100 numflags 2 sub flagsep mul sub lineto stroke",
+       "               gsave",
+       "               -70 -2100 numflags 2 sub flagsep mul sub translate",
+       "               0 1 numflags 1 sub {",
+       "                       do_upflag       %do an upflag",
+       "                       pop             %we don't need the loop variable",
+       "                       0 flagsep translate",
+       "               } for",
+       "               grestore",
+       "               end",
+       "       } def",
+       "",
+       "       /do_shortrest {",
+       "               utildict begin",
+       "               sety setx setoffsets sethooksm1 %set variable from the stack",
+       "               gsave",
+       "               -105.8 offsets mul -600 offsets mul translate",
+       "               0 1 hooksm1 {           %loop once per hook",
+       "                       newpath",
+       "                       1 setlinewidth",
+       "                       gsave",
+       "                       1 1.2 scale",
+       "                       -150 300 1.2 div 140 0 360 arc fill     %the dot",
+       "                       grestore",
+       "                       lwid setlinewidth",
+       "                       -50 700 550 255 315 arc         %rest of the hook",
+       "                       hooksm1 lt { stroke 105.8 600 translate } if",
+       "               } for",
+       "               x y lineto stroke",
+       "               grestore",
+       "               end",
+       "       } def",
+       "",
+       "",
+       "       % subsidiary dictionary of character definitions",
+       "       /CharStrings 128 dict def",
+       "       CharStrings begin",
+       "",
+       "               /.notdef {} def",
+       "",
+       "               % Here are the definitions of the characters.  A stepsize here",
+       "               % is 300 units (assuming the character is drawn at its default",
+       "               % size).",
+       "",
+       "               % gclef",
+       "               /A {",
+       "                       newpath",
+       "                       %start with inner curl, inside boundary",
+       "                       -50 -300 moveto",
+       "                       -450 600 700 700 750 0 curveto",
+       "                       750 -800 -700 -800 -700 200 curveto",
+       "                       -700 900 500 1400 520 2250 curveto",
+       "                       520 2900 300 3000 200 3000 curveto",
+       "                       100 3000 -400 2500 -200 1800 curveto",
+       "                       350 -600 lineto",
+       "                       720 -1600 0 -1650 -400 -1400 curveto",
+       "",
+       "                       %go back to start, drawing the other boundary",
+       "                       -400 -1480 lineto",
+       "                       0 -1700 800 -1700 430 -600 curveto",
+       "                       -120 1800 lineto",
+       "                       -300 2400 200 2800 250 2800 curveto",
+       "                       400 2800 430 2700 430 2450 curveto",
+       "                       430 1800 -900 1200 -900 300 curveto",
+       "                       -750 -900 800 -900 850 0 curveto",
+       "                       900 1100 -750 900 -120 -300 curveto fill",
+       "",
+       "                       %circle at the bottom",
+       "                       -300 -1250 250 0 360 arc fill",
+       "               } def",
+       "",
+       "               % fclef",
+       "               /B {",
+       "                       newpath",
+       "                       %start with outside boundary, at bottom",
+       "                       -1000 -1700 moveto",
+       "                       100 -1100 500 -600 450 0 curveto",
+       "                       450 850 -1100 850 -950 0 curveto",
+       "",
+       "                       %go back to start, drawing the other boundary",
+       "                       -880 0 lineto",
+       "                       -920 400 -600 560 -300 560 curveto",
+       "                       0 560 150 400 150 0 curveto",
+       "                       150 -400 100 -900 -1000 -1620 curveto fill",
+       "",
+       "                       %circle at the left",
+       "                       newpath",
+       "                       -700 0 250 0 360 arc fill",
+       "",
+       "                       %do the two dots after the main curve",
+       "                       700 -300 100 0 360 arc fill",
+       "                       700 300 100 0 360 arc fill",
+       "               } def",
+       "",
+       "               % cclef",
+       "               /C {",
+       "                       gsave",
+       "                       %do upper curved part, then scale to do mirror image",
+       "                       0 1 1 {",
+       "                               pop     %we don't need the loop variable",
+       "                               %outer boundary of curve",
+       "                               -170 0 moveto 100 300 lineto",
+       "                               400 -200 750 300 750 650 curveto",
+       "                               750 1100 450 1235 250 1235 curveto",
+       "                               0 1235 -143 1100 -143 950 curveto",
+       "",
+       "                               %inner boundary of curve",
+       "                               0 950 lineto",
+       "                               0 1100 30 1165 250 1165 curveto",
+       "                               300 1165 450 1100 450 650 curveto",
+       "                               450 400 400 -100 100 400 curveto",
+       "                               -270 0 lineto fill",
+       "                               %stroke",
+       "                               %-270 0 moveto 100 400 lineto",
+       "                               %400 -100 450 400 450 650 curveto",
+       "                               %450 1100 300 1165 250 1165 curveto",
+       "                               %30 1165 0 1100 0 950 curveto",
+       "                               %stroke",
+       "",
+       "                               %elliptical ball at end of curve",
+       "                               gsave",
+       "                               1.3 1 scale",
+       "                               10 950 120 0 360 arc fill",
+       "                               grestore",
+       "                               1 -1 scale      %reflect across X axis",
+       "                       } for",
+       "                       grestore",
+       "",
+       "                       % two vertical lines on the left",
+       "                       300 setlinewidth -600 -1200 halflwid sub moveto",
+       "                       -600 1200 halflwid add lineto stroke",
+       "                       lwid setlinewidth -300 -1200 halflwid sub moveto",
+       "                       -300 1200 halflwid add lineto stroke",
+       "               } def",
+       "",
+       "               % dblwhole",
+       "               /D {",
+       "                       do_1n           %do a whole note",
+       "                       lwid setlinewidth",
+       "                       -490 -600 moveto -490 600 lineto stroke",
+       "                       490 -600 moveto 490 600 lineto stroke",
+       "               } def",
+       "",
+       "               % 1n",
+       "               /E {",
+       "                       do_1n           %do a whole note",
+       "               } def",
+       "",
+       "               % 2n",
+       "               /F {",
+       "                       do_2n           %do a half note",
+       "               } def",
+       "",
+       "               % 4n",
+       "               /G {",
+       "                       do_4n           %do a quarter note head",
+       "               } def",
+       "",
+       "               % upflag",
+       "               /H {",
+       "                       do_upflag               %do an upflag",
+       "               } def",
+       "",
+       "               % dnflag",
+       "               /I {",
+       "                       gsave",
+       "                       1 -1 scale      %reflect across X axis",
+       "                       do_upflag               %do an upflag",
+       "                       grestore",
+       "               } def",
+       "",
+       "               % dwhrest",
+       "               /J {",
+       "                       300 setlinewidth",
+       "                       0 0 moveto 0 600 lineto stroke",
+       "               } def",
+       "",
+       "               % 1rest",
+       "               /K {",
+       "                       lwid setlinewidth",
+       "                       -750 600 moveto 750 600 lineto stroke",
+       "                       300 setlinewidth",
+       "                       -400 450 moveto 400 450 lineto stroke",
+       "               } def",
+       "",
+       "               % 2rest",
+       "               /L {",
+       "                       lwid setlinewidth",
+       "                       -750 0 moveto 750 0 lineto stroke",
+       "                       300 setlinewidth",
+       "                       -400 150 moveto 400 150 lineto stroke",
+       "               } def",
+       "",
+       "               % 4rest",
+       "               /M {",
+       "                       newpath",
+       "                       cor3x cor3y halflwid add moveto",
+       "                       %-400 -200 -450 -650 50 -950 lwid add curveto",
+       "                       -450 -50 -450 -650 50 -950 lwid add curveto",
+       "                       -150 -650 -100 -250 cor3x cor3y halflwid sub curveto",
+       "                       fill",
+       "",
+       "                       cor1x cor1y moveto cor1x 200 sub cor1y 200 add lineto",
+       "                       cor2x cor2y lineto cor2x 200 add cor2y 200 sub lineto",
+       "                       fill",
+       "",
+       "                       lwid setlinewidth",
+       "                       topx topy moveto cor1x cor1y lineto stroke",
+       "                       cor2x cor2y moveto cor3x cor3y lineto stroke",
+       "               } def",
+       "",
+       "               % 8rest",
+       "               /N {",
+       "                       0 0 0 -600 do_shortrest",
+       "               } def",
+       "",
+       "               % 16rest",
+       "               /O {",
+       "                       1 1 100 -1200 do_shortrest",
+       "               } def",
+       "",
+       "               % 32rest",
+       "               /P {",
+       "                       2 1 0 -1800 do_shortrest",
+       "               } def",
+       "",
+       "               % 64rest",
+       "               /Q {",
+       "                       3 2 -80 -2100 do_shortrest",
+       "               } def",
+       "",
+       "               % 128rest",
+       "               /R {",
+       "                       4 2 -150 -2700 do_shortrest",
+       "               } def",
+       "",
+       "               % 256rest",
+       "               /S {",
+       "                       5 3 -280 -3300 do_shortrest",
+       "               } def",
+       "",
+       "               % dot",
+       "               /T {",
+       "                       newpath",
+       "                       0 0 120 0 360 arc fill",
+       "               } def",
+       "",
+       "               % nat",
+       "               /U {",
+       "                       % fill crossbars so that we can do parallelograms",
+       "                       -235 -470 moveto -235 -270 lineto",
+       "                       235 -130 lineto 235 -330 lineto fill",
+       "                       -235 130 moveto -235 330 lineto",
+       "                       235 470 lineto 235 270 lineto fill",
+       "",
+       "                       % vertical strokes",
+       "                       lwid setlinewidth",
+       "                       -200 -380 moveto -200 850 lineto stroke",
+       "                       200 -850 moveto 200 380 lineto stroke",
+       "               } def",
+       "",
+       "               % sharp",
+       "               /V {",
+       "                       % fill crossbars so that we can do parallelograms",
+       "                       -325 -480 moveto -325 -280 lineto",
+       "                       325 -120 lineto 325 -320 lineto fill",
+       "                       -325 120 moveto -325 320 lineto",
+       "                       325 480 lineto 325 280 lineto fill",
+       "",
+       "                       % vertical strokes",
+       "                       lwid setlinewidth",
+       "                       -150 -930 moveto -150 880 lineto stroke",
+       "                       150 -880 moveto 150 930 lineto stroke",
+       "               } def",
+       "",
+       "               % flat",
+       "               /W {",
+       "                       do_flat         %do a flat",
+       "               } def",
+       "",
+       "               % dblsharp",
+       "               /X {",
+       "                       gsave",
+       "                       0 1 3 {         %loop once for each of 4 sticks",
+       "                               pop     %we don't need the loop variable",
+       "                               0 off neg moveto",
+       "                               outbendbig outbendsmall lineto",
+       "                               inbendbig inbendsmall lineto",
+       "                               limit limit lineto",
+       "                               inbendsmall inbendbig lineto",
+       "                               outbendsmall outbendbig lineto",
+       "                               off neg 0 lineto",
+       "                               fill",
+       "                               -90 rotate",
+       "                       } for",
+       "                       grestore",
+       "               } def",
+       "",
+       "               % dblflat",
+       "               /Y {",
+       "                       -290 580 290 {  %loop once for each flat",
+       "",
+       "                               gsave",
+       "                               1 setlinewidth",
+       "                               0 translate     %translate left/right (loop var)",
+       "                               do_flat         %do a flat",
+       "                               grestore",
+       "",
+       "                       } for",
+       "               } def",
+       "",
+       "               % xnote",
+       "               /Z {",
+       "                       gsave",
+       "                       1.15 1 scale 120 setlinewidth 1 setlinecap      %round",
+       "                       -300 -300 moveto 300 300 lineto stroke",
+       "                       -300 300 moveto 300 -300 lineto stroke",
+       "                       grestore",
+       "               } def",
+       "",
+       "               % dwhdiamond",
+       "               /a {",
+       "                       do_diamond      %do a diamond",
+       "                       lwid setlinewidth",
+       "                       -420 -600 moveto -420 600 lineto stroke",
+       "                       420 -600 moveto 420 600 lineto stroke",
+       "               } def",
+       "",
+       "               % diamond",
+       "               /b {",
+       "                       do_diamond      %do a diamond",
+       "               } def",
+       "",
+       "               % filldiamond",
+       "               /c {",
+       "                       420 0 moveto 0 300 lineto",
+       "                       -420 0 lineto 0 -300 lineto fill",
+       "               } def",
+       "",
+       "               % up2n",
+       "               /d {",
+       "                       lwid setlinewidth",
+       "                       380 0 moveto 380 2100 lineto stroke",
+       "                       do_2n           %do a half note",
+       "               } def",
+       "",
+       "               % dn2n",
+       "               /e {",
+       "                       lwid setlinewidth",
+       "                       -380 0 moveto -380 -2100 lineto stroke",
+       "                       do_2n           %do a half note",
+       "               } def",
+       "",
+       "               % up4n",
+       "               /f {",
+       "                       do_4n           %do a quarter note head",
+       "                       lwid setlinewidth",
+       "                       370 0 moveto 370 2100 lineto stroke",
+       "               } def",
+       "",
+       "               % dn4n",
+       "               /g {",
+       "                       do_4n           %do a quarter note head",
+       "                       lwid setlinewidth",
+       "                       -370 0 moveto -370 -2100 lineto stroke",
+       "               } def",
+       "",
+       "               % up8n",
+       "               /h {",
+       "                       gsave",
+       "                       -330 0 translate        % half a flag width",
+       "                       do_4n           %do a quarter note head",
+       "                       lwid setlinewidth",
+       "                       370 0 moveto 370 2100 lineto stroke",
+       "                       670 2100 translate",
+       "                       1 -1 scale      %reflect across X axis",
+       "                       do_upflag               %do an upflag",
+       "                       grestore",
+       "               } def",
+       "",
+       "               % dn8n",
+       "               /i {",
+       "                       do_4n           %do a quarter note head",
+       "                       lwid setlinewidth",
+       "                       -370 0 moveto -370 -2100 lineto stroke",
+       "                       gsave",
+       "                       -70 -2100 translate",
+       "                       do_upflag               %do an upflag",
+       "                       grestore",
+       "               } def",
+       "",
+       "               % up16n",
+       "               /j {",
+       "                       2 do_upshortnote",
+       "               } def",
+       "",
+       "               % dn16n",
+       "               /k {",
+       "                       2 do_dnshortnote",
+       "               } def",
+       "",
+       "               % up32n",
+       "               /l {",
+       "                       3 do_upshortnote",
+       "               } def",
+       "",
+       "               % dn32n",
+       "               /m {",
+       "                       3 do_dnshortnote",
+       "               } def",
+       "",
+       "               % up64n",
+       "               /n {",
+       "                       4 do_upshortnote",
+       "               } def",
+       "",
+       "               % dn64n",
+       "               /o {",
+       "                       4 do_dnshortnote",
+       "               } def",
+       "",
+       "               % up128n",
+       "               /p {",
+       "                       5 do_upshortnote",
+       "               } def",
+       "",
+       "               % dn128n",
+       "               /q {",
+       "                       5 do_dnshortnote",
+       "               } def",
+       "",
+       "               % up256n",
+       "               /r {",
+       "                       6 do_upshortnote",
+       "               } def",
+       "",
+       "               % dn256n",
+       "               /s {",
+       "                       6 do_dnshortnote",
+       "               } def",
+       "",
+       "               % com",
+       "               /t {",
+       "                       do_com          %do a common time symbol",
+       "               } def",
+       "",
+       "               % cut",
+       "               /u {",
+       "                       do_com          %do a common time symbol",
+       "                       lwid setlinewidth",
+       "                       0 -900 moveto 0 900 lineto stroke",
+       "               } def",
+       "",
+       "               % begped",
+       "               /v {",
+       "                       lwid setlinewidth",
+       "                       -200 600 moveto -200 0 lineto 200 0 lineto stroke",
+       "               } def",
+       "",
+       "               % pedal",
+       "               /w {",
+       "                       lwid setlinewidth",
+       "                       -500 0 moveto -450 0 lineto 0 600 lineto",
+       "                       450 0 lineto 500 0 lineto stroke",
+       "               } def",
+       "",
+       "               % endped",
+       "               /x {",
+       "                       lwid setlinewidth",
+       "                       200 600 moveto 200 0 lineto -200 0 lineto stroke",
+       "               } def",
+       "",
+       "               % dnbow",
+       "               /y {",
+       "                       lwid setlinewidth",
+       "                       -350 0 moveto -350 900 lineto stroke",
+       "                       350 0 moveto 350 900 lineto stroke",
+       "                       200 setlinewidth",
+       "                       -350 800 moveto 350 800 lineto stroke",
+       "               } def",
+       "",
+       "               % upbow",
+       "               /z {",
+       "                       lwid setlinewidth",
+       "                       -300 900 moveto 0 0 lineto 300 900 lineto stroke",
+       "               } def",
+       "",
+       "               % wedge",
+       "               /one {",
+       "                       0 0 moveto -150 500 lineto 150 500 lineto fill",
+       "               } def",
+       "",
+       "               % uwedge",
+       "               /two {",
+       "                       -150 0 moveto 150 0 lineto 0 500 lineto fill",
+       "               } def",
+       "",
+       "               % ferm",
+       "               /three {",
+       "                       newpath",
+       "                       do_ferm         %do a right side up fermata",
+       "               } def",
+       "",
+       "               % uferm",
+       "               /four {",
+       "                       newpath",
+       "                       gsave",
+       "                       0 270 lwid sub 800 add translate %baseline at bottom",
+       "                       180 rotate                      %upside down",
+       "                       do_ferm         %do a right side up fermata",
+       "                       grestore",
+       "               } def",
+       "",
+       "               % sign",
+       "               /five {",
+       "                       gsave",
+       "                       %do upper left curved part, upper right dot;",
+       "                       %then rotate 180 to do other half",
+       "                       0 1 1 {",
+       "                               pop     %we don't need the loop variable",
+       "                               0 100 moveto            %inner boundary",
+       "                               -1000 300 -400 750 -200 700 curveto",
+       "                               -200 800 lineto         %outer boundary",
+       "                               -550 900 -1100 100 0 -100 curveto",
+       "                               fill",
+       "                               %dot at end of curve",
+       "                               -200 700 100 0 360 arc fill",
+       "                               %dot in upper right quadrant",
+       "                               500 200 70 0 360 arc fill",
+       "                               180 rotate",
+       "                       } for",
+       "                       grestore",
+       "",
+       "                       %slash through middle",
+       "                       lwid setlinewidth",
+       "                       -400 -800 moveto 400 800 lineto stroke",
+       "               } def",
+       "",
+       "               % coda",
+       "               /six {",
+       "                       newpath",
+       "                       gsave",
+       "                       0.6 1 scale",
+       "                       0 0 550 0 360 arc       %outside boundary",
+       "                       1 0.6 div 1 scale       %back to original",
+       "                       0.9 1 scale",
+       "                       0 0 650 0 360 arc       %inside boundary",
+       "                       eofill",
+       "                       grestore",
+       "                       lwid setlinewidth",
+       "                       0 -850 moveto 0 850 lineto stroke",
+       "                       -800 0 moveto 800 0 lineto stroke",
+       "               } def",
+       "",
+       "               % mor",
+       "               /seven {",
+       "                       do_mor          %do a mordent",
+       "               } def",
+       "",
+       "               % invmor",
+       "               /eight {",
+       "                       do_mor          %do a mordent",
+       "                       lwid setlinewidth",
+       "                       0 -450 moveto 0 450 lineto stroke",
+       "               } def",
+       "",
+       "               % turn",
+       "               /nine {",
+       "                       do_turn         %do a turn",
+       "               } def",
+       "",
+       "               % invturn",
+       "               /zero {",
+       "                       gsave",
+       "                       1 -1 scale      %reflect across X axis",
+       "                       do_turn         %do a turn",
+       "                       grestore",
+       "               } def",
+       "",
+       "               % acc_gt",
+       "               /numbersign {",
+       "                       lwid setlinewidth",
+       "                       -500 300 moveto 500 0 lineto -500 -300 lineto stroke",
+       "               } def",
+       "",
+       "               % acc_hat",
+       "               /dollar {",
+       "                       newpath",
+       "                       -365 0 moveto 0 860 lineto 365 0 lineto",
+       "                       150 0 lineto -75 530 lineto -300 0 lineto fill",
+       "               } def",
+       "",
+       "               % acc_uhat",
+       "               /quotedbl {",
+       "                       newpath",
+       "                       365 860 moveto 0 0 lineto -365 860 lineto",
+       "                       -150 860 lineto 75 330 lineto 300 860 lineto fill",
+       "               } def",
+       "",
+       "               % tr",
+       "               /asterisk {",
+       "                       %vertical bar of t",
+       "                       -350 1000 moveto -550 200 lineto",
+       "                       -612.5 -50 -212.5 -50 -160 200 curveto",
+       "                       -230 200 lineto",
+       "                       -300 50 -420 50 -400 200 curveto",
+       "                       -200 1000 lineto fill",
+       "",
+       "                       %crossbar of t and vertical bar of r",
+       "                       -700 600 moveto -160 600 lineto",
+       "                       20 600 30 520 60 440 curveto",
+       "                       -50 0 lineto 70 0 lineto 180 440 lineto",
+       "                       190 480 100 670 -150 670 curveto",
+       "                       -690 670 lineto fill",
+       "",
+       "                       %horizontal curve of r",
+       "                       100 480 moveto",
+       "                       300 630 450 700 650 550 curveto",
+       "                       560 480 lineto",
+       "                       450 630 300 560 100 390 curveto",
+       "                       fill",
+       "",
+       "                       %knob at end of r",
+       "                       600 460 100 0 360 arc fill",
+       "               } def",
+       "",
+       "               % leg",
+       "               /comma {",
+       "                       100 setlinewidth",
+       "                       -400 0 moveto 400 0 lineto stroke",
+       "               } def",
+       "",
+       "               % rr",
+       "               /hyphen {",
+       "                       100 setlinewidth",
+       "                       -400 0 moveto 0 1000 lineto stroke",
+       "                       0 0 moveto 400 1000 lineto stroke",
+       "               } def",
+       "",
+       "               % measrpt",
+       "               /period {",
+       "                       newpath -450 400 150 0 360 arc fill",
+       "                       newpath 450 -400 150 0 360 arc fill",
+       "                       200 setlinewidth",
+       "                       -550 -600 moveto 550 600 lineto stroke",
+       "               } def",
+       "",
+       "               % copyright",
+       "               /slash {",
+       "                       lwid setlinewidth",
+       "                       newpath 0 400 400 0 360 arc stroke",
+       "                       newpath 0 400 200 45 315 arc stroke",
+       "               } def",
+       "",
+       "               % dim",
+       "               /quoteleft {",
+       "                       50 setlinewidth",
+       "                       newpath 0 640 220 0 360 arc stroke",
+       "               } def",
+       "",
+       "               % halfdim",
+       "               /quoteright {",
+       "                       50 setlinewidth",
+       "                       newpath 0 640 220 0 360 arc stroke",
+       "                       newpath -340 300 moveto 340 980 lineto stroke",
+       "               } def",
+       "",
+       "               % triangle",
+       "               /asciicircum {",
+       "                       50 setlinewidth",
+       "                       newpath -340 -10 moveto 0 710 lineto",
+       "                       340 -10 lineto closepath stroke",
+       "               } def",
+       "",
+       "               % qwhrest",
+       "               /ampersand {",
+       "                       300 setlinewidth",
+       "                       0 -600 moveto 0 600 lineto stroke",
+       "               } def",
+       "",
+       "               % ll1rest",
+       "               /exclam {",
+       "                       310 setlinewidth",
+       "                       -400 455 moveto 400 450 lineto stroke",
+       "               } def",
+       "",
+       "               % ll2rest",
+       "               /at {",
+       "                       310 setlinewidth",
+       "                       -400 145 moveto 400 150 lineto stroke",
+       "               } def",
+       "       end",
+       "",
+       "       /BuildChar {",
+       "",
+       "               exch begin",
+       "               Encoding exch get",
+       "",
+       "               dup",
+       "               Mcbbox0 exch get",
+       "               aload pop setcachedevice",
+       "",
+       "               CharStrings exch get",
+       "               exec",
+       "               end",
+       "       } def",
+       "end",
+       "",
+       "",
+       "% Define another music character font, since there are too many to fit in one",
+       "% font.  It works the same way as the first one.",
+       "",
+       "/mfont1 100 dict def",
+       "mfont1 begin",
+       "       /FontType 3 def",
+       "       /FontMatrix [ .001 0 0 0.001 0 0 ] def",
+       "       /FontBBox [ -2000 -4030 2000 4030 ] def",
+       "       /FontName (Mfont1) def",
+       "",
+       "       % set up Encoding vector with standard names",
+       "       /Encoding 256 array def",
+       "       StandardEncoding Encoding copy",
+       "       pop",
+       "",
+       "       %%%%% define routines that will be used by multiple characters %%%%%",
+       "",
+       "       /do_dwh_bars {",
+       "               % the two bars surrounding a double whole note",
+       "               lwid setlinewidth",
+       "               -420 -600 moveto -420 600 lineto stroke",
+       "               420 -600 moveto 420 600 lineto stroke",
+       "       } def",
+       "       /do_righttriangle {",
+       "               newpath",
+       "               420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto",
+       "               350 150 moveto -140 150 lineto 350 -213 lineto",
+       "               eofill",
+       "       } def",
+       "       /do_fillrighttriangle {",
+       "               newpath",
+       "               420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto",
+       "               fill",
+       "       } def",
+       "       /do_rectangle {",
+       "               newpath",
+       "               420 270 moveto -420 270 lineto -420 -270 lineto 420 -270 lineto",
+       "               350 150 moveto -350 150 lineto -350 -150 lineto 350 -150 lineto",
+       "               eofill",
+       "       } def",
+       "       /do_isostriangle {",
+       "               newpath",
+       "               0 300 moveto -420 -270 lineto 420 -270 lineto",
+       "               0 182 moveto -245 -150 lineto 245 -150 lineto",
+       "               eofill",
+       "       } def",
+       "       /do_piewedge {",
+       "               newpath",
+       "               0 -300 moveto 0 -244 514 35 145 arc",
+       "               0 -209 moveto 0 -244 394 43 137 arc",
+       "               eofill",
+       "       } def",
+       "       /do_semicircle {",
+       "               newpath",
+       "               gsave",
+       "               1 1.357 scale 420 199 moveto 0 199 420 180 360 arc",
+       "               1 1.09 scale 350 111 moveto 0 199 350 194.1 345.9 arc",
+       "               eofill",
+       "               grestore",
+       "       } def",
+       "       /do_slashhead {",
+       "               newpath",
+       "               lwid setlinewidth",
+       "               -620 -530 moveto -480 -670 lineto 620 530 lineto 480 670 lineto",
+       "               closepath stroke",
+       "       } def",
+       "",
+       "       % subsidiary dictionary of character definitions",
+       "       /CharStrings 128 dict def",
+       "       CharStrings begin",
+       "",
+       "               /.notdef {} def",
+       "",
+       "               % Here are the definitions of the characters.  A stepsize here",
+       "               % is 300 units (assuming the character is drawn at its default",
+       "               % size).",
+       "",
+       "               % dwhrighttriangle",
+       "               /A {",
+       "                       do_righttriangle",
+       "                       do_dwh_bars",
+       "               } def",
+       "",
+       "               % righttriangle",
+       "               /B {",
+       "                       do_righttriangle",
+       "               } def",
+       "",
+       "               % fillrighttriangle",
+       "               /C {",
+       "                       newpath",
+       "                       420 270 moveto -420 270 lineto 350 -300 lineto",
+       "                       420 -300 lineto",
+       "                       fill",
+       "               } def",
+       "",
+       "               % udwhrighttriangle",
+       "               /D {",
+       "                       gsave",
+       "                       180 rotate",
+       "                       do_righttriangle",
+       "                       do_dwh_bars",
+       "                       grestore",
+       "               } def",
+       "",
+       "               % urighttriangle",
+       "               /E {",
+       "                       gsave",
+       "                       180 rotate",
+       "                       do_righttriangle",
+       "                       grestore",
+       "               } def",
+       "",
+       "               % ufillrighttriangle",
+       "               /F {",
+       "                       gsave",
+       "                       180 rotate",
+       "                       do_fillrighttriangle",
+       "                       grestore",
+       "               } def",
+       "",
+       "               % dwhrectangle",
+       "               /G {",
+       "                       do_rectangle",
+       "                       do_dwh_bars",
+       "               } def",
+       "",
+       "               % rectangle",
+       "               /H {",
+       "                       do_rectangle",
+       "               } def",
+       "",
+       "               % fillrectangle",
+       "               /I {",
+       "                       newpath",
+       "                       420 270 moveto -420 270 lineto -420 -270 lineto",
+       "                       420 -270 lineto",
+       "                       fill",
+       "               } def",
+       "",
+       "               % dwhisostriangle",
+       "               /J {",
+       "                       do_isostriangle",
+       "                       do_dwh_bars",
+       "               } def",
+       "",
+       "               % isostriangle",
+       "               /K {",
+       "                       do_isostriangle",
+       "               } def",
+       "",
+       "               % fillisostriangle",
+       "               /L {",
+       "                       newpath",
+       "                       0 300 moveto -420 -270 lineto 420 -270 lineto",
+       "                       fill",
+       "               } def",
+       "",
+       "               % dwhpiewedge",
+       "               /M {",
+       "                       do_piewedge",
+       "                       do_dwh_bars",
+       "               } def",
+       "",
+       "               % piewedge",
+       "               /N {",
+       "                       do_piewedge",
+       "               } def",
+       "",
+       "               % fillpiewedge",
+       "               /O {",
+       "                       newpath",
+       "                       0 -300 moveto 0 -244 514 35 145 arc",
+       "                       fill",
+       "               } def",
+       "",
+       "               % dwhsemicircle",
+       "               /P {",
+       "                       do_semicircle",
+       "                       do_dwh_bars",
+       "               } def",
+       "",
+       "               % semicircle",
+       "               /Q {",
+       "                       do_semicircle",
+       "               } def",
+       "",
+       "               % fillsemicircle",
+       "               /R {",
+       "                       newpath",
+       "                       gsave",
+       "                       1 570 420 div scale",
+       "                       420 199 moveto 0 199 420 180 360 arc",
+       "                       fill",
+       "                       grestore",
+       "               } def",
+       "",
+       "               % dwhslashhead",
+       "               /S {",
+       "                       do_slashhead",
+       "                       lwid setlinewidth",
+       "                       -650 -600 moveto -650 600 lineto stroke",
+       "                       650 -600 moveto 650 600 lineto stroke",
+       "               } def",
+       "",
+       "               % slashhead",
+       "               /T {",
+       "                       do_slashhead",
+       "               } def",
+       "",
+       "               % fillslashhead",
+       "               /U {",
+       "                       newpath",
+       "                       200 setlinewidth",
+       "                       -550 -600 moveto 550 600 lineto stroke",
+       "               } def",
+       "",
+       "               % blankhead",
+       "               /V {",
+       "                       %print nothing",
+       "               } def",
+       "       end",
+       "",
+       "       /BuildChar {",
+       "",
+       "               exch begin",
+       "               Encoding exch get",
+       "",
+       "               dup",
+       "               Mcbbox1 exch get",
+       "               aload pop setcachedevice",
+       "",
+       "               CharStrings exch get",
+       "               exec",
+       "               end",
+       "       } def",
+       "end",
+       "",
+       "",
+       "% General routines for printing any music character, invoked by each music",
+       "% character's specific routine below.  The scaling factor (default 1) needs",
+       "% to be multiplied by 10 to get the actual size.  These routines restore the",
+       "% preexisting current font when they are done.",
+       "",
+       "/printmchar0 {",
+       "       gsave",
+       "       /musicchar exch def",
+       "       /Mfont0 findfont exch 10 mul scalefont setfont moveto ",
+       "       musicchar show",
+       "       grestore",
+       "} def",
+       "/printmchar1 {",
+       "       gsave",
+       "       /musicchar exch def",
+       "       /Mfont1 findfont exch 10 mul scalefont setfont moveto ",
+       "       musicchar show",
+       "       grestore",
+       "} def",
+       "",
+       "% Define each music character name to be a routine that prints the character.",
+       "% Each character is to be invoked as in this example:",
+       "%      100 200 1 gclef         % at (100, 200), scale to default size & print",
+       "",
+       "/gclef                 { (A) printmchar0 } def",
+       "/fclef                 { (B) printmchar0 } def",
+       "/cclef                 { (C) printmchar0 } def",
+       "/dblwhole              { (D) printmchar0 } def",
+       "/1n                    { (E) printmchar0 } def",
+       "/2n                    { (F) printmchar0 } def",
+       "/4n                    { (G) printmchar0 } def",
+       "/upflag                        { (H) printmchar0 } def",
+       "/dnflag                        { (I) printmchar0 } def",
+       "/dwhrest               { (J) printmchar0 } def",
+       "/1rest                 { (K) printmchar0 } def",
+       "/2rest                 { (L) printmchar0 } def",
+       "/4rest                 { (M) printmchar0 } def",
+       "/8rest                 { (N) printmchar0 } def",
+       "/16rest                        { (O) printmchar0 } def",
+       "/32rest                        { (P) printmchar0 } def",
+       "/64rest                        { (Q) printmchar0 } def",
+       "/128rest               { (R) printmchar0 } def",
+       "/256rest               { (S) printmchar0 } def",
+       "/dot                   { (T) printmchar0 } def",
+       "/nat                   { (U) printmchar0 } def",
+       "/sharp                 { (V) printmchar0 } def",
+       "/flat                  { (W) printmchar0 } def",
+       "/dblsharp              { (X) printmchar0 } def",
+       "/dblflat               { (Y) printmchar0 } def",
+       "/xnote                 { (Z) printmchar0 } def",
+       "/dwhdiamond            { (a) printmchar0 } def",
+       "/diamond               { (b) printmchar0 } def",
+       "/filldiamond           { (c) printmchar0 } def",
+       "/up2n                  { (d) printmchar0 } def",
+       "/dn2n                  { (e) printmchar0 } def",
+       "/up4n                  { (f) printmchar0 } def",
+       "/dn4n                  { (g) printmchar0 } def",
+       "/up8n                  { (h) printmchar0 } def",
+       "/dn8n                  { (i) printmchar0 } def",
+       "/up16n                 { (j) printmchar0 } def",
+       "/dn16n                 { (k) printmchar0 } def",
+       "/up32n                 { (l) printmchar0 } def",
+       "/dn32n                 { (m) printmchar0 } def",
+       "/up64n                 { (n) printmchar0 } def",
+       "/dn64n                 { (o) printmchar0 } def",
+       "/up128n                        { (p) printmchar0 } def",
+       "/dn128n                        { (q) printmchar0 } def",
+       "/up256n                        { (r) printmchar0 } def",
+       "/dn256n                        { (s) printmchar0 } def",
+       "/com                   { (t) printmchar0 } def",
+       "/cut                   { (u) printmchar0 } def",
+       "/begped                        { (v) printmchar0 } def",
+       "/pedal                 { (w) printmchar0 } def",
+       "/endped                        { (x) printmchar0 } def",
+       "/dnbow                 { (y) printmchar0 } def",
+       "/upbow                 { (z) printmchar0 } def",
+       "/wedge                 { (1) printmchar0 } def",
+       "/uwedge                        { (2) printmchar0 } def",
+       "/ferm                  { (3) printmchar0 } def",
+       "/uferm                 { (4) printmchar0 } def",
+       "/sign                  { (5) printmchar0 } def",
+       "/coda                  { (6) printmchar0 } def",
+       "/mor                   { (7) printmchar0 } def",
+       "/invmor                        { (8) printmchar0 } def",
+       "/turn                  { (9) printmchar0 } def",
+       "/invturn               { (0) printmchar0 } def",
+       "/acc_gt                        { (#) printmchar0 } def",
+       "/acc_hat               { ($) printmchar0 } def",
+       "/acc_uhat              { (\") printmchar0 } def",
+       "/tr                    { (*) printmchar0 } def",
+       "/leg                   { (,) printmchar0 } def",
+       "/rr                    { (-) printmchar0 } def",
+       "/measrpt               { (.) printmchar0 } def",
+       "/copyright             { (/) printmchar0 } def",
+       "/dim                   { (`) printmchar0 } def",
+       "/halfdim               { (') printmchar0 } def",
+       "/triangle              { (^) printmchar0 } def",
+       "/qwhrest               { (&) printmchar0 } def",
+       "/ll1rest               { (!) printmchar0 } def",
+       "/ll2rest               { (@) printmchar0 } def",
+       "/dwhrighttriangle      { (A) printmchar1 } def",
+       "/righttriangle         { (B) printmchar1 } def",
+       "/fillrighttriangle     { (C) printmchar1 } def",
+       "/udwhrighttriangle     { (D) printmchar1 } def",
+       "/urighttriangle                { (E) printmchar1 } def",
+       "/ufillrighttriangle    { (F) printmchar1 } def",
+       "/dwhrectangle          { (G) printmchar1 } def",
+       "/rectangle             { (H) printmchar1 } def",
+       "/fillrectangle         { (I) printmchar1 } def",
+       "/dwhisostriangle       { (J) printmchar1 } def",
+       "/isostriangle          { (K) printmchar1 } def",
+       "/fillisostriangle      { (L) printmchar1 } def",
+       "/dwhpiewedge           { (M) printmchar1 } def",
+       "/piewedge              { (N) printmchar1 } def",
+       "/fillpiewedge          { (O) printmchar1 } def",
+       "/dwhsemicircle         { (P) printmchar1 } def",
+       "/semicircle            { (Q) printmchar1 } def",
+       "/fillsemicircle                { (R) printmchar1 } def",
+       "/dwhslashhead          { (S) printmchar1 } def",
+       "/slashhead             { (T) printmchar1 } def",
+       "/fillslashhead         { (U) printmchar1 } def",
+       "/blankhead             { (V) printmchar1 } def",
+       "",
+       "",
+       "% Define routines for Mup output other than music characters.",
+       "",
+       "/stepsize 3 def           % define a step size as 3 points (at default magnification)",
+       "",
+       "% x1 y1 x2 lines dist staffscale staff",
+       "%              draw a staff starting at x1, y1 and extending to x2 with \"lines\"",
+       "%              lines, 2*dist*stepsize apart, scaled by staffscale",
+       "/staff {",
+       "       /staffscale exch def",
+       "       /dist exch def",
+       "       /lines exch def",
+       "       /x2 exch def",
+       "       /y1 exch def",
+       "       /x1 exch def",
+       "       0.7 staffscale mul sb setlinewidth",
+       "       1 lines sub  2  lines 1 sub {   % loop from bottom line to top line",
+       "               dup stepsize mul staffscale mul dist mul y1 add x1 exch moveto",
+       "               stepsize mul staffscale mul dist mul y1 add x2 exch lineto stroke",
+       "       } for",
+       "} def",
+       "",
+       "% x y1 y2 bracket      draw a bracket; y1 is the top",
+       "/bracket {",
+       "       /y2 exch def",
+       "       /y1 exch def",
+       "       /x exch def",
+       "       gsave",
+       "       3 setlinewidth",
+       "       x 2 sub y1 1 add moveto",
+       "       x 2 sub y2 1 sub lineto",
+       "       stroke",
+       "       x 2 sub y1 1 add moveto",
+       "       x 1 sub y1 1 add   x 3 add y1 1 add   x 5 add y1 6 add   curveto",
+       "       x 6 add y1 5 add lineto",
+       "       x 5 add y1 2 add   x 1 add y1 2 sub   x 2 sub y1 2 sub   curveto",
+       "       fill",
+       "       x 2 sub y2 1 sub moveto",
+       "       x 1 sub y2 1 sub   x 3 add y2 1 sub   x 5 add y2 6 sub   curveto",
+       "       x 6 add y2 5 sub lineto",
+       "       x 5 add y2 2 sub   x 1 add y2 2 add   x 2 sub y2 2 add   curveto",
+       "       fill",
+       "       grestore",
+       "} def",
+       "",
+       "% x y1 y2 brace                draw a brace; y1 is the top",
+       "/brace {",
+       "       /y2 exch def",
+       "       /y1 exch def",
+       "       /x exch def",
+       "       gsave",
+       "       x 9 sub y1 y2 add 2 div translate",
+       "       /topy y1 y2 sub 2 div 1 sub def",
+       "       0 1 1 {",
+       "               pop",
+       "               %0 topy moveto 0 0 lineto stroke",
+       "               0 0 moveto",
+       "               16 topy 0.2 mul   -11 topy 0.6 mul   8 topy   curveto",
+       "               8.7 topy lineto",
+       "               -7 topy 0.7 mul   20 topy 0.3 mul   1 0   curveto",
+       "               fill",
+       "               1 -1 scale      % flip to do bottom half",
+       "       } for",
+       "       grestore",
+       "} def",
+       "",
+       "% endx endy wavy staffscale    draw a wavy line from current point to here,",
+       "%                              scaled by staffscale",
+       "/wavy {",
+       "       /staffscale exch def",
+       "       /endy exch def          % define the end point of the line",
+       "       /endx exch def",
+       "       currentpoint            % line starts at current point",
+       "       /begy exch def          % define the beginning point of the line",
+       "       /begx exch def",
+       "       gsave",
+       "       /dx endx begx sub def   % find delta x and delta y",
+       "       /dy endy begy sub def",
+       "       /r dx dx mul dy dy mul add sqrt def     % hypotenuse",
+       "       /theta dy dx atan def                   % angle with positive x axis",
+       "       begx begy translate     % change axes so that we can draw the line",
+       "       theta rotate            %   from (0, 0) to (r, 0)",
+       "       staffscale staffscale scale     % scale everything by staffscale",
+       "       /scaledr r staffscale div def   % but scale r in reverse to keep length",
+       "",
+       "       % Each outer loop draws one cycle of the squiggle.  It continues until",
+       "       % we are at or beyond the desired end point.",
+       "       0 0 moveto",
+       "       0 6 scaledr {",
+       "               gsave",
+       "               % first loop draws left half of squiggle; second draws right",
+       "               0 1 1 {",
+       "                       0.0 0.4 moveto",
+       "                       2.0 1.9 3.4 2.3 3.9 0.0 curveto",
+       "                       2.1 0.0 lineto",
+       "                       1.9 0.8 1.4 0.7 0.0 -0.4 curveto",
+       "                       fill",
+       "                       pop 180 rotate -6 0 translate",
+       "               } for",
+       "               grestore",
+       "",
+       "               pop 6 0 translate       % shift axes right one squiggle",
+       "       } for",
+       "",
+       "       grestore",
+       "} def",
+       "",
+       "% x y space frets fretno numvert curvel curver [ f1 f2 f3 ... ] grid",
+       "%                              print a guitar grid diagram",
+       "/grid {",
+       "       /grid_positions exch def % 0=\"o\", -1=\"x\", -2=nothing, positive=dot",
+       "       /curver exch def        % right string for curve, 0 if none",
+       "       /curvel exch def        % left string for curve, 0 if none",
+       "       /numvert exch def       % vertical position to print fretno, 0 if none",
+       "       /fretno exch def        % fret no. to print at right, 0 if none",
+       "       /frets exch def         % number of fret lines",
+       "       /space exch def         % points between two neighboring lines",
+       "       /y exch def             % y coord of top fret line",
+       "       /x exch def             % x coord of left strings",
+       "",
+       "       gsave",
+       "       /strings grid_positions length def      % number of strings",
+       "       /lmarky 0.4 space mul y add def         % lowest Y of a \"o\" or \"x\"",
+       "       space 10 div setlinewidth",
+       "       2 setlinecap",
+       "",
+       "       % draw the lines of the grid",
+       "       0  1  strings 1 sub {   % loop from left string to right string",
+       "               dup space mul x add y moveto",
+       "               space mul x add frets 1 sub space mul y exch sub lineto stroke",
+       "       } for",
+       "       0  -1  1 frets sub {    % loop from top fret (nut) to bottom fret",
+       "               dup space mul y add x exch moveto",
+       "               space mul y add strings 1 sub space mul x add exch lineto stroke",
+       "       } for",
+       "",
+       "       % draw the curved line if there is one",
+       "       curvel 0 gt {",
+       "               % within strings curvel to curver, find smallest positive fret",
+       "               /minfret 1000 def",
+       "               curvel 1 curver {",
+       "                       /strno exch def",
+       "                       /grid_p grid_positions strno 1 sub get def",
+       "                       grid_p 0 gt grid_p minfret lt and {",
+       "                               /minfret grid_p def",
+       "                       } if",
+       "               } for",
+       "",
+       "               % if curve goes above top fret, other marks must be higher",
+       "               minfret 1 eq {",
+       "                       /hmarky 1.2 space mul y add def",
+       "               } {",
+       "                       /hmarky lmarky def",
+       "               } ifelse",
+       "",
+       "               /strdiff curver curvel sub def",
+       "               space 8 div setlinewidth",
+       "",
+       "               % set endpoint coords of curve; higher if curve is short",
+       "               /curvex1 curvel 1 sub space mul x add def",
+       "               /curvex2 curver 1 sub space mul x add def",
+       "               /curvey 1 minfret sub space mul y add def",
+       "               strdiff 3 lt {",
+       "                       /curvey 0.2 strdiff div space mul curvey add def",
+       "               } if",
+       "",
+       "               % move to left end, set other points, draw curve",
+       "               curvex1 curvey moveto",
+       "",
+       "               curvex1 curvex2 curvex1 sub 3 div add",
+       "               curvey space 0.4 strdiff sqrt mul mul add",
+       "",
+       "               curvex2 curvex2 curvex1 sub 3 div sub",
+       "               curvey space 0.4 strdiff sqrt mul mul add",
+       "",
+       "               curvex2 curvey curveto stroke",
+       "       } if",
+       "",
+       "       space 10 div setlinewidth",
+       "",
+       "       % draw dots and x and o marks",
+       "       0  1  strings 1 sub {   % loop from left string to right string",
+       "               /strno exch def % first string is 0",
+       "               /grid_p grid_positions strno get def",
+       "               /strx strno space mul x add def",
+       "",
+       "               % set Y of mark higher if curved line covers this string",
+       "               strno 1 add curvel ge  strno 1 add curver le  and {",
+       "                       /marky hmarky def",
+       "               } {",
+       "                       /marky lmarky def",
+       "               } ifelse",
+       "",
+       "               grid_p -1 eq {          % draw an X above the string",
+       "                       /xhwid space 3 div def",
+       "                       strx xhwid sub marky xhwid sub moveto",
+       "                       strx xhwid add marky xhwid add lineto stroke",
+       "                       strx xhwid sub marky xhwid add moveto",
+       "                       strx xhwid add marky xhwid sub lineto stroke",
+       "               } if",
+       "               grid_p 0 eq {           % draw a circle above the string",
+       "                       strx marky space 0.3 mul 0 360 arc stroke",
+       "               } if",
+       "               grid_p 1 ge {           % draw a dot by the proper fret",
+       "                       strx y grid_p space mul sub space 3 div add",
+       "                       space 3 div 0 360 arc fill",
+       "               } if",
+       "       } for",
+       "",
+       "       % print \"X fr\" if requested",
+       "       fretno 0 gt {",
+       "               /Palatino-Roman findfont space 1.9 mul scalefont setfont",
+       "               x strings 0.5 sub space mul add",
+       "               y space numvert 0.3 add mul sub moveto",
+       "               fretno 2 string cvs show ( fr) show",
+       "       } if",
+       "       grestore",
+       "} def",
+       "",
+       "% x1 y1 x2 y2 whitebox         draw a white rectangle with opposite",
+       "%                              corners of (x1,y1) and (x2,y2)",
+       "/whitebox {",
+       "       /y2 exch def",
+       "       /x2 exch def",
+       "       /y1 exch def",
+       "       /x1 exch def",
+       "       1.0 setgray",
+       "       newpath",
+       "       x1 y1 moveto",
+       "       x1 y2 lineto",
+       "       x2 y2 lineto",
+       "       x2 y1 lineto",
+       "       closepath",
+       "       fill",
+       "       stroke",
+       "       0.0 setgray",
+       "} def",
+       "",
+       "",
+       "/LineNum 0 def",
+       "/InputFile (unknown) def",
+       "",
+       "% n linenum",
+       "/linenum {",
+       "       /LineNum exch def",
+       "} def",
+       "",
+       "% (inputfilename) inputfile",
+       "/inputfile {",
+       "       /InputFile exch def",
+       "} def",
+       "",
+       "% find size of Encoding and make a dictionary",
+       "% that size for bounding box information",
+       "mfont0 begin",
+       "/dictsize Encoding length def",
+       "mfont0 /Mcbbox0 dictsize dict put",
+       "",
+       "% temporarily redefine printmchar0 to get code",
+       "5 dict begin",
+       "/printmchar0 { {} forall } def",
+       "",
+       "Mcbbox0 Encoding 128rest get [ 1140.0 0 -515.0 -1515.0 615.0 1685.0 ] put",
+       "Mcbbox0 Encoding 16rest get [ 830.0 0 -415.0 -1215.0 405.0 485.0 ] put",
+       "Mcbbox0 Encoding 1n get [ 1080.0 0 -535.0 -335.0 535.0 345.0 ] put",
+       "Mcbbox0 Encoding 1rest get [ 1540.0 0 -765.0 -5.0 765.0 645.0 ] put",
+       "Mcbbox0 Encoding 256rest get [ 1250.0 0 -625.0 -2115.0 615.0 1685.0 ] put",
+       "Mcbbox0 Encoding 2n get [ 880.0 0 -435.0 -345.0 435.0 355.0 ] put",
+       "Mcbbox0 Encoding 2rest get [ 1540.0 0 -765.0 -45.0 765.0 315.0 ] put",
+       "Mcbbox0 Encoding 32rest get [ 940.0 0 -415.0 -1215.0 515.0 1085.0 ] put",
+       "Mcbbox0 Encoding 4n get [ 840.0 0 -415.0 -335.0 415.0 345.0 ] put",
+       "Mcbbox0 Encoding 4rest get [ 650.0 0 -345.0 -885.0 295.0 985.0 ] put",
+       "Mcbbox0 Encoding 64rest get [ 1040.0 0 -515.0 -1515.0 515.0 1085.0 ] put",
+       "Mcbbox0 Encoding 8rest get [ 750.0 0 -305.0 -615.0 435.0 485.0 ] put",
+       "Mcbbox0 Encoding acc_gt get [ 1170.0 0 -525.0 -335.0 635.0 345.0 ] put",
+       "Mcbbox0 Encoding acc_hat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put",
+       "Mcbbox0 Encoding acc_uhat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put",
+       "Mcbbox0 Encoding begped get [ 470.0 0 -245.0 -45.0 215.0 615.0 ] put",
+       "Mcbbox0 Encoding cclef get [ 1540.0 0 -765.0 -1245.0 765.0 1255.0 ] put",
+       "Mcbbox0 Encoding coda get [ 1640.0 0 -815.0 -855.0 815.0 865.0 ] put",
+       "Mcbbox0 Encoding com get [ 1100.0 0 -575.0 -635.0 515.0 655.0 ] put",
+       "Mcbbox0 Encoding copyright get [ 920.0 0 -455.0 -45.0 455.0 855.0 ] put",
+       "Mcbbox0 Encoding cut get [ 1100.0 0 -575.0 -905.0 515.0 915.0 ] put",
+       "Mcbbox0 Encoding dblflat get [ 1170.0 0 -595.0 -405.0 565.0 1115.0 ] put",
+       "Mcbbox0 Encoding dblsharp get [ 720.0 0 -355.0 -345.0 355.0 355.0 ] put",
+       "Mcbbox0 Encoding dblwhole get [ 1090.0 0 -535.0 -605.0 545.0 615.0 ] put",
+       "Mcbbox0 Encoding diamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put",
+       "Mcbbox0 Encoding dim get [ 540.0 0 -265.0 -5.0 265.0 905.0 ] put",
+       "Mcbbox0 Encoding dn128n get [ 840.0 0 -415.0 -3545.0 415.0 345.0 ] put",
+       "Mcbbox0 Encoding dn16n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put",
+       "Mcbbox0 Encoding dn256n get [ 840.0 0 -415.0 -3965.0 415.0 345.0 ] put",
+       "Mcbbox0 Encoding dn2n get [ 880.0 0 -435.0 -2105.0 435.0 355.0 ] put",
+       "Mcbbox0 Encoding dn32n get [ 840.0 0 -415.0 -2585.0 415.0 345.0 ] put",
+       "Mcbbox0 Encoding dn4n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put",
+       "Mcbbox0 Encoding dn64n get [ 840.0 0 -415.0 -3065.0 415.0 345.0 ] put",
+       "Mcbbox0 Encoding dn8n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put",
+       "Mcbbox0 Encoding dnbow get [ 810.0 0 -395.0 -5.0 405.0 915.0 ] put",
+       "Mcbbox0 Encoding dnflag get [ 640.0 0 -335.0 -1705.0 295.0 15.0 ] put",
+       "Mcbbox0 Encoding dot get [ 280.0 0 -135.0 -125.0 135.0 135.0 ] put",
+       "Mcbbox0 Encoding dwhdiamond get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put",
+       "Mcbbox0 Encoding dwhrest get [ 340.0 0 -165.0 -5.0 165.0 615.0 ] put",
+       "Mcbbox0 Encoding endped get [ 480.0 0 -215.0 -45.0 255.0 615.0 ] put",
+       "Mcbbox0 Encoding fclef get [ 1840.0 0 -1015.0 -1705.0 815.0 655.0 ] put",
+       "Mcbbox0 Encoding ferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put",
+       "Mcbbox0 Encoding filldiamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put",
+       "Mcbbox0 Encoding flat get [ 580.0 0 -295.0 -405.0 275.0 1115.0 ] put",
+       "Mcbbox0 Encoding gclef get [ 1790.0 0 -915.0 -1605.0 865.0 3015.0 ] put",
+       "Mcbbox0 Encoding halfdim get [ 760.0 0 -375.0 -5.0 375.0 1015.0 ] put",
+       "Mcbbox0 Encoding invmor get [ 1320.0 0 -655.0 -455.0 655.0 465.0 ] put",
+       "Mcbbox0 Encoding invturn get [ 1300.0 0 -645.0 -335.0 645.0 345.0 ] put",
+       "Mcbbox0 Encoding leg get [ 840.0 0 -415.0 -55.0 415.0 65.0 ] put",
+       "Mcbbox0 Encoding ll1rest get [ 840.0 0 -415.0 -5.0 415.0 625.0 ] put",
+       "Mcbbox0 Encoding ll2rest get [ 840.0 0 -415.0 -15.0 415.0 315.0 ] put",
+       "Mcbbox0 Encoding measrpt get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put",
+       "Mcbbox0 Encoding mor get [ 1320.0 0 -655.0 -285.0 655.0 295.0 ] put",
+       "Mcbbox0 Encoding nat get [ 520.0 0 -255.0 -855.0 255.0 865.0 ] put",
+       "Mcbbox0 Encoding pedal get [ 1040.0 0 -515.0 -45.0 515.0 675.0 ] put",
+       "Mcbbox0 Encoding qwhrest get [ 340.0 0 -165.0 -605.0 165.0 615.0 ] put",
+       "Mcbbox0 Encoding rr get [ 940.0 0 -465.0 -25.0 465.0 1035.0 ] put",
+       "Mcbbox0 Encoding sharp get [ 700.0 0 -345.0 -935.0 345.0 945.0 ] put",
+       "Mcbbox0 Encoding sign get [ 1340.0 0 -665.0 -825.0 665.0 835.0 ] put",
+       "Mcbbox0 Encoding tr get [ 1440.0 0 -715.0 -5.0 715.0 1015.0 ] put",
+       "Mcbbox0 Encoding triangle get [ 800.0 0 -395.0 -45.0 395.0 785.0 ] put",
+       "Mcbbox0 Encoding turn get [ 1300.0 0 -645.0 -325.0 645.0 345.0 ] put",
+       "Mcbbox0 Encoding uferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put",
+       "Mcbbox0 Encoding up128n get [ 1390.0 0 -745.0 -335.0 635.0 3555.0 ] put",
+       "Mcbbox0 Encoding up16n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put",
+       "Mcbbox0 Encoding up256n get [ 1390.0 0 -745.0 -335.0 635.0 3975.0 ] put",
+       "Mcbbox0 Encoding up2n get [ 880.0 0 -435.0 -345.0 435.0 2115.0 ] put",
+       "Mcbbox0 Encoding up32n get [ 1390.0 0 -745.0 -335.0 635.0 2595.0 ] put",
+       "Mcbbox0 Encoding up4n get [ 850.0 0 -415.0 -335.0 425.0 2115.0 ] put",
+       "Mcbbox0 Encoding up64n get [ 1390.0 0 -745.0 -335.0 635.0 3075.0 ] put",
+       "Mcbbox0 Encoding up8n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put",
+       "Mcbbox0 Encoding upbow get [ 720.0 0 -355.0 -115.0 355.0 925.0 ] put",
+       "Mcbbox0 Encoding upflag get [ 640.0 0 -335.0 -5.0 295.0 1715.0 ] put",
+       "Mcbbox0 Encoding uwedge get [ 340.0 0 -165.0 -5.0 165.0 505.0 ] put",
+       "Mcbbox0 Encoding wedge get [ 340.0 0 -165.0 5.0 165.0 515.0 ] put",
+       "Mcbbox0 Encoding xnote get [ 880.0 0 -435.0 -365.0 435.0 375.0 ] put",
+       "",
+       "end",
+       "end",
+       "",
+       "/Mfont0 mfont0 definefont",
+       "",
+       "",
+       "% find size of Encoding and make a dictionary",
+       "% that size for bounding box information",
+       "mfont1 begin",
+       "/dictsize Encoding length def",
+       "mfont1 /Mcbbox1 dictsize dict put",
+       "",
+       "% temporarily redefine printmchar1 to get code",
+       "5 dict begin",
+       "/printmchar1 { {} forall } def",
+       "",
+       "Mcbbox1 Encoding blankhead get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put",
+       "Mcbbox1 Encoding dwhisostriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put",
+       "Mcbbox1 Encoding dwhpiewedge get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put",
+       "Mcbbox1 Encoding dwhrectangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put",
+       "Mcbbox1 Encoding dwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put",
+       "Mcbbox1 Encoding dwhsemicircle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put",
+       "Mcbbox1 Encoding dwhslashhead get [ 1410.0 0 -695.0 -725.0 705.0 735.0 ] put",
+       "Mcbbox1 Encoding fillisostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put",
+       "Mcbbox1 Encoding fillpiewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put",
+       "Mcbbox1 Encoding fillrectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put",
+       "Mcbbox1 Encoding fillrighttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put",
+       "Mcbbox1 Encoding fillsemicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put",
+       "Mcbbox1 Encoding fillslashhead get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put",
+       "Mcbbox1 Encoding isostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put",
+       "Mcbbox1 Encoding piewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put",
+       "Mcbbox1 Encoding rectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put",
+       "Mcbbox1 Encoding righttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put",
+       "Mcbbox1 Encoding semicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put",
+       "Mcbbox1 Encoding slashhead get [ 1380.0 0 -685.0 -725.0 685.0 735.0 ] put",
+       "Mcbbox1 Encoding udwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put",
+       "Mcbbox1 Encoding ufillrighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put",
+       "Mcbbox1 Encoding urighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put",
+       "",
+       "end",
+       "end",
+       "",
+       "/Mfont1 mfont1 definefont",
+       "",
+       "/makeExtEncoding {",
+       "       /extendedencoding 256 array def",
+       "       StandardEncoding extendedencoding copy",
+       "       extendedencoding 32 /exclamdown put",
+       "       extendedencoding 33 /cent put",
+       "       extendedencoding 34 /sterling put",
+       "       extendedencoding 35 /yen put",
+       "       extendedencoding 36 /quotedblleft put",
+       "       extendedencoding 37 /guillemotleft put",
+       "       extendedencoding 38 /guillemotright put",
+       "       extendedencoding 39 /guilsinglleft put",
+       "       extendedencoding 40 /guilsinglright put",
+       "       extendedencoding 41 /dagger put",
+       "       extendedencoding 42 /daggerdbl put",
+       "       extendedencoding 43 /bullet put",
+       "       extendedencoding 44 /quotedblbase put",
+       "       extendedencoding 45 /quotedblright put",
+       "       extendedencoding 46 /questiondown put",
+       "       extendedencoding 47 /grave put",
+       "       extendedencoding 48 /acute put",
+       "       extendedencoding 49 /macron put",
+       "       extendedencoding 50 /breve put",
+       "       extendedencoding 51 /dotaccent put",
+       "       extendedencoding 52 /dieresis put",
+       "       extendedencoding 53 /ring put",
+       "       extendedencoding 54 /cedilla put",
+       "       extendedencoding 55 /hungarumlaut put",
+       "       extendedencoding 56 /ogonek put",
+       "       extendedencoding 57 /caron put",
+       "       extendedencoding 58 /emdash put",
+       "       extendedencoding 59 /AE put",
+       "       extendedencoding 60 /ae put",
+       "       extendedencoding 61 /ordfeminine put",
+       "       extendedencoding 62 /ordmasculine put",
+       "       extendedencoding 63 /Lslash put",
+       "       extendedencoding 64 /lslash put",
+       "       extendedencoding 65 /Oslash put",
+       "       extendedencoding 66 /oslash put",
+       "       extendedencoding 67 /OE put",
+       "       extendedencoding 68 /oe put",
+       "       extendedencoding 69 /dotlessi put",
+       "       extendedencoding 70 /germandbls put",
+       "       extendedencoding 71 /Aacute put",
+       "       extendedencoding 72 /aacute put",
+       "       extendedencoding 73 /Acircumflex put",
+       "       extendedencoding 74 /acircumflex put",
+       "       extendedencoding 75 /Adieresis put",
+       "       extendedencoding 76 /adieresis put",
+       "       extendedencoding 77 /Agrave put",
+       "       extendedencoding 78 /agrave put",
+       "       extendedencoding 79 /Aring put",
+       "       extendedencoding 80 /aring put",
+       "       extendedencoding 81 /Atilde put",
+       "       extendedencoding 82 /atilde put",
+       "       extendedencoding 83 /Ccedilla put",
+       "       extendedencoding 84 /ccedilla put",
+       "       extendedencoding 85 /Eacute put",
+       "       extendedencoding 86 /eacute put",
+       "       extendedencoding 87 /Ecircumflex put",
+       "       extendedencoding 88 /ecircumflex put",
+       "       extendedencoding 89 /Edieresis put",
+       "       extendedencoding 90 /edieresis put",
+       "       extendedencoding 91 /Egrave put",
+       "       extendedencoding 92 /egrave put",
+       "       extendedencoding 93 /Iacute put",
+       "       extendedencoding 94 /iacute put",
+       "       extendedencoding 95 /Icircumflex put",
+       "       extendedencoding 96 /icircumflex put",
+       "       extendedencoding 97 /Idieresis put",
+       "       extendedencoding 98 /idieresis put",
+       "       extendedencoding 99 /Igrave put",
+       "       extendedencoding 100 /igrave put",
+       "       extendedencoding 101 /Ntilde put",
+       "       extendedencoding 102 /ntilde put",
+       "       extendedencoding 103 /Oacute put",
+       "       extendedencoding 104 /oacute put",
+       "       extendedencoding 105 /Ocircumflex put",
+       "       extendedencoding 106 /ocircumflex put",
+       "       extendedencoding 107 /Odieresis put",
+       "       extendedencoding 108 /odieresis put",
+       "       extendedencoding 109 /Ograve put",
+       "       extendedencoding 110 /ograve put",
+       "       extendedencoding 111 /Otilde put",
+       "       extendedencoding 112 /otilde put",
+       "       extendedencoding 113 /Scaron put",
+       "       extendedencoding 114 /scaron put",
+       "       extendedencoding 115 /Uacute put",
+       "       extendedencoding 116 /uacute put",
+       "       extendedencoding 117 /Ucircumflex put",
+       "       extendedencoding 118 /ucircumflex put",
+       "       extendedencoding 119 /Udieresis put",
+       "       extendedencoding 120 /udieresis put",
+       "       extendedencoding 121 /Ugrave put",
+       "       extendedencoding 122 /ugrave put",
+       "       extendedencoding 123 /Ydieresis put",
+       "       extendedencoding 124 /ydieresis put",
+       "       extendedencoding 125 /Zcaron put",
+       "       extendedencoding 126 /zcaron put",
+       "       extendedencoding 127 /space put",
+       "} def",
+       "",
+       "/makeExtendedFont {",
+       "       findfont",
+       "       dup length dict /newdict exch def",
+       "       { 1 index /FID ne",
+       "               { newdict 3 1 roll put }",
+       "               { pop pop }",
+       "               ifelse",
+       "       } forall",
+       "       newdict /Encoding extendedencoding put",
+       "       newdict /UniqueID newdict /UniqueID get 1 add put",
+       "       newdict definefont pop",
+       "} def",
+(char *) 0
+};
+
+/* generate the PostScript prolog */
+
+void
+ps_prolog()
+{
+       int line;
+
+       for (line = 0; prolog_text[line] != (char *) 0; line++) {
+               (void) printf("%s\n", prolog_text[line]);
+       }
+}
diff --git a/mup/mup/range.c b/mup/mup/range.c
new file mode 100644 (file)
index 0000000..c7cc22c
--- /dev/null
@@ -0,0 +1,432 @@
+
+/* Copyright (c) 1995, 1997, 1998, 1999, 2002, 2004 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* Functions for saving away ranges of staff numbers or vno's when user
+ * is defining groups, lyrics, or stuff for one or more staffs and/or
+ * voices/verses. */
+
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+/* special marker for "all." use something that can't possibly be a staff num */
+#define ALL    (-1)
+
+
+static void free_rangelist P((struct RANGELIST *list_p));
+
+
+
+/* When a line of input is being gathered for groups, lyrics, or stuff,
+ * this function should be called first. It makes
+ * sure the current range list is set to empty and makes a note of the place,
+ * (PL_ABOVE, PL_BELOW, or PL_BETWEEN) for later reference
+ */
+
+void
+begin_range(place)
+
+int place;     /* PL_ABOVE, etc */
+
+{
+       Staffrange_p = (struct RANGELIST *) 0;
+       Vnorange_p = (struct RANGELIST *) 0;
+       Place = (short) place;
+}
+\f
+
+/* This function is called when the parser has found a range of staffs that
+ * is to get the current set of groups, lyrics or stuff.
+ * In the degenerate case, the range
+ * may be a single staff. In the case of PL_BETWEEN, the ending staff number
+ * must be one more than the beginning. 
+ * If the endstaffno is ALL, this is a special case of "all" as in
+ * "above all" or "below all."
+ */
+
+void
+save_staff_range(beginstaffno, endstaffno)
+
+int beginstaffno;      /* first staff in range */
+int endstaffno;                /* last staff in range */
+
+{
+       struct RANGELIST *new_p;        /* to save info about this range */
+       short is_all = NO;
+       
+
+       /* handle special case of "all" */
+       if (endstaffno == ALL) {
+               is_all = YES;
+               endstaffno = beginstaffno;
+       }
+
+       /* do error checks */
+       if (rangecheck(beginstaffno, 1, MAXSTAFFS, "staff number") == NO) {
+               return;
+       }
+       if (rangecheck(endstaffno, 1, MAXSTAFFS, "staff number") == NO) {
+               return;
+       }
+
+       if (endstaffno < beginstaffno) {
+               yyerror("end of staff range smaller than beginning");
+               return;
+       }
+
+       if (Place == PL_BETWEEN) {
+               if (endstaffno != beginstaffno + 1) {
+                       yyerror("if place is 'between', second staff must be 1 greater than first");
+                       return;
+               }
+
+               if (beginstaffno == Score.staffs) {
+                       yyerror("can't use 'between' on bottom staff");
+                       return;
+               }
+       }
+
+       /* allocate a new struct and link onto head of list */
+       CALLOC(RANGELIST, new_p, 1);
+       new_p->next = Staffrange_p;
+       Staffrange_p = new_p;
+
+       /* fill in other fields */
+       new_p->begin = (short) beginstaffno;
+       new_p->end = (short) (Place == PL_BETWEEN ? beginstaffno : endstaffno);
+       new_p->all = is_all;
+       new_p->place = Place;
+}
+\f
+
+/* given a range of vno's, save the range for later use */
+/* Any error checking of the numbers should be done before calling this
+ * function. */
+
+void
+save_vno_range(begin, end)
+
+int begin;     /* first vno */
+int end;       /* last vno */
+
+{
+       struct RANGELIST *new_p;        /* to store vno info */
+
+
+       /* allocate a new struct and link onto head of list */
+       CALLOC(RANGELIST, new_p, 1);
+       new_p->next = Vnorange_p;
+       Vnorange_p = new_p;
+
+       /* fill in other fields */
+       new_p->begin = (short) begin;
+       new_p->end = (short) end;
+}
+\f
+
+/* free list of staff ranges */
+
+void
+free_staffrange()
+
+{
+       free_rangelist(Staffrange_p);
+       Staffrange_p = (struct RANGELIST *) 0;
+}
+
+
+
+/* free list of vno ranges */
+
+void
+free_vnorange()
+
+{
+       free_rangelist(Vnorange_p);
+       Vnorange_p = (struct RANGELIST *) 0;
+}
+
+
+
+
+/* free both the staff and vno lists */
+
+void
+free_rlists()
+
+{
+       if (Svrangelist_p != (struct SVRANGELIST *) 0) {
+               free_sv_list(Svrangelist_p);
+               Svrangelist_p = (struct SVRANGELIST *) 0;
+       }
+       else {
+               free_staffrange();
+               free_vnorange();
+       }
+}
+\f
+
+/* free the Svrangelist and the RANGELISTs hanging off of it */
+
+void
+free_sv_list(svrangelist_p)
+
+struct SVRANGELIST *svrangelist_p;
+
+{
+       if (svrangelist_p == (struct SVRANGELIST *) 0) {
+               return;
+       }
+
+       free_rangelist(svrangelist_p->stafflist_p);
+       free_rangelist(svrangelist_p->vnolist_p);
+
+       /* recurse */
+       free_sv_list(svrangelist_p->next);
+       FREE(svrangelist_p);
+}
+\f
+
+/* recursively free a list of RANGELIST structs */
+
+static void
+free_rangelist(list_p)
+
+struct RANGELIST *list_p;      /* the list to free */
+
+{
+       if (list_p == (struct RANGELIST *) 0) {
+               return;
+       }
+
+       free_rangelist(list_p->next);
+       FREE(list_p);
+}
+\f
+
+/* If doing between, staff ranges must be of the form N&M. If not doing
+ * between, must be either a single number or N-M. Make sure this is so.
+ */
+
+void
+chk_range_type(has_ampersand)
+
+int has_ampersand;     /* YES if range was of the form N&M */
+
+{
+       if (has_ampersand == YES && Place != PL_BETWEEN) {
+               yyerror("& only valid with 'between'");
+               return;
+       }
+
+       if (has_ampersand == NO && Place == PL_BETWEEN) {
+               yyerror("must use & to specify ranges with 'between'");
+       }
+}
+\f
+
+/* Create a STAFF struct in the main list for every staff.
+ * Point List_of_staffs_p to the first of them.
+ * Fill in Staffmap_p for each of them to allow quick mapping from staffno
+ * to STAFF struct.
+ */
+
+void
+create_staffs()
+
+{
+       struct MAINLL *mll_insert_p;    /* where to insert in main list */
+       struct MAINLL *new_p;           /* newly allocated struct */
+       struct MAINLL *mll_p;           /* for verifiying proper order */
+       struct MAINLL *next_mll_p;      /* next main list item to be checked */
+       register int s;                 /* index through staffs */
+
+
+       debug(4, "create_staffs");
+
+       if (List_of_staffs_p != (struct MAINLL *) 0) {
+               /* this function has already been called for current measure, so
+                * nothing more to do. This is normal, because this function
+                * is called whenever another function needs to make sure
+                * the STAFFs have been created.
+                */
+               return;
+       }
+
+       /* STAFFS are supposed to come before LINES, CURVES, and PRHEADS.
+        * However, the user is not constrained to put things in in that
+        * order, so there may be some already on the list. If so, back
+        * up to before where they should begin and insert the STAFFS there. */
+       for (mll_insert_p = Mainlltc_p; mll_insert_p != (struct MAINLL *) 0;
+                                       mll_insert_p = mll_insert_p->prev) {
+
+               if (mll_insert_p->str != S_LINE
+                                       && mll_insert_p->str != S_CURVE
+                                       && mll_insert_p->str != S_PRHEAD) {
+                       break;
+               }
+       }
+
+       /* keep track of place in main list, for later use */
+       mll_p = mll_insert_p;
+
+       /* allocate and add a struct for each staff in the range */
+       for ( s = 1; s <= Score.staffs; s++) {
+
+               new_p = newMAINLLstruct(S_STAFF, yylineno);
+               new_p->u.staff_p->staffno = (short) s;
+               insertMAINLL(new_p, mll_insert_p);
+
+               if (List_of_staffs_p == (struct MAINLL *) 0) {
+                       List_of_staffs_p = new_p;
+               }
+
+               Staffmap_p[s] = new_p;
+               mll_insert_p = new_p;
+       }
+
+       /* while we're making sure the main list in in the prescribed order,
+        * back up all the way to the previous bar (or beginning of list).
+        * If there are any LINES, CURVES, or PRHEADS in between there, move
+        * them to the end. This could happen if, for example, the user
+        * put in a print statement followed by a change of clef */
+       while (mll_p != (struct MAINLL *) 0) {
+               if (mll_p->str == S_BAR) {
+                       /* this is far enough to back up */
+                       break;
+               }
+
+               if (mll_p->str == S_LINE || mll_p->str == S_CURVE ||
+                                       mll_p->str == S_PRHEAD) {
+                       next_mll_p = mll_p->prev;
+                       unlinkMAINLL(mll_p);
+                       insertMAINLL(mll_p, mll_insert_p);
+                       mll_insert_p = mll_p;
+                       mll_p = next_mll_p;
+               }
+               else {
+                       mll_p = mll_p->prev;
+               }
+       }
+}
+\f
+
+/* if user specifies staff as "all", need to find the top visible
+ * staff (if above) or bottom visible (if below). If not above or below,
+ * error. */
+
+void
+all()
+
+{
+       int s;          /* staff number */
+
+
+       /* if user didn't specify a place, have to get default value */
+       if (Place == PL_UNKNOWN) {
+               Place = dflt_place();
+       }
+
+       switch(Place) {
+       case PL_ABOVE:
+               for (s = 1; s <= Score.staffs; s++) {
+                       if ( (svpath(s, VISIBLE))->visible == YES) {
+                               save_staff_range(s, ALL);
+                               return;
+                       }
+               }
+               break;
+
+       case PL_BELOW:
+               for (s = Score.staffs; s > 0; s--) {
+                       if ( (svpath(s, VISIBLE))->visible == YES) {
+                               save_staff_range(s, ALL);
+                               return;
+                       }
+               }
+               break;
+
+       default:
+               yyerror("'all' invalid");
+               return;
+       }
+
+       yyerror("no staffs visible");
+}
+\f
+
+/* start a new staff-voice list */
+
+void
+begin_sv_list()
+
+{
+       Svrangelist_p = (struct SVRANGELIST *) 0;
+}
+\f
+
+/* add the current staff and vno list to the staff-vno list */
+
+void
+add_to_sv_list()
+
+{
+       struct SVRANGELIST *new_p;
+       struct SVRANGELIST **insert_p_p;
+
+       MALLOC(SVRANGELIST, new_p, 1);
+       new_p->stafflist_p = Staffrange_p;
+       new_p->vnolist_p = Vnorange_p;
+       new_p->next = (struct SVRANGELIST *) 0;
+
+       /* link onto end of list */
+       for (insert_p_p = & Svrangelist_p;
+                               *insert_p_p != (struct SVRANGELIST *) 0;
+                               insert_p_p = & ((*insert_p_p)->next) ) {
+               ;
+       }
+       *insert_p_p = new_p;
+}
+\f
+
+/* return YES if given staff is a tab staff, NO if not */
+
+int
+is_tab_staff(staffno)
+
+int staffno;
+
+{
+       if (staffno < 1 && staffno > MAXSTAFFS) {
+               /* not a staff, so not a tab staff. */
+               return(NO);
+       }
+       return (Staff[staffno - 1].strinfo == (struct STRINGINFO *) 0 ? NO : YES);
+}
+\f
+
+/* return the staff number of the first staff on the current list of staffs.
+ * In this context, the "first staff" means the first staff the user defined,
+ * so if they said something like 5,6,9-12,2 this would return 5 */
+
+int
+leadstaff()
+
+{
+       struct RANGELIST *r_p;
+
+       if (Staffrange_p == (struct RANGELIST *) 0) {
+               pfatal("leadstaff called when no staffs on list");
+       }
+
+       /* since new ranges are linked onto the head of the list, we need
+        * to find the last range on the list. That will be the first one
+        * the user specified. */
+       for (r_p = Staffrange_p; r_p->next != (struct RANGELIST *) 0;
+                                               r_p = r_p->next) {
+               ;
+       }
+       return(r_p->begin);
+}
diff --git a/mup/mup/rational.c b/mup/mup/rational.c
new file mode 100644 (file)
index 0000000..90bf411
--- /dev/null
@@ -0,0 +1,1158 @@
+/* Copyright (c) 1995, 1996, 2001 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ *     rational.c      functions to do operations on rational numbers
+ *
+ *     Contents:
+ *
+ *             radd(), rsub(), rmul(), rdiv(), rneg(), rinv(), rrai(), rred(),
+ *             ator(), rtoa(); also gtrat(), called by macros GT,GE,LT,LE
+ *
+ *             ratmsg(), add64_64(), mul32_64(), divmod64(), red64_64()
+ *
+ *             The first group of functions are for the user.  The second
+ *             are for internal use only.
+ *
+ *     Description:
+ *             The functions in this file do operations on rational numbers.
+ *             The rational arguments to functions that the users can call
+ *             must be in standard form (lowest terms, with positive
+ *             denominator) except for rred().  There are checks for division
+ *             by zero and for overflow of numerators and denominators.
+ *             (The absolute values of each are limited to MAXLONG, defined
+ *             in rational.h.)  If there is an error, the external int
+ *             raterrno is set to RATDIV0 or RATOVER, as the case may be,
+ *             and *raterrfuncp is checked.  If nonzero, it is assumed to
+ *             point at the user's error handler, and it is called with a
+ *             parameter equal to raterrno.  Otherwise, a message is printed
+ *             to stderr.  In any case, the answer returned to the user is
+ *             0/1.  If there was no error, raterrno is set to RATNOERR.
+ *
+ *             In general, the functions assume they are being called with
+ *             valid parameters.  If they are not, results are not guaranteed
+ *             to be correct.  However, they are defensive enough so that
+ *             invalid parameters will not cause a crash in these routines.
+ *             They will not always detect invalid parameters, but if they
+ *             do, they will use the raterrno/raterrfuncp mechanism described
+ *             above, with the value RATPARM.
+ *
+ *             These routines depend on a INT32B being a 32-bit number,
+ *             stored in two's complement form, and UINT32B being the same
+ *             for unsigned.  See rational.h.  Numerators and denominators
+ *             are assumed to be INT32B.  Furthermore, the number 0x80000000
+ *             is not allowed.  The routines should work on any machine and
+ *             compiler where these requirements are met.
+ *
+ *             Internally, when 64-bit numbers are used, they are represented
+ *             by an array of two INT32B.  The 0 subscript contains the low
+ *             order bits and the 1 subscript contains the high order bits.
+ *             The numbers are usually used as two's complement signed
+ *             integers, so the high bit of the 1 subscript is a sign bit.
+ */
+
+#ifndef stderr
+#      include <stdio.h>
+#endif
+
+#ifndef isspace
+#      include <ctype.h>
+#endif
+
+#ifndef _RATIONAL
+#      include "rational.h"
+#endif
+
+
+
+/*
+ * Define SMALL to be a number that uses less than half as many bits as
+ * MAXLONG (15 as compared to 31).  Define a SMALLRAT as a rational number
+ * whose numerator (absolute value) and denominator are in that range.
+ * The denominator is assumed to be positive.
+ */
+#define SMALL          0x7fff
+#define SMALLRAT(q)    ((q).n <= SMALL && (q).n >= -SMALL && (q).d <= SMALL)
+
+
+/*
+ * This macro checks whether a 64-bit integer is actually less than or
+ * equal to MAXLONG in absolute value, 0x7fffffff.
+ */
+#define INT32(n)       ((n)[1] ==  0 && (n)[0] >= 0 ||         \
+                        (n)[1] == -1 && (n)[0] < 0 && (n)[0] != 0x80000000)
+
+
+/*
+ * Return whether the first 64-bit number equals the second.
+ * To be equal, both words must be equal.
+ */
+#define EQ64(x, y)     ( (x)[1] == (y)[1] && (x)[0] == (y)[0] )
+
+
+/*
+ * Return whether the first 64-bit number is greater than the second.
+ * If the high order words are equal, use the low order words, unsigned;
+ * otherwise, just use the high order words.
+ */
+#define GT64(x, y) (                                           \
+       (x)[1] == (y)[1] ?                                      \
+               (UINT32B)(x)[0] > (UINT32B)(y)[0]               \
+       :                                                       \
+               (x)[1] > (y)[1]                                 \
+)
+
+
+/*
+ * Return whether the first 64-bit number is less than the second.
+ * If the high order words are equal, use the low order words, unsigned;
+ * otherwise, just use the high order words.
+ */
+#define LT64(x, y) (                                           \
+       (x)[1] == (y)[1] ?                                      \
+               (UINT32B)(x)[0] < (UINT32B)(y)[0]               \
+       :                                                       \
+               (x)[1] < (y)[1]                                 \
+)
+
+
+/*
+ * Return whether the first *unsigned* 64-bit number is less than or equal to
+ * the second.  If the high order words are equal, use the low order words;
+ * otherwise, just use the high order words.
+ */
+#define LEU64(x, y) (                                          \
+       (x)[1] == (y)[1] ?                                      \
+               (UINT32B)(x)[0] <= (UINT32B)(y)[0]              \
+       :                                                       \
+               (UINT32B)(x)[1] <= (UINT32B)(y)[1]              \
+)
+
+
+/*
+ * Negate a 64-bit number.
+ */
+#define NEG64(x)       {                                               \
+       (x)[1] = ~(x)[1];       /* one's complement */                  \
+       (x)[0] = -(x)[0];       /* two's complement */                  \
+       if ((x)[0] == 0)        /* if "carry" must inc high word */     \
+               (x)[1]++;                                               \
+}
+
+
+/*
+ * Shift a 64-bit number left one bit as unsigned (not that it matters).
+ */
+#define SHL1U64(x)     {                                               \
+       (x)[1] <<= 1;           /* shift high word */                   \
+       if ((x)[0] < 0)         /* if high bit of low word is set */    \
+               (x)[1]++;       /* shift it into the high word */       \
+       (x)[0] <<= 1;           /* shift low word */                    \
+}
+
+
+/*
+ * Shift a 64-bit number right one bit as unsigned.
+ */
+#define SHR1U64(x)     {                                               \
+       (x)[0] = (UINT32B)(x)[0] >> 1;  /* shift low word */            \
+       if ((x)[1] & 1)                 /* if low bit of high word set*/\
+               (x)[0] |= 0x80000000;   /* shift it into low word */    \
+       (x)[1] = (UINT32B)(x)[1] >> 1;  /* shift low word */            \
+}
+
+
+
+/* declare as static the functions that are only used internally */
+#ifdef __STDC__
+static void ratmsg(int code);
+static void add64_64(INT32B a[], INT32B x[], INT32B y[]);
+static void mul32_64(INT32B a[], INT32B x, INT32B y);
+static void divmod64(INT32B x[], INT32B y[], INT32B q[], INT32B r[]);
+static void red64_64(INT32B num[], INT32B den[]);
+#else
+static void ratmsg(), add64_64(), mul32_64(), divmod64(), red64_64();
+#endif
+
+
+int raterrno;                  /* set to error type upon return to user */
+void (*raterrfuncp)();         /* error handler functions to be called */
+
+static RATIONAL zero = {0,1};
+\f
+/*
+ *     radd()          add two rational numbers
+ *
+ *     This function adds two rational numbers.  They must be in standard
+ *     form.
+ *
+ *     Parameters:     x       the first number
+ *                     y       the second number
+ *
+ *     Return value:   The sum (x + y), if it can be represented as a
+ *                     RATIONAL, else 0/1.
+ *
+ *     Side effects:   If radd() succeeds, it sets raterrno to RATNOERR.
+ *                     Otherwise, the numerator or denominator must have
+ *                     overflowed, so it sets raterrno to RATOVER and
+ *                     either prints a message or calls a user-supplied
+ *                     error handler.
+ */
+
+RATIONAL
+radd(x, y)
+
+RATIONAL x, y;
+
+{
+       RATIONAL a;                     /* the answer */
+       INT32B bign[2];                 /* 64-bit numerator */
+       INT32B bigd[2];                 /* 64-bit denominator */
+       INT32B bigt[2];                 /* temp storage */
+
+
+       raterrno = RATNOERR;            /* no error yet */
+
+       /*
+        * If the numbers are small enough, do it the easy way, since there is
+        * then no danger of overflow.
+        */
+       if (SMALLRAT(x) && SMALLRAT(y)) {
+               a.n = x.n * y.d + x.d * y.n;
+               a.d = x.d * y.d;
+               rred(&a);               /* reduce to standard form */
+               return(a);
+       }
+
+       /*
+        * To avoid overflow during the calculations, use two INT32B to
+        * hold numbers.
+        */
+       mul32_64(bign, x.n, y.d);       /* get first part of numerator */
+       mul32_64(bigt, x.d, y.n);       /* get second part of numerator */
+       add64_64(bign, bign, bigt);     /* add to get full numerator */
+       mul32_64(bigd, x.d, y.d);       /* get denominator */
+       red64_64(bign, bigd);           /* reduce */
+
+       /* overflow if the result can't fit in a RATIONAL */
+       if ( ! INT32(bign) || ! INT32(bigd) ) {
+               ratmsg(RATOVER);        /* set raterrno, report error */
+               return(zero);
+       }
+
+       a.n = bign[0];                  /* set answer */
+       a.d = bigd[0];
+
+       return(a);
+}
+\f
+/*
+ *     rsub()          subtract two rational numbers
+ *
+ *     This function subtracts two rational numbers.  They must be in standard
+ *     form.
+ *
+ *     Parameters:     x       the first number
+ *                     y       the second number
+ *
+ *     Return value:   The difference (x - y), if it can be represented as a
+ *                     RATIONAL, else 0/1.
+ *
+ *     Side effects:   If rsub() succeeds, it sets raterrno to RATNOERR.
+ *                     Otherwise, the numerator or denominator must have
+ *                     overflowed, so it sets raterrno to RATOVER and
+ *                     either prints a message or calls a user-supplied
+ *                     error handler.
+ */
+
+RATIONAL
+rsub(x, y)
+
+RATIONAL x, y;
+
+{
+       /*
+        * Just negate the second operand and add.  We could call rneg() to
+        * negate y, but why waste the time?
+        */
+       y.n = -y.n;
+       return(radd(x, y));
+}
+\f
+/*
+ *     rmul()          multiply two rational numbers
+ *
+ *     This function multiplies two rational numbers.  They must be in standard
+ *     form.
+ *
+ *     Parameters:     x       the first number
+ *                     y       the second number
+ *
+ *     Return value:   The product (x * y), if it can be represented as a
+ *                     RATIONAL, else 0/1.
+ *
+ *     Side effects:   If rsub() succeeds, it sets raterrno to RATNOERR.
+ *                     Otherwise, the numerator or denominator must have
+ *                     overflowed, so it sets raterrno to RATOVER and
+ *                     either prints a message or calls a user-supplied
+ *                     error handler.
+ */
+
+RATIONAL
+rmul(x, y)
+
+RATIONAL x, y;
+
+{
+       RATIONAL a;                     /* the answer */
+       INT32B bign[2];                 /* 64-bit numerator */
+       INT32B bigd[2];                 /* 64-bit denominator */
+
+
+       raterrno = RATNOERR;            /* no error yet */
+
+       /*
+        * If the numbers are small enough, do it the easy way, since there is
+        * then no danger of overflow.
+        */
+       if (SMALLRAT(x) && SMALLRAT(y)) {
+               a.n = x.n * y.n;
+               a.d = x.d * y.d;
+               rred(&a);               /* reduce to standard form */
+               return(a);
+       }
+
+       /*
+        * To avoid overflow during the calculations, use two INT32B to
+        * hold numbers.
+        */
+       mul32_64(bign, x.n, y.n);       /* get numerator */
+       mul32_64(bigd, x.d, y.d);       /* get denominator */
+       red64_64(bign, bigd);           /* reduce */
+
+       /* overflow if the result can't fit in a RATIONAL */
+       if ( ! INT32(bign) || ! INT32(bigd) ) {
+               ratmsg(RATOVER);        /* set raterrno, report error */
+               return(zero);
+       }
+
+       a.n = bign[0];                  /* set answer */
+       a.d = bigd[0];
+
+       return(a);
+}
+\f
+/*
+ *     rdiv()          divide two rational numbers
+ *
+ *     This function divides two rational numbers.  They must be in standard
+ *     form.
+ *
+ *     Parameters:     x       the first number
+ *                     y       the second number
+ *
+ *     Return value:   The quotient (x / y), if it is defined and can be
+ *                     represented as a RATIONAL, else 0/1.
+ *
+ *     Side effects:   If rdiv() succeeds, it sets raterrno to RATNOERR.
+ *                     Otherwise, either the second number was zero or the
+ *                     numerator or denominator overflowed.  In this case,
+ *                     it sets raterrno to RATDIV0 or RATOVER, respectively,
+ *                     and either prints a message or calls a user-supplied
+ *                     error handler.
+ */
+
+RATIONAL
+rdiv(x, y)
+
+RATIONAL x, y;
+
+{
+       RATIONAL r;                     /* reciprocal of y */
+
+
+       r = rinv(y);                    /* first find 1/y */
+
+       if (raterrno != RATNOERR)       /* if y was 0, return failure now */
+               return(zero);
+
+       /*
+        * Return  x * r.   Whether rmul() succeeds or fails, we still just want
+        * to leave raterrno the same and return what rmul() returns.
+        */
+       return(rmul(x, r));
+}
+\f
+/*
+ *     rneg()          negate a rational number
+ *
+ *     This function negates a rational number.  It must be in standard form.
+ *
+ *     Parameters:     x       the number
+ *
+ *     Return value:   The negative (-x).
+ *
+ *     Side effects:   It sets raterrno to RATNOERR.
+ */
+
+RATIONAL
+rneg(x)
+
+RATIONAL x;
+
+{
+       raterrno = RATNOERR;            /* no errors are possible */
+
+       x.n = -x.n;
+
+       /* answer is already in standard form since x was */
+       return(x);
+}
+\f
+/*
+ *     rinv()          invert a rational number
+ *
+ *     This function inverts a rational number.  It must be in standard form.
+ *
+ *     Parameters:     x       the number
+ *
+ *     Return value:   The reciprocal (1 / x), if it is defined, else 0/1.
+ *
+ *     Side effects:   If rinv() succeeds, it sets raterrno to RATNOERR.
+ *                     Otherwise, the second number must have been zero,
+ *                     so it sets raterrno to RATDIV0 and either prints a
+ *                     message or calls a user-supplied error handler.
+ */
+
+RATIONAL
+rinv(x)
+
+RATIONAL x;
+
+{
+       RATIONAL a;                     /* the answer */
+
+
+       /* check for division by 0 */
+       if (ZE(x)) {
+               ratmsg(RATDIV0);        /* set raterrno, report error */
+               return(zero);
+       }
+
+       raterrno = RATNOERR;            /* no errors from here on */
+
+       a.n = x.d;                      /* flip numerator and denominator */
+       a.d = x.n;
+
+       if (a.d < 0) {                  /* if x was negative, reverse signs */
+               a.n = -a.n;
+               a.d = -a.d;
+       }
+
+       return(a);
+}
+\f
+/*
+ *     rrai()          raise a rational number to an integral power
+ *
+ *     This function raises a rational number to an integral power.  The
+ *     rational number must be in standard form.
+ *
+ *     Parameters:     x       the rational number
+ *                     n       the power, an integer
+ *
+ *     Return value:   The result (x to the nth power), if it is defined and
+ *                     can be represented as a RATIONAL, else 0/1.
+ *
+ *     Side effects:   If rrai() succeeds, it sets raterrno to RATNOERR.
+ *                     Otherwise, either zero is being raised to a non-
+ *                     positive power, or the numerator or denominator
+ *                     overflowed.  In this case, it sets raterrno to
+ *                     RATDIV0 or RATOVER, respectively, and either prints
+ *                     a message or calls a user-supplied error handler.
+ */
+
+RATIONAL
+rrai(x, n)
+
+RATIONAL x;
+register int n;
+
+{
+       static RATIONAL one = {1,1};
+
+       RATIONAL a;                     /* the answer */
+       register int i;                 /* loop counter */
+
+
+       /* it is undefined to raise zero to a nonpositive power */
+       if (ZE(x) && n <= 0) {
+               ratmsg(RATDIV0);        /* set raterrno, report error */
+               return(zero);
+       }
+
+       raterrno = RATNOERR;            /* no error yet */
+
+       a = one;                        /* init to 1 */
+       if (n >= 0) {
+               for (i = 0; i < n; i++) {
+                       a = rmul(a, x);         /* mul again by x */
+                       if (raterrno != RATNOERR)
+                               return(zero);
+               }
+       } else {
+               for (i = 0; i > n; i--) {
+                       a = rdiv(a, x);         /* div again by x */
+                       if (raterrno != RATNOERR)
+                               return(zero);
+               }
+       }
+
+       return(a);
+}
+\f
+/*
+ *     rred()          reduce a rational number to standard form
+ *
+ *     This function puts a rational number into standard form; that is,
+ *     numerator and denominator will be relatively prime and the denominator
+ *     will be positive.  On input, they may be any integers whose absolute
+ *     values do not exceed MAXLONG.
+ *
+ *     Parameters:     ap      pointer to the rational number
+ *
+ *     Return value:   None.
+ *
+ *     Side effects:   If ap->d is 0, the function sets raterrno to RATDIV0,
+ *                     either prints a message or calls a user-supplied
+ *                     error handler, and sets *ap to 0/1.  Otherwise, it
+ *                     sets raterrno to RATNOERR and puts *ap in standard form.
+ */
+
+void
+rred(ap)
+
+register RATIONAL *ap;
+
+{
+       register INT32B b, c, r; /* temp variables for Euclidean algorithm */
+       register int sign;      /* answer is pos (1) or neg (-1) */
+
+
+       /*
+        * Since the numerator and denominator can be anything <= MAXLONG,
+        * we must guard against division by 0.
+        */
+       if (ap->d == 0) {
+               ratmsg(RATDIV0);        /* set raterrno, report error */
+               *ap = zero;
+               return;
+       }
+
+       raterrno = RATNOERR;            /* no errors possible from here on */
+
+       if (ap->n == 0) {               /* if so, answer is "0/1" */
+               ap->d = 1;
+               return;
+       }
+
+       /* now figure out sign of answer, and make n & d positive */
+       sign = 1;                       /* init to positive */
+       if (ap->n < 0) {                /* reverse if numerator neg */
+               sign = -sign;
+               ap->n = -(ap->n);
+       }
+       if (ap->d < 0) {                /* reverse if denominator neg */
+               sign = -sign;
+               ap->d = -(ap->d);
+       }
+
+       /* now check whether numerator or denominator are equal */
+       if (ap->n == ap->d) {           /* if so, answer is +1 or -1 */
+               ap->n = sign;
+               ap->d = 1;
+               return;
+       }
+
+       if (ap->n < ap->d) {            /* set so that c > b */
+               c = ap->d;
+               b = ap->n;
+       } else {
+               c = ap->n;
+               b = ap->d;
+       }
+
+       /* use Euclidean Algorithm to find greatest common divisor of c & b */
+       do {
+               r = c % b;
+               c = b;
+               b = r;
+       } while (r != 0);
+
+       /* now c is the greatest common divisor */
+
+       ap->n /= c;             /* divide out greatest common divisor */
+       ap->d /= c;             /* divide out greatest common divisor */
+
+       if (sign < 0)           /* put sign in if result should be negative */
+               ap->n = -(ap->n);
+
+       return;
+}
+\f
+/*
+ *     ator()          convert an ascii string to a rational number
+ *
+ *     This function takes an ascii string as input and interprets it as
+ *     a rational number.  White space may precede the number, but the
+ *     number may not contain white space.  The numerator may be preceded
+ *     by a minus sign.  The denomintor is optional, but if present, must
+ *     not contain a sign.  In short, the number must match one of the
+ *     following lex regular expressions, which starts where s points and
+ *     ends before the first character not matching the pattern:
+ *             [ \t\n]*-?[0-9]+
+ *             [ \t\n]*-?[0-9]+\/[0-9]+
+ *     Further restrictions are that the absolute values of numerator and
+ *     denominator cannot exceed MAXLONG, and the denominator cannot be 0.
+ *     If neither pattern is matched, or the further restrictions are
+ *     violated, the function sets *rp to 0/1 and returns NULL.  Otherwise,
+ *     it sets *rp to the result in standard form, and returns a pointer to
+ *     the first char after the number found.
+ *
+ *     Parameters:     rp      pointer to where the answer goes
+ *                     s       string containing ascii rational number
+ *
+ *     Return value:   If a valid rational number is found, the function
+ *                     returns a pointer to the next char in the string
+ *                     following the number.  Otherwise it returns NULL.
+ *
+ *     Side effects:   If ator() succeeds, it sets *rp to the result.
+ *                     Otherwise, it sets it to 0/1.
+ */
+
+char *
+ator(rp, s)
+
+register RATIONAL *rp;
+register char s[];
+
+{
+       register char *p;       /* point somewhere in s[] */
+       int sign;               /* 1 means positive, -1 negative */
+
+
+       /* skip by white space */
+       for (p = s; isspace(*p); p++)
+               ;
+
+       /* init sign to positive; then reverse it if a dash is found */
+       sign = 1;
+       if (p[0] == '-') {
+               sign = -1;
+               p++;
+       }
+
+       /* fail if there are no digits */
+       if ( ! isdigit(*p) ) {
+               *rp = zero;
+               return(NULL);
+       }
+
+       /*
+        * Collect the numerator digits, and defend against overflow.
+        */
+       rp->n = 0;
+       while ( isdigit(*p) ) {
+               if (rp->n > MAXLONG / 10) {
+                       *rp = zero;
+                       return(NULL);
+               }
+               rp->n *= 10;
+               if (rp->n > MAXLONG - (*p - '0')) {
+                       *rp = zero;
+                       return(NULL);
+               }
+               rp->n += *p++ - '0';
+       }
+
+       if (sign < 0)                   /* make negative if necessary */
+               rp->n = -(rp->n);
+
+
+       /*
+        * If there is to be a denominator, collect its digits.  Otherwise,
+        * set it to 1.  Defend against overflow.
+        */
+       if (*p == '/') {
+               p++;
+               if ( ! isdigit(*p) ) {  /* must be digit (no '-' allowed) */
+                       *rp = zero;
+                       return(NULL);
+               }
+               rp->d = 0;
+               while ( isdigit(*p) ) {
+                       if (rp->d > MAXLONG / 10) {
+                               *rp = zero;
+                               return(NULL);
+                       }
+                       rp->d *= 10;
+                       if (rp->d > MAXLONG - (*p - '0')) {
+                               *rp = zero;
+                               return(NULL);
+                       }
+                       rp->d += *p++ - '0';
+               }
+               if (rp->d == 0) {       /* zero denominator is a failure */
+                       *rp = zero;
+                       return(NULL);
+               }
+       } else {
+               rp->d = 1;              /* no denominator; assume 1 */
+       }
+
+       rred(rp);                       /* reduce the fraction */
+
+       return(p);                      /* first char after the number */
+}
+\f
+/*
+ *     rtoa()          convert a rational number to an ascii string
+ *
+ *     This function takes a rational number as input converts it into
+ *     an ascii string.  If the denominator is 1, it will not be printed.
+ *     The number must be in standard form.
+ *
+ *     Parameters:     s       pointer to where the answer goes
+ *                     rp      pointer to the rational number
+ *
+ *     Return value:   The function returns a pointer to the next char in
+ *                     the string following the number.
+ *
+ *     Side effects:   The function sets s[] to the result.
+ */
+
+char *
+rtoa(s, rp)
+
+register char s[];
+RATIONAL *rp;
+
+{
+       register INT32B num, den;       /* copy of num and den from *rp */
+       register int i;                 /* index into t[] */
+       char t[12];                     /* temp answer string */
+
+
+       num = rp->n;                    /* copy num and den for efficiency */
+       den = rp->d;
+
+       if (num < 0) {                  /* if num is negative */
+               *s++ = '-';             /* output minus sign */
+               num = -num;             /* and make num positive */
+       }
+
+       i = 0;
+       do {                            /* calc digits in reverse order */
+               t[i++] = num % 10 + '0';
+               num /= 10;
+       } while (num > 0);              /* always loop at least once so 0="0"*/
+
+       while (--i >= 0)                /* copy digits to answer string */
+               *s++ = t[i];
+
+       if (den != 1) {                 /* if a denominator is needed */
+               *s++ = '/';             /* fraction bar */
+               i = 0;
+               do {                    /* calc digits in reverse order */
+                       t[i++] = den % 10 + '0';
+                       den /= 10;
+               } while (den > 0);
+
+               while (--i >= 0)        /* copy digits to answer string */
+                       *s++ = t[i];
+       }
+
+       return(s);
+}
+\f
+/*
+ *     gtrat()         decide whether one rational is greater than another
+ *
+ *     This function decides whether its first parameter is greater than
+ *     its second.  It is used by the macros GT, GE, LT, and LE.
+ *     The numbers must be in standard form.  (Actually, all that is
+ *     matters is that the denominators be positive.)
+ *
+ *     Parameters:     x       the first rational
+ *                     y       the second rational
+ *
+ *     Return value:   1 if x > y, otherwise 0
+ *
+ *     Side effects:   none
+ */
+
+int
+gtrat(x, y)
+
+RATIONAL x, y;
+
+{
+       INT32B a[2];            /* temp holding areas for 64-bit numbers */
+       INT32B b[2];
+
+
+       /* if no overflow possible, cross-multiply and return truth value */
+       /* note:  this depends on positive denominators */
+       if (SMALLRAT(x) && SMALLRAT(y))
+               return(x.n * y.d > x.d * y.n);
+
+       /*
+        * The numbers are too big; we have to do it the hard way to avoid
+        * overflow.  Cross-multiply.  Note: this depends on positive
+        * denominators.
+        */
+       mul32_64(a, x.n, y.d);
+       mul32_64(b, x.d, y.n);
+
+       return(GT64(a, b));
+}
+\f
+/*
+ *     ratmsg()        handle rational error of type "code"
+ *
+ *     This function sets raterrno.  Then calls the user's error handler,
+ *     if there is one, or else prints a message to standard error.
+ *
+ *     Parameters:     code    the error code
+ *
+ *     Return value:   None.
+ *
+ *     Side effects:   raterrno is set; then either a message is printed
+ *                     to standard error or the user's error handler is
+ *                     called.
+ */
+
+static void
+ratmsg(code)
+
+int code;
+
+{
+       raterrno = code;                /* set global error flag */
+
+       if (raterrfuncp == 0) {
+               /* no user trap exists, so print message from here */
+               switch (code) {
+               case RATOVER:
+                       (void)fputs("rational overflow\n", stderr);
+                       break;
+
+               case RATDIV0:
+                       (void)fputs("rational division by zero\n", stderr);
+                       break;
+
+               case RATPARM:
+                       (void)fputs("invalid number passed to rational number routine\n", stderr);
+                       break;
+
+               default:
+                       (void)fputs("error in rational routines\n", stderr);
+                       break;
+               }
+       } else {
+               /* call user trap function to handle the error */
+               (*raterrfuncp)(code);
+       }
+}
+\f
+/*
+ *     add64_64()      add 64-bit numbers to get a 64-bit number
+ *
+ *     This function adds two 64-bit signed numbers to get a 64-bit
+ *     signed number.  It is assumed that the result will not overflow.
+ *     Any of the inputs may be the same arrays.
+ *
+ *     Parameters:     a       answer goes here
+ *                     x       the first input
+ *                     y       the second input
+ *
+ *     Return value:   none
+ *
+ *     Side effects:   a is set to the result.
+ */
+
+static void
+add64_64(a, x, y)
+
+INT32B a[2];
+INT32B x[2];
+INT32B y[2];
+
+{
+       INT32B t[2];                    /* temp storage */
+
+
+       /* first add low and high parts separately */
+       /* use temp storage in case a[] is the same array as x[] or y[] */
+       t[0] = x[0] + y[0];
+       t[1] = x[1] + y[1];
+
+       /* figure out if the low part carries into the high part */
+       if (x[0] < 0 && y[0] < 0) {             /* both high order bits set */
+               t[1]++;                         /* must be a carry */
+       } else if (x[0] < 0 || y[0] < 0) {      /* exactly one high bit set */
+               if (t[0] >= 0)                  /* if result high bit clear */
+                       t[1]++;                 /* must be a carry */
+       }
+
+       a[0] = t[0];                    /* copy results */
+       a[1] = t[1];
+}
+\f
+/*
+ *     mul32_64()      multiply 32-bit numbers to get a 64-bit number
+ *
+ *     This function multiplies two 32-bit signed numbers to get a 64-bit
+ *     signed number.  The numbers must not equal 0x80000000.  Overflow
+ *     cannot occur.
+ *
+ *     Parameters:     a       answer goes here
+ *                     x       the first 32-bit number
+ *                     y       the second 32-bit number
+ *
+ *     Return value:   none
+ *
+ *     Side effects:   a is set to the result.
+ */
+
+static void
+mul32_64(a, x, y)
+
+INT32B a[2];
+INT32B x;
+INT32B y;
+
+{
+       INT32B t[2];                    /* temp storage for inner terms */
+       INT32B xl, xh;                  /* low and high 16 bits of x */
+       INT32B yl, yh;                  /* low and high 16 bits of y */
+       int sign;                       /* sign of the result */
+
+
+       /* make both numbers positive and determine the sign of the result */
+       sign = 1;                               /* start at positive */
+       if (x < 0) {
+               x = -x;
+               sign = -sign;
+       }
+       if (y < 0) {
+               y = -y;
+               sign = -sign;
+       }
+
+       /* break x and y into high and low pieces */
+       xl = x & 0xffff;                /* 0 <= xl <= 0xffff */
+       xh = x >> 16;                   /* 0 <= xh <= 0x7fff */
+       yl = y & 0xffff;                /* 0 <= yl <= 0xffff */
+       yh = y >> 16;                   /* 0 <= yh <= 0x7fff */
+
+       /* multiply the outer parts */
+       a[0] = xl * yl;                 /* 0 <= a[0] <= 0xfffe0001 */
+       a[1] = xh * yh;                 /* 0 <= a[1] <= 0x3fff0001 */
+
+       /* multiply the inner parts and break the result in two pieces */
+       t[0] = xl * yh + xh * yl;       /* 0 <= t[0] <= 0xfffd0002 */
+       t[1] = (UINT32B)t[0] >> 16;             /* 0 <= t[1] <= 0x0000fffd */
+       t[0] <<= 16;                            /* 0 <= t[0] <= 0xffff0000 */
+
+       /* add the two partial products */
+       add64_64(a, a, t);              /* 0 <= a <= 0x3fffffff00000001 */
+
+       /* if the answer is supposed to be negative, negate it */
+       if (sign < 0)
+               NEG64(a);
+}
+\f
+/*
+ *     divmod64()      find quotient and remainder of two 64-bit numbers
+ *
+ *     This function takes two 64-bit numbers and divides the first by the
+ *     second, to get a quotient and remainder, both 64 bits.  It is assumed
+ *     that the first number is nonnegative and the second number is positive.
+ *     q and r must be different arrays.
+ *
+ *     Parameters:     x       first number (dividend)
+ *                     y       second number (divisor)
+ *                     q       quotient
+ *                     r       remainder
+ *
+ *     Return value:   none
+ *
+ *     Side effects:   q and r are altered to be the results
+ *                     x and y are not altered
+ */
+
+static void
+divmod64(x, y, q, r)
+
+INT32B x[2];
+INT32B y[2];
+INT32B q[2];
+INT32B r[2];
+
+{
+       INT32B s[2];            /* temp storage for divisor */
+       INT32B t[2];            /* temp storage for scratch */
+       register int shift;     /* how far has y been shifted? */
+
+
+       r[0] = x[0];            /* copy dividend to remainder place */
+       r[1] = x[1];
+       s[0] = y[0];            /* copy divisor to temp storage */
+       s[1] = y[1];
+
+       /* shift divisor left until greater than dividend */
+       /* compare as unsigned so no problem if it gets shifted into sign bit */
+       for (shift = 0; LEU64(s, r); shift++)
+               SHL1U64(s);
+
+       SHR1U64(s);             /* shift it back right one, so <= dividend */
+       shift--;
+
+       q[0] = 0;               /* start quotient at 0 */
+       q[1] = 0;
+
+       /*
+        * Loop once for each bit shifted.
+        */
+       for ( ; shift >= 0; shift--) {
+               /*
+                * If the current divisor does not exceed what's left of the
+                * dividend, subtract it from it, and record that by setting
+                * the low order bit of the current quotient.
+                */
+               if ( ! GT64(s, r) ) {
+                       t[0] = s[0];
+                       t[1] = s[1];
+                       NEG64(t);
+                       add64_64(r, r, t);
+                       q[0] |= 1;
+               }
+
+               /* shift quotient left and divisor right */
+               SHL1U64(q);
+               SHR1U64(s);
+       }
+
+       SHR1U64(q);             /* shift quotient right */
+}
+\f
+/*
+ *     red64_64()      reduce a 64 bit over 64 bit rational to lowest terms
+ *
+ *     This function takes two 64-bit numbers as numerator and denominator
+ *     of a rational number, and reduces them to lowest terms, with the
+ *     denominator positive.  If the user called this package correctly, the
+ *     denominator cannot be zero, but to be defensive we check for that, and
+ *     if it happens, set raterrno to RATPARM and either print a message or
+ *     call a user-supplied error handler.
+ *
+ *     Parameters:     num     numerator
+ *                     den     denominator
+ *
+ *     Return value:   none
+ *
+ *     Side effects:   num and den are altered to be the result
+ */
+
+static void
+red64_64(num, den)
+
+INT32B num[2];
+INT32B den[2];
+
+{
+       INT32B b[2], c[2], r[2]; /* temp variables for Euclidean algorithm */
+       INT32B junk[2];         /* placeholder for calling divmod64 */
+       int sign;               /* answer is pos (1) or neg (-1) */
+
+
+       if (den[1] == 0 && den[0] == 0) { /* if den == 0 */
+               /*
+                * This is an error.  The user must have called a routine with
+                * an invalid number for us to get here, in fact a number with
+                * a zero denominator, since "den" here always was created as
+                * the product of denominators.  Report the error and return
+                * zero.
+                */
+               num[1] = 0;             /* set num = 0 */
+               num[0] = 0;
+               den[1] = 0;             /* set den = 1 */
+               den[0] = 1;
+               ratmsg(RATPARM);        /* set raterrno, report error */
+               return;
+       }
+
+       if (num[1] == 0 && num[0] == 0) { /* if num == 0 */
+               den[1] = 0;             /* set den = 1; answer is 0/1 */
+               den[0] = 1;
+               return;
+       }
+
+       /* now figure out sign of answer, and make num & den positive */
+       sign = 1;                       /* init to positive */
+       if (num[1] < 0) {               /* if numerator neg */
+               sign = -sign;           /* reverse the sign */
+               NEG64(num);
+       }
+       if (den[1] < 0) {               /* if denominator neg */
+               sign = -sign;           /* reverse the sign */
+               NEG64(den);
+       }
+
+       /* now check whether numerator or denominator is larger */
+       if (EQ64(num, den)) {
+               num[0] = sign;          /* answer is +1 or -1 */
+
+               if (sign < 0)           /* set high order word to sign bit */
+                       num[1] = -1;
+               else
+                       num[1] = 0;
+
+               den[1] = 0;             /* set den to 1 */
+               den[0] = 1;
+
+               return;
+       }
+
+       /* set up c and b so that one is num, the other den, and c > b */
+       if (LT64(num, den)) {                   /* if num < den */
+               c[0] = den[0];                  /* c = den */
+               c[1] = den[1];
+               b[0] = num[0];                  /* b = num */
+               b[1] = num[1];
+       } else {
+               c[0] = num[0];                  /* c = num */
+               c[1] = num[1];
+               b[0] = den[0];                  /* b = den */
+               b[1] = den[1];
+       }
+
+       /* use Euclidean Algorithm to find greatest common divisor of c & b */
+       do {
+               divmod64(c, b, junk, r);        /* r = c % b */
+               c[0] = b[0];                    /* c = b */
+               c[1] = b[1];
+               b[0] = r[0];                    /* b = r */
+               b[1] = r[1];
+       } while (r[0] != 0 || r[1] != 0);       /* while r != 0 */
+
+       /* now c is the greatest common divisor of num and den */
+
+       /* divide out the greatest common divisor and put the sign in */
+       divmod64(num, c, num, junk);            /* num /= c */
+       if (sign < 0)                           /* if should be negative */
+               NEG64(num);                     /* negate the numerator */
+       divmod64(den, c, den, junk);            /* den /= c */
+
+       return;
+}
diff --git a/mup/mup/rational.h b/mup/mup/rational.h
new file mode 100644 (file)
index 0000000..8530dca
--- /dev/null
@@ -0,0 +1,108 @@
+/* Copyright (c) 1995, 1996, 1997, 2001 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ *     rational.h      definitions for using rational numbers
+ */
+#ifndef _RATIONAL
+#define _RATIONAL
+
+
+/*
+ * The code in rational.h/rational.c is written in a way that depends on
+ * certain variables being 32-bit numbers stored in two's complement form.  For
+ * most compilers, "long" works for this, but for some compilers, "long" is
+ * 64 bits, or maybe something else.  C standards after (and not including) the
+ * 1994 version guarantee the existence of a header file stdint.h which defines
+ * typedefs int32_t and uint32_t.  So for those standards we will use those
+ * typedefs from that header when defining our INT32B and UINT32B.  Otherwise
+ * we will just use long and unsigned long.  If these aren't 32-bit, two's
+ * complement, you will have to change this code.
+ */
+#if __STDC_VERSION__ > 199409L
+#include <stdint.h>
+#define        INT32B  int32_t
+#define        UINT32B uint32_t
+#else
+#define        INT32B  long
+#define        UINT32B unsigned long
+#endif
+
+/*
+ * Define the structure that represents a rational number.  The number
+ * should be kept in standard form; that is, in lowest terms with a positive
+ * denominator.  Zero should be stored as 0/1.
+ */
+struct rational {
+       INT32B n;       /* numerator */
+       INT32B d;       /* denominator */
+};
+
+typedef struct rational RATIONAL;
+
+
+/* macros for comparing rational numbers */
+/* numbers must be in standard form */
+
+#define EQ(a, b)       ((a).n == (b).n && (a).d == (b).d)
+#define NE(a, b)       ((a).n != (b).n || (a).d != (b).d)
+
+/* must call function for inequalities, because overflow possibilities */
+
+#define GT(a, b)       gtrat(a, b)
+#define LT(a, b)       gtrat(b, a)
+#define GE(a, b)       ( ! gtrat(b, a) )
+#define LE(a, b)       ( ! gtrat(a, b) )
+
+
+/* macros for testing a rational number */
+/* numbers must be in standard form, or at least have positive denominator */
+
+#define ZE(a)          ((a).n == 0)
+#define PL(a)          ((a).n >  0)
+#define MI(a)          ((a).n <  0)
+#define NZ(a)          ((a).n != 0)
+#define NM(a)          ((a).n >= 0)
+#define NP(a)          ((a).n <= 0)
+
+
+/* definitions for error handling */
+
+#define        RATNOERR        0
+#define RATOVER                1
+#define RATDIV0                2
+#define RATPARM                3
+
+#ifndef MAXLONG
+#define MAXLONG                0x7fffffff
+#endif
+
+extern int raterrno;                   /* holds error code */
+#ifdef __STDC__
+extern void (*raterrfuncp)(int);       /* pointer to user error handler */
+#else
+extern void (*raterrfuncp)();          /* pointer to user error handler */
+#endif
+
+
+/* functions to do operations on rational numbers */
+
+#ifdef __STDC__
+extern RATIONAL radd(RATIONAL x, RATIONAL y);
+extern RATIONAL rsub(RATIONAL x, RATIONAL y);
+extern RATIONAL rmul(RATIONAL x, RATIONAL y);
+extern RATIONAL rdiv(RATIONAL x, RATIONAL y);
+extern RATIONAL rneg(RATIONAL x);
+extern RATIONAL rinv(RATIONAL x);
+extern RATIONAL rrai(RATIONAL x, int n);
+extern void rred(RATIONAL *ap);
+extern char *ator(RATIONAL *rp, char s[]);
+extern char *rtoa(char s[], RATIONAL *rp);
+extern int gtrat(RATIONAL x, RATIONAL y);
+#else
+extern RATIONAL radd(), rsub(), rmul(), rdiv(), rneg(), rinv(), rrai();
+extern void rred();
+extern char *ator(), *rtoa();
+extern int gtrat();
+#endif
+
+#endif
diff --git a/mup/mup/relvert.c b/mup/mup/relvert.c
new file mode 100644 (file)
index 0000000..f0b623e
--- /dev/null
@@ -0,0 +1,2758 @@
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ * Name:       relvert.c
+ *
+ * Description:        This file contains functions for setting all remaining
+ *             relative vertical coordinates.
+ */
+
+#include <string.h>
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+/* how many rectangles to malloc initially and at each realloc if needed */
+#define RECTCHUNK      (100)
+
+/* rectangle structure; see procscore() prologue for explanation of its use */
+struct RECTAB {
+       float n, s, e, w;       /* boundaries of a rectangle */
+                               /* horz coords are absolute; vertical coords */
+                               /*  are relative to center staff line */
+                               /*  (baseline for "between") */
+       short relevant;         /* is rectangle relevant? */
+       short tried;            /* have we tried this one yet? */
+};
+static struct RECTAB *rectab;  /* ptr to malloc'ed and realloc'ed array */
+
+/* this fudge factor prevents roundoff error from causing overlap */
+#define FUDGE  (0.001)
+
+/* these symbols tell certain subroutines which things to work on */
+#define        DO_OTHERS       0       /* default */
+#define        DO_PHRASE       1
+
+
+static int reclim;             /* index after last rectangle in rectab */
+
+static void procstaff P((struct MAINLL *mainll_p, int s)); 
+static void dostaff P((int s, int place));
+static void dogroups P((struct MAINLL *start_p, int s, int place));
+static void llgrps P((struct STAFF *staff_p, struct GRPSYL *gs_p, int place));
+static void dobeamalt P((struct MAINLL *start_p, int s, int place));
+static void onebeamalt P((struct GRPSYL *gs_p));
+static double getstemendvert P((struct GRPSYL *gs_p));
+static void linerects P((double x1, double y1, double x2, double y2, int side,
+               double halfstaff));
+static void docurve P((struct MAINLL *start_p, int s, int place,
+               int do_which));
+static void curverect P((int s, struct STUFF *stuff_p, double halfstaff));
+static void curvepiecerect P((double x1, double y1, double x2, double y2,
+               double halfstaff));
+static void dotuplet P((struct MAINLL *start_p, int s, int place));
+static void onetuplet P((struct STAFF *staff_p, struct GRPSYL *start_p,
+               int place));
+static void domiscstuff P((struct MAINLL *start_p, int s, int place,
+               unsigned long do_which));
+static void dolyrics P((struct MAINLL *start_p, int s, int place));
+static void getvsize P((struct MAINLL *start_p, int s, int place, int v,
+               float *asc_p, float *des_p));
+static void setsylvert P((struct MAINLL *start_p, int s, int place, int v,
+               double baseline));
+static void dopedal P((struct MAINLL *start_p, int s));
+static void doendings P((struct MAINLL *start_p, int s));
+static void storeend P((struct MAINLL *start_p, struct MAINLL *end_p, int s));
+static void dorehears P((struct MAINLL *start_p, int s));
+static double stackit P((double west, double east, double height, double dist,
+               int place));
+static void inc_reclim P((void));
+\f
+/*
+ * Name:        relvert()
+ *
+ * Abstract:    Set all relative vertical coords not already set.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets all remaining relative vertical coords.
+ *             It calls procstaff() once for each staff in each score to
+ *             do this.
+ */
+
+void
+relvert()
+
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct MAINLL *end_p;           /* point at end of a piece of MLL */
+       struct MAINLL *m2_p;            /* another pointer along MLL */
+       int s;                          /* staff number */
+       int gotbar;                     /* was a bar found in this chunk? */
+
+
+       debug(16, "relvert");
+       /*
+        * Find each section of the main linked list, delimited by FEEDs.
+        * For each such section, call procstaff() for each visible staff.
+        * Keep SSVs up to date so that we always know what staffs are visible.
+        */
+       initstructs();                  /* clean out old SSV info */
+
+       /* skip anything before first FEED first */
+       for (mainll_p = Mainllhc_p; mainll_p->str != S_FEED;
+                       mainll_p = mainll_p->next) {
+               if (mainll_p->str == S_SSV)
+                       asgnssv(mainll_p->u.ssv_p);
+       }
+
+       /*
+        * Initially allocate RECTCHUNK rectangles.  If we find we need more at
+        * some point, we'll realloc to get more.
+        */
+       MALLOC(RECTAB, rectab, RECTCHUNK);
+
+       for (;;) {
+               /*
+                * Find end of this chunk.  If it has no bars in it, this must
+                * either be the end of the MLL and there was a final feed
+                * after all the music data, or else this is a block.  Either
+                * way, there is no need to process this chunk.
+                */
+               gotbar = NO;
+               for (end_p = mainll_p->next; end_p != 0 &&
+                               end_p->str != S_FEED; end_p = end_p->next) {
+                       if (end_p->str == S_BAR)
+                               gotbar = YES;
+               }
+               if (gotbar == NO) {
+                       if (end_p == 0)
+                               break;          /* end of MLL, get out */
+
+                       /* update SSVs to beginning of next score */
+                       for (m2_p = mainll_p->next; m2_p != end_p;
+                                               m2_p = m2_p->next) {
+                               if (m2_p->str == S_SSV)
+                                       asgnssv(m2_p->u.ssv_p);
+                       }
+
+                       mainll_p = end_p;       /* block, skip by it */
+                       continue;
+               }
+
+               for (s = 1; s <= Score.staffs; s++) {
+                       if (svpath(s, VISIBLE)->visible == YES)
+                               procstaff(mainll_p, s);
+               }
+
+               /* update SSVs to beginning of next score */
+               for (m2_p = mainll_p->next; m2_p != end_p; m2_p = m2_p->next) {
+                       if (m2_p->str == S_SSV)
+                               asgnssv(m2_p->u.ssv_p);
+               }
+
+               if (end_p == 0)
+                       break;
+               mainll_p = end_p;
+       }
+
+       FREE(rectab);
+}
+\f
+/*
+ * Name:        procstaff()
+ *
+ * Abstract:    Set all relative vertical coords for a staff in one score.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets all remaining relative vertical coords
+ *             for a given staff of a given score.
+ */
+
+static void
+procstaff(start_p, s)
+
+struct MAINLL *start_p;                /* FEED at the start of this score */
+int s;                         /* the staff we are to work on */
+
+{
+       struct MAINLL *mainll_p;/* point along main linked list */
+       char *order;            /* point at a subarray in markorder */
+       int stk;                /* stacking order number */
+       int mk;                 /* mark type */
+       unsigned long do_which; /* bit map of which mark types to do */
+       float north, south;     /* relative coords of staff */
+       float hb;               /* height of "between" objects */
+       int k;                  /* loop variable */
+
+
+       debug(32, "procstaff file=%s line=%d s=%d", start_p->inputfile,
+                       start_p->inputlineno, s);
+
+       /* set globals like Staffscale for use by the rest of the file */
+       set_staffscale(s);
+
+       /*
+        * Each structure in rectab[] represents something to be drawn that
+        * is associated with this staff, beginning with the staff itself.
+        * The coordinates define the rectangle that surrounds the object.
+        * The rectangles' edges are horizontal and vertical.  So if an object
+        * (like a slanted beam) doesn't fit well in such a recangle, multiple
+        * rectangles are used to enclose pieces of it, as in integration in
+        * calculus.
+        *
+        * The first part of this function does this for things that are above
+        * the staff.  The second part does it for things that are below it.
+        * The third part does it for items that are to be centered (if
+        * possible) between two staffs.  In the first two parts, rectangles
+        * are added to the table one at a time, working outwards from the
+        * staff.  In the third part, they are piled on an imaginary baseline.
+        *
+        * Some objects (like note groups) already have an assigned position.
+        * and their rectangles are simply added to the table, regardless of
+        * whether they overlap preexisting rectangles.
+        *
+        * Some objects (like phrase marks) get their positions figured out
+        * now, by some unique algorithm that doesn't make use of the table of
+        * rectangles, and then their rectangles are added to the table, again
+        * not worrying about overlap with preexisting rectangles.
+        *
+        * Some objects (like "stuff" to be printed) make use of the table to
+        * figure out where their rectangles should be placed.  They are placed
+        * as close to the staff (or baseline, for "between") as is possible
+        * without overlapping preexisting rectangles (or, in the case of
+        * chords, getting closer to the staff than allowed by "chorddist"; or
+        * in the case of rom, ital, bold, boldital, or rehearsal marks, closer
+        * than "dist"; or in the case of dynamics, closer than "dyndist").
+        * (And some things have their own "dist" to override these parameters,
+        * and the optional ability to force a distance regardless of overlap.)
+        * To see if the rectangle being added overlaps, first its east and
+        * west are tested.  All previous rectangles that are "out of its way"
+        * horizontally are marked not "relevant"; the others are marked
+        * "relevant".  As positions are tried, working outwards, positions
+        * that fail to avoid overlap are marked "tried".  (For chords, and
+        * rom/ital/bold/boldital, previous rectangles that are closer to the
+        * staff than the stuff is allowed to come anyhow are pre-marked as if
+        * "tried".)
+        */
+
+       /*
+        * Fill rectab for the objects above this staff.
+        */
+       reclim = 0;                     /* rectab is initially empty */
+
+       dostaff(s, PL_ABOVE);
+       dogroups(start_p, s, PL_ABOVE);
+       dobeamalt(start_p, s, PL_ABOVE);
+       docurve(start_p, s, PL_ABOVE, DO_OTHERS);
+       dotuplet(start_p, s, PL_ABOVE);
+       docurve(start_p, s, PL_ABOVE, DO_PHRASE);
+
+       /* get stacking order of the user-controllable mark types */
+       order = svpath(s, ABOVEORDER)->markorder[PL_ABOVE];
+
+       /* loop on each possible stacking order number */
+       for (stk = 1; stk <= NUM_MARK; stk++) {
+
+               /* set bit map for each mark type that has this order number */
+               do_which = 0;
+               for (mk = 0; mk < NUM_MARK; mk++) {
+                       if (order[mk] == stk) {
+                               do_which |= (1L << mk);
+                       }
+               }
+               /* if no marks, we're done; stacking orders are contiguous */
+               if (do_which == 0)
+                       break;
+
+               /*
+                * Some mark types must have a unique order number, not shared
+                * with any others.  For each of them, do a case statement to
+                * call their subroutine.  The other ones all share the same
+                * subroutine, so call it in the default to do the mark types
+                * listed in the bit map.
+                */
+               switch (do_which) {
+               case 1L << MK_LYRICS:
+                       dolyrics(start_p, s, PL_ABOVE);
+                       break;
+               case 1L << MK_ENDING:
+                       doendings(start_p, s);
+                       break;
+               case 1L << MK_REHEARSAL:
+                       dorehears(start_p, s);
+                       break;
+               case 1L << MK_PEDAL:
+                       break;  /* ignore for above */
+               default:
+                       domiscstuff(start_p, s, PL_ABOVE, do_which);
+                       break;
+               }
+       }
+
+       /*
+        * Find the northernmost rectangle, for setting the staff's north.
+        * But don't let north be so close that things sticking out might
+        * almost touch another staff.  Staffs smaller than a regular 5 line
+        * staff will still be given as much space.  In any case, we want at
+        * least 3 stepsizes of white space.
+        */
+       north = staffvertspace(s) / 2.0 + 3.0 * Stepsize;
+       for (k = 0; k < reclim; k++) {
+               if (rectab[k].n > north)
+                       north = rectab[k].n;
+       }
+
+       /*
+        * Fill rectab for the objects below this staff.
+        */
+       reclim = 0;                     /* rectab is initially empty */
+
+       dostaff(s, PL_BELOW);
+       dogroups(start_p, s, PL_BELOW);
+       dobeamalt(start_p, s, PL_BELOW);
+       docurve(start_p, s, PL_BELOW, DO_OTHERS);
+       dotuplet(start_p, s, PL_BELOW);
+       docurve(start_p, s, PL_BELOW, DO_PHRASE);
+
+       /* get stacking order of the user-controllable mark types */
+       order = svpath(s, BELOWORDER)->markorder[PL_BELOW];
+
+       /* loop on each possible stacking order number */
+       for (stk = 1; stk <= NUM_MARK; stk++) {
+
+               /* set bit map for each mark type that has this order number */
+               do_which = 0;
+               for (mk = 0; mk < NUM_MARK; mk++) {
+                       if (order[mk] == stk) {
+                               do_which |= (1L << mk);
+                       }
+               }
+               /* if no marks, we're done; stacking orders are contiguous */
+               if (do_which == 0)
+                       break;
+
+               /*
+                * Some mark types must have a unique order number, not shared
+                * with any others.  For each of them, do a case statement to
+                * call their subroutine.  The other ones all share the same
+                * subroutine, so call it in the default to do the mark types
+                * listed in the bit map.
+                */
+               switch (do_which) {
+               case 1L << MK_LYRICS:
+                       dolyrics(start_p, s, PL_BELOW);
+                       break;
+               case 1L << MK_ENDING:
+               case 1L << MK_REHEARSAL:
+                       break;  /* ignore for below */
+               case 1L << MK_PEDAL:
+                       dopedal(start_p, s);
+                       break;
+               default:
+                       domiscstuff(start_p, s, PL_BELOW, do_which);
+                       break;
+               }
+       }
+
+       /*
+        * Find the southernmost rectangle, for setting the staff's south.
+        * But don't let south be so close that things sticking out might
+        * almost touch another staff.  Staffs smaller than a regular 5 line
+        * staff will still be given as much space.  In any case, we want at
+        * least 3 stepsizes of white space.
+        */
+       south = -(staffvertspace(s) / 2.0 + 3.0 * Stepsize);
+       for (k = 0; k < reclim; k++) {
+               if (rectab[k].s < south)
+                       south = rectab[k].s;
+       }
+
+       /*
+        * Fill rectab for the objects between this staff and the one below.
+        */
+       reclim = 0;                     /* rectab is initially empty */
+
+       /* set up baseline, a rectangle of height 0 spanning the page */
+       rectab[reclim].w = 0;
+       rectab[reclim].e = PGWIDTH;
+       rectab[reclim].n = 0;
+       rectab[reclim].s = 0;
+       inc_reclim();
+
+
+       /* get stacking order of the user-controllable mark types */
+       order = svpath(s, BETWEENORDER)->markorder[PL_BETWEEN];
+
+       /* loop on each possible stacking order number */
+       for (stk = 1; stk <= NUM_MARK; stk++) {
+
+               /* set bit map for each mark type that has this order number */
+               do_which = 0;
+               for (mk = 0; mk < NUM_MARK; mk++) {
+                       if (order[mk] == stk) {
+                               do_which |= (1L << mk);
+                       }
+               }
+               /* if no marks, we're done; stacking orders are contiguous */
+               if (do_which == 0)
+                       break;
+
+               /*
+                * Some mark types must have a unique order number, not shared
+                * with any others.  For each of them, do a case statement to
+                * call their subroutine.  The other ones all share the same
+                * subroutine, so call it in the default to do the mark types
+                * listed in the bit map.
+                */
+               switch (do_which) {
+               case 1L << MK_LYRICS:
+                       dolyrics(start_p, s, PL_BETWEEN);
+                       break;
+               case 1L << MK_ENDING:
+               case 1L << MK_REHEARSAL:
+               case 1L << MK_PEDAL:
+                       break;  /* ignore for between */
+               default:
+                       domiscstuff(start_p, s, PL_BETWEEN, do_which);
+                       break;
+               }
+       }
+
+       /*
+        * Find the northernmost rectangle, for finding the height of these
+        * objects between.
+        */
+       hb = 0;
+       for (k = 0; k < reclim; k++) {
+               if (rectab[k].n > hb)
+                       hb = rectab[k].n;
+       }
+
+       /*
+        * Set the relative north and south of every STAFF structure for this
+        * staff number on this score.  (There's one per measure.)  While
+        * we're at it, set RX to 0, in case anyone cares.  Set the height of
+        * "between" objects in each STAFF, too.
+        */
+       for (mainll_p = start_p->next; mainll_p != 0 &&
+                       mainll_p->str != S_FEED; mainll_p = mainll_p->next) {
+
+               if (mainll_p->str == S_STAFF &&
+                               mainll_p->u.staff_p->staffno == s) {
+
+                       mainll_p->u.staff_p->c[RN] = north;
+                       mainll_p->u.staff_p->c[RX] = 0;
+                       mainll_p->u.staff_p->c[RS] = south;
+                       mainll_p->u.staff_p->heightbetween = hb;
+               }
+       }
+}
+\f
+/*
+ * Name:        dostaff()
+ *
+ * Abstract:    Set up the rectangle for the staff itself.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts into rectab the rectangle for the staff
+ *             itself.  The staff's relative vertical coords are not set now,
+ *             though, because they must later be set to include all the
+ *             objects associated with the staff.
+ */
+
+static void
+dostaff(s, place)
+
+int s;                         /* staff number */
+int place;                     /* above or below? */
+
+{
+       debug(32, "dostaff s=%d place=%d", s, place);
+       /*
+        * Use the full page width, even though the staff will not actually
+        * reach the edges, due to margins, etc.  This way nothing will ever
+        * fall beyond this base rectangle.  Put a STDPAD of padding around
+        * it vertically.
+        */
+       rectab[reclim].w = 0;
+       rectab[reclim].e = PGWIDTH;
+
+       if (place == PL_ABOVE) {
+               rectab[reclim].n = halfstaffhi(s) + Stdpad;
+               rectab[reclim].s = 0;
+       } else {        /* PL_BELOW */
+               rectab[reclim].n = 0;
+               rectab[reclim].s = -(halfstaffhi(s) + Stdpad);
+       }
+
+       inc_reclim();
+}
+\f
+/*
+ * Name:        dogroups()
+ *
+ * Abstract:    Set up rectangles & relative vert coords for staff's groups.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts into rectab the rectangles for each group on
+ *             this staff.  The groups' relative vertical coords were already
+ *             set in proclist() in beamstem.c.
+ */
+
+static void
+dogroups(start_p, s, place)
+
+struct MAINLL *start_p;                /* FEED at the start of this score */
+int s;                         /* staff number */
+int place;                     /* above or below? */
+
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       int v;                          /* voice number */
+
+
+       debug(32, "dogroups file=%s line=%d s=%d place=%d", start_p->inputfile,
+                       start_p->inputlineno, s, place);
+       /*
+        * Loop through this score's part of the MLL.
+        */
+       for (mainll_p = start_p->next; mainll_p != 0 &&
+                       mainll_p->str != S_FEED; mainll_p = mainll_p->next) {
+               /*
+                * Whenever we find a structure for this staff (another
+                * measure of this staff), call llgrps() for each voice.
+                * If some voice doesn't exist, llgrps() will get a
+                * null pointer and just return.
+                */
+               if (mainll_p->str == S_STAFF &&
+                               mainll_p->u.staff_p->staffno == s) {
+
+                       for (v = 0; v < MAXVOICES; v++)
+                               llgrps(mainll_p->u.staff_p,
+                                      mainll_p->u.staff_p->groups_p[v], place);
+               }
+       }
+}
+\f
+/*
+ * Name:        llgrps()
+ *
+ * Abstract:    Set up rectangles for note and rest groups.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts rectangles into rectab for all groups in
+ *             this measure of this voice, for groups consisting of notes or
+ *             rests.
+ */
+
+static void
+llgrps(staff_p, first_p, place)
+
+struct STAFF *staff_p;         /* point to the staff */
+struct GRPSYL *first_p;                /* point to first group */
+int place;                     /* above or below? */
+
+{
+       struct GRPSYL *gs_p;            /* point at a group */
+       struct NOTE *note_p;            /* point at a note */
+       double mx, my_offset, mheight, mwidth;  /* multirest number coords */
+       int n;                          /* loop through notelist */
+       float asc, des, wid;            /* ascent, descent, and width of acc */
+
+
+       /*
+        * For each group that is notes or a rest, put a rectangle into rectab.
+        * However, on tablature staffs, don't do this for rests, since they
+        * aren't printed there.
+        */
+       for (gs_p = first_p; gs_p != 0; gs_p = gs_p->next) {
+               if (gs_p->grpcont == GC_SPACE)
+                       continue;
+
+               if (gs_p->grpcont == GC_REST && is_tab_staff(gs_p->staffno))
+                       continue;
+
+               if (place == PL_ABOVE && (
+                       gs_p->basictime < -1 && svpath(staff_p->staffno,
+                                       PRINTMULTNUM)->printmultnum == YES ||
+                       is_mrpt(gs_p) && svpath(staff_p->staffno,
+                                       NUMBERMRPT)->numbermrpt == YES
+               )) {
+                       /*
+                        * Special case for multirests and measure repeats.
+                        * The rest or mrpt symbol itself is inside the staff,
+                        * so we don't have to worry about it.  But we need to
+                        * make a rectangle for the number, if the number is
+                        * to be printed.
+                        */
+                       (void)mrnum(staff_p, &mx, &my_offset, &mheight,
+                                       &mwidth);
+                       rectab[reclim].w = mx;
+                       rectab[reclim].e = mx + mwidth;
+                       rectab[reclim].n = my_offset + mheight;
+                       rectab[reclim].s = 0;
+
+                       inc_reclim();
+                       continue;
+               }
+
+               /* for "below", no rectangles are needed for multirests */
+               if (gs_p->basictime < -1)
+                       continue;
+
+               /*
+                * We have a normal note or rest group.  Make a rectangle for
+                * it, making sure it reaches the center staff line.
+                */
+               rectab[reclim].w = gs_p->c[AW];
+               rectab[reclim].e = gs_p->c[AE];
+
+               if (place == PL_ABOVE) {
+                       rectab[reclim].n = MAX(gs_p->c[RN], 0);
+                       rectab[reclim].s = 0;
+               } else {        /* PL_BELOW */
+                       rectab[reclim].n = 0;
+                       rectab[reclim].s = MIN(gs_p->c[RS], 0);
+               }
+
+               inc_reclim();
+
+               /* if a clef precedes this group, make a rectangle for it */
+               if (gs_p->clef != NOCLEF) {
+                       float north, south;     /* clef coords */
+
+                       rectab[reclim].e = gs_p->c[AW] - Staffscale * CLEFPAD;
+                       rectab[reclim].w = rectab[reclim].e - Staffscale *
+                                       clefwidth(gs_p->clef, YES);
+                       (void)clefvert(gs_p->clef, YES, &north, &south);
+                       rectab[reclim].n = north * Staffscale;
+                       rectab[reclim].s = south * Staffscale;
+
+                       inc_reclim();
+               }
+
+               /*
+                * An additional rectangle is needed for each note that has an
+                * accidental.  This is because although the east/west group
+                * boundaries include any accidentals, the north/south
+                * boundaries ingore them.  It needs to be this way because,
+                * for other reasons, like ties, we want the north/south group
+                * boundaries to consider only the note heads.  But for general
+                * stuff, the accidentals should also be considered.  The
+                * rectangles added below take care of this.
+                * Similarly, if the top or bottom note is on a line and has a
+                * dot in the space away from the group, it needs a rectangle.
+                */
+               if (gs_p->grpcont == GC_NOTES &&
+                                       ! is_tab_staff(gs_p->staffno)) {
+                       for (n = 0; n < gs_p->nnotes; n++) {
+                               note_p = &gs_p->notelist[n];
+
+                               if (gs_p->dots != 0 &&
+                               note_p->stepsup % 2 == 0 &&
+                               (n == 0 && note_p->ydotr > 0.0 ||
+                                n == gs_p->nnotes - 1 && note_p->ydotr < 0.0)){
+                                       float radius;   /* of a dot, + pad */
+                                       radius = Stdpad + Staffscale *
+                                               ascent(FONT_MUSIC, (note_p->
+                                               notesize == GS_NORMAL ?
+                                               DFLT_SIZE : SMALLSIZE), C_DOT);
+                                       rectab[reclim].n = gs_p->c[RY] +
+                                               note_p->ydotr + radius;
+                                       rectab[reclim].s = gs_p->c[RY] +
+                                               note_p->ydotr - radius;
+                                       rectab[reclim].w = gs_p->c[AX] +
+                                               gs_p->xdotr - radius;
+                                       rectab[reclim].e = gs_p->c[AX] +
+                                               gs_p->xdotr + radius +
+                                               (gs_p->dots - 1) * 2.0 *
+                                               (radius + Stdpad);
+                                       inc_reclim();
+                               }
+
+                               if (note_p->accidental == '\0')
+                                       continue;
+
+                               /* this note has an acc; create a rectangle */
+                               accdimen(note_p, &asc, &des, &wid);
+                               asc *= Staffscale;
+                               des *= Staffscale;
+                               wid *= Staffscale;
+
+                               rectab[reclim].w = gs_p->c[AX] + note_p->waccr;
+                               rectab[reclim].e = rectab[reclim].w + wid;
+                               rectab[reclim].n = note_p->c[RY] + asc;
+                               rectab[reclim].s = note_p->c[RY] - des;
+
+                               inc_reclim();
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        dobeamalt()
+ *
+ * Abstract:    Set up rectangles for beams and alternation bars.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts into rectab rectangles for each beam or
+ *             alternation bar on this staff in this score, where the thing
+ *             is on the "place" side of the notes.
+ */
+
+static void
+dobeamalt(start_p, s, place)
+
+struct MAINLL *start_p;                /* FEED at the start of this score */
+int s;                         /* staff number */
+int place;                     /* above or below? */
+
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct GRPSYL *gs_p;            /* point along a GRPSYL linked list */
+       int v;                          /* voice number */
+
+
+       debug(32, "dobeamalt file=%s line=%d s=%d place=%d", start_p->inputfile,
+                       start_p->inputlineno, s, place);
+       /*
+        * Loop through this score's part of the MLL.
+        */
+       for (mainll_p = start_p->next; mainll_p != 0 &&
+                       mainll_p->str != S_FEED; mainll_p = mainll_p->next) {
+               /*
+                * Whenever we find a structure for this staff (another
+                * measure of this staff), loop through its voices.
+                */
+               if (mainll_p->str == S_STAFF &&
+                               mainll_p->u.staff_p->staffno == s) {
+
+                       for (v = 0; v < MAXVOICES; v++) {
+                               for (gs_p = mainll_p->u.staff_p->groups_p[v];
+                                               gs_p != 0; gs_p = gs_p->next) {
+                                       /*
+                                        * Whenever we find the first group of
+                                        * a nongrace beamed or alted set with
+                                        * the stem direction on the side we
+                                        * are dealing with, call onebeamalt()
+                                        * to put rectangle(s) in rectab.
+                                        * But not for cross staff beams.
+                                        * Grace groups are included in the
+                                        * following nongrace group's rectangle
+                                        * already.
+                                        */
+                                       if (gs_p->grpcont == GC_NOTES &&
+                                           gs_p->grpvalue == GV_NORMAL &&
+                                           gs_p->beamloc == STARTITEM &&
+                                           gs_p->beamto == CS_SAME) {
+
+                                               if (place == PL_ABOVE &&
+                                                   gs_p->stemdir == UP ||
+                                                   place == PL_BELOW &&
+                                                   gs_p->stemdir == DOWN)
+
+                                                       onebeamalt(gs_p);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        onebeamalt()
+ *
+ * Abstract:    Set up rectangle(s) for one beam or alternation bar.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts zero or more rectangles in rectab for the
+ *             beam or alternation that starts at the given group.  The longer
+ *             and more slanted the beam/alternation is, the more rectangles
+ *             will be necessary to enclose it without wasting a lot of space.
+ *             If the beam/alt lies within the staff, there's no need to make
+ *             any rectangles.  All rectangles' inner edges are the center
+ *             staff line.
+ */
+
+static void
+onebeamalt(gs_p)
+
+struct GRPSYL *gs_p;           /* initially points to first group */
+
+{
+       float stemshift;        /* how far a stem is from its group's X */
+       float x1, y1;           /* coords of left end of beam/alt */
+       float x2, y2;           /* coords of right end of beam/alt */
+
+
+       /*
+        * Set coords of the ends of the beam/alt.  We are given the first
+        * group, but must search forward to the end to find the last group,
+        * being careful to ignore embedded grace groups.  We adjust the X
+        * coords (for groups that can have stems) because stems are offset
+        * from their group's X.  The Y coords can't always be based on the
+        * group boundaries, because there might be "with" lists on the
+        * abnormal (beam) side, and they don't affect the position of the beam.
+        */
+       x1 = gs_p->c[AX];
+       y1 = getstemendvert(gs_p);
+
+       while (gs_p != 0 && (gs_p->grpvalue == GV_ZERO ||
+                            gs_p->beamloc != ENDITEM))
+               gs_p = gs_p->next;
+       if (gs_p == 0)
+               pfatal("beam or alt group has no ENDITEM");
+
+       x2 = gs_p->c[AX];
+       y2 = getstemendvert(gs_p);
+
+       stemshift = getstemshift(gs_p);
+
+       if (gs_p->basictime >= 2) {
+               /* the groups have stems (if first one does, others must too)*/
+               if (gs_p->stemdir == UP) {
+                       x1 += stemshift;
+                       x2 += stemshift;
+               } else {
+                       x1 -= stemshift;
+                       x2 -= stemshift;
+               }
+       }
+
+       /* make zero or more rectangles for this beam/alt */
+       linerects(x1, y1, x2, y2, gs_p->stemdir, halfstaffhi(gs_p->staffno));
+}
+\f
+/*
+ * Name:        getstemendvert()
+ *
+ * Abstract:    Find the vertical coord of the end of a stem.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given a GRPSYL of a group that has either a
+ *             real, visible stem, or an invisible one (alt).  If finds
+ *             the relative vertical coordinate of the end of the stems
+ *             farthest from the note head(s).
+ */
+
+static double
+getstemendvert(gs_p)
+
+struct GRPSYL *gs_p;   /* the group in question */
+
+{
+       double y;       /* the answer */
+
+
+       if (gs_p->nwith == 0 || gs_p->normwith == YES) {
+               /*
+                * Either there is no "with" list, or it's on the notes' end
+                * of the stem.  So we can use the group boundary.
+                */
+               y = gs_p->stemdir == UP ? gs_p->c[RN] : gs_p->c[RS];
+       } else {
+               /*
+                * There is a "with" list at this end of the stem.  Find where
+                * the end of the stem is by applying the stem's length to the
+                * farthest note on the opposite side.
+                */
+               if (gs_p->stemdir == UP)
+                       y = gs_p->notelist[ gs_p->nnotes - 1 ].c[RY] +
+                                       gs_p->stemlen;
+               else
+                       y = gs_p->notelist[ 0 ].c[RY] - gs_p->stemlen;
+       }
+
+       /* counteract the stem shortening that was done in finalstemadjust() */
+       if (gs_p->beamloc != NOITEM) {
+               if (gs_p->stemdir == UP) {
+                       y += (W_WIDE * Stdpad / 2.0);
+               } else {
+                       y -= (W_WIDE * Stdpad / 2.0);
+               }
+       }
+
+       return (y);
+}
+\f
+/*
+ * Name:        linerects()
+ *
+ * Abstract:    Set up rectangle(s) to contain a (possibly) slanted line.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts zero or more rectangles in rectab to contain
+ *             a (possibly) slanted line.  The longer and more slanted the
+ *             line is, the more rectangles will be necessary to enclose it
+ *             without wasting a lot of space.  If the line lies within the
+ *             staff, there's no need to make any rectangles.  All rectangles'
+ *             inner edges are the center staff line.
+ */
+
+static void
+linerects(x1, y1, x2, y2, side, halfstaff)
+
+double x1, y1;         /* coords of left end of line */
+double x2, y2;         /* coords of right end of line */
+int side;              /* side to favor, UP or DOWN */
+double halfstaff;      /* half the staff height */
+
+{
+       float slope, yintercept;/* of a line a STDPAD beyond beam/alt */
+       float deltax;           /* width of one rectangle */
+       float leftx, rightx;    /* X coord of sides of a rectangle */
+
+
+       /* if line is within staff, no need for any rectangles */
+       if (fabs(y1) < halfstaff && fabs(y2) < halfstaff)
+               return;
+
+       /*
+        * If this beam/alt is level, make one big rectangle, and get out.
+        */
+       if (y1 == y2) {
+               rectab[reclim].w = x1;
+               rectab[reclim].e = x2;
+               if (side == UP) {
+                       rectab[reclim].n = y1;
+                       rectab[reclim].s = 0;
+               } else {
+                       rectab[reclim].n = 0;
+                       rectab[reclim].s = y1;
+               }
+               inc_reclim();
+               return;
+       }
+
+       /*
+        * We may need multiple rectangles.  Make them narrow enough so that
+        * the change in Y across the width of one is one STEPSIZE.  The
+        * rightmost one will probably be narrower, using whatever room
+        * remains.  The equation of our line is  y = slope * x + yintercept.
+        */
+       slope = (y1 - y2) / (x1 - x2);
+       yintercept = y1 - slope * x1;
+       deltax = Stepsize / fabs(slope);
+
+       for (leftx = x1; leftx < x2; leftx += deltax) {
+               rightx = MIN(x2, leftx + deltax);
+               rectab[reclim].w = leftx;
+               rectab[reclim].e = rightx;
+               if (side == UP) {
+                       rectab[reclim].n = slope * (slope > 0 ? rightx : leftx)
+                                       + yintercept;
+                       rectab[reclim].s = 0;
+               } else {
+                       rectab[reclim].n = 0;
+                       rectab[reclim].s = slope * (slope > 0 ? leftx : rightx)
+                                       + yintercept;
+               }
+               inc_reclim();
+       }
+}
+\f
+/*
+ * Name:        docurve()
+ *
+ * Abstract:    Get point list and set up rectangles for tie/slur/bend/phrase.
+ *
+ * Returns:     void
+ *
+ * Description: This function goes through all ties, slurs, bends, phrases for
+ *             staff.  The first time it is called for a staff (which is for
+ *             place "above") it calls a function to set up the curve list.
+ *             Whichever time it is called, it calls a function to put
+ *             rectangles in rectab.
+ */
+
+static void
+docurve(start_p, s, place, do_which)
+
+struct MAINLL *start_p;                /* FEED at the start of this score */
+int s;                         /* staff number */
+int place;                     /* above or below? */
+int do_which;                  /* which stuff types are to be handled */
+
+{
+       struct MAINLL *mainll_p;        /* loop through main linked list */
+       struct STUFF *stuff_p;          /* point along a STUFF list */
+       float halfstaff;                /* half the staff height */
+
+
+       debug(32, "docurve file=%s line=%d s=%d place=%d do_which=%d",
+               start_p->inputfile, start_p->inputlineno, s, place, do_which);
+       halfstaff = halfstaffhi(s);
+
+       /*
+        * Loop through this score's part of the MLL, looking for matching
+        * staffs.
+        */
+       for (mainll_p = start_p->next; mainll_p != 0 &&
+                       mainll_p->str != S_FEED; mainll_p = mainll_p->next) {
+
+               if (mainll_p->str != S_STAFF ||
+                               mainll_p->u.staff_p->staffno != s)
+                       continue;
+
+               /* loop through each stuff of the indicated type */
+               for (stuff_p = mainll_p->u.staff_p->stuff_p;
+                               stuff_p != 0; stuff_p = stuff_p->next){
+
+                       switch (stuff_p->stuff_type) {
+                       case ST_TIESLUR:
+                       case ST_TABSLUR:
+                       case ST_BEND:
+                       case ST_PHRASE:
+                               break;          /* docurve works on these */
+                       default:
+                               continue;       /* for some other function */
+                       }
+
+                       /*
+                        * If we are to do phrases and this is not a phrase, or
+                        * vice versa, skip this.
+                        */
+                       if ((do_which == DO_PHRASE) !=
+                           (stuff_p->stuff_type == ST_PHRASE))
+                               continue;
+
+                       /*
+                        * When we're in here the first time (for PL_ABOVE),
+                        * call a function to set up the curve list.  For
+                        * everything but ST_PHRASE it also sets "place".
+                        */
+                       if (place == PL_ABOVE) {
+                               switch (stuff_p->stuff_type) {
+                               case ST_TIESLUR:
+                                       /* don't call tieslur_points now if the
+                                        * positions of the tie/slur's endpoints
+                                        * would change later due to CSS */
+                                       if (css_affects_tieslurbend(stuff_p,
+                                                       mainll_p) == YES) {
+                                               break;
+                                       }
+                                       tieslur_points(mainll_p, stuff_p);
+                                       break;
+                               case ST_TABSLUR:
+                                       tabslur_points(mainll_p, stuff_p);
+                                       break;
+                               case ST_BEND:
+                                       /* don't call bend_points now if the
+                                        * positions of the bend's endpoints
+                                        * would change later due to CSS */
+                                       if (css_affects_tieslurbend(stuff_p,
+                                                       mainll_p) == YES) {
+                                               break;
+                                       }
+                                       bend_points(mainll_p, stuff_p);
+                                       break;
+                               case ST_PHRASE:
+                                       /* don't call phrase_points now if the
+                                        * positions of the phrase's endpoints
+                                        * would change later due to CSS */
+                                       if (css_affects_phrase(stuff_p,
+                                                       mainll_p) == YES) {
+                                               break;
+                                       }
+                                       phrase_points(mainll_p, stuff_p);
+                                       break;
+                               }
+                       }
+
+                       /*
+                        * Make rectangles no matter what side of the staff the
+                        * curve is supposed to be on, because, depending on
+                        * how high or low the notes are, rectangles may be
+                        * needed even on the opposite side you'd expect.
+                        */
+                       if (stuff_p->crvlist_p != 0) {
+                               curverect(s, stuff_p, halfstaff);
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        curverect()
+ *
+ * Abstract:    Put rectangles in rectab for a tie, slur, bend, or phrase.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts rectangles in rectab for a tie, slur, bend,
+ *             or phrase.  Each segment of the curve gets one or more
+ *             rectangles, depending on how long and how slanted it is.  To do
+ *             this, we call curvepiecerect().
+ */
+
+static void
+curverect(s, stuff_p, halfstaff)
+
+int s;                         /* staff number */
+struct STUFF *stuff_p;         /* the curve's STUFF */
+double halfstaff;              /* half the staff height */
+
+{
+       struct CRVLIST *point_p; /* point at a phrase point */
+       float x1, y1;           /* coords of left end of a segment */
+       float x2, y2;           /* coords of right end of a segment */
+       float midx, midy;       /* middle of one segment of a curve */
+
+
+       /*
+        * Loop through the curve list.  For each pair of neighboring points,
+        * there is a segment of the curve.  For items that are actually
+        * straight line segments, call curvepiecerect() once.  But for actual
+        * curves, find the midpoint, and call curvepiecerect() for each half.
+        * This way we more closely approximate the real curve.
+        */
+       for (point_p = stuff_p->crvlist_p; point_p->next != 0;
+                       point_p = point_p->next) {
+
+               x1 = point_p->x;
+               y1 = point_p->y;
+               x2 = point_p->next->x;
+               y2 = point_p->next->y;
+
+               if (stuff_p->stuff_type == ST_BEND ||
+                   stuff_p->stuff_type == ST_TABSLUR) {
+                       /* bend, or slur on tab or tabnote */
+                       curvepiecerect(x1, y1, x2, y2, halfstaff);
+               } else {
+                       /* a real curve */
+                       midx = (x1 + x2) / 2.0;
+                       midy = curve_y_at_x(stuff_p->crvlist_p, midx);
+                       curvepiecerect(x1, y1, midx, midy, halfstaff);
+                       curvepiecerect(midx, midy, x2, y2, halfstaff);
+               }
+       }
+}
+\f
+/*
+ * Name:        curvepiecerect()
+ *
+ * Abstract:    Put rects in rectab for a piece of a tie, slur, bend, or phrase.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts rectangles in rectab for one piece of a
+ *             curve.  The piece gets one or more rectangles, depending on how
+ *             long and how slanted it is.
+ */
+
+static void
+curvepiecerect(x1, y1, x2, y2, halfstaff)
+
+double x1, y1;                 /* coords of left end of the piece */
+double x2, y2;                 /* coords of right end of the piece */
+double halfstaff;              /* half the staff height */
+
+{
+       float slope, yintercept;/* of a line a segment */
+       float deltax;           /* width of one rectangle */
+       float leftx, rightx;    /* X coord of sides of a rectangle */
+
+
+       /* if whole piece is within the staff, no rectangles are needed */
+       if (fabs(y1) < halfstaff && fabs(y2) < halfstaff)
+               return;
+
+       /*
+        * If this piece is level, make 1 big rectangle, and continue.
+        */
+       if (y1 == y2) {
+               rectab[reclim].w = x1;
+               rectab[reclim].e = x2;
+               rectab[reclim].n = MAX(y1 + 2 * Stdpad, 0.0);
+               rectab[reclim].s = MIN(y1 - 2 * Stdpad, 0.0);
+               inc_reclim();
+               return;
+       }
+
+       /*
+        * We may need multiple rectangles.  Make them narrow enough so that
+        * the change in Y across the width of one is one Stepsize.  The
+        * rightmost one will probably be narrower, using whatever room
+        * remains.  The equation of our line is
+        *      y = slope * x + yintercept
+        * Initially each rectangle only includes its segment (plus padding),
+        * but then we extend it to reach the center line of the staff.
+        */
+       slope = (y1 - y2) / (x1 - x2);
+       yintercept = y1 - slope * x1;
+       deltax = Stepsize / fabs(slope);
+
+       for (leftx = x1; leftx < x2; leftx += deltax) {
+               rightx = MIN(x2, leftx + deltax);
+
+               rectab[reclim].w = leftx;
+               rectab[reclim].e = rightx;
+
+               /*
+                * For north and south boundaries, use the side of the rect
+                * that sticks out more, to err on the side of making the rect
+                * big enough.  Also add in padding, to 1) allow for the fact
+                * that the real curve probably bulges out beyond our segment
+                * approximation, and 2) because we don't want anything
+                * actually touching the curve.
+                */
+               rectab[reclim].n = slope * (slope > 0.0 ?  rightx : leftx) +
+                               yintercept + 2.0 * Stdpad;
+               rectab[reclim].s = slope * (slope < 0.0 ?  rightx : leftx) +
+                               yintercept - 2.0 * Stdpad;
+
+               /* rectangle must reach the center line of the staff */
+               if (rectab[reclim].n < 0.0)
+                       rectab[reclim].n = 0.0;
+               if (rectab[reclim].s > 0.0)
+                       rectab[reclim].s = 0.0;
+
+               inc_reclim();
+       }
+}
+\f
+/*
+ * Name:        dotuplet()
+ *
+ * Abstract:    Set up rectangles for tuplet brackets.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts into rectab rectangles for each tuplet
+ *             bracket on this staff in this score, where the thing is on
+ *             the "place" side of the notes.
+ */
+
+
+static void
+dotuplet(start_p, s, place)
+
+struct MAINLL *start_p;                /* FEED at the start of this score */
+int s;                         /* staff number */
+int place;                     /* above or below? */
+
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct GRPSYL *gs_p;            /* point along a GRPSYL linked list */
+       int v;                          /* voice number */
+
+
+       debug(32, "dotuplet file=%s line=%d s=%d place=%d", start_p->inputfile,
+                       start_p->inputlineno, s, place);
+
+       /* tuplet brackets are never printed on tablature staffs */
+       if (is_tab_staff(s))
+               return;
+
+       /*
+        * Loop through this score's part of the MLL.
+        */
+       for (mainll_p = start_p->next; mainll_p != 0 &&
+                       mainll_p->str != S_FEED; mainll_p = mainll_p->next) {
+               /*
+                * Whenever we find a structure for this staff (another
+                * measure of this staff), loop through its voices.
+                */
+               if (mainll_p->str == S_STAFF &&
+                               mainll_p->u.staff_p->staffno == s) {
+
+                       for (v = 0; v < MAXVOICES; v++) {
+                               for (gs_p = mainll_p->u.staff_p->groups_p[v];
+                                               gs_p != 0; gs_p = gs_p->next) {
+                                       /*
+                                        * Whenever we find the first group of
+                                        * a tuplet with a bracket on the
+                                        * "place" side of the group, call
+                                        * onetuplet() to put rectangle(s) in
+                                        * rectab.
+                                        */
+                                       if ((gs_p->tuploc == STARTITEM ||
+                                            gs_p->tuploc == LONEITEM) &&
+                                           gs_p->printtup != PT_NEITHER) {
+
+                                               if (tupdir(gs_p, mainll_p->u.
+                                                       staff_p) == place)
+
+                                                       onetuplet(mainll_p->u.
+                                                       staff_p, gs_p, place);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        onetuplet()
+ *
+ * Abstract:    Set up rectangle(s) for one tuplet bracket or number.
+ *
+ * Returns:     void
+ *
+ * Description:        If this tuplet is not going to be given a bracket (like because
+ *             its notes are already beamed), this function just makes one
+ *             rectangle, for the number.  Otherwise, this function puts zero
+ *             or more rectangles in rectab for the tuplet that starts at the
+ *             given group.  The longer and more slanted the tuplet bracket
+ *             is, the more rectangles will be necessary to enclose it without
+ *             wasting a lot of space.  All rectangles' inner edges are the
+ *             center staff line.
+ */
+
+static void
+onetuplet(staff_p, start_p, place)
+
+struct STAFF *staff_p;         /* point to the staff we're on */
+struct GRPSYL *start_p;                /* points to first group in tuplet */
+int place;                     /* above or below? */
+
+{
+       struct GRPSYL *gs_p;    /* point to a group in tuplet */
+       float stemshift;        /* how far a stem is from its group's X */
+       float x1, y1;           /* coords of left end of beam/alt */
+       float x2, y2;           /* coords of right end of beam/alt */
+       float numeast, numwest; /* horizontal coords of the tuplet number */
+       float height;           /* height of the tuplet number */
+
+
+       /*
+        * Set coords of the ends of the tuplet.  We are given the first
+        * group, but must search forward to the end to find the last group,
+        * being careful to ignore embedded grace groups.  We adjust the X
+        * coords because brackets reach beyond their group's X.
+        */
+       x1 = start_p->c[AX];
+       y1 = (place == PL_ABOVE ? start_p->c[RN] : start_p->c[RS])
+                       + start_p->tupextend;
+
+       for (gs_p = start_p; gs_p != 0 && (gs_p->grpvalue == GV_ZERO ||
+                       gs_p->tuploc != ENDITEM && gs_p->tuploc != LONEITEM);
+                       gs_p = gs_p->next)
+               ;
+       if (gs_p == 0)
+               pfatal("tuplet has no ENDITEM");
+
+       x2 = gs_p->c[AX];
+       y2 = (place == PL_ABOVE ? gs_p->c[RN] : gs_p->c[RS]) + gs_p->tupextend;
+
+       /*
+        * If there is not going to be a bracket, create one rectangle for the
+        * tuplet number, and return.
+        */
+       if (tupgetsbrack(start_p) == NO) {
+               (void)tupnumsize(start_p, &numwest, &numeast, &height, staff_p);
+               rectab[reclim].n = (y1 + y2) / 2 + height / 2;
+               rectab[reclim].s = (y1 + y2) / 2 - height / 2;
+               rectab[reclim].w = numwest;
+               rectab[reclim].e = numeast;
+
+               inc_reclim();
+               return;
+       }
+
+       /* there is going to be a bracket; extend x coords to reach to end */
+       stemshift = getstemshift(gs_p);
+
+       x1 -= stemshift;
+       x2 += stemshift;
+
+       /* make zero or more rectangles for this bracket */
+       linerects(x1, y1, x2, y2, place == PL_ABOVE ? UP : DOWN,
+                       halfstaffhi(gs_p->staffno));
+}
+\f
+/*
+ * Name:        domiscstuff()
+ *
+ * Abstract:    Set up rectangles and vert coords for miscellaneous STUFF.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts into rectab a rectangle for each STUFF
+ *             structure in the "place" relationship to the given staff on
+ *             this score, except for stuff types that have special,
+ *             dedicated functions for their type.  It also sets their
+ *             relative vertical coordinates.
+ */
+
+static void
+domiscstuff(start_p, s, place, do_which)
+
+struct MAINLL *start_p;                /* FEED at the start of this score */
+int s;                         /* staff number */
+int place;                     /* above, below, or between? */
+unsigned long do_which;                /* which stuff types are to be handled */
+
+{
+       struct MAINLL *mainll_p;        /* loop through main linked list */
+       struct STUFF *stuff_p;          /* point along a STUFF list */
+       float high;                     /* height of a rectangle */
+       float len;                      /* length of a cresc/descresc */
+       float lowpart;                  /* dist between stuff's Y and S */
+       float dist;                     /* how close chord can get to staff */
+       int stype;                      /* stuff type */
+
+
+       debug(32, "domiscstuff file=%s line=%d s=%d place=%d do_which=%ld",
+               start_p->inputfile, start_p->inputlineno, s, place, do_which);
+       /*
+        * Loop through this score's part of the MLL.  Whenever we find a
+        * structure for this staff (another measure), loop through its
+        * STUFF list, dealing with each STUFF that is above, below, or
+        * between, as specified by "place".
+        */
+       for (mainll_p = start_p->next; mainll_p != 0 &&
+                       mainll_p->str != S_FEED; mainll_p = mainll_p->next) {
+
+               if (mainll_p->str != S_STAFF ||
+                               mainll_p->u.staff_p->staffno != s) {
+                       continue;
+               }
+
+               for (stuff_p = mainll_p->u.staff_p->stuff_p;
+                               stuff_p != 0; stuff_p = stuff_p->next) {
+
+                       if (stuff_p->place != place) {
+                               continue;
+                       }
+
+                       stype = stuff_p->stuff_type;
+
+                       /* if wrong type for this pass, exit */
+                       if (stype == ST_MUSSYM) {
+                               if ((do_which & (1L << MK_MUSSYM)) == 0)
+                                       continue;
+                       } else if (stype == ST_OCTAVE) {
+                               if ((do_which & (1L << MK_OCTAVE)) == 0)
+                                       continue;
+                       } else if (stype != ST_PHRASE &&
+                                       stuff_p->modifier == TM_DYN) {
+                               if ((do_which & (1L << MK_DYN)) == 0)
+                                       continue;
+                       } else if (stype != ST_PHRASE &&
+                                       IS_CHORDLIKE(stuff_p->modifier)) {
+                               if ((do_which & (1L << MK_CHORD)) == 0)
+                                       continue;
+                       } else if (IS_TEXT(stype)) {
+                               if ((do_which & (1L << MK_OTHERTEXT)) == 0)
+                                       continue;
+                       }
+
+                       /*
+                        * We found a "stuff" that needs to be positioned.
+                        * First find its total height, and the height of the
+                        * part of it below its Y coord.
+                        */
+                       /* avoid 'used before set' warning */
+                       high = lowpart = 0.0;
+
+                       /* handle various types differently */
+                       switch (stype) {
+                       case ST_PEDAL:
+                       case ST_PHRASE:
+                       case ST_TIESLUR:
+                       case ST_TABSLUR:
+                       case ST_BEND:
+                       case ST_MIDI:
+                               /* don't handle these types here; */
+                               /* they have their own subroutines */
+                               continue;
+
+                       case ST_OCTAVE:
+                       case ST_ROM:
+                       case ST_BOLD:
+                       case ST_ITAL:
+                       case ST_BOLDITAL:
+                       case ST_MUSSYM:
+                               /* high is string's height */
+                               high = strheight( stuff_p->string);
+                               lowpart = strdescent( stuff_p->string);
+
+                               /*
+                                * If a chord grid is to be printed under the
+                                * string, the Y and N of the stuff remain
+                                * unchanged, but its S is lowered by the total
+                                * height of the grid.  So add its height to
+                                * both "high" and "lowpart".
+                                */
+                               if (stuff_p->modifier == TM_CHORD && svpath(s,
+                               GRIDSWHEREUSED)->gridswhereused == YES) {
+                                       struct GRID *grid_p;
+                                       float gnorth, gsouth;
+
+                                       grid_p = findgrid(stuff_p->string);
+                                       /* if none, skip this; stuff.c warned*/
+                                       if (grid_p == 0)
+                                               break;
+
+                                       gridsize(grid_p, stuff_p->all ? 0 :
+                                               mainll_p->u.staff_p->staffno,
+                                               &gnorth, &gsouth,
+                                               (float *)0, (float *)0);
+
+                                       high += gnorth - gsouth;
+                                       lowpart += gnorth - gsouth;
+                               }
+                               break;
+
+                       case ST_CRESC:
+                       case ST_DECRESC:
+                               /* height depends on length */
+                               len = stuff_p->c[AE] - stuff_p->c[AW];
+
+                               if (len < 0.5)
+                                       high = 2.00 * STEPSIZE + 2 * STDPAD;
+                               else if (len < 2.0)
+                                       high = 2.67 * STEPSIZE + 2 * STDPAD;
+                               else
+                                       high = 3.33 * STEPSIZE + 2 * STDPAD;
+
+                               if (stuff_p->all)
+                                       high *= Score.staffscale;
+                               else
+                                       high *= Staffscale;
+
+                               lowpart = high / 2;
+
+                               break;
+
+                       default:
+                               pfatal("unknown stuff type (%d)", stype);
+                       }
+
+                       /*
+                        * Now find "dist", the minimum distance it should be
+                        * put from the staff.
+                        */
+                       if (stuff_p->dist_usage == SD_NONE) {
+                               /*
+                                * The user didn't specify the dist, so we get
+                                * it from the appropriate parameter or hard-
+                                * coded value, as the case may be.  For
+                                * parameters, if the stuff belongs to the
+                                * score as a whole ("all"), use the Score
+                                 * value instead of svpath.
+                                */
+                               /* if "dyn", fake to use same logic as cresc */
+                               if (stuff_p->modifier == TM_DYN)
+                                       stype = ST_CRESC;
+                               switch (stype) {
+                               case ST_ROM:
+                               case ST_BOLD:
+                               case ST_ITAL:
+                               case ST_BOLDITAL:
+                                       if (stuff_p->all) {
+                                               if (IS_CHORDLIKE(
+                                               stuff_p->modifier)) {
+                                                       dist =
+                                                       halfstaffhi(s) +
+                                                       STEPSIZE *
+                                                       Score.staffscale *
+                                                       Score.chorddist;
+                                               } else {
+                                                       dist =
+                                                       halfstaffhi(s) +
+                                                       STEPSIZE *
+                                                       Score.staffscale *
+                                                       Score.dist;
+                                               }
+                                       } else {
+                                               if (IS_CHORDLIKE(
+                                               stuff_p->modifier)) {
+                                                       dist =
+                                                       halfstaffhi(s) +
+                                                       Stepsize *
+                                                       svpath(s, CHORDDIST)->
+                                                       chorddist;
+                                               } else {
+                                                       dist =
+                                                       halfstaffhi(s) +
+                                                       Stepsize *
+                                                       svpath(s, DIST)->dist;
+                                               }
+                                       }
+                                       break;
+                               case ST_CRESC:
+                               case ST_DECRESC:
+                                       if (stuff_p->all) {
+                                               dist = halfstaffhi(s) +
+                                               STEPSIZE * Score.staffscale *
+                                               Score.dyndist;
+                                       } else {
+                                               dist = halfstaffhi(s) +
+                                               Stepsize * svpath(s,
+                                               DYNDIST)->dyndist;
+                                       }
+                                       break;
+                               default:
+                                       dist = 0;
+                                       break;
+                               }
+                       } else {
+                               /* the user specified the dist, so use that */
+                               if (stuff_p->all) {
+                                       dist = halfstaffhi(s) +
+                                               STEPSIZE * stuff_p->dist;
+                               } else {
+                                       dist = halfstaffhi(s) +
+                                               Stepsize * stuff_p->dist;
+                               }
+                       }
+
+                       if (stuff_p->dist_usage == SD_FORCE) {
+                               /*
+                                * The user is forcing this dist, so don't
+                                * stack; just put it there.  Note: the user
+                                * cannot specify "dist" for "between" items.
+                                */
+                               if (stuff_p->place == PL_ABOVE) {
+                                       rectab[reclim].n = dist + high;
+                                       rectab[reclim].s = dist;
+                                       stuff_p->c[RS] = dist;
+                               } else {        /* PL_BELOW */
+                                       rectab[reclim].n = -dist;
+                                       rectab[reclim].s = -dist - high;
+                                       stuff_p->c[RS] = -dist - high;
+                               }
+                               rectab[reclim].e = stuff_p->c[AE];
+                               rectab[reclim].w = stuff_p->c[AW];
+                               inc_reclim();
+                       } else {
+                               /*
+                                * Stack the usual way.  For the case of
+                                * "between", stackit() will ignore "dist".
+                                */
+                               stuff_p->c[RS] = stackit(stuff_p->c[AW],
+                                       stuff_p->c[AE], high, dist, place);
+                       }
+
+                       stuff_p->c[RN] = stuff_p->c[RS] + high;
+                       stuff_p->c[RY] = stuff_p->c[RS] + lowpart;
+               }
+       }
+}
+\f
+/*
+ * Name:        dolyrics()
+ *
+ * Abstract:    Set up rectangles and vert coords for lyrics.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts into rectab a rectangle for each verse in
+ *             the "place" relationship to the given staff on this score.
+ */
+
+static void
+dolyrics(start_p, s, place)
+
+struct MAINLL *start_p;                /* FEED at the start of this score */
+int s;                         /* staff number */
+int place;                     /* above, below, or between? */
+
+{
+       int *versenums;         /* malloc'ed array of verse numbers in score */
+       struct MAINLL *mainll_p;/* point along main linked list */
+       struct STAFF *staff_p;  /* point at a staff structure */
+       struct GRPSYL *gs_p;    /* point at a syllable */
+       float protrude;         /* farthest protrusion of rectangle */
+       int vfound;             /* number of verse numbers found in score */
+       int v;                  /* verse number */
+       int begin, end, delta;  /* for looping over verses in proper order */
+       float dist;             /* how close lyrics can get to staff */
+       float farwest, fareast; /* farthest east and west of any syllable */
+       float baseline;         /* baseline of a verse of syllables */
+       float maxasc, maxdes;   /* max ascent & descent of syllables */
+       int gotverse0;          /* is there a verse 0 (centered verse)? */
+       int gototherverse;      /* is there a normal verse (not 0)? */
+       int n, k, j;            /* loop variables */
+
+
+       debug(32, "dolyrics file=%s line=%d s=%d place=%d", start_p->inputfile,
+                       start_p->inputlineno, s, place);
+       /* if there are no lyrics in this song, get out now */
+       if (Maxverses == 0)
+               return;
+
+       /*
+        * Allocate an array containing room for all the verse numbers used in
+        * this score.  Maxverses is the number of verse numbers used in the
+        * whole user input, so this will certainly be enough.
+        */
+       MALLOCA(int, versenums, Maxverses);
+
+       /*
+        * Loop through this score's part of the MLL, noting whether verse 0
+        * (the centered verse) and/or other verses exist on the "place" side
+        * of the staff.  We have to find this out before actually processing
+        * the verses, because verse 0 is to be treated as a normal verse if
+        * and only if there are no other verses.
+        */
+       gotverse0 = NO;
+       gototherverse = NO;
+       for (mainll_p = start_p->next; mainll_p != 0 &&
+                       mainll_p->str != S_FEED; mainll_p = mainll_p->next) {
+               /*
+                * Whenever we find a structure for this staff (another
+                * measure of this staff), loop through its verse headcells.
+                */
+               if (mainll_p->str == S_STAFF &&
+                               mainll_p->u.staff_p->staffno == s) {
+                       staff_p = mainll_p->u.staff_p;
+                       for (n = 0; n < staff_p->nsyllists; n++) {
+                               if (staff_p->sylplace[n] == place) {
+                                       if (staff_p->syls_p[n]->vno == 0)
+                                               gotverse0 = YES;
+                                       else
+                                               gototherverse = YES;
+                               }
+                       }
+               }
+       }
+
+       /* if no verses, get out now */
+       if (gotverse0 == NO && gototherverse == 0) {
+               FREE(versenums);
+               return;
+       }
+
+       /*
+        * Loop through this score's part of the MLL, recording all the verse
+        * numbers that occur on the "place" side of the staff in versenums[].
+        * Verse 0 may or may not be included, depending on the above results.
+        * Also set farwest and fareast.
+        */
+       vfound = 0;                     /* no verses have been found yet */
+       farwest = PGWIDTH;              /* init it all the way east */
+       fareast = 0;                    /* init it all the way west */
+       for (mainll_p = start_p->next; mainll_p != 0 &&
+                       mainll_p->str != S_FEED; mainll_p = mainll_p->next) {
+               /*
+                * Whenever we find a structure for this staff (another
+                * measure of this staff), loop through its verse headcells.
+                */
+               if (mainll_p->str == S_STAFF &&
+                               mainll_p->u.staff_p->staffno == s) {
+
+                       staff_p = mainll_p->u.staff_p;
+
+                       for (n = 0; n < staff_p->nsyllists; n++) {
+
+                               if (staff_p->sylplace[n] == place) {
+                                       /*
+                                        * We found a verse number.  Search the
+                                        * the array to see if it's already
+                                        * been found.  If not, insert it into
+                                        * versenums[] in the right place, so
+                                        * that they'll end up being in order
+                                        * (actually, reverse order).
+                                        */
+                                       v = staff_p->syls_p[n]->vno;
+                                       /* ignore verse 0 if others exist */
+                                       if (v == 0 && gototherverse == YES)
+                                               continue;
+                                       for (k = 0; k < vfound &&
+                                                   v < versenums[k]; k++) {
+                                               ;
+                                       }
+                                       if (k == vfound || v > versenums[k]) {
+                                               for (j = vfound; j > k; j--) {
+                                                       versenums[j] =
+                                                       versenums[j-1];
+                                               }
+                                               versenums[k] = v;
+                                               vfound++;  /* found one more */
+                                       }
+
+                                       /*
+                                        * If any syl sticks out farther than
+                                        * any previous one, extend farwest or
+                                        * fareast.
+                                        */
+                                       for (gs_p = staff_p->syls_p[n];
+                                            gs_p != 0; gs_p = gs_p->next) {
+
+                                               if (gs_p->c[AW] < farwest)
+                                                       farwest = gs_p->c[AW];
+                                               if (gs_p->c[AE] > fareast)
+                                                       fareast = gs_p->c[AE];
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /*
+        * Enclose all the syllables of all the verses (of this place) in one
+        * big rectangle.  Pad on west and east by 8 step sizes.  Pretend the
+        * rectangle is PGHEIGHT high.  We don't actually know yet how high
+        * it is, and this will prevent it from getting between the staff and
+        * anything else.  Later in this function we will correct the entry
+        * that stackit put in rectab, to reflect the true height.  For above
+        * and below cases, don't let it get any closer than 2 step sizes to
+        * the staff.  The half-height of a one-line staff is regarded as 1
+        * instead of the true 0, to give a little breathing room.
+        */
+       if (place == PL_BETWEEN)
+               dist = 0;
+       else
+               dist = halfstaffhi(s) + 2.0 * Stepsize;
+
+       (void)stackit(farwest - 8 * STEPSIZE, fareast + 8 * STEPSIZE, PGHEIGHT,
+                       dist, place);
+
+       /*
+        * Find the greatest protrusion of any currently existing rectangle
+        * that horizontally is within the span of our new rectangle.  That's
+        * the same as the top or bottom of the new rectangle.
+        */
+       if (place == PL_BELOW)
+               protrude = rectab[reclim - 1].n;
+       else
+               protrude = rectab[reclim - 1].s;
+
+       /*
+        * Loop through the verses, from the inside out. setting the relative
+        * vertical coords of their syllables.  When necessary, we also insert
+        * new syllables on the next score for continuing underscores.
+        */
+       if (place == PL_BELOW) {        /* work downward from staff */
+               begin = vfound - 1;     /* first verse number */
+               end = -1;               /* beyond last verse number */
+               delta = -1;
+       } else {        /* above and between both work upwards from bottom */
+               begin = 0;              /* last verse number */
+               end = vfound;           /* before first verse number */
+               delta = 1;
+       }
+       for (n = begin; n != end; n += delta) {
+               /*
+                * Find the farthest any syllable ascends and descends from the
+                * baseline of the verse.
+                */
+               getvsize(start_p, s, place, versenums[n], &maxasc, &maxdes);
+
+               /*
+                * Set the baseline for this verse, based on where we're
+                * pushing up against (the last verse we did, or earlier
+                * things), and how far this verse sticks out.
+                */
+               if (place == PL_BELOW)
+                       baseline = protrude - maxasc;
+               else    /* above or between */
+                       baseline = protrude + maxdes;
+
+               /* set syllables' vertical coords; continue underscores */
+               setsylvert(start_p, s, place, versenums[n], baseline);
+
+               /* set new lower bound, for next time through loop */
+               if (place == PL_BELOW)
+                       protrude = baseline - maxdes;
+               else    /* above or between */
+                       protrude = baseline + maxasc;
+
+       } /* for every verse */
+
+       /*
+        * If there was a verse 0 (centered verse) and also normal verses, then
+        * in the above code we have handled only the normal verses, and we now
+        * need to handle verse 0.
+        */
+       if (gotverse0 == YES && gototherverse == YES) {
+               float mid;      /* RY of the middle of the normal verses */
+               struct RECTAB rec;      /* one rectangle */
+
+               /* get ascent and descent of verse 0 */
+               getvsize(start_p, s, place, 0, &maxasc, &maxdes);
+
+               /*
+                * We will use stackit's "dist" mechanism to try to get verse 0
+                * to line up with the center of the other verses.  The last
+                * rectangle in rectab is currently the normal verses', but the
+                * one coord isn't really set right yet.  Fortunately, the
+                * "protrude" variable is what we need for that coord.
+                */
+               if (place == PL_BELOW) {
+                       mid = (rectab[reclim - 1].n + protrude) / 2.0;
+                       dist = -mid - (maxasc + maxdes) / 2.0;
+               } else {
+                       mid = (protrude + rectab[reclim - 1].s) / 2.0;
+                       dist = mid - (maxasc + maxdes) / 2.0;
+               }
+
+               /*
+                * Find the easternmost and westernmost points of verse 0.
+                * It's easier to loop through all the syllables than to try to
+                * find the first and last syllables on the line.
+                */
+               farwest = PGWIDTH;              /* init it all the way east */
+               fareast = 0;                    /* init it all the way west */
+               for (mainll_p = start_p->next;
+                               mainll_p != 0 && mainll_p->str != S_FEED;
+                               mainll_p = mainll_p->next) {
+
+                       if (mainll_p->str != S_STAFF ||
+                                       mainll_p->u.staff_p->staffno != s)
+                               continue;
+
+                       staff_p = mainll_p->u.staff_p;
+                       for (n = 0; n < staff_p->nsyllists; n++) {
+                               if (staff_p->sylplace[n] == place &&
+                                               staff_p->syls_p[n]->vno == 0) {
+                                       for (gs_p = staff_p->syls_p[n];
+                                            gs_p != 0; gs_p = gs_p->next) {
+
+                                               if (gs_p->c[AW] < farwest)
+                                                       farwest = gs_p->c[AW];
+                                               if (gs_p->c[AE] > fareast)
+                                                       fareast = gs_p->c[AE];
+                                       }
+                               }
+                       }
+               }
+
+               /*
+                * Squeeze the regular verses' rectangle to zero so that it
+                * won't affect verse 0's.  We hope they wouldn't interfere
+                * anyway, but the +8 and -8 might make them.  The regular
+                * verses' rectangle will be corrected later anyway.
+                */
+               rectab[reclim - 1].n = rectab[reclim - 1].s = 0;
+
+               /*
+                * Stack verse 0's rectangle and set its baseline.  We have to
+                * play games with "place", because for "between" stackit
+                * ignores "dist", but we need it to use "dist".
+                */
+               baseline = stackit(farwest - 8 * STEPSIZE,
+                       fareast + 8 * STEPSIZE, maxasc + maxdes, dist,
+                       place == PL_BETWEEN ? PL_ABOVE : place) + maxdes;
+
+               /*
+                * Switch verse 0's rectangle and the normal verses' so that
+                * the later code can always use reclim-1 for the normal.
+                */
+               rec = rectab[reclim - 2];
+               rectab[reclim - 2] = rectab[reclim - 1];
+               rectab[reclim - 1] = rec;
+
+               setsylvert(start_p, s, place, 0, baseline);
+       }
+
+       /*
+        * Now that we know how high this rectangle really is, correct it in
+        * rectab.  Make it reach the center of the staff/baseline, to prevent
+        * anything later from getting in between there.
+        */
+       if (place == PL_BELOW) {
+               rectab[reclim - 1].n = 0;
+               rectab[reclim - 1].s = protrude;
+       } else {        /* above or between */
+               rectab[reclim - 1].n = protrude;
+               rectab[reclim - 1].s = 0;
+       }
+
+       FREE(versenums);
+}
+\f
+/*
+ * Name:        getvsize()
+ *
+ * Abstract:    Get the maximum ascent and descent for a verse on a score.
+ *
+ * Returns:     void
+ *
+ * Description: This function returns (through pointers) the maximum ascent and
+ *             descent of a verse on this score.  Usually this is the standard
+ *             ascent and descent of the font, but it could be greater if
+ *             there are font or size changes inside some syllable.
+ */
+
+static void
+getvsize(start_p, s, place, v, maxasc_p, maxdes_p)
+
+struct MAINLL *start_p;                /* FEED at the start of this score */
+int s;                         /* staff number */
+int place;                     /* above, below, or between? */
+int v;                         /* verse number */
+float *maxasc_p, *maxdes_p;    /* ascent and descent to be returned */
+
+{
+       int lyricsfont;         /* that is set for this staff */
+       int lyricssize;         /* that is set for this staff */
+       float asc, des;         /* max ascent & descent of syllables */
+       struct MAINLL *mainll_p;/* point along main linked list */
+       struct STAFF *staff_p;  /* point at a staff structure */
+       struct GRPSYL *gs_p;    /* point at a syllable */
+       int k;                  /* loop variable */
+
+
+       /*
+        * Get the standard max ascent and descent for any syllable.
+        */
+       lyricsfont = svpath(s, LYRICSFONT)->lyricsfont;
+       lyricssize = svpath(s, LYRICSSIZE)->lyricssize;
+       *maxasc_p = fontascent(lyricsfont, lyricssize) * Staffscale;
+       *maxdes_p = fontdescent(lyricsfont, lyricssize) * Staffscale;
+
+       /*
+        * Find the farthest any syllable ascends and descends from the
+        * baseline of the verse.  Start with the standard amount for this font
+        * size.  If the loop finds any weird syllable with bigger characters
+        * embedded, they will be increased.
+        */
+       for (mainll_p = start_p->next; mainll_p != 0 && mainll_p->str
+                               != S_FEED; mainll_p = mainll_p->next) {
+
+               if (mainll_p->str != S_STAFF ||
+                               mainll_p->u.staff_p->staffno != s)
+                       continue;
+
+               /* found a STAFF of the number we're dealing with */
+               staff_p = mainll_p->u.staff_p;
+
+               /*
+                * See if this verse is present in this staff,
+                * and if so, loop through it.
+                */
+               for (k = 0; k < staff_p->nsyllists; k++) {
+
+                       if (staff_p->sylplace[k] == place &&
+                                       staff_p->syls_p[k]->vno == v) {
+
+                               for (gs_p = staff_p->syls_p[k]; gs_p != 0;
+                                               gs_p = gs_p->next) {
+                                       /*
+                                        * If asc or des is greater
+                                        * for this syl, save it.
+                                        */
+                                       asc = strascent(gs_p->syl);
+
+                                       des = strdescent(gs_p->syl);
+
+                                       if (asc > *maxasc_p)
+                                               *maxasc_p = asc;
+                                       if (des > *maxdes_p)
+                                               *maxdes_p = des;
+                               }
+
+                               /* no need to look any more */
+                               break;
+                       }
+               }
+       } /* for every MLL stucture in score */
+}
+\f
+/*
+ * Name:        setsylvert()
+ *
+ * Abstract:    Set the maximum ascent and descent for a verse on a score.
+ *
+ * Returns:     void
+ *
+ * Description: This function, using the given baseline, sets the relative
+ *             vertical coords of each syllable in the verse on this score.
+ *             If there are any nonnull syllables, it calls a function to
+ *             continue underscores if need be.
+ */
+
+static void
+setsylvert(start_p, s, place, v, baseline)
+
+struct MAINLL *start_p;                /* FEED at the start of this score */
+int s;                         /* staff number */
+int place;                     /* above, below, or between? */
+int v;                         /* verse number */
+double baseline;               /* baseline of a verse of syllables */
+
+{
+       struct MAINLL *mainll_p;/* point along main linked list */
+       struct STAFF *staff_p;  /* point at a staff structure */
+       struct GRPSYL *gs_p;    /* point at a syllable */
+       struct MAINLL *laststaff_p; /* point last staff that has a syllable */
+       struct GRPSYL *lastgs_p;/* point at last nonnull syllable in a verse */
+       int k;                  /* loop variable */
+
+
+       /*
+        * Loop through all these syllables as before, setting their relative
+        * vertical coords.
+        */
+       lastgs_p = 0;           /* set later to last nonnull syl, if exists */
+       laststaff_p = 0;        /* set later to staff containing lastgs_p */
+
+       for (mainll_p = start_p->next; mainll_p != 0 && mainll_p->str
+                               != S_FEED; mainll_p = mainll_p->next) {
+
+               if (mainll_p->str != S_STAFF ||
+                               mainll_p->u.staff_p->staffno != s)
+                       continue;
+
+               /* found a STAFF of the number we're dealing with */
+               staff_p = mainll_p->u.staff_p;
+
+               /*
+                * See if this verse is present in this staff,
+                * and if so, loop through it.
+                */
+               for (k = 0; k < staff_p->nsyllists; k++) {
+
+                       if (staff_p->sylplace[k] == place &&
+                                       staff_p->syls_p[k]->vno == v) {
+
+                               for (gs_p = staff_p->syls_p[k]; gs_p != 0;
+                                               gs_p = gs_p->next) {
+
+                                       if (gs_p->syl == 0) {
+                                               continue;
+                                       }
+
+                                       gs_p->c[RY] = baseline;
+
+                                       gs_p->c[RN] = baseline
+                                               + strascent(gs_p->syl);
+
+                                       gs_p->c[RS] = baseline
+                                               - strdescent(gs_p->syl);
+
+                                       /* remember last nonnull syl */
+                                       if (gs_p->syl[0] != '\0') {
+                                               lastgs_p = gs_p;
+                                               laststaff_p = mainll_p;
+                                       }
+                               }
+                       }
+               }
+       } /* for every MLL stucture in score */
+
+       /*
+        * At this point, if this score has any nonnull syllables for
+        * this verse, lastgs_p points at the last one and laststaff_p
+        * points at its STAFF.  If that last syllable ends in '_' or
+        * '-', we may need to continue this character onto the next
+        * score, so call a function to do that.
+        */
+       if (lastgs_p != 0 && has_extender(lastgs_p->syl))
+               cont_extender(laststaff_p, place, v);
+}
+\f
+/*
+ * Name:        dopedal()
+ *
+ * Abstract:    Set a rectangle for pedal marks, if there are any.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts a rectangle into rectab for pedal marks, if
+ *             there are any on this score.  It also sets their relative
+ *             vertical coordinates.
+ */
+
+static void
+dopedal(start_p, s)
+
+struct MAINLL *start_p;                /* FEED at the start of this score */
+int s;                         /* staff number */
+
+{
+       struct MAINLL *mainll_p;        /* loop through main linked list */
+       struct STUFF *stuff_p;          /* point along a STUFF list */
+       float protrude;                 /* farthest protrusion of rectangle */
+       float lowpoint;                 /* the lowest any mark goes */
+       float asc;                      /* ascent of a pedal mark */
+       float hi;                       /* height of a pedal mark */
+       int k;                          /* loop variable */
+
+
+       debug(32, "dopedal file=%s line=%d s=%d", start_p->inputfile,
+                       start_p->inputlineno, s);
+       /*
+        * Find the greatest protrusion of any currently existing rectangle.
+        */
+       protrude = 0;
+       for (k = 0; k < reclim; k++) {
+               if (rectab[k].s < protrude)
+                       protrude = rectab[k].s;
+       }
+
+       lowpoint = 0;
+
+       /*
+        * Loop through this score's part of the MLL.  Whenever we find a
+        * structure for this staff (another measure), loop through its
+        * STUFF list, setting coords for each pedal mark.
+        */
+       for (mainll_p = start_p->next; mainll_p != 0 &&
+                       mainll_p->str != S_FEED; mainll_p = mainll_p->next) {
+
+               if (mainll_p->str != S_STAFF ||
+                               mainll_p->u.staff_p->staffno != s)
+                       continue;
+
+               for (stuff_p = mainll_p->u.staff_p->stuff_p;
+                               stuff_p != 0; stuff_p = stuff_p->next) {
+
+                       if (stuff_p->stuff_type != ST_PEDAL)
+                               continue;
+
+                       /*
+                        * Whichever pedal character this is, always use
+                        * C_BEGPED if pedstyle is P_LINE and the "Ped." string
+                        * for the other cases.  For the former, all three
+                        * characters are the same height; and for the latter,
+                        * this string is taller than the "*".  This also
+                        * handles the pedal continuation situation.
+                        */
+                       stuff_p->c[RN] = protrude;
+                       if (svpath(s, PEDSTYLE)->pedstyle == P_LINE) {
+                               asc = ascent(FONT_MUSIC, DFLT_SIZE, C_BEGPED);
+                               hi  = height(FONT_MUSIC, DFLT_SIZE, C_BEGPED);
+                       } else { /* P_PEDSTAR or P_ALTPEDSTAR */
+                               asc = strascent(Ped_start);
+                               hi  = strheight(Ped_start);
+                       }
+                       if (stuff_p->all) {
+                               asc *= Score.staffscale;
+                               hi  *= Score.staffscale;
+                       } else {
+                               asc *= Staffscale;
+                               hi  *= Staffscale;
+                       }
+                       stuff_p->c[RY] = protrude - asc;
+                       stuff_p->c[RS] = protrude - hi;
+
+                       if (stuff_p->c[RS] < lowpoint)
+                               lowpoint = stuff_p->c[RS];
+               }
+       }
+
+       /*
+        * If we found pedal mark(s), put one big rectangle in rectab, spanning
+        * the width of the page.
+        */
+       if (lowpoint < 0) {
+               rectab[reclim].n = protrude;
+               rectab[reclim].s = lowpoint;
+               rectab[reclim].w = 0;
+               rectab[reclim].e = PGWIDTH;
+
+               inc_reclim();
+       }
+}
+\f
+/*
+ * Name:        doendings()
+ *
+ * Abstract:    Set up rectangles and vert coords for ending marks.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts into rectab rectangles for ending marks.
+ *             Also, MARKCOORD structures get linked to BARs for them.
+ */
+
+static void
+doendings(start_p, s)
+
+struct MAINLL *start_p;                /* FEED at the start of this score */
+int s;                         /* staff number */
+
+{
+       struct MAINLL *mainll_p;/* point along main linked list */
+       struct BAR *bar_p;      /* point at a bar or pseudobar on this score */
+
+
+       debug(32, "doendings file=%s line=%d s=%d", start_p->inputfile,
+                       start_p->inputlineno, s);
+       /* if endings are not to be drawn over this staff, get out */
+       if (has_ending(s) == NO)
+               return;
+
+       /* point at pseudobar in clefsig that immediately follows this feed */
+       mainll_p = start_p->next;
+       bar_p = mainll_p->u.clefsig_p->bar_p;
+
+       /*
+        * If an ending starts at the pseudobar, or is continuing on from the
+        * previous score, handle it, along with any following continguous ones.
+        */
+       if (bar_p->endingloc != NOITEM) {
+               /*
+                * Search forward for the end of this ending (or following
+                * contiguous ones), or the end of the score, whichever comes
+                * first.
+                */
+               while ( ! (mainll_p->str == S_BAR &&
+                                       mainll_p->u.bar_p->endingloc == ENDITEM)
+                               && mainll_p->str != S_FEED) {
+
+                       mainll_p = mainll_p->next;
+               }
+
+               /* handle ending(s) from start to this bar or feed */
+               storeend(start_p, mainll_p, s);
+
+               /* if feed, there's nothing more to look for */
+               if (mainll_p->str == S_FEED)
+                       return;
+
+               /* point after this bar at end of this ending(s) */
+               mainll_p = mainll_p->next;
+       }
+
+       /*
+        * Search the rest of the score for contiguous groups of endings.
+        */
+       while (mainll_p != 0 && mainll_p->str != S_FEED) {
+
+               /* find another bar; return if there aren't any more */
+               while (mainll_p != 0 && mainll_p->str != S_BAR &&
+                                       mainll_p->str != S_FEED)
+                       mainll_p = mainll_p->next;
+               if (mainll_p == 0 || mainll_p->str == S_FEED)
+                       return;
+
+               /*
+                * We found another bar.  If it isn't associated with an
+                * ending, point beyond it and continue to go look for the
+                * next bar.
+                */
+               if (mainll_p->u.bar_p->endingloc == NOITEM) {
+                       mainll_p = mainll_p->next;
+                       continue;
+               }
+
+               /*
+                * This bar is the start of an ending.  Search forward for the
+                * end of this ending (or following contiguous ones), or the
+                * end of the score, whichever comes first.
+                */
+               start_p = mainll_p;
+               while ( ! (mainll_p->str == S_BAR &&
+                                       mainll_p->u.bar_p->endingloc == ENDITEM)
+                               && mainll_p->str != S_FEED) {
+
+                       mainll_p = mainll_p->next;
+               }
+
+               /* handle ending(s) from start to this bar or feed */
+               storeend(start_p, mainll_p, s);
+
+               /* if feed, there's nothing more to look for */
+               if (mainll_p->str == S_FEED)
+                       return;
+
+               /* point after this bar at end of this ending */
+               mainll_p = mainll_p->next;
+       }
+}
+\f
+/*
+ * Name:        storeend()
+ *
+ * Abstract:    Set up rectangles and vert coords for contiguous endings.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given the starting and ending bars of a group
+ *             of continguous ending marks on a staff.  The starting "bar"
+ *             may be the pseudobar at the start of the score; and the ending
+ *             bar may be the end of the score.  This function applies stackit
+ *             to them as a unit.  It adds another rectangle to rectab to
+ *             prevent anything later from getting in between the ending(s)
+ *             and the staff.  Then, for the starting bar of each ending in
+ *             the group, it allocates a MARKCOORD structure.
+ */
+
+static void
+storeend(start_p, end_p, s)
+
+struct MAINLL *start_p;                /* the start of these ending(s) */
+struct MAINLL *end_p;          /* the end of these ending(s) */
+int s;                         /* staff number */
+
+{
+       struct MAINLL *mainll_p;/* point along main linked list */
+       struct BAR *bar_p;      /* point at a bar or pseudobar on this score */
+       struct MARKCOORD *mark_p; /* we allocate these for bars to point at */
+       float west, east;       /* extremities of group of ending(s) */
+       float south;            /* their bottom boundary */
+
+
+       /*
+        * Find the west and east boundaries of the ending(s).
+        */
+       if (start_p->str == S_FEED)
+               west = start_p->next->u.clefsig_p->bar_p->c[AX]; /* pseudobar */
+       else
+               west = start_p->u.bar_p->c[AX];         /* normal bar */
+
+       if (end_p->str == S_FEED)
+               east = PGWIDTH - eff_rightmargin(end_p); /* end of score */
+       else
+               east = end_p->u.bar_p->c[AX];           /* normal bar */
+
+       /* make a rectangle out of the ending(s) and find where they go */
+       south = stackit(west, east, ENDINGHEIGHT, (double)0.0, PL_ABOVE);
+
+       /*
+        * Superimpose another rectangle on top of the one stackit put there;
+        * one that reaches down to the staff.  This ensures that nothing later
+        * will get between the ending(s) and the staff.
+        */
+       rectab[reclim].n = south + ENDINGHEIGHT;
+       rectab[reclim].s = 0;
+       rectab[reclim].e = east;
+       rectab[reclim].w = west;
+       inc_reclim();
+
+       /*
+        * If the pseudobar has an ending, calloc a markcoord structure and put
+        * it in the pseudobar's linked list of them.
+        */
+       if (start_p->str == S_FEED) {
+               bar_p = start_p->next->u.clefsig_p->bar_p;
+               CALLOC(MARKCOORD, mark_p, 1);
+               mark_p->next = bar_p->ending_p;
+               bar_p->ending_p = mark_p;
+               mark_p->staffno = (short)s;
+               mark_p->ry = south;
+       }
+
+       /*
+        * Loop through this part of the score.  Wherever there is a bar that
+        * is the start of an ending, calloc a markcoord structure and put it
+        * in the bar's linked list of them.
+        */
+       for (mainll_p = start_p; mainll_p != end_p; mainll_p = mainll_p->next) {
+               if (mainll_p->str != S_BAR)
+                       continue;
+               bar_p = mainll_p->u.bar_p;
+               if (bar_p->endingloc != STARTITEM)
+                       continue;
+               CALLOC(MARKCOORD, mark_p, 1);
+               mark_p->next = bar_p->ending_p;
+               bar_p->ending_p = mark_p;
+               mark_p->staffno = (short)s;
+               mark_p->ry = south;
+       }
+}
+\f
+/*
+ * Name:        dorehears()
+ *
+ * Abstract:    Set up rectangles and vert coords for rehearsal marks.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts into rectab rectangles for rehearsal marks.
+ *             Also, MARKCOORD structures get linked to BARs for them.
+ */
+
+static void
+dorehears(start_p, s)
+
+struct MAINLL *start_p;                /* FEED at the start of this score */
+int s;                         /* staff number */
+
+{
+       struct MAINLL *mainll_p;/* point along main linked list */
+       struct BAR *bar_p;      /* point at a bar or pseudobar on this score */
+       struct MARKCOORD *mark_p; /* we allocate these for bars to point at */
+       float west, east;       /* of a rehearsal mark */
+       float south;            /* of a rehearsal mark */
+       float height;           /* of a rehearsal mark */
+       float dist;             /* distance from center of staff */
+       int dopseudo;           /* do the pseudobar's rehearsal mark? */
+       char *reh_string;       /* string for the reh mark */
+
+
+       debug(32, "dorehears file=%s line=%d s=%d", start_p->inputfile,
+                       start_p->inputlineno, s);
+       /* if rehearsal marks are not to be drawn over this staff, get out */
+       if (has_ending(s) == NO)
+               return;
+
+       /* point at pseudobar in clefsig that immediately follows this feed */
+       mainll_p = start_p->next;
+       bar_p = mainll_p->u.clefsig_p->bar_p;
+
+       /* if there's a rehearsal mark at the pseudobar, note that fact */
+       if (bar_p->reh_type != REH_NONE)
+               dopseudo = YES;
+       else
+               dopseudo = NO;
+
+       /*
+        * Loop through the score, dealing with the pseudobar (if it has a
+        * rehearsal mark), and all real bars that have a rehearsal mark.
+        */
+       for ( ; mainll_p != 0 && mainll_p->str != S_FEED;
+                               mainll_p = mainll_p->next) {
+
+               if (dopseudo == YES || mainll_p->str == S_BAR &&
+                                      mainll_p->u.bar_p->reh_type != REH_NONE){
+                       if (dopseudo == YES)
+                               dopseudo = NO;
+                       else
+                               bar_p = mainll_p->u.bar_p;
+
+                       /*
+                        * Find the size of the rehearsal label, including 6
+                        * more points to allow for the box around it.  Make
+                        * its first character be centered over the bar line.
+                        * Place it by using stackit.
+                        */
+                       reh_string = get_reh_string(bar_p->reh_string, s);
+                       height = strheight(reh_string);
+                       west = bar_p->c[AX] - left_width(reh_string);
+                       east = west + strwidth(reh_string);
+
+                       if (bar_p->dist_usage == SD_NONE) {
+                               /* get the usual dist */
+                               dist = svpath(s, DIST)->dist;
+                       } else {
+                               /* override with this bar's dist */
+                               dist = bar_p->dist;
+                       }
+                       /* convert to inches from center of staff */
+                       dist = halfstaffhi(s) + STEPSIZE * dist;
+
+                       if (bar_p->dist_usage == SD_FORCE) {
+                               /*
+                                * The user is forcing this dist, so don't
+                                * stack; just put it there.
+                                */
+                               south = dist;
+                               rectab[reclim].n = south + height;
+                               rectab[reclim].s = south;
+                               rectab[reclim].e = east;
+                               rectab[reclim].w = west;
+                               inc_reclim();
+                       } else {
+                               /* stack the usual way */
+                               south = stackit(west, east, height, dist,
+                                               PL_ABOVE);
+                       }
+
+                       /*
+                        * Allocate and link a MARKCOORD, and put the necessary
+                        * info in it.
+                        */
+                       CALLOC(MARKCOORD, mark_p, 1);
+                       mark_p->next = bar_p->reh_p;
+                       bar_p->reh_p = mark_p;
+                       mark_p->staffno = (short)s;
+                       mark_p->ry = south + strdescent(reh_string);
+               }
+       }
+}
+\f
+/*
+ * Name:        stackit()
+ *
+ * Abstract:    Place a rectangle and add it to rectab.
+ *
+ * Returns:     south boundary of the new rectangle
+ *
+ * Description: This function puts the given rectangle into rectab.  It is put
+ *             as close to the staff or baseline as is possible without
+ *             overlapping rectangles already in rectab, and without letting
+ *             it get any closer to the staff/baseline than "dist" STEPSIZE.
+ */
+
+static double
+stackit(west, east, height, dist, place)
+
+double west;                   /* west edge of the new rectangle */
+double east;                   /* east edge of the new rectangle */
+double height;                 /* height of the new rectangle */
+double dist;                   /* min dist from item to center line of staff*/
+int place;                     /* above, below, or between? */
+
+{
+       float north, south;     /* trial boundaries for new rectangle */
+       int try;                /* which element of rectab to try */
+       int overlap;            /* does our rectangle overlap existing ones? */
+       int j;                  /* loop variable */
+
+
+       /*
+        * For each rectangle in rectab, decide whether (based on
+        * its horizontal coords) it could possibly overlap with our
+        * new rectangle.  If it's totally left or right of ours, it
+        * can't.  We allow a slight overlap (FUDGE) so that round
+        * off errors don't stop us from packing things as tightly
+        * as possible.
+        */
+       for (j = 0; j < reclim; j++) {
+               if (rectab[j].w + FUDGE > east ||
+                   rectab[j].e < west + FUDGE)
+                       rectab[j].relevant = NO;
+               else
+                       rectab[j].relevant = YES;
+       }
+
+       /*
+        * Set up first trial position for this rectangle:  "dist" inches
+        * away from the center line of the staff.  For "between", it always
+        * starts at the baseline.
+        */
+       north = south = 0.0;    /* prevent useless 'used before set' warning */
+       switch (place) {
+       case PL_BELOW:
+               /* work downward from staff, allowing "dist" distance */
+               north = -dist;
+               south = north - height;
+               break;
+       case PL_ABOVE:
+               /* work upward from staff, allowing "dist" distance */
+               south = dist;
+               north = south + height;
+               break;
+       case PL_BETWEEN:
+               /* work upward from baseline */
+               south = 0;
+               north = height;
+               break;
+       }
+
+       /*
+        * Mark the "tried" field for all relevant rectangles.  This says
+        * whether we have already tried using their boundaries for positioning
+        * our rectangle.  Any rectangle that is closer to the staff/baseline
+        * than we want to allow, we mark as if we have tried it already.
+        */
+       for (j = 0; j < reclim; j++) {
+               if (rectab[j].relevant == YES) {
+                       if (place == PL_BELOW && rectab[j].s > north ||
+                           place != PL_BELOW && rectab[j].n < south)
+                               rectab[j].tried = YES;
+                       else
+                               rectab[j].tried = NO;
+               }
+       }
+
+       /*
+        * Keep trying positions for this rectangle, working outwards from the
+        * first trial position.  When we find one that doesn't overlap an
+        * existing rectangle, break.  This has to succeed at some point, at
+        * at the outermost rectangle position if not earlier.
+        */
+       for (;;) {
+               overlap = NO;
+               for (j = 0; j < reclim; j++) {
+                       /* ignore ones too far east or west */
+                       if (rectab[j].relevant == NO)
+                               continue;
+
+                       /* if all south or north, okay; else overlap */
+                       if (rectab[j].s + FUDGE <= north &&
+                           rectab[j].n >= south + FUDGE) {
+                               overlap = YES;
+                               break;
+                       }
+               }
+
+               /* if no rectangle overlapped, we found a valid place */
+               if (overlap == NO)
+                       break;
+
+               /*
+                * Something overlapped, so we have to try again.  Find the
+                * innermost relevant outer rectangle boundary that hasn't been
+                * tried already, to use as the next trial position for our
+                * rectangle's inner boundary.
+                */
+               try = -1;
+               for (j = 0; j < reclim; j++) {
+                       /* ignore ones too far east or west */
+                       if (rectab[j].relevant == NO || rectab[j].tried == YES)
+                               continue;
+
+                       /*
+                        * If this is the first relevant one we haven't tried,
+                        * or if this is farther in than the innermost so far,
+                        * save it as being the new innermost so far.
+                        */
+                       if (place == PL_BELOW) {
+                               if (try == -1 || rectab[j].s > rectab[try].s)
+                                       try = j;
+                       } else {
+                               if (try == -1 || rectab[j].n < rectab[try].n)
+                                       try = j;
+                       }
+               }
+
+               if (try == -1)
+                       pfatal("bug in stackit()");
+
+               /*
+                * Mark this one as having been tried (for next time around, if
+                * necessary).  Set new trial values for north and south of our
+                * rectangle.
+                */
+               rectab[try].tried = YES;
+               if (place == PL_BELOW) {
+                       north = rectab[try].s;
+                       south = north - height;
+               } else {
+                       south = rectab[try].n;
+                       north = south + height;
+               }
+
+       } /* end of while loop trying positions for this rectangle */
+
+       /*
+        * We found the correct position for the new rectangle.  Enter it
+        * into rectab.
+        */
+       rectab[reclim].n = north;
+       rectab[reclim].s = south;
+       rectab[reclim].e = east;
+       rectab[reclim].w = west;
+
+       inc_reclim();
+
+       return (south);
+}
+\f
+/*
+ * Name:        inc_reclim()
+ *
+ * Abstract:    Increment no. of rectangles, and realloc more if we run out.
+ *
+ * Returns:     void
+ *
+ * Description: This function increments reclim, the index into rectab.  If it
+ *             finds that rectab[reclim] is now beyond the end of the space
+ *             that's been allocated, it does a realloc to get more space.
+ */
+
+static void
+inc_reclim()
+{
+       /* when first called, relvert will have allocated this many */
+       static int rectabsize = RECTCHUNK;
+
+
+       reclim++;
+
+       /* if rectab[reclim] is still valid, no need to allocate more */
+       if (reclim < rectabsize)
+               return;
+
+       /* must allocate another chunk of rectangles */
+       rectabsize += RECTCHUNK;
+       REALLOC(RECTAB, rectab, rectabsize);
+}
diff --git a/mup/mup/restsyl.c b/mup/mup/restsyl.c
new file mode 100644 (file)
index 0000000..54a006b
--- /dev/null
@@ -0,0 +1,2682 @@
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ * Name:       restsyl.c
+ *
+ * Description:        This file contains functions for setting the relative
+ *             horizontal and vertical coordinates of all groups that
+ *             contain a rest or space (grpcont != GC_NOTES), and the relative
+ *             horizontal coordinates of syllables.  It then completes
+ *             the relative horizontal work by setting the relative
+ *             horizontal coords of chords.  But before it does that last
+ *             step, it scales all the relative coords set so far according
+ *             to staffscale.
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+#define PK_LEFT                (0)
+#define PK_RIGHT       (1)
+#define PK_CENTER      (2)
+#define PK_NONE                (3)
+
+static double highcoord P((struct GRPSYL *gs_p, struct GRPSYL *altgs_p));
+static double lowcoord P((struct GRPSYL *gs_p, struct GRPSYL *altgs_p));
+static void procrests P((struct CHORD *ch_p, struct STAFF *staff_p,
+               struct GRPSYL *gs_p, double limhigh, double limlow));
+static void procspaces P((struct GRPSYL *gs_p));
+static struct GRPSYL *finalgroupproc P((struct GRPSYL *gs1_p));
+static int v3pack P((struct GRPSYL *g_p[], int numgrps));
+static void fixclef P((struct GRPSYL *gs1_p));
+static void restsize P((struct GRPSYL *gs_p, float *wid_p, float *asc_p,
+               float *des_p));
+static void procsyls P((struct GRPSYL *gs_p));
+static void apply_staffscale P((void));
+static void relxchord P((void));
+static double effwest P((struct MAINLL *mainll_p, struct CHORD *ch_p,
+               struct GRPSYL *gs_p));
+static double effeast P((struct CHORD *ch_p, struct GRPSYL *gs_p));
+static int collision_danger P((struct GRPSYL *g1_p, struct GRPSYL *g2_p));
+static struct CHORD *prevchord P((struct MAINLL *mainll_p, struct CHORD *ch_p));
+static struct GRPSYL *nextchsyl P((struct GRPSYL *gs_p, struct CHORD *ch_p));
+static struct GRPSYL *prevchsyl P((struct GRPSYL *gs_p,
+               struct CHORD *prevch_p));
+static void pedalroom P((void));
+static struct CHORD *closestchord P((double count, struct CHORD *firstch_p));
+static double rightped P((int pedstyle, int pedchar));
+static double leftped P((int pedstyle, int pedchar));
+static void fixspace P((void));
+\f
+/*
+ * Name:        restsyl()
+ *
+ * Abstract:    Sets all relative coords for rests and spaces, and horizontal
+ *             ones for syllables; set relative horz. coords of chords.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through the main linked list, finding every
+ *             STAFF structure.  For groups, it calls procrests() to process
+ *             every rest in the linked list, and procspaces() to process
+ *             every space in the linked list.  For syllables, it calls
+ *             procsyls().  At the end it calls apply_staffscale() to apply
+ *             staffscale to all the relative coords set so far, and then
+ *             relxchord() to set the relative horizontal coords of chords.
+ */
+
+void
+restsyl()
+
+{
+       register struct MAINLL *mainll_p; /* point item in main linked list */
+       struct MAINLL *mll_p;           /* another MLL pointer */
+       struct STAFF *staff_p;          /* point at a staff */
+       struct STAFF *stafflist[MAXSTAFFS + 1]; /* point to this meas's staffs*/
+       float limhigh[MAXSTAFFS + 1];   /* high y coord of limit of groups */
+       float limlow[MAXSTAFFS + 1];    /* low y coord of limit of groups */
+       int vscheme;                    /* voice scheme */
+       int v;                          /* index into verse headcell array */
+       struct CHORD *ch_p;             /* point at a chord */
+       struct GRPSYL *gs1_p;           /* point at a group */
+
+
+       debug(16, "restsyl");
+       initstructs();
+
+
+       /*
+        * Loop down the main linked list looking for each chord list
+        * headcell.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               if (mainll_p->str == S_SSV) {
+                       asgnssv(mainll_p->u.ssv_p);
+                       continue;
+               }
+
+               if (mainll_p->str != S_CHHEAD)
+                       continue;       /* skip everything but chord HC */
+
+               /*
+                * For each visible staff in this measure, find the high and
+                * low limits of the relevant voices, so that we know what to
+                * avoid when placing rests in other voices.
+                */
+               for (mll_p = mainll_p->next; mll_p->str == S_STAFF;
+                               mll_p = mll_p->next) {
+
+                       staff_p = mll_p->u.staff_p;
+                       stafflist[staff_p->staffno] = staff_p;
+                       vscheme = svpath(staff_p->staffno, VSCHEME)->vscheme;
+                       if (staff_p->visible == NO) {
+                               continue;
+                       }
+
+                       /*
+                        * If there is more than one voice, each voice's rests
+                        * have to worry about avoiding other voices' notes.
+                        * So find how high voice 2 and how low voice 1, get,
+                        * in this measure.  But voice 3 can "stand in" for
+                        * either, so pass that in too.  If it's null, that's
+                        * okay, the subroutines handle that.
+                        */
+                       if (vscheme != V_1) {
+                               limhigh[staff_p->staffno] =
+                                       highcoord(staff_p->groups_p[1],
+                                       staff_p->groups_p[2]);
+                               limlow[staff_p->staffno] =
+                                       lowcoord(staff_p->groups_p[0],
+                                       staff_p->groups_p[2]);
+                       } else {
+                               /* prevent uninitialized var, though not used*/
+                               limhigh[staff_p->staffno] = 0;
+                               limlow[staff_p->staffno] = 0;
+                       }
+               }
+
+               /*
+                * Loop through each chord in this list.
+                */
+               for (ch_p = mainll_p->u.chhead_p->ch_p; ch_p != 0;
+                                       ch_p = ch_p->ch_p) {
+                       /*
+                        * Loop through the linked list of GRPSYLs hanging off
+                        * this chord.  Skip the syllables; just deal with the
+                        * groups.  Upon finding the first group on a staff
+                        * (which could be for any of the voices, since not all
+                        * might be present in this chord), call procrests and
+                        * finalgroupproc to process the groups.
+                        */
+                       gs1_p = ch_p->gs_p;
+                       for (;;) {
+                               /* find first group on a staff */
+                               while (gs1_p != 0 &&
+                                               gs1_p->grpsyl == GS_SYLLABLE)
+                                       gs1_p = gs1_p->gs_p;
+                               if (gs1_p == 0)
+                                       break;
+
+                               /*
+                                * Call procrests() to place any rest in the
+                                * voice on this staff in this chord.
+                                */
+                               procrests(ch_p, stafflist[gs1_p->staffno],
+                                               gs1_p, limhigh[gs1_p->staffno],
+                                               limlow[gs1_p->staffno]);
+
+                               /* set gs1_p to after this staff's groups */
+                               gs1_p = finalgroupproc(gs1_p);
+                       }
+               }
+       }
+
+       initstructs();
+
+       /*
+        * Loop once for each item in the main linked list.  Now that we're all
+        * done with notes and rests, do the spaces and syllables.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               if (mainll_p->str == S_SSV) {
+
+                       asgnssv(mainll_p->u.ssv_p);
+
+               } else if (mainll_p->str == S_STAFF &&
+                                       mainll_p->u.staff_p->visible == YES) {
+
+                       /* for each voice that exists, process the spaces */
+                       for (v = 0; v < MAXVOICES; v++) {
+                               if (mainll_p->u.staff_p->groups_p[v] != 0) {
+                                       procspaces(mainll_p->u.staff_p->
+                                                       groups_p[v]);
+                               }
+                       }
+
+                       /* set relative horizontal coords for syllables */
+                       for (v = 0; v < mainll_p->u.staff_p->nsyllists; v++) {
+                               procsyls(mainll_p->u.staff_p->syls_p[v]);
+                       }
+               }
+       }
+
+       /* scale all relative coords set so far according to staffscale */
+       apply_staffscale();
+
+       /* now we are ready to set relative horizontal coords for all chords */
+       relxchord();
+}
+\f
+/*
+ * Name:        highcoord()
+ *
+ * Abstract:    Find highest relative y coord of a group in one GRPSYL list.
+ *
+ * Returns:     void
+ *
+ * Description: This function goes down one of the linked lists of GRPSYLs,
+ *             one that is for groups, not syllables, and finds the highest
+ *             relative y coordinate of any group containing notes.  If there
+ *             are no notes but there are rests, it returns 0.  If there are
+ *             only spaces, it returns -100.  The answer, though, is rounded
+ *             off to the nearest staff line.  Besides the primary linked list
+ *             of GRPSYLs, it also looks for GRPSYLs in the alternate list
+ *             (voice 3 if it exists) and considers ones that are "standing in"
+ *             for the first list's voice.
+ */
+
+static double
+highcoord(gs_p, altgs_p)
+
+register struct GRPSYL *gs_p;  /* starts pointing at first GRPSYL in list */
+register struct GRPSYL *altgs_p;/* first GRPSYL of voice 3, if any */
+
+{
+       float result;
+       int normvoice;          /* main voice we are dealing with, 1 or 2 */
+       float edge;             /* of a group in the other voice */
+
+
+       debug(32, "highcoord file=%s line=%d", gs_p->inputfile,
+                       gs_p->inputlineno);
+       result = -100;          /* init as if only spaces */
+       normvoice = gs_p->vno;  /* remember the voice we're dealing with */
+
+       /* 
+        * Loop through all groups (even grace), moving result up when
+        * something higher is found.  Rests count as 0 (the middle line).
+        */
+       for ( ; gs_p != 0; gs_p = gs_p->next) {
+               switch (gs_p->grpcont) {
+               case GC_NOTES:
+                       edge = gs_p->c[RN];
+                       /* if wrong way stem, account for it as best we can */
+                       if (gs_p->stemdir == UP) {
+                               edge += (stemroom(gs_p) - 1.0) * STEPSIZE;
+                       }
+                       if (edge > result) {
+                               result = edge;
+                       }
+                       break;
+               case GC_REST:
+                       if (result < 0)
+                               result = 0;
+                       break;
+               /* ignore spaces */
+               }
+       }
+
+       /*
+        * Look at every GRPSYL in voice 3, if any.  If it is "standing in" for
+        * the normal voice, move result up if need be.
+        */
+       for ( ; altgs_p != 0; altgs_p = altgs_p->next) {
+               if (altgs_p->pvno == normvoice) {
+                       switch (altgs_p->grpcont) {
+                       case GC_NOTES:
+                               if (altgs_p->c[RN] > result)
+                                       result = altgs_p->c[RN];
+                               break;
+                       case GC_REST:
+                               if (result < 0)
+                                       result = 0;
+                               break;
+                       /* ignore spaces */
+                       }
+               }
+       }
+
+       return (nearestline(result));
+}
+\f
+/*
+ * Name:        lowcoord()
+ *
+ * Abstract:    Find lowest relative y coord of a group in one GRPSYL list.
+ *
+ * Returns:     void
+ *
+ * Description: This function goes down one of the linked lists of GRPSYLs,
+ *             one that is for groups, not syllables, and finds the lowest
+ *             relative y coordinate of any group containing notes.  If there
+ *             are no notes but there are rests, it returns 0.  If there are
+ *             only spaces, it returns 100.  The answer, though, is rounded
+ *             off to the nearest staff line.  Besides the primary linked list
+ *             of GRPSYLs, it also looks for GRPSYLs in the alternate list
+ *             (voice 3 if it exists) and considers ones that are "standing in"
+ *             for the first list's voice.
+ */
+
+static double
+lowcoord(gs_p, altgs_p)
+
+register struct GRPSYL *gs_p;  /* starts pointing at first GRPSYL in list */
+register struct GRPSYL *altgs_p;/* first GRPSYL of voice 3, if any */
+
+{
+       float result;
+       int normvoice;          /* main voice we are dealing with, 1 or 2 */
+       float edge;             /* of a group in the other voice */
+
+
+       debug(32, "lowcoord file=%s line=%d", gs_p->inputfile,
+                       gs_p->inputlineno);
+       result = 100;           /* init as if only spaces */
+       normvoice = gs_p->vno;  /* remember the voice we're dealing with */
+
+       /* 
+        * Loop through all groups (even grace), moving result down when
+        * something lower is found.  Rests count as 0 (the middle line).
+        */
+       for ( ; gs_p != 0; gs_p = gs_p->next) {
+               switch (gs_p->grpcont) {
+               case GC_NOTES:
+                       edge = gs_p->c[RS];
+                       /* if wrong way stem, account for it as best we can */
+                       if (gs_p->stemdir == DOWN) {
+                               edge -= (stemroom(gs_p) - 1.0) * STEPSIZE;
+                       }
+                       if (edge < result) {
+                               result = edge;
+                       }
+                       break;
+               case GC_REST:
+                       if (result > 0)
+                               result = 0;
+                       break;
+               /* ignore spaces */
+               }
+       }
+
+       /*
+        * Look at every GRPSYL in voice 3, if any.  If it is "standing in" for
+        * the normal voice, move result up if need be.
+        */
+       for ( ; altgs_p != 0; altgs_p = altgs_p->next) {
+               if (altgs_p->pvno == normvoice) {
+                       switch (altgs_p->grpcont) {
+                       case GC_NOTES:
+                               if (altgs_p->c[RS] < result)
+                                       result = altgs_p->c[RS];
+                               break;
+                       case GC_REST:
+                               if (result > 0)
+                                       result = 0;
+                               break;
+                       /* ignore spaces */
+                       }
+               }
+       }
+
+       return (nearestline(result));
+}
+\f
+/*
+ * Name:        procrests()
+ *
+ * Abstract:    Sets relative coordinates for rests in one CHORD/STAFF.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given the top GRPSYL on a STAFF in a CHORD.
+ *             It sets the relative coordinates of each rest GRPSYL on this
+ *             STAFF/CHORD.
+ */
+
+static void
+procrests(ch_p, staff_p, gs1_p, limhigh, limlow)
+
+struct CHORD *ch_p;            /* the chord we are in */
+struct STAFF *staff_p;         /* the staff we are processing */
+struct GRPSYL *gs1_p;          /* point at top GRPSYL in chord */
+double limhigh;                        /* highest relative y coord below v1 */
+double limlow;                 /* lowest relative y coord above v2 */
+
+{
+       RATIONAL endtime;       /* time at the end of the rest */
+       struct GRPSYL *g_p[MAXVOICES + 1]; /* index by vno, point at GRPSYL */
+       struct GRPSYL *gs_p;    /* a GRPSYL we are now working on */
+       struct GRPSYL *ogs_p;   /* other voice to be considered */
+       float wid, asc, des;    /* width, ascent, and descent of a rest */
+       int vscheme;            /* voice scheme */
+       int restsabove;         /* are these rests above another voice? */
+       int stafflines;         /* no. of lines in staff */
+       int v;                  /* voice number */
+       float y;                /* relative y coord for this rest */
+
+
+       debug(32, "procrests file=%s line=%d limhigh=%f limlow=%f",
+               gs1_p->inputfile, gs1_p->inputlineno,
+               (float)limhigh, (float)limlow);
+
+
+       /* get voice scheme and number of lines in staff */
+       vscheme = svpath(gs1_p->staffno, VSCHEME)->vscheme;
+       stafflines = svpath(gs1_p->staffno, STAFFLINES)->stafflines;
+
+       /* set pointers to all nonspace groups in this chord on this staff */
+       for (v = 1; v <= MAXVOICES; v++) {
+               g_p[v] = 0;
+       }
+       for (gs_p = gs1_p; gs_p != 0 && gs_p->staffno == gs1_p->staffno &&
+                           gs_p->grpsyl == GS_GROUP; gs_p = gs_p->gs_p) {
+               if (gs_p->grpcont != GC_SPACE) {
+                       g_p[gs_p->vno] = gs_p;
+               }
+       }
+
+       y = 0.0;        /* to avoid useless 'used before set' warning */
+       ogs_p = 0;      /* to avoid useless 'used before set' warning */
+
+       /*
+        * Loop through each possible voice, setting its coords if it is a rest.
+        */
+       for (v = 1; v <= MAXVOICES; v++) {
+
+               gs_p = g_p[v];
+
+               if (gs_p == 0 || gs_p->grpcont != GC_REST) {
+                       continue;
+               }
+
+               /* find the time at the end of the rest */
+               endtime = radd(ch_p->starttime, gs_p->fulltime);
+
+               /* find width, ascent, and descent of the rest */
+               restsize(gs_p, &wid, &asc, &des);
+
+               /*
+                * Find out if another voice needs to be considered in the
+                * placement of this rest, and set ogs_p to that voice's first
+                * GRPSYL if so.
+                */
+               ogs_p = 0;
+               if (vscheme == V_2FREESTEM ||
+                               vscheme == V_3FREESTEM && gs_p->pvno != 3) {
+                       ogs_p = gs_p->pvno == 1 ? staff_p->groups_p[1] :
+                                                 staff_p->groups_p[0];
+               }
+
+               /* 
+                * Find the RY of the rest.
+                */
+               if (vscheme == V_1 || (vscheme == V_2FREESTEM ||
+                               vscheme == V_3FREESTEM) &&
+                               hasspace(ogs_p, ch_p->starttime, endtime)) {
+                       /*
+                        * There is either only 1 voice, or we are 2f/3f and the
+                        * other voice is all spaces during this time.  Usually
+                        * RY should be 0.  But for one-line staffs, whole
+                        * rest characters need to be lowered so that they hang
+                        * under the line.
+                        */
+                       if (stafflines == 1 && gs_p->basictime == 1) {
+                               y = -2 * STEPSIZE;
+                       } else {
+                               y = 0;
+                       }
+               } else {
+                       /*
+                        * We are 2o, or 2f/3f with notes/rests in the other
+                        * voice that we must avoid hitting.  Set up the
+                        * relative y coord, based on whether gs_p is acting
+                        * as v1 or v2.  We also have to set up restsabove
+                        * for use below.
+                        */
+                       restsabove = NO;        /* default value for now */
+                       switch (gs_p->pvno) {
+                       case 1:
+                               y = limhigh < -4 * STEPSIZE ?
+                                               0 : limhigh + 4 * STEPSIZE;
+                               restsabove = ! hasspace(staff_p->groups_p[1],
+                                               Zero, Maxtime);
+                               /* also check for v3 groups acting as v2 */
+                               for (ogs_p = staff_p->groups_p[2];
+                                               ogs_p != 0 && restsabove == NO;
+                                               ogs_p = ogs_p->next) {
+                                       if (ogs_p->pvno == 2 &&
+                                       ogs_p->grpcont != GC_SPACE) {
+                                               restsabove = YES;
+                                               break;
+                                       }
+                               }
+                               break;
+                       case 2:
+                               y = limlow > 4 * STEPSIZE ?
+                                               0 : limlow - 4 * STEPSIZE;
+                               break;
+                       }
+
+                       /*
+                        * Usually RY should be the y was set above.  But
+                        * if this is the upper voice, half rests and longer
+                        * should be lower to fall within the staff when
+                        * feasible, since they don't take much space
+                        * vertically and we don't want needless ledger lines.
+                        * (But nothing should ever be lowered if already on
+                        * the center line.)  Short rests need to be moved
+                        * away from the other voice by varying amounts,
+                        * depending on how tall they are.  Quad whole rests
+                        * below need to be raised a notch.
+                        */
+                       if (restsabove == YES) {
+                               /* lower whole & double only if above middle */
+                               if (gs_p->basictime <= 2 && y > 0)
+                                       y -= 2 * STEPSIZE;
+                               if (gs_p->basictime >= 16)
+                                       y += 2 * STEPSIZE;
+                               if (gs_p->basictime == 256)
+                                       y += 2 * STEPSIZE;
+                       } else {
+                               if (gs_p->basictime >= 128)
+                                       y -= 2 * STEPSIZE;
+                               if (gs_p->basictime == -1)
+                                       y += 2 * STEPSIZE;
+                       }
+               }
+
+               /*
+                * If restdist was set by the user, use that instead of
+                * whatever we calculated above.
+                */
+               if (gs_p->restdist != NORESTDIST) {
+                       y = gs_p->restdist * STEPSIZE;
+               }
+
+               /* set all the relative coords */
+               gs_p->c[RX] = 0;
+               gs_p->c[RE] = wid / 2;
+               gs_p->c[RW] = -wid / 2 - gs_p->padding -
+                               vvpath(gs_p->staffno, gs_p->vno, PAD)->pad;
+               gs_p->c[RY] = y;
+               gs_p->c[RN] = y + asc;
+               gs_p->c[RS] = y - des;
+
+               /* if there are dot(s), add their widths to the east side */
+               if (gs_p->dots > 0) {
+                       gs_p->c[RE] += gs_p->dots * (width(FONT_MUSIC,
+                                       DFLT_SIZE, C_DOT) + 2 * STDPAD);
+               }
+       }
+}
+\f
+/*
+ * Name:        procspaces()
+ *
+ * Abstract:    Sets relative coordinates for spaces in one GRPSYL list.
+ *
+ * Returns:     void
+ *
+ * Description: This function goes down one of the linked lists of GRPSYLs,
+ *             one that is for groups, not syllables, and sets the relative
+ *             coordinates for each space found.  Usually these coords will
+ *             be left as 0, the way they were calloc'ed, but not when there
+ *             is padding or uncompressible spaces.
+ */
+
+static void
+procspaces(gs_p)
+
+register struct GRPSYL *gs_p;  /* starts pointing at first GRPSYL in list */
+
+{
+       static float half_us_width;     /* half width of uncompressible space*/
+       char headchar;                  /* char representing a note head */
+       int headfont;                   /* music font for head char */
+
+
+       /*
+        * Loop, setting all relative coords of spaces, except that if they are
+        * to be zero there's no need to set them, since calloc zeroed them.
+        * The vertical ones are always zero, and so is RX.
+        */
+       for ( ; gs_p != 0; gs_p = gs_p->next) {
+               if (gs_p->grpcont != GC_SPACE)
+                       continue;
+
+               if (gs_p->uncompressible == YES) {
+                       /*
+                        * If this is the first time in here, set this to half
+                        * a blank quarter note head plus standard pad.
+                        */
+                       if (half_us_width == 0.0) {
+                               headchar = nheadchar(get_shape_num("blank"),
+                                               4, UP, &headfont);
+                               half_us_width = width(headfont, DFLT_SIZE,
+                                               headchar) / 2.0 + STDPAD;
+                       }
+
+                       /* center the imaginary note head */
+                       gs_p->c[RE] = half_us_width / 2;
+                       gs_p->c[RW] = -half_us_width / 2;
+
+                       /* apply global user requested padding; notice that
+                        * normal spaces (s) don't get this */
+                       gs_p->c[RW] -= vvpath(gs_p->staffno,
+                                               gs_p->vno, PAD)->pad;
+               }
+
+               /* add any user requested padding */
+               gs_p->c[RW] -= gs_p->padding;
+       }
+}
+\f
+/*
+ * Name:        finalgroupproc()
+ *
+ * Abstract:    Do final processing of groups.
+ *
+ * Returns:     pointer to the first GRPSYL after these groups, 0 if none
+ *
+ * Description: This function is given the GRPSYL for the first (topmost) voice
+ *             that is on this staff in this chord.  It find what other
+ *             GRPSYLs exist.  For all the nonspace groups, it applies any
+ *             horizontal offsets needed.
+ */
+
+static struct GRPSYL *
+finalgroupproc(gs1_p)
+
+struct GRPSYL *gs1_p;          /* first voice on this staff in this chord */
+
+{
+       struct GRPSYL *g_p[MAXVOICES];  /* point at nonspace voices' groups */
+       struct GRPSYL *gs_p;            /* point at groups in the chord */
+       struct GRPSYL *last_p;          /* point at last nonspace group */
+       int numgrps;                    /* how many nonspace groups are here */
+       int staffno;                    /* staff these groups are on */
+       int n;                          /* loop variable */
+       float offset;                   /* of each when + and - are used */
+       float edge;                     /* west or east coord of group 1 or 2 */
+       int pack;                       /* optimization for voice 3 */
+
+
+       staffno = gs1_p->staffno;       /* remember staffno of first group */
+       numgrps = 0;                    /* no groups found yet */
+       last_p = 0;                     /* no last nonspace group yet */
+
+       /* find all groups in this chord on this staff; remember nonspaces */
+       for (gs_p = gs1_p; gs_p != 0 && gs_p->staffno == staffno &&
+                           gs_p->grpsyl == GS_GROUP; gs_p = gs_p->gs_p) {
+               if (gs_p->grpcont != GC_SPACE) {
+                       g_p[numgrps++] = gs_p;
+                       last_p = gs_p;
+               }
+       }
+
+       /*
+        * If all groups on this staff were spaces, just make sure clef is
+        * marked correctly and return, though it's unlikely we have a clef
+        * change before a space.
+        */
+       if (numgrps == 0) {
+               fixclef(gs1_p);
+               return (gs_p);
+       }
+
+       /* nothing to do for tab, since "ho" is ignored and rests invisible */
+       if (is_tab_staff(g_p[0]->staffno))
+               return (gs_p);
+
+       /* for any voice with a user supplied offset value, apply it now */
+       for (n = 0; n < numgrps; n++) {
+               if (g_p[n]->ho_usage == HO_VALUE)
+                       shiftgs(g_p[n], g_p[n]->ho_value * STEPSIZE);
+       }
+
+       /*
+        * If both voices 1 and 2 are nonspace, handle any ho "+" or "-".
+        */
+       if (numgrps >= 2 && g_p[0]->vno == 1 && g_p[1]->vno == 2) {
+               /*
+                * Verify and fix offsets.  We did this in setgrps.c for note
+                * groups so that compatible note groups could then be handled
+                * together.  But we need to check again in case rest groups
+                * are involved.
+                */
+               vfyoffset(g_p);
+
+               /*
+                * Check each of these 2 groups:  If it has "+" or "-" and the
+                * other one doesn't, shift it to be next to the other one on
+                * the appropriate side.
+                */
+               for (n = 0; n < 2; n++) {
+                       if ((g_p[n]->ho_usage == HO_LEFT ||
+                            g_p[n]->ho_usage == HO_RIGHT) &&
+                         ! (g_p[1-n]->ho_usage == HO_LEFT ||
+                            g_p[1-n]->ho_usage == HO_RIGHT)) {
+
+                               if (g_p[n]->ho_usage == HO_LEFT) {
+                                       shiftgs(g_p[n],
+                                       g_p[1-n]->c[RW] - g_p[n]->c[RE]);
+                               } else {
+                                       shiftgs(g_p[n],
+                                       g_p[1-n]->c[RE] - g_p[n]->c[RW]);
+                               }
+                       }
+               }
+
+               /*
+                * If one has "+" and one has "-", shift them each by half of
+                * the amount of space needed to avoid a collision.
+                */
+               if (g_p[0]->ho_usage == HO_LEFT &&
+                   g_p[1]->ho_usage == HO_RIGHT) {
+
+                       offset = (g_p[0]->c[RE] - g_p[1]->c[RW]) / 2.0;
+                       shiftgs(g_p[0], -offset);
+                       shiftgs(g_p[1], offset);
+               }
+               if (g_p[0]->ho_usage == HO_RIGHT &&
+                   g_p[1]->ho_usage == HO_LEFT) {
+
+                       offset = (g_p[1]->c[RE] - g_p[0]->c[RW]) / 2.0;
+                       shiftgs(g_p[0], offset);
+                       shiftgs(g_p[1], -offset);
+               }
+
+       } else if (g_p[0]->vno != 3) {
+               /*
+                * If only one of groups 1 and 2 is nonspace, check whether it
+                * has "+" or "-", and warn if so.
+                */
+               if (g_p[0]->ho_usage == HO_LEFT || g_p[0]->ho_usage == HO_RIGHT)
+               {
+                       l_warning(
+                               g_p[0]->inputfile, g_p[0]->inputlineno,
+                               "voice %d cannot have horizontal offset '%c' since voice %d is not present; ignoring it",
+                               g_p[0]->vno,
+                               g_p[0]->ho_usage == HO_LEFT ? '-' :'+',
+                               3 - g_p[0]->vno);
+
+                       g_p[0]->ho_usage = HO_NONE;
+               }
+       }
+
+       /*
+        * If voice 3 and at least one other voice exist here, and the user
+        * didn't state an offset value for voice 3, offset it next to the
+        * other voices, on the left or right, as requested.  But exclude the
+        * case where voice 3 was being treated as 1 or 2, by checking pvno
+        * instead of vno.
+        */
+       if (numgrps > 1 && last_p->pvno == 3 && last_p->ho_usage != HO_VALUE) {
+               /*
+                * See if we can pack v3 tightly against v1 and v2.  (This will
+                * not be allowed if ho_usage != HO_NONE for any voice, or any
+                * other of many conditions doesn't hold true.)
+                */
+               pack = v3pack(g_p, numgrps);
+               if (pack != PK_NONE) {
+                       /*
+                        * Yes, we can; shift v3 a little if necessary.  Make
+                        * it so that v3's stem is one stepsize away from the
+                        * group that its stem is pointing toward.
+                        */
+                       switch (pack) {
+                       case PK_LEFT:
+                               /* since v3 is on left, v2 must exist, and is
+                                * the voice preceding v3 in g_p */
+                               shiftgs(last_p, -STEPSIZE +
+                                       widest_head(last_p) / 2.0 +
+                                       g_p[numgrps-2]->c[RW]);
+                               break;
+                       case PK_RIGHT:
+                               /* since v3 is on right, v1 must exist, and is
+                                * the first voice in g_p */
+                               shiftgs(last_p, STEPSIZE +
+                                       g_p[0]->c[RE] -
+                                       widest_head(last_p) / 2.0);
+                               break;
+                       /* for PK_CENTER, nothing to do */
+                       }
+
+               } else if (last_p->ho_usage == HO_LEFT) {
+
+                       /* find leftmost edge of the other voice(s) */
+                       edge = g_p[0]->c[RW];
+                       for (n = 1; n < numgrps - 1; n++) {
+                               if (g_p[n]->c[RW] < edge)
+                                       edge = g_p[n]->c[RW];
+                       }
+                       /* set right edge of voice 3 == left edge of others */
+                       shiftgs(last_p, edge - last_p->c[RE]);
+
+               } else { /* HO_RIGHT, or HO_NONE which defaults to HO_RIGHT */
+
+                       /* find rightmost edge of the other voice(s) */
+                       edge = g_p[0]->c[RE];
+                       for (n = 1; n < numgrps - 1; n++) {
+                               if (g_p[n]->c[RE] > edge)
+                                       edge = g_p[n]->c[RE];
+                       }
+                       /* set left edge of voice 3 == right edge of others */
+                       shiftgs(last_p, edge - last_p->c[RW]);
+               }
+       } else if (g_p[0]->vno == 3 && (g_p[0]->ho_usage == HO_LEFT ||
+                                       g_p[0]->ho_usage == HO_RIGHT)) {
+               /*
+                * If the first (and thus only) voice is 3, it should not have
+                * ho "+" or "-".
+                */
+               l_warning(
+                       g_p[0]->inputfile, g_p[0]->inputlineno,
+                       "voice 3 cannot have horizontal offset '%c' since voices 1 and 2 are not present; ignoring it",
+                       g_p[0]->ho_usage == HO_LEFT ? '-' :'+');
+
+               g_p[0]->ho_usage = HO_NONE;
+       }
+
+       /* in case of midmeasure clef change, make sure it's marked right */
+       fixclef(gs1_p);
+
+       /* return the first GRPSYL after the groups we processed */
+       return (gs_p);
+}
+\f
+/*
+ * Name:        v3pack()
+ *
+ * Abstract:    Decide whether v3 can be packed tighter than the default.
+ *
+ * Returns:     PK_NONE                no, it can't
+ *             PK_LEFT         pack tightly on left
+ *             PK_RIGHT        pack tightly on right
+ *             PK_CENTER       pack in the center
+ *
+ * Description: This function decides whether the voice 3 group can be packed
+ *             in more tightly against voices 1 and 2 than the usual default
+ *             of just putting v3's group's rectangle to the right of the
+ *             other voices.  If there seems to be any danger that v3 would
+ *             collide with v1 or v2, it gives up and returns PK_NONE.  It
+ *             could be made a lot more sophisticated and not give up so soon
+ *             in many cases.  However many of these improvements can't be
+ *             done very well at this stage of the game, where we don't know
+ *             yet about stem lengths, beam positions, etc.
+ */
+
+static int
+v3pack(g_p, numgrps)
+
+struct GRPSYL *g_p[];          /* point at nonspace voices' groups */
+int numgrps;                   /* how many nonspace groups are here */
+
+{
+       struct GRPSYL *gs_p;            /* point at a group */
+       struct GRPSYL *v3_p;            /* point at v3's group */
+       struct NOTE *v3note_p;          /* v3 note that neighbors other voice*/
+       struct NOTE *onote_p;           /* v1/v2 note that neighbors v3 */
+       float north;                    /* highest coord of note or acc */
+       float south;                    /* lowest coord of note or acc */
+       float topdesc;                  /* descent of acc of top group */
+       float botasc;                   /* ascent of acc of bottom group */
+       int v3hasacc, otherhasacc;      /* do v3 and other voice have acc(s)?*/
+       int pack;
+       int n;                          /* loop variable */
+       int k;                          /* loop variable */
+
+
+       /* either v1 or v2 must be nonspace */
+       if (numgrps == 1) {
+               return (PK_NONE);
+       }
+
+       /* point at v3's group for convenience */
+       v3_p = g_p[numgrps - 1];
+
+       /* set up what the answer will be if we can apply the optimization */
+       if (v3_p->basictime >= 2) {
+               /* there is a stem, so offset such that stem will avoid v1/v2 */
+               if (v3_p->stemdir == UP) {
+                       pack = PK_RIGHT;
+               } else {        /* DOWN */
+                       pack = PK_LEFT;
+               }
+       } else {
+               pack = PK_CENTER;       /* no stem, so we can center v3 */
+       }
+
+       /* v3 must not be standing in for v1 or v2 */
+       if (v3_p->pvno != 3) {
+               return (PK_NONE);
+       }
+
+       /* if v3 would be on left, it must not have a flag or be start of beam*/
+       if (pack == PK_LEFT && (v3_p->basictime >= 8 && v3_p->beamloc == NOITEM
+                               || v3_p->beamloc == STARTITEM)) {
+               return (PK_NONE);
+       }
+
+       /* if v3 would be on right, it must not have grace groups preceding */
+       if (pack == PK_RIGHT && v3_p->prev != 0 &&
+                               v3_p->prev->grpvalue == GV_ZERO) {
+               return (PK_NONE);
+       }
+
+       /* v3 cannot have slashes or alternation */
+       if (v3_p->slash_alt != 0) {
+               return (PK_NONE);
+       }
+
+       /*
+        * Loop through all voices, checking for rule violations.  We do it
+        * in reverse so that we know v3 is notes (the first check) before
+        * checking the other voices.
+        */
+       for (n = numgrps - 1; n >= 0; n--) {
+               gs_p = g_p[n];  /* set to current voice for convenience */
+
+               /* voice must be notes, and not measure repeat */
+               if (gs_p->grpcont != GC_NOTES || gs_p->is_meas) {
+                       return (PK_NONE);
+               }
+
+               /* voice cannot have user requested horizontal offset */
+               if (gs_p->ho_usage != HO_NONE) {
+                       return (PK_NONE);
+               }
+
+               /* voice cannot have a "with" list */
+               if (gs_p->nwith != 0) {
+                       return (PK_NONE);
+               }
+
+               /* voice cannot have a roll */
+               if (gs_p->roll != NOITEM) {
+                       return (PK_NONE);
+               }
+
+               /* do voice specific checks */
+               switch (gs_p->vno) {
+
+               case 1:
+                       /* stem must be up */
+                       if (gs_p->stemdir != UP) {
+                               return (PK_NONE);
+                       }
+
+                       /* find neighboring notes of v1 and v3 */
+                       v3note_p = &v3_p->notelist[0];
+                       onote_p = &gs_p->notelist[gs_p->nnotes - 1];
+
+                       /* neighboring notes in v1 & v3 must not be too close */
+                       if (onote_p->stepsup < v3note_p->stepsup + 2 ||
+                       onote_p->stepsup == v3note_p->stepsup + 2 &&
+                       pack != PK_CENTER &&
+                       (v3_p->basictime < 1 || gs_p->basictime < 1)) {
+                               return (PK_NONE);
+                       }
+
+                       /* if 2 steps apart and on lines and v3 would not be on
+                        * right, v1 can't have dots and v3 can't unless it
+                        * is on the right */
+                       if (onote_p->stepsup == v3note_p->stepsup + 2 &&
+                       EVEN(v3note_p->stepsup) &&
+                       (gs_p->dots != 0 ||
+                       pack != PK_RIGHT && v3_p->dots != 0)) {
+                               return (PK_NONE);
+                       }
+
+                       /*
+                        * Find the lowest extension of any accidental in v1.
+                        * If no accidentals, the initial value for "south"
+                        * will remain.  It's not good enough to check accs
+                        * only on the neighboring notes, because some of them
+                        * stick out pretty far.  We have to go through these
+                        * gyrations because group boundaries do not consider
+                        * accidentals that stick out up or down.
+                        */
+                       otherhasacc = NO;
+                       south = onote_p->c[RY] - STEPSIZE + 0.001;
+                       for (k = 0; k < gs_p->nnotes; k++) {
+                               accdimen(&gs_p->notelist[k], (float *)0,
+                                               &topdesc, (float *)0);
+                               if (gs_p->notelist[k].c[RY] - topdesc < south) {
+                                       south = gs_p->notelist[k].c[RY]
+                                                       - topdesc;
+                               }
+                               if (gs_p->notelist[k].accidental != '\0') {
+                                       otherhasacc = YES;
+                               }
+                       }
+                       /* similarly, find highest extension of v3 accs */
+                       v3hasacc = NO;
+                       north = v3note_p->c[RY] + STEPSIZE - 0.001;
+                       for (k = 0; k < v3_p->nnotes; k++) {
+                               accdimen(&v3_p->notelist[k], &botasc,
+                                               (float *)0, (float *)0);
+                               if (v3_p->notelist[k].c[RY] + botasc > north) {
+                                       north = v3_p->notelist[k].c[RY]
+                                                       + botasc;
+                               }
+                               if (v3_p->notelist[k].accidental != '\0') {
+                                       v3hasacc = YES;
+                               }
+                       }
+                       /* if v1 and v3 overlap due to acc(s), fail */
+                       if (south < north) {
+                               switch (pack) {
+                               case PK_RIGHT:
+                                       if (v3hasacc == YES) {
+                                               return (PK_NONE);
+                                       }
+                                       break;
+                               case PK_CENTER:
+                                       if (v3hasacc == YES &&
+                                           otherhasacc == YES) {
+                                               return (PK_NONE);
+                                       }
+                                       break;
+                               case PK_LEFT:
+                                       if (otherhasacc == YES) {
+                                               return (PK_NONE);
+                                       }
+                                       break;
+                               }
+                       }
+
+                       /* if left or right offset, neighboring notes in v1 &
+                        * v3 must not have parentheses when accs exist */
+                       if ((pack != PK_CENTER || v3hasacc == YES || otherhasacc == YES) &&
+                          (v3note_p->note_has_paren || onote_p->note_has_paren)) {
+                               return (PK_NONE);
+                       }
+
+                       break;
+
+               case 2:
+                       if (gs_p->stemdir != DOWN) {
+                               return (PK_NONE);
+                       }
+
+                       /* find neighboring notes of v2 and v3 */
+                       v3note_p = &v3_p->notelist[v3_p->nnotes - 1];
+                       onote_p = &gs_p->notelist[0];
+
+                       /* neighboring notes in v1 & v3 must not be too close */
+                       if (onote_p->stepsup > v3note_p->stepsup - 2 ||
+                       onote_p->stepsup == v3note_p->stepsup - 2 &&
+                       pack != PK_CENTER &&
+                       (v3_p->basictime < 1 || gs_p->basictime < 1)) {
+                               return (PK_NONE);
+                       }
+
+                       /* if 2 steps apart and on lines and v3 would not be on
+                        * right, neither can have dots */
+                       if (onote_p->stepsup == v3note_p->stepsup - 2 &&
+                                       EVEN(v3note_p->stepsup) &&
+                                       pack != PK_RIGHT &&
+                                       (gs_p->dots != 0 || v3_p->dots != 0)) {
+                               return (PK_NONE);
+                       }
+
+                       /*
+                        * Find the highest extension of any accidental in v2.
+                        * If no accidentals, the initial value for "north"
+                        * will remain.
+                        */
+                       otherhasacc = NO;
+                       north = onote_p->c[RY] + STEPSIZE - 0.001;
+                       for (k = 0; k < gs_p->nnotes; k++) {
+                               accdimen(&gs_p->notelist[k], &botasc,
+                                               (float *)0, (float *)0);
+                               if (gs_p->notelist[k].c[RY] + botasc > north) {
+                                       north = gs_p->notelist[k].c[RY]
+                                                       + botasc;
+                               }
+                               if (gs_p->notelist[k].accidental != '\0') {
+                                       otherhasacc = YES;
+                               }
+                       }
+                       /* similarly, find highest extension of v3 accs */
+                       v3hasacc = NO;
+                       south = v3note_p->c[RY] - STEPSIZE + 0.001;
+                       for (k = 0; k < v3_p->nnotes; k++) {
+                               accdimen(&v3_p->notelist[k], (float *)0,
+                                               &topdesc, (float *)0);
+                               if (v3_p->notelist[k].c[RY] - topdesc < south) {
+                                       south = v3_p->notelist[k].c[RY]
+                                                       - topdesc;
+                               }
+                               if (v3_p->notelist[k].accidental != '\0') {
+                                       v3hasacc = YES;
+                               }
+                       }
+                       /* if v2 and v3 overlap due to acc(s), fail */
+                       if (south < north) {
+                               switch (pack) {
+                               case PK_RIGHT:
+                                       if (v3hasacc == YES) {
+                                               return (PK_NONE);
+                                       }
+                                       break;
+                               case PK_CENTER:
+                                       if (v3hasacc == YES &&
+                                           otherhasacc == YES) {
+                                               return (PK_NONE);
+                                       }
+                                       if (v3hasacc == YES &&
+                                       gs_p->nnotes >= 2 &&
+                                       onote_p->stepsup ==
+                                       gs_p->notelist[1].stepsup + 1) {
+                                               return (PK_NONE);
+                                       }
+                                       break;
+                               case PK_LEFT:
+                                       if (otherhasacc == YES) {
+                                               return (PK_NONE);
+                                       }
+                                       break;
+                               }
+                       }
+
+                       /* if left or right offset, neighboring notes in v2 &
+                        * v3 must not have parentheses when accs exist */
+                       if ((pack != PK_CENTER || v3hasacc == YES || otherhasacc == YES) &&
+                          (v3note_p->note_has_paren || onote_p->note_has_paren)) {
+                               return (PK_NONE);
+                       }
+
+                       break;
+               }
+       }
+
+       /* all checks passed, so return the answer */
+       return (pack);
+}
+\f
+/*
+ * Name:        fixclef()
+ *
+ * Abstract:    If midmeasure clef change at this chord, mark in right GRPSYL.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given the GRPSYL for the first (topmost) voice
+ *             that is on this staff in this chord.  If the clef changed at
+ *             this time value, locllnotes() in setnotes.c will have set the
+ *             "clef" field in each of the GRPSYLs in this chord on this
+ *             staff (actually in their first preceding grace group, if
+ *             any).  But it should only be set in the GRPSYL that has the
+ *             westernmost west boundary.  So this function erases it from
+ *             any other GRPSYLs.
+ */
+
+static void
+fixclef(gs1_p)
+
+struct GRPSYL *gs1_p;          /* starts at first voice on this staff */
+
+{
+       struct GRPSYL *g_p[MAXVOICES];  /* point at voices' groups */
+       struct GRPSYL *gs_p;            /* point at groups in the chord */
+       int numgrps;                    /* how many groups are in the chord */
+       struct GRPSYL *westgs_p;        /* remember westernmost */
+       int staffno;                    /* staff number */
+       int n;                          /* loop variable */
+
+
+       staffno = gs1_p->staffno;       /* remember staffno of first group */
+
+       /* point at all groups in this chord on this staff */
+       numgrps = 0;                    /* no groups found yet */
+       for (gs_p = gs1_p; gs_p != 0 && gs_p->staffno == staffno &&
+                           gs_p->grpsyl == GS_GROUP; gs_p = gs_p->gs_p) {
+               g_p[numgrps++] = gs_p;
+       }
+
+       /*
+        * For each that is preceded by grace group(s), change the pointer to
+        * point at the first in that sequence of grace groups.  Any clef
+        * change would occur at that group.
+        */
+       for (n = 0; n < numgrps; n++) {
+               while (g_p[n]->prev != 0 && g_p[n]->prev->grpvalue == GV_ZERO) {
+                       g_p[n] = g_p[n]->prev;
+               }
+       }
+
+       /* if clef not marked in first, it's not marked in any, so return */
+       if (g_p[0]->clef == NOCLEF) {
+               return;
+       }
+
+       westgs_p = 0;   /* prevent useless "used before set" warning */
+
+       /*
+        * Find the westernmost group of notes, if any; if it's a tie, use the
+        * first one.  We don't want to put clefs in front of rests, spaces, or
+        * mrpt, unless we have no choice.
+        */
+       for (n = 0; n < numgrps; n++) {
+               if (g_p[n]->grpcont == GC_NOTES && g_p[n]->is_meas == NO) {
+                       if (westgs_p == 0 || g_p[n]->c[RW] < westgs_p->c[RW]) {
+                               westgs_p = g_p[n];
+                       }
+               }
+       }
+       /* we have no choice; arbitrarily choose the first voice */
+       if (westgs_p == NULL) {
+               westgs_p = g_p[0];
+       }
+
+       /* erase clef from all but the group found above */
+       for (n = 0; n < numgrps; n++) {
+               if (g_p[n] != westgs_p) {
+                       g_p[n]->clef = NOCLEF;
+               }
+       }
+
+       /* if there were no notes, there will be no clef here */
+       if (westgs_p == 0) {
+               return;
+       }
+
+       /* move western boundary of GRPSYL to allow room to print the clef */
+       westgs_p->c[RW] -= clefwidth(westgs_p->clef, YES) + CLEFPAD;
+
+       /*
+        * If this is a grace group, we also have to alter its main group's
+        * boundary, because the main group's boundary needs to enclose all
+        * its grace groups.
+        */
+       for (gs_p = westgs_p; gs_p->grpvalue == GV_ZERO; gs_p = gs_p->next) {
+               ;
+       }
+       if (gs_p != westgs_p) {
+               gs_p->c[RW] -= clefwidth(westgs_p->clef, YES) + CLEFPAD;
+       }
+}
+\f
+/*
+ * Name:        restsize()
+ *
+ * Abstract:    Find the size of a rest.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given a GRPSYL which is a rest.  It returns
+ *             the width, ascent, and descent through pointers.
+ */
+
+static void
+restsize(gs_p, wid_p, asc_p, des_p)
+
+register struct GRPSYL *gs_p;  /* the GRPSYL containing the rest */
+float *wid_p, *asc_p, *des_p;  /* return width, ascent, and descent of rest */
+
+{
+       char rchar;             /* char for the rest */
+       int size;               /* font size */
+
+
+       /* multirest has no music character; just return the answer */
+       if (gs_p->basictime < -1) {
+               *wid_p = MINMULTIWIDTH;
+               *asc_p = 2 * STEPSIZE;
+               *des_p = 2 * STEPSIZE;
+               return;
+       }
+
+       /* on a tab staff rests are invisible, so set to a very small size */
+       if (is_tab_staff(gs_p->staffno)) {
+               *wid_p = *asc_p = *des_p = 0.01;
+               return;
+       }
+
+       /*
+        * The "normal" rest case.  Find the name of the character.  Then get
+        * the width, ascent, and descent of the rest.
+        */
+       rchar = restchar(gs_p->basictime);
+       size = (gs_p->grpsize == GS_NORMAL ? DFLT_SIZE : SMALLSIZE);
+       *wid_p = width(FONT_MUSIC, size, rchar);
+       *asc_p = ascent(FONT_MUSIC, size, rchar);
+       *des_p = descent(FONT_MUSIC, size, rchar);
+}
+\f
+/*
+ * Name:        procsyls()
+ *
+ * Abstract:    Sets relative horizontal coords for syllables in 1 GRPSYL list.
+ *
+ * Returns:     void
+ *
+ * Description: This function goes down one of the linked lists of GRPSYLs,
+ *             one that is for syllables, not groups, and sets the relative
+ *             horizontal coordinates for each syllable found.
+ */
+
+static void
+procsyls(gs_p)
+
+register struct GRPSYL *gs_p;  /* starts pointing at first GRPSYL in list */
+
+{
+       float wid_b4_syl;       /* width of leading non-lyrics */
+       float wid_real_syl;     /* width of actual lyric */
+       float wid_after_syl;    /* width of trailing non-lyrics */
+       float lyricsalign;      /* fraction of syl to go left of chord center*/
+       int font, size;         /* of the last char in a syllable */
+       char lc;                /* last char of syllable */
+
+
+       debug(32, "procsyls file=%s line=%d", gs_p->inputfile,
+                       gs_p->inputlineno);
+       /* find what fraction of each syl should go left of center of chord */
+       lyricsalign = svpath(gs_p->staffno, LYRICSALIGN)->lyricsalign;
+
+       /*
+        * Set coords for every syllable.  A syllable can consist of 3 parts.
+        * The middle part is the actual lyric.  The optional first and last
+        * parts are surrounded in the user's input by angle brackets.  The
+        * syllable is to be positioned such that "lyricsalign" of the middle
+        * part goes to the left of the chord's center, and the rest goes to
+        * the right; unless sylposition is set, in which case the left edge of
+        * the actual lyric is offset by that many points from the chord's
+        * center.  Then adjust the east side for padding purposes.
+        */
+       for ( ; gs_p != 0; gs_p = gs_p->next) {
+               sylwidth(gs_p->syl, &wid_b4_syl, &wid_real_syl, &wid_after_syl);
+
+               gs_p->c[RX] = 0;
+               if (gs_p->sylposition == NOSYLPOSITION) {
+                       gs_p->c[RW] = -lyricsalign * wid_real_syl - wid_b4_syl;
+                       gs_p->c[RE] = (1 - lyricsalign) * wid_real_syl +
+                                       wid_after_syl;
+               } else {
+                       gs_p->c[RW] = gs_p->sylposition * POINT - wid_b4_syl;
+                       gs_p->c[RE] = gs_p->sylposition * POINT + wid_real_syl +
+                                       wid_after_syl;
+               }
+
+               /* get last char of syl; if null syl don't alter RE any more */
+               lc = last_char(gs_p->syl);
+               if (lc == '\0')
+                       continue;
+
+               /*
+                * If this is not the last syllable of the measure, and it
+                * doesn't end in '-', leave space for a blank after it, to
+                * separate it from the next syllable.
+                */
+               if ( gs_p->next != 0 && lc != '-') {
+                       end_fontsize(gs_p->syl, &font, &size);
+                       gs_p->c[RE] += width(font, size, ' ');
+               }
+
+               /*
+                * If this is the last syllable of the measure, and it ends in
+                * '-', back up a space, letting the '-' go into the bar line.
+                */
+               if ( gs_p->next == 0 && lc == '-' ) {
+                       end_fontsize(gs_p->syl, &font, &size);
+                       gs_p->c[RE] -= width(font, size, ' ');
+               }
+       }
+}
+\f
+/*
+ * Name:        apply_staffscale()
+ *
+ * Abstract:    Scale all relative coordinates according to staffscale.
+ *
+ * Returns:     void
+ *
+ * Description:        Throughout Mup, we are able to almost entirely avoid dealing
+ *             with the "scale" parameter, by the following trick:  We pretend
+ *             the paper is a different size than it really is, by the inverse
+ *             of the "scale" factor, place and print everything at standard
+ *             size, and then at the end apply the scale to everything at
+ *             once, in PostScript.  (Margins are exempt from scaling, hence
+ *             the EFF_* macros to cancel it out.)
+ *
+ *             But for the "staffscale" parameter, this kind of trick only
+ *             works up to a point.  As long as we are dealing only with
+ *             relative coords on one staff at a time, as we have up to this
+ *             point in the program, we can ignore staffscale.  But now we're
+ *             about to start dealing with chord coords, and chords span
+ *             staffs.  So the jig is up.
+ *
+ *             This function goes through all the relative coords set so far,
+ *             and scales them according to staffscale.  It also scales the
+ *             font sizes in strings.  From this point on staffscale must
+ *             always be considered.
+ */
+
+static void
+apply_staffscale()
+
+{
+       struct MAINLL *mainll_p;        /* point at items in main linked list*/
+       struct STAFF *staff_p;          /* point at a staff structure */
+       register float staffscale;      /* current staffscale */
+       register struct GRPSYL *gs_p;   /* point at groups */
+       register struct NOTE *note_p;   /* point at notes */
+       struct STUFF *stuff_p;          /* point at a stuff structure */
+       int n;                          /* loop variable */
+       int v;                          /* voice number, 0 to 2 */
+
+
+       debug(16, "apply_staffscale");
+
+       initstructs();
+
+       /*
+        * Loop down the main linked list looking for each staff.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               switch (mainll_p->str) {
+               case S_SSV:
+                       /* apply SSVs to keep staffscale up to date */
+                        asgnssv(mainll_p->u.ssv_p);
+                       continue;
+
+               case S_STAFF:
+                       staff_p = mainll_p->u.staff_p;
+                       break;          /* break out to handle staffs */
+
+               default:
+                       continue;       /* nothing to do */
+               }
+
+               /* get staffscale for this staff in this measure */
+               staffscale = svpath(staff_p->staffno, STAFFSCALE)->staffscale;
+
+               /* go through each voice this staff has */
+               for (v = 0; v < MAXVOICES; v++) {
+
+                       /* and each group in each voice */
+                       for (gs_p = staff_p->groups_p[v]; gs_p != 0;
+                                       gs_p = gs_p->next) {
+
+                               /* scale the group's relative coords */
+                               gs_p->c[RX] *= staffscale;
+                               gs_p->c[RN] *= staffscale;
+                               gs_p->c[RY] *= staffscale;
+                               gs_p->c[RS] *= staffscale;
+
+                               /* but don't disturb this E,W constant value */
+                               /* (see setgrps.c and abshorz.c) */
+                               if (gs_p->c[RE] != TEMPMRPTWIDTH / 2.0) {
+                                       gs_p->c[RE] *= staffscale;
+                                       gs_p->c[RW] *= staffscale;
+                               }
+
+                               gs_p->xdotr *= staffscale;
+
+                               /* usually we're done caring about padding */
+                               /*  by now, but not always, so scale it */
+                               gs_p->padding *= staffscale;
+
+                               if (gs_p->grpcont == GC_NOTES) {
+                                       for (n = 0; n < gs_p->nnotes; n++) {
+                                               note_p = &gs_p->notelist[n];
+
+                                               /* scale note's rel. coords */
+                                               note_p->c[RW] *= staffscale;
+                                               note_p->c[RX] *= staffscale;
+                                               note_p->c[RE] *= staffscale;
+                                               note_p->c[RN] *= staffscale;
+                                               note_p->c[RY] *= staffscale;
+                                               note_p->c[RS] *= staffscale;
+
+                                               note_p->waccr *= staffscale;
+                                               note_p->ydotr *= staffscale;
+                                               note_p->wlparen *= staffscale;
+                                               note_p->erparen *= staffscale;
+
+                                               /* this isn't really scaling,
+                                                * but it's a convenient place
+                                                * to undo CSS_STEPS */
+                                               if (gs_p->stemto == CS_ABOVE &&
+                                                   n <= gs_p->stemto_idx) {
+                                                       gs_p->notelist[n].stepsup -= CSS_STEPS;
+                                                       gs_p->notelist[n].ydotr -=
+                                                       CSS_STEPS * STEPSIZE * staffscale;
+                                               } else if (gs_p->stemto == CS_BELOW &&
+                                                   n >= gs_p->stemto_idx) {
+                                                       gs_p->notelist[n].stepsup += CSS_STEPS;
+                                                       gs_p->notelist[n].ydotr +=
+                                                       CSS_STEPS * STEPSIZE * staffscale;
+                                               }
+                                       }
+                               }
+
+                               for (n = 0; n < gs_p->nwith; n++) {
+                                       (void)resize_string(gs_p->withlist[n],
+                                               staffscale,
+                                               gs_p->inputfile,
+                                               gs_p->inputlineno);
+                               }
+                       }
+               }
+
+               /* scale the syllables' coords and font sizes */
+               for (v = 0; v < staff_p->nsyllists; v++) {
+                       for (gs_p = staff_p->syls_p[v]; gs_p != 0;
+                                                       gs_p = gs_p->next) {
+                               gs_p->c[RW] *= staffscale;
+                               gs_p->c[RX] *= staffscale;
+                               gs_p->c[RE] *= staffscale;
+                               gs_p->c[RN] *= staffscale;
+                               gs_p->c[RY] *= staffscale;
+                               gs_p->c[RS] *= staffscale;
+
+                               (void)resize_string(gs_p->syl, staffscale,
+                                       gs_p->inputfile, gs_p->inputlineno);
+                       }
+               }
+
+               /* scale the STUFF structures' font sizes */
+               /* (their coords won't be set until we get to stuff.c) */
+               for (stuff_p = staff_p->stuff_p; stuff_p != 0;
+                               stuff_p = stuff_p->next) {
+                       if (stuff_p->string != 0) {
+                               (void)resize_string(
+                                       stuff_p->string,
+                                       stuff_p->all == YES ? Score.staffscale
+                                                       : staffscale,
+                                       stuff_p->inputfile,
+                                       stuff_p->inputlineno);
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        relxchord()
+ *
+ * Abstract:    Set relative horizontal coordinates of each chord.
+ *
+ * Returns:     void
+ *
+ * Description: This function goes through the chord lists, and for each chord,
+ *             sets its horizontal relative coordinates, by going down the
+ *             list of GRPSYLs hanging off it.
+ */
+
+static void
+relxchord()
+
+{
+       struct CHORD *ch_p;             /* point at a chord */
+       struct CHORD *pch_p;            /* point at previous chord */
+       struct CHORD *ppch_p;           /* point at chord before that */
+       struct MAINLL *mainll_p;        /* point at items in main linked list*/
+       struct GRPSYL *gs_p;            /* point at groups */
+       struct GRPSYL *nsyl_p;          /* point at next syl */
+       struct GRPSYL *psyl_p;          /* point at previous syl */
+       float stealable;                /* from previous chord */
+       float eff;                      /* effective coord */
+
+
+       debug(16, "relxchord");
+       initstructs();
+
+       /*
+        * Loop down the main linked list looking for each chord list headcell.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               /* need to keep "pad" up to date */
+               if (mainll_p->str == S_SSV)
+                       asgnssv(mainll_p->u.ssv_p);
+
+               if (mainll_p->str != S_CHHEAD)
+                       continue;       /* skip everything but chord HC */
+
+               /*
+                * Pretend that all the chords will be jammed tightly together,
+                * starting at absolute coordinate zero.  We set absolute
+                * coords here for the benefit of effwest(), but they will be
+                * overwritten with their true values later in abshorz().
+                */
+               mainll_p->u.chhead_p->ch_p->c[AW] = 0.0; /* west of 1st chord*/
+
+               /*
+                * First, loop forwards through the chord list, setting the
+                * boundaries and widths of each chord based only on its
+                * groups.  The chord is to extend outwards just enough to
+                * contain every group.
+                */
+               for (ch_p = mainll_p->u.chhead_p->ch_p; ch_p != 0;
+                                       ch_p = ch_p->ch_p) {
+
+                       /* start chord as if 0 width */
+                       ch_p->c[RX] = 0;
+                       ch_p->c[RE] = 0;
+                       ch_p->c[RW] = 0;
+
+                       /* loop through groups, expanding chord when necessary*/
+                       for (gs_p = ch_p->gs_p; gs_p != 0; gs_p = gs_p->gs_p) {
+                               if (gs_p->grpsyl == GS_GROUP) {
+                                       /*
+                                        * If last chord in measure, add pad
+                                        * parameter on right side of groups;
+                                        * but not for collapseable spaces (s).
+                                        */
+                                       if (ch_p->ch_p == 0 &&
+                                          (gs_p->grpcont != GC_SPACE ||
+                                          gs_p->uncompressible == YES)) {
+                                               gs_p->c[RE] += vvpath(gs_p->
+                                               staffno, gs_p->vno, PAD)->pad *
+                                               svpath(gs_p->staffno,
+                                               STAFFSCALE)->staffscale;
+                                       }
+
+                                       eff = effwest(mainll_p, ch_p, gs_p);
+                                       if (eff < ch_p->c[RW])
+                                               ch_p->c[RW] = eff;
+                                       eff = effeast(ch_p, gs_p);
+                                       if (eff > ch_p->c[RE])
+                                               ch_p->c[RE] = eff;
+                               }
+                       }
+
+                       /* store width; will be updated later to include syls */
+                       ch_p->width = ch_p->c[RE] - ch_p->c[RW];
+
+                       /* set phony absolute coords for effwest() */
+                       ch_p->c[AX] = ch_p->c[AW] - ch_p->c[RW];
+                       ch_p->c[AE] = ch_p->c[AX] + ch_p->c[RE];
+                       if (ch_p->ch_p != 0)
+                               ch_p->ch_p->c[AW] = ch_p->c[AE];
+               }
+
+               /*
+                * Loop again through each chord in this list, this time
+                * expanding chords when necessary to include eastward
+                * extensions of syllables.  Work right to left, so that when
+                * a syllable steals space from the following chord, the
+                * following chord has already been widened eastwards, if it
+                * needed to be, based on its syllables.
+                */
+               /* find last chord in the chord LL */
+               ch_p = mainll_p->u.chhead_p->ch_p;      /* first chord */
+               while (ch_p->ch_p != 0)
+                       ch_p = ch_p->ch_p;
+
+               /* loop backwards through them (too bad there's no back ptr) */
+               for ( ; ch_p != 0; ch_p = prevchord(mainll_p, ch_p)) {
+                       /*
+                        * Loop through the linked list of GRPSYLs hanging off
+                        * this chord, altering RE when finding a syl that
+                        * sticks out farther.  There is one exception to
+                        * this.  If a syllable extends farther east than any
+                        * one so far, a test is made so that it can steal
+                        * space from the following chord if that chord has
+                        * no syllable there.
+                        */
+                       for (gs_p = ch_p->gs_p; gs_p != 0; gs_p = gs_p->gs_p) {
+
+                               /* if not a syl or not sticking out east */
+                               if (gs_p->grpsyl != GS_SYLLABLE ||
+                                               gs_p->c[RE] <= ch_p->c[RE])
+                                       continue;
+
+                               /* syl seems to be sticking out east */
+
+                               /*
+                                * If this is the last chord in the measure,
+                                * the chord boundary must include the syl.
+                                */
+                               if (ch_p->ch_p == 0) {
+                                       ch_p->c[RE] = gs_p->c[RE];
+                                       continue;
+                               }
+
+                               /*
+                                * The syl is sticking out east of the current
+                                * chord boundary, and this is not the last
+                                * chord in the measure.  See if the next
+                                * chord contains the next syl of this verse.
+                                * If not, there's an empty space there, and
+                                * we can let the current syl steal space from
+                                * the next chord.
+                                */
+                               nsyl_p = nextchsyl(gs_p, ch_p);
+                               if (nsyl_p == 0) {
+                                       /*
+                                        * Next chord has no syl here.  We can
+                                        * steal its space.  If the syl is so
+                                        * long that even that isn't enough
+                                        * room, we'll force the current chord
+                                        * boundary far enough out to contain
+                                        * the excess.
+                                        */
+                                       if (gs_p->c[RE] > ch_p->c[RE] +
+                                                       ch_p->ch_p->width) {
+                                               ch_p->c[RE] = gs_p->c[RE] -
+                                                       ch_p->ch_p->width;
+                                       }
+                               } else {
+                                       /*
+                                        * Next chord has a syl, so we can't
+                                        * steal its space.  Extend this chord.
+                                        */
+                                       ch_p->c[RE] = gs_p->c[RE];
+                               }
+                       }
+
+                       /* revise width; will be revised again later */
+                       ch_p->width = ch_p->c[RE] - ch_p->c[RW];
+
+               } /* end of backwards loop through chords in this measure */
+
+               /*
+                * Loop again through each chord in this list, this time
+                * expanding chords when necessary to include westward
+                * extensions of syllables.  Work left to right, so that when
+                * a syllable steals space from the preceding chord, the
+                * preceding chord has already been widened westwards, if it
+                * needed to be, based on its syllables.
+                */
+               for (ch_p = mainll_p->u.chhead_p->ch_p; ch_p != 0;
+                                       ch_p = ch_p->ch_p) {
+                       /*
+                        * Loop through the linked list of GRPSYLs hanging off
+                        * this chord, altering RW when finding a syl that
+                        * sticks out farther.  There is one exception to
+                        * this.  If a syllable extends farther west than any
+                        * one so far, a test is made so that it can steal
+                        * space from the following chord if that chord has
+                        * no syllable there.
+                        */
+                       for (gs_p = ch_p->gs_p; gs_p != 0; gs_p = gs_p->gs_p) {
+
+                               /* if not a syl or not sticking out west */
+                               if (gs_p->grpsyl != GS_SYLLABLE ||
+                                               gs_p->c[RW] >= ch_p->c[RW])
+                                       continue;
+
+                               /* syl seems to be sticking out west */
+
+                               /*
+                                * If this is the first chord in the measure,
+                                * the chord boundary must include the syl.
+                                */
+                               if (prevchord(mainll_p, ch_p) == 0) {
+                                       ch_p->c[RW] = gs_p->c[RW];
+                                       continue;
+                               }
+
+                               /*
+                                * The syl is sticking out west of the current
+                                * chord boundary, and this is not the first
+                                * chord in the measure.  See if the previous
+                                * chord contains the previous syl of this
+                                * verse, or if the one before that stole
+                                * space from it.  If not, there's an empty
+                                * space there, and we can let the current syl
+                                * steal space from the previous chord.  Even
+                                * if the previous chord has no syl but the one
+                                * before stole some space from it, we can use
+                                * the part of the space it didn't steal.
+                                */
+                               /* get prev chord, & prev syl in this verse */
+                               pch_p = prevchord(mainll_p, ch_p);
+                               psyl_p = prevchsyl(gs_p, pch_p);
+
+                               if (psyl_p == 0) {
+                                       /* first, assume all of the previous */
+                                       /*  chord's width is available */
+                                       stealable = pch_p->width;
+
+                                       /*
+                                        * Get the chord before the previous.
+                                        * If it exists and contains a syl,
+                                        * syl may already be stealing space
+                                        * east of it, in which case we can
+                                        * only steal what's left over.
+                                        */
+                                       ppch_p = prevchord(mainll_p, pch_p);
+                                       if (ppch_p != 0) {
+                                               psyl_p = prevchsyl(gs_p,
+                                                               ppch_p);
+
+                                               if (psyl_p != 0 && psyl_p->c[RE]
+                                               > ppch_p->c[RE]) {
+                                                       stealable -= (psyl_p->
+                                                       c[RE] - ppch_p->c[RE]);
+                                               }
+                                       }
+
+                                       /*
+                                        * If our syl needs more space than is
+                                        * available for stealing, widen our
+                                        * chord by the necessary amount.
+                                        */
+                                       if (gs_p->c[RW] < ch_p->c[RW] -
+                                                               stealable)
+                                               ch_p->c[RW] = gs_p->c[RW] +
+                                                               stealable;
+                               } else {
+                                       /*
+                                        * Prev chord has a syl, so we can't
+                                        * steal its space.  Extend this chord.
+                                        */
+                                       ch_p->c[RW] = gs_p->c[RW];
+                               }
+                       }
+
+                       /* final revision of width */
+                       ch_p->width = ch_p->c[RE] - ch_p->c[RW];
+
+               } /* end of forwards loop through chords in this measure */
+
+       } /* end of loop through each CHHEAD in main linked list */
+
+       pedalroom();            /* make room for "Ped." and "*" if need be */
+
+       fixspace();             /* set a width for certain space chords */
+}
+\f
+/*
+ * Name:        effwest()
+ *
+ * Abstract:    Find the effective west boundary of a group.
+ *
+ * Returns:     the RW to be used for the group
+ *
+ * Description: This function returns an "effective" RW for the given group.
+ *             Sometimes this is just the true RW.  But if the previous chord
+ *             has no groups on this staff that are in danger of colliding, we
+ *             pretend it is a smaller number, so that our group can overlap
+ *             horizonally with previous ones that have no possibly colliding
+ *             groups.
+ */
+
+static double
+effwest(mainll_p, ch_p, gs_p)
+
+struct MAINLL *mainll_p;       /* point at MLL item for this chord */
+struct CHORD *ch_p;            /* point at this chord */
+struct GRPSYL *gs_p;           /* point at this group */
+
+{
+       struct CHORD *pch_p;    /* point at previous chord */
+       struct CHORD *ech_p;    /* point at earlier chord */
+       struct GRPSYL *pgs_p;   /* point a group in previous chord */
+       float small;            /* small number to be used */
+       int found;              /* found a chord with a group on our staff? */
+       float ourax;            /* tentative value for our chord's AX */
+       float temp;             /* temp variable */
+
+
+       pch_p = prevchord(mainll_p, ch_p);      /* find previous chord */
+
+       /* if we are the first chord, return our group's true RW */
+       if (pch_p == 0)
+               return (gs_p->c[RW]);
+
+       /* set default to -1.5 stepsize */
+       small = -1.5 * STEPSIZE * svpath(gs_p->staffno, STAFFSCALE)->staffscale;
+
+       /* if already closer to 0 than "small", return true RW */
+       if (gs_p->c[RW] > small)
+               return (gs_p->c[RW]);
+
+       /*
+        * Loop through the previous chord's GRPSYLs to see if it has any
+        * groups on this staff.  If so, return our true RW, if there is a
+        * danger of collision.  If there isn't a group, or it's far enough
+        * away vertically that we know we won't collide with it, we will leave
+        * the loop and later return a phony RW.
+        */
+       for (pgs_p = pch_p->gs_p; pgs_p != 0; pgs_p = pgs_p->gs_p) {
+               /* skip cases where there can't be any interference */
+               if (pgs_p->staffno > gs_p->staffno)
+                       break;          /* nothing more could be on our staff*/
+               if (pgs_p->staffno < gs_p->staffno)
+                       continue;       /* ignore if wrong staff */
+               if (pgs_p->grpsyl == GS_SYLLABLE)
+                       continue;       /* ignore if not a group */
+               if (collision_danger(pgs_p, gs_p) == NO)
+                       continue;
+
+               /* found a group that might collide, return our true RW */
+               return (gs_p->c[RW]);
+       }
+
+       /*
+        * There is no group on our staff in the preceding chord, or at least
+        * none that we're in danger of colliding with.  We'd like to
+        * let our group overlap into that space if necessary.  But there
+        * might be a group in some earlier chord, and if there are enough dots
+        * on it, or enough accidentals on our group, they could still
+        * interfere.  Find the first earlier chord, looking right to left,
+        * that has a group neighboring our group that might collide.
+        */
+       found = NO;
+       for (ech_p = prevchord(mainll_p, pch_p); ech_p != 0;
+                               ech_p = prevchord(mainll_p, ech_p)) {
+
+               for (pgs_p = ech_p->gs_p; pgs_p != 0; pgs_p = pgs_p->gs_p) {
+
+                       if (pgs_p->staffno > gs_p->staffno)
+                               break;  /* nothing more could be on our staff*/
+                       if (pgs_p->staffno < gs_p->staffno)
+                               continue;       /* ignore if wrong staff */
+                       if (pgs_p->grpsyl == GS_SYLLABLE)
+                               continue;       /* ignore if not a group */
+                       if (collision_danger(pgs_p, gs_p) == NO)
+                               continue;
+
+                       /* found a group that might collide */
+                       found = YES;
+                       break;
+               }
+               if (found == YES)
+                       break;
+       }
+
+       if (ech_p == 0)
+               pfatal("no preceding group in effwest()");
+
+       /*
+        * Since there could be multiple voices on this staff, there could be
+        * multiple groups on this staff in the chord we found.  Loop through
+        * each of them, keeping track of the max value our chord's AX would
+        * have to be to keep our group from overlapping that group.
+        */
+       ourax = 0.0;
+       for ( ; pgs_p != 0 && pgs_p->staffno == gs_p->staffno &&
+                       pgs_p->grpsyl == GS_GROUP; pgs_p = pgs_p->gs_p) {
+
+               /* ignore ones that are vertically out of the way */
+               if (collision_danger(pgs_p, gs_p) == NO)
+                       continue;
+
+               temp = ech_p->c[AX] + pgs_p->c[RE] - gs_p->c[RW];
+               if (temp > ourax)
+                       ourax = temp;
+       }
+
+       /* find what that value for our AX would make our RW be */
+       temp = ch_p->c[AW] - ourax;
+
+       /* return that amount, but not more than "small" */
+       return (MIN(temp, small));
+}
+\f
+/*
+ * Name:        effeast()
+ *
+ * Abstract:    Find the effective east boundary of a group.
+ *
+ * Returns:     the RE to be used for the group
+ *
+ * Description: This function returns an "effective" RE for the given group.
+ *             Sometimes this is just the true RE.  But if the next chord
+ *             has no groups on this staff that are in danger of colliding, we
+ *             pretend it is a smaller number, so that our group can overlap
+ *             horizonally with the next chord.  Don't worry about colliding
+ *             with a group in a later chord; effwest() will handle that when
+ *             processing that later group.
+ */
+
+static double
+effeast(ch_p, gs_p)
+
+struct CHORD *ch_p;            /* point at this chord */
+struct GRPSYL *gs_p;           /* point at this group */
+
+{
+       struct CHORD *nch_p;    /* point at next chord */
+       struct GRPSYL *ngs_p;   /* point a group in next chord */
+       float small;            /* small number to be used */
+       float onestep;          /* a stepsize, scaled */
+
+
+       nch_p = ch_p->ch_p;     /* find next chord */
+
+       /* if we are the last chord, return our group's true RE */
+       if (nch_p == 0)
+               return (gs_p->c[RE]);
+
+       /* set default to 1.5 stepsize */
+       onestep = STEPSIZE * svpath(gs_p->staffno, STAFFSCALE)->staffscale;
+       small = 1.5 * onestep;
+
+       /* if already closer to 0 than "small", return true RE */
+       if (gs_p->c[RE] < small)
+               return (gs_p->c[RE]);
+
+       /*
+        * Loop through the next chord's GRPSYLs to see if it has any
+        * groups on this staff.  If so, return our true RE, unless they are
+        * not in danger of colliding.
+        */
+       for (ngs_p = nch_p->gs_p; ngs_p != 0; ngs_p = ngs_p->gs_p) {
+               /* skip cases where there can't be any interference */
+               if (ngs_p->staffno > gs_p->staffno)
+                       break;          /* nothing more could be on our staff*/
+               if (ngs_p->staffno < gs_p->staffno)
+                       continue;       /* ignore if wrong staff */
+               if (ngs_p->grpsyl == GS_SYLLABLE)
+                       continue;       /* ignore if not a group */
+               if (collision_danger(gs_p, ngs_p) == NO)
+                       continue;
+
+               /* found a group that might collide, return true RE */
+               return (gs_p->c[RE]);
+       }
+
+       return (small);
+}
+\f
+/*
+ * Name:        collision_danger()
+ *
+ * Abstract:    Find whether the given groups are in danger of colliding.
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function is given two groups, a left and a right group,
+ *             that are on the same staff.  If they are in the same voice, it
+ *             just returns YES (we don't want one note of a voice to go under
+ *             another in the same voice, and it would rarely work anyhow due
+ *             to stem directions).  Otherwise it decides whether they are so
+ *             close vertically that they are in danger of colliding unless
+ *             kept apart horizontally.
+ */
+
+static int
+collision_danger(g1_p, g2_p)
+
+struct GRPSYL *g1_p;           /* ptr to left group */
+struct GRPSYL *g2_p;           /* ptr to right group */
+
+{
+       float staffscale;
+       float stepsize;                 /* adjusted by staff scale */
+       float north[2], south[2];       /* RN and RS of the groups */
+       float dotoutside;               /* RY just beyond outside edge of dot*/
+       float ascent, descent;          /* of an accidental */
+       struct GRPSYL *g_p[2];          /* point at these two groups */
+       int k, j;                       /* loop variables */
+       float accedge;                  /* RN or RS of edge of accidental */
+
+
+       /* same voice, always assume collideable */
+       if (g1_p->vno == g2_p->vno) {
+               return (YES);
+       }
+
+       /* a space can't collide with anything */
+       if (g1_p->grpcont == GC_SPACE || g2_p->grpcont == GC_SPACE) {
+               return (NO);
+       }
+
+       /* if measure repeat, there won't be anything else to collide with */
+       if (is_mrpt(g1_p) || is_mrpt(g2_p)) {
+               return (NO);
+       }
+
+       staffscale = svpath(g1_p->staffno, STAFFSCALE)->staffscale;
+       stepsize = STEPSIZE * staffscale;
+       g_p[0] = g1_p;
+       g_p[1] = g2_p;
+
+       /* find the RN and RS of the groups */
+       for (k = 0; k < 2; k++) {
+               if (g_p[k]->grpcont == GC_REST) {
+                       /* for rests, simply use the group boundaries */
+                       north[k] = g_p[k]->c[RN];
+                       south[k] = g_p[k]->c[RS];
+
+               /*
+                * We can't use the group boundaries for notes.  For one thing,
+                * we don't know the stem length yet.  Assume the worst, that
+                * they are way long.  It won't usually negatively impact the
+                * result, nor will the fact that some notes don't have stems,
+                * because most collisions would be on the non-stem side of the
+                * groups.  On the non-stem side, we can't use the group
+                * boundary because it includes padding which would often make
+                * it seem like there'd be a collision, when really there won't
+                * be.
+                */
+               } else if (g_p[k]->stemdir == UP) {
+
+                       north[k] = 10000.;      /* way long stem */
+
+                       /* one step below lowest note */
+                       south[k] = (g_p[k]->notelist[g_p[k]->nnotes-1].
+                                       stepsup - 1) * stepsize;
+
+                       /* if dots, and lower than current RS, lower the RS */
+                       if (k == 0 && g_p[k]->dots > 0) {
+                               dotoutside = g_p[k]->notelist[g_p[k]->nnotes-1].
+                                               ydotr - 0.6 * stepsize;
+                               if (dotoutside < south[k]) {
+                                       south[k] = dotoutside;
+                               }
+                       }
+
+                       /* if any note has acc going below RS, lower the RS */
+                       if (k == 1) {
+                               for (j = 0; j < g_p[k]->nnotes; j++) {
+                                       if (g_p[k]->notelist[j].accidental !=
+                                                               '\0') {
+                                               accdimen(&g_p[k]->notelist[j],
+                                                       (float *)0, &descent,
+                                                       (float *)0);
+                                               descent *= staffscale;
+
+                                               /* bottom edge of acc */
+                                               accedge = stepsize *
+                                               g_p[k]->notelist[j].stepsup -
+                                               descent;
+
+                                               if (accedge < south[k]) {
+                                                       south[k] = accedge;
+                                               }
+                                       }
+                               }
+                       }
+
+                       /* if bottom note has parens, the group boundary shows
+                        * close to how far down they go; extend to there */
+                       if (g_p[k]->notelist[g_p[k]->nnotes-1].note_has_paren
+                                       && g_p[k]->c[RS] < south[k]) {
+                               south[k] = g_p[k]->c[RS];
+                       }
+
+               } else {        /* stemdir == DOWN */
+
+                       south[k] = -10000.;     /* way long stem */
+
+                       /* one step above highest note */
+                       north[k] = (g_p[k]->notelist[0].
+                                       stepsup + 1) * stepsize;
+
+                       /* if dots, and higher than current RN, raise the RN */
+                       if (k == 0 && g_p[k]->dots > 0) {
+                               dotoutside = g_p[k]->notelist[0].
+                                               ydotr + 0.6 * stepsize;
+                               if (dotoutside > north[k]) {
+                                       north[k] = dotoutside;
+                               }
+                       }
+
+                       /* if any note has acc going above RN, raise the RN */
+                       if (k == 1) {
+                               for (j = 0; j < g_p[k]->nnotes; j++) {
+                                       if (g_p[k]->notelist[j].accidental !=
+                                                               '\0') {
+                                               accdimen(&g_p[k]->notelist[j],
+                                                       &ascent, (float *)0,
+                                                       (float *)0);
+                                               ascent *= staffscale;
+
+                                               /* top edge of acc */
+                                               accedge = stepsize *
+                                               g_p[k]->notelist[j].stepsup +
+                                               ascent;
+
+                                               if (accedge > north[k]) {
+                                                       north[k] = accedge;
+                                               }
+                                       }
+                               }
+                       }
+
+                       /* if top note has parens, the group boundary shows
+                        * close to how far up they go; extend to there */
+                       if (g_p[k]->notelist[0].note_has_paren
+                                       && g_p[k]->c[RN] > north[k]) {
+                               north[k] = g_p[k]->c[RN];
+                       }
+               }
+       }
+
+       /* if the groups don't overlap vertically, no collision danger */
+       if (south[0] >= north[1] || north[0] <= south[1]) {
+               return (NO);
+       }
+
+       return (YES);           /* collision danger */
+}
+\f
+/*
+ * Name:        prevchord()
+ *
+ * Abstract:    Find chord preceding the given one.
+ *
+ * Returns:     pointer to previous chord, or 0 if none
+ *
+ * Description: This function is given a pointer to a chord headcell and a
+ *             chord in that list.  It finds the preceding chord, returning
+ *             it, or 0 if none.  If chord linked lists were doubly linked,
+ *             we wouldn't have to go through this aggravation.
+ */
+
+static struct CHORD *
+prevchord(mainll_p, ch_p)
+
+struct MAINLL *mainll_p;       /* ptr to current syllable */
+struct CHORD *ch_p;            /* ptr to current chord */
+
+{
+       register struct CHORD *prevch_p;
+
+
+       prevch_p = mainll_p->u.chhead_p->ch_p;  /* get first chord in list */
+
+       /* if current chord is first chord, there is none before it */
+       if (prevch_p == ch_p)
+               return (0);
+
+       /* loop until we find it, then return */
+       while (prevch_p->ch_p != ch_p)
+               prevch_p = prevch_p->ch_p;
+       return (prevch_p);
+}
+\f
+/*
+ * Name:        nextchsyl()
+ *
+ * Abstract:    Find following syllable if it is in the next chord.
+ *
+ * Returns:     pointer to next syllable, or 0 if none
+ *
+ * Description: This function is given a pointer to a syllable, and the chord
+ *             it is in.  It looks in the next chord, to see if there is a
+ *             syllable there that follows this syllable.  If there is, it
+ *             returns it.  Otherwise it returns 0.
+ *             Note:  if the next syllable is was given as a space, it counts
+ *             as if it weren't there at all (return 0).
+ */
+
+static struct GRPSYL *
+nextchsyl(gs_p, ch_p)
+
+struct GRPSYL *gs_p;   /* ptr to current syllable */
+struct CHORD *ch_p;    /* ptr to current chord */
+
+{
+       struct GRPSYL *nextgs_p;        /* point, looking for next syl */
+
+
+       /* if last chord in measure, return no next syllable */
+       if (ch_p->ch_p == 0)
+               return (0);
+
+       /*
+        * Look down next chord until we hit either the end, or the syllable
+        * that follows the given one.  Return what was found.
+        */
+       for (nextgs_p = ch_p->ch_p->gs_p;
+                       nextgs_p != 0 && nextgs_p != gs_p->next;
+                       nextgs_p = nextgs_p->gs_p)
+               ;
+
+       /* if syl doesn't exist or is a space, return 0 */
+       if (nextgs_p == 0 || nextgs_p->syl == 0)
+               return (0);
+
+       return (nextgs_p);
+}
+\f
+/*
+ * Name:        prevchsyl()
+ *
+ * Abstract:    Find preceding syllable if it is in the previous chord.
+ *
+ * Returns:     pointer to previous syllable, or 0 if none
+ *
+ * Description: This function is given a pointer to a syllable, and the chord
+ *             it is in.  It looks in the previous chord, to see if there is a
+ *             syllable there that precedes this syllable.  If there is, it
+ *             returns it.  Otherwise it returns 0.
+ *
+ *             Note:  if the prev syllable is given as a space, it counts
+ *             as if it weren't there at all (return 0).
+ *
+ *             Also note:  unlike nextchsyl, this function compares against
+ *             not only the given GRPSYL, but the also the previous GRPSYL.
+ *             It has to, because it is sometimes called with the previous
+ *             chord, and sometimes with the one before that.
+ */
+
+static struct GRPSYL *
+prevchsyl(gs_p, prevch_p)
+
+struct GRPSYL *gs_p;           /* ptr to current syllable */
+struct CHORD *prevch_p;                /* ptr to previous chord */
+
+{
+       struct GRPSYL *prevgs_p;        /* point, looking for next syl */
+
+
+       /* if first chord in measure, return no previous syllable */
+       if (prevch_p == 0)
+               return (0);
+
+       /*
+        * Look down previous chord until we hit either the end, or the syllable
+        * that precedes the given one.  Return what was found.
+        * "Precede" here means either directly precedes, or precedes in two
+        * steps.
+        */
+       for (prevgs_p = prevch_p->gs_p;
+                       prevgs_p != 0 && ! (prevgs_p == gs_p->prev ||
+                       (gs_p->prev != 0 && prevgs_p == gs_p->prev->prev));
+                       prevgs_p = prevgs_p->gs_p)
+               ;
+
+       /* if syl doesn't exist or is a space, return 0 */
+       if (prevgs_p == 0 || prevgs_p->syl == 0)
+               return (0);
+
+       return (prevgs_p);
+}
+\f
+/*
+ * Name:        pedalroom()
+ *
+ * Abstract:    Increase some chords' width to make room for pedal characters.
+ *
+ * Returns:     void
+ *
+ * Description: This function tries to make room for "Ped." and "*", so that
+ *             they don't overwrite each other.  For each "pedstar" style
+ *             pedal mark, it finds the chord it's closest to.  If two of them
+ *             are on neighboring chords, it may widen the left chord to
+ *             provide enough room.  The problem is, the best it can do is
+ *             assume that the pedal marks are exactly aligned with their
+ *             closest chords.  It doesn't do anything about marks that are
+ *             not on neighboring chords, since that would be quite a bit
+ *             more work and would rarely be necessary.  Worst of all, if two
+ *             marks' closest chords are the same chord, nothing can be done.
+ */
+
+static void
+pedalroom()
+
+{
+       struct MAINLL *mainll_p;        /* point at items in main linked list*/
+       struct CHHEAD *chhead_p;        /* point at a chord head cell */
+       struct STAFF *staff_p;          /* point at a staff */
+       struct STUFF *stuff_p;          /* point at a stuff */
+       struct CHORD *pedch_p;          /* point at a chord near a pedal mark*/
+       struct CHORD *opedch_p;         /* point at prev chord near pedal */
+       int pedstyle;                   /* P_* */
+       int pedchar, opedchar;          /* current and previous pedal char */
+       int font, size;                 /* of a pedal char */
+       char *string;                   /* for pedal char */
+       float needed;                   /* amount of room needed */
+
+
+       debug(16, "pedalroom");
+       initstructs();
+
+       chhead_p = 0;           /* prevent useless 'used before set' warning */
+
+       /*
+        * Loop down the main linked list looking for each chord list headcell.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               switch (mainll_p->str) {
+               case S_SSV:
+                       /* need to keep pedstyle and timeden up to date */
+                       asgnssv(mainll_p->u.ssv_p);
+                       continue;       /* go to next MLL structure */
+
+               case S_CHHEAD:
+                       /* remember this measure's chord list */
+                       chhead_p = mainll_p->u.chhead_p;
+                       continue;       /* go to next MLL structure */
+
+               case S_STAFF:
+                       pedstyle = svpath(mainll_p->u.staff_p->staffno,
+                                       PEDSTYLE)->pedstyle;
+                       if (pedstyle != P_LINE) {
+                               staff_p = mainll_p->u.staff_p;
+                               break;          /* break out and handle this */
+                       }
+
+                       continue;       /* not pedstar, ignore this staff */
+
+               default:
+                       continue;       /* skip everything else */
+               }
+
+               /*
+                * At this point we are at a staff that has a pedstyle that
+                * uses "Ped." and "*".  Loop down the stuff list, looking for
+                * pedal marks.
+                */
+               opedch_p = 0;           /* no pedal mark yet in measure */
+               opedchar = '\0';/* prevent useless 'used before set' warning */
+               for (stuff_p = staff_p->stuff_p; stuff_p != 0;
+                                       stuff_p = stuff_p->next) {
+                       /*
+                        * If it is not a pedal stuff, or it has no character,
+                        * like a continuation from the previous score, skip.
+                        */
+                       if (stuff_p->stuff_type != ST_PEDAL ||
+                           stuff_p->string == 0)
+                               continue;
+                       /*
+                        * Find the chord that is closest to this pedal mark,
+                        * and which character this pedal mark is.
+                        * But following the usual policy of applying "steps"
+                        * offsets only after everything else is done, we
+                        * ignore start.steps and use only start.count.
+                        */
+                       pedch_p = closestchord(stuff_p->start.count,
+                                       chhead_p->ch_p);
+                       font = stuff_p->string[0];
+                       size = stuff_p->string[1];
+                       string = stuff_p->string + 2;
+                       pedchar = next_str_char(&string, &font, &size) & 0xff;
+
+                       /* if first pedal mark in measure, nothing more to do*/
+                       if (opedch_p == 0) {
+                               /* remember as previous chord with pedal */
+                               opedch_p = pedch_p;
+                               opedchar = pedchar;
+                               continue;
+                       }
+
+                       /*
+                        * If this pedal mark and the previous one are by
+                        * neighboring chords, assume these marks are exactly
+                        * aligned with their chords.  Make sure the east half
+                        * of the previous chord plus the west half of this
+                        * chord is enough room for them.  If it isn't, enlarge
+                        * the east half of the previous chord.  (Note: RW is
+                        * negative, so it must be negated.)
+                        */
+                       if (pedch_p == opedch_p->ch_p) {
+                               needed = rightped(pedstyle, opedchar) +
+                                        leftped(pedstyle, pedchar);
+                               if (stuff_p->all == YES) {
+                                       needed *= Score.staffscale;
+                               } else {
+                                       needed *= svpath(staff_p->staffno,
+                                               STAFFSCALE)->staffscale;
+                               }
+                               if (opedch_p->c[RE] - pedch_p->c[RW] < needed){
+                                       opedch_p->c[RE] = needed +
+                                                       pedch_p->c[RW];
+                                       opedch_p->width = opedch_p->c[RE] -
+                                                       opedch_p->c[RW];
+                               }
+                       }
+
+                       /* remember previous chord with pedal, and its char */
+                       opedch_p = pedch_p;
+                       opedchar = pedchar;
+               }
+       }
+}
+\f
+/*
+ * Name:        closestchord()
+ *
+ * Abstract:    Find closest chord to given time value.
+ *
+ * Returns:     pointer to the closest chord
+ *
+ * Description: This function finds the CHORD in the given linked list that is
+ *             closest, timewise, to the given count number.
+ */
+
+static struct CHORD *
+closestchord(count, firstch_p)
+
+double count;                  /* which count of the measure */
+struct CHORD *firstch_p;       /* first CHORD in this measure */
+
+{
+       RATIONAL reqtime;       /* time requested */
+       struct CHORD *ch_p;     /* point along chord list */
+       struct CHORD *och_p;    /* (old) point along chord list */
+
+
+       /* if at or before the first count, it's closest to first group */
+       if (count <= 1)
+               return (firstch_p);
+
+       /* get requested time to nearest tiny part of a count, in lowest terms*/
+       reqtime.n = 4 * MAXBASICTIME * (count - 1) + 0.5;
+       reqtime.d = 4 * MAXBASICTIME * Score.timeden;
+       rred(&reqtime);
+
+       /*
+        * Loop through the chord list.  As soon as a chord starts at or after
+        * the requested time value, check whether the requested time is closer
+        * to the new chord's time, or the previous chord's.  Return the
+        * closest one.
+        */
+       for (och_p = firstch_p, ch_p = och_p->ch_p; ch_p != 0;
+                               och_p = ch_p, ch_p = ch_p->ch_p) {
+               if (GE(ch_p->starttime, reqtime)) {
+                       if (GT( rsub(reqtime, och_p->starttime),
+                                       rsub(ch_p->starttime, reqtime) ))
+                               return (ch_p);
+                       else
+                               return (och_p);
+               }
+       }
+
+       /* requested time is after last chord; return last chord */
+       return (och_p);
+}
+\f
+/*
+ * Name:        rightped()
+ *
+ * Abstract:    Find the size of the right side of a pedstar pedal char.
+ *
+ * Returns:     the size
+ *
+ * Description: This function finds the size of the part of the given pedal
+ *             character (pedstar style) that is to the right of where it
+ *             should be centered.
+ */
+
+static double
+rightped(pedstyle, pedchar)
+
+int pedstyle;                  /* pedstar or alt pedstar */
+int pedchar;                   /* the given char */
+
+{
+       switch (pedchar) {
+       case C_BEGPED:
+               return (strwidth(Ped_start) / 2.0);
+       case C_PEDAL:
+               if (pedstyle == P_PEDSTAR)
+                       return (strwidth(Ped_start) - ped_offset());
+               else /* P_ALTPEDSTAR */
+                       return (strwidth(Ped_start) / 2.0);
+       case C_ENDPED:
+               return (strwidth(Ped_stop) / 2.0);
+       default:
+               pfatal("bad pedal character passed to rightped()");
+       }
+       return (0);     /* to keep lint happy */
+}
+\f
+/*
+ * Name:        leftped()
+ *
+ * Abstract:    Find the size of the left side of a pedstar pedal char.
+ *
+ * Returns:     the size
+ *
+ * Description: This function finds the size of the part of the given pedal
+ *             character (pedstar style) that is to the left of where it
+ *             should be centered.
+ */
+
+static double
+leftped(pedstyle, pedchar)
+
+int pedstyle;                  /* pedstar or alt pedstar */
+int pedchar;                   /* the given char */
+
+{
+       switch (pedchar) {
+       case C_BEGPED:
+               return (strwidth(Ped_start) / 2.0);
+       case C_PEDAL:
+               if (pedstyle == P_PEDSTAR)
+                       return (strwidth(Ped_stop) + ped_offset());
+               else /* P_ALTPEDSTAR */
+                       return (strwidth(Ped_start) / 2.0);
+       case C_ENDPED:
+               return (strwidth(Ped_stop) / 2.0);
+       default:
+               pfatal("bad pedal character passed to leftped()");
+       }
+       return (0);     /* to keep lint happy */
+}
+\f
+/*
+ * Name:        fixspace()
+ *
+ * Abstract:    Reset width, if need be, for chords of all spaces.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through chord lists, looking for each chord
+ *             that is all spaces (as shown by the fact that its width is 0).
+ *             If any voice has a nonspace during the time value of this
+ *             chord, we reset its width to a very small positive number, to
+ *             prevent abshorz from treating it like it "deserves" no width
+ *             (rather than what its duration would imply).
+ */
+
+static void
+fixspace()
+
+{
+       struct CHORD *ch_p;             /* point at a chord */
+       struct MAINLL *mainll_p;        /* point at items in main linked list*/
+       struct MAINLL *m2_p;            /* another pointer down the MLL */
+       int crunch;                     /* should chord be crunched to 0 width*/
+       int v;                          /* voice number, 0 or 1 */
+
+
+       debug(16, "fixspace");
+       /*
+        * Loop down the main linked list looking for each chord list headcell.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               if (mainll_p->str != S_CHHEAD)
+                       continue;       /* skip everything but chord HC */
+
+               /*
+                * Loop through the chord list, looking for all-space chords.
+                * Skip the first one in the list; we always want that one to
+                * be crunched to zero width, since there's nothing earlier
+                * that could extend into it.
+                */
+               for (ch_p = mainll_p->u.chhead_p->ch_p->ch_p; ch_p != 0;
+                                       ch_p = ch_p->ch_p) {
+
+                       if (ch_p->width != 0)
+                               continue;       /* skip nonspace chord */
+
+                       crunch = YES;           /* init to crunch */
+
+                       /* loop through every staff and every voice in meas */
+                       for (m2_p = mainll_p->next; m2_p->str == S_STAFF;
+                                       m2_p = m2_p->next) {
+
+                               for (v = 0; v < MAXVOICES && m2_p->u.staff_p->
+                                                       groups_p[v] != 0; v++) {
+
+                                       /* if voice has nonspace, don't crunch*/
+                                       if ( ! hasspace(m2_p->u.staff_p->
+                                       groups_p[v], ch_p->starttime,
+                                       radd(ch_p->starttime, ch_p->duration))){
+                                               crunch = NO;
+                                               break;
+                                       }
+                               }
+
+                               if (crunch == NO)
+                                       break;
+                       }
+
+                       /* if should not crunch, set nonzero width to stop it */
+                       if (crunch == NO)
+                               ch_p->width = 0.001;
+
+               } /* for every chord in this measure */
+
+       } /* looping through MLL, dealing with chord headcells */
+}
diff --git a/mup/mup/roll.c b/mup/mup/roll.c
new file mode 100644 (file)
index 0000000..ad58d18
--- /dev/null
@@ -0,0 +1,661 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 2000, 2002, 2004 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions to deal with rolls. This includes both parse phase and print
+ * phase code for rolls. */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+
+/* each "roll" input statement can have multiple beat offsets to specify
+ * more than one roll. This is a linked list struct to hold these offsets */
+struct ROLLOFFSET {
+       float                   offset; /* beat offset where roll is */
+       struct ROLLOFFSET       *next;  /* linked list */
+};
+
+
+/* struct to hold all needed info about a roll input statement */
+struct ROLLINFO {
+       short   topstaff;       /* roll goes from here */
+       short   topvoice;
+       short   botstaff;       /* roll ends here */
+       short   botvoice;
+       short   rolldir;        /* UP, DOWN, or UNKNOWN. UNKNOWN really means
+                                * UP but with no arrow drawn (the default) */
+       short   error;          /* YES if got bad value for some parameter */
+       int     lineno;         /* input line number where defined */
+       char    *inputfile;     /* input file where defined */
+       struct ROLLOFFSET *offsets_p;   /* list of beat offsets */
+       struct ROLLINFO *next;  /* linked list */
+};
+
+static struct ROLLINFO *Roll_list_p;   /* rolls defined in current measure */
+               /* rolls are linked to the head of this list, so this pointer
+                * will point to the roll currently being defined */
+
+
+/* static functions declarations */
+static void do_a_roll P((struct ROLLINFO *roll_p, struct MAINLL *mll_p));
+static void roll P((struct MAINLL * mll_p, struct ROLLINFO *roll_p, 
+               struct ROLLOFFSET * offset_p));
+static void set_roll P((struct GRPSYL *gs_p, int item,
+               struct ROLLINFO *roll_p));
+static void draw_roll P((double x, double y1, double y2, int rolldir));
+
+\f
+
+/* allocate struct for info about roll, and add to list */
+
+void
+newROLLINFO()
+
+{
+       struct ROLLINFO *roll_p;        /* newly allocated roll info */
+
+
+       MALLOC(ROLLINFO, roll_p, 1);
+
+       roll_p->offsets_p = (struct ROLLOFFSET *) 0;
+       /* assume direction will be up, but with no direction arrow */
+       roll_p->rolldir = UNKNOWN;
+       /* incomplete info so far, so mark as in error */
+       roll_p->error = YES;
+
+       /* link onto head of list */
+       roll_p->next = Roll_list_p;
+       Roll_list_p = roll_p;
+
+       roll_p->lineno = yylineno;
+       roll_p->inputfile = Curr_filename;
+}
+\f
+
+/* alter the roll direction (default is UNKNOWN) */
+
+void
+setrolldir(int dir)
+
+{
+       Roll_list_p->rolldir = dir;
+}
+\f
+
+/* set roll parameters. Any parameter that is -1 should be left as is.
+ * Others should be error checked, and if okay, filled in */
+/* Must be called once to fill in the top staff and voice. At that point,
+ * the bottom staff and voice are assummed to be the same as the top.
+ * If they aren't, this function should be called again
+ * with the bottom parameters set
+ * to a non-negative number and the top parameters set to -1 */
+
+void
+rollparam(topstaff, topvoice, botstaff, botvoice)
+
+int topstaff;          /* top of roll is here */
+int topvoice;
+int botstaff;          /* bottom of roll is here */
+int botvoice;
+
+{
+       /* we now have enough info to check, so assume it's okay, then check */
+       Roll_list_p->error = NO;
+
+       /* for each value, if being set, error check and save away if okay.
+        * If no good, set error flag */
+       if (topstaff >= 0) {
+               if (rangecheck(topstaff, 1, Score.staffs, "staff number")
+                                                               == NO) {
+                       Roll_list_p->error = YES;
+               }
+               Roll_list_p->topstaff = Roll_list_p->botstaff
+                                                       = (short) topstaff;
+       }
+
+       if (topvoice >= 0) {
+               if (rangecheck(topvoice, MINVOICES, NORMVOICES, "roll voice number")
+                                                       == NO) {
+                       Roll_list_p->error = YES;
+               }
+               Roll_list_p->topvoice = Roll_list_p->botvoice
+                                                       = (short) topvoice;
+       }
+
+       if (botstaff >= 0) {
+               if (rangecheck(botstaff, 1, Score.staffs, "ending staff number")
+                                                       == NO) {
+                       Roll_list_p->error = YES;
+               }
+               Roll_list_p->botstaff = (short) botstaff;
+       }
+
+       if (botvoice >= 0) {
+               if (rangecheck(botvoice, MINVOICES, NORMVOICES,
+                                       "ending voice number") == NO) {
+                       Roll_list_p->error = YES;
+               }
+               Roll_list_p->botvoice = (short) botvoice;
+       }
+
+       if (Roll_list_p->topstaff > Roll_list_p->botstaff ||
+                       (Roll_list_p->topstaff == Roll_list_p->botstaff
+                       && Roll_list_p->topvoice > Roll_list_p->botvoice)) {
+               yyerror("end of roll must be below beginning of roll");
+               Roll_list_p->error = YES;
+       }
+}
+\f
+
+/* allocate space for offset information, fill it in, and link onto current
+ * roll information struct */
+
+void
+rolloffset(offset)
+
+double offset;         /* count offset where roll is to go */
+
+{
+       struct ROLLOFFSET *offset_p;    /* where to save offset info */
+
+
+       /* error check */
+       if (offset > Score.timenum + 1) {
+               yyerror("roll offset beyond end of measure");
+               Roll_list_p->error = YES;
+               return;
+       }
+
+       /* allocate */
+       MALLOC(ROLLOFFSET, offset_p, 1);
+
+       /* fill in */
+       offset_p->offset = offset;
+
+       /* link to list */
+       offset_p->next = Roll_list_p->offsets_p;
+       Roll_list_p->offsets_p = offset_p;
+}
+\f
+
+/* at end of bar, do each roll. For each roll, find closest group of
+ * top and bottom voice of roll. If they aren't at precisely the same
+ * fulltime into the measure, error. Otherwise, mark these groups STARTITEM and
+ * ENDITEM for roll, unless they are the same, in which case LONEITEM.
+ * Also find any intervening groups that are also at the same fulltime.
+ * Mark them INITEM. Finally, free the roll information. */
+
+void
+do_rolls(mll_p)
+
+struct MAINLL *mll_p;  /* MAINLL of BAR */
+
+{
+       debug(4, "do_rolls lineno=%d", mll_p->inputlineno);
+
+       do_a_roll(Roll_list_p, mll_p);
+       Roll_list_p = (struct ROLLINFO *) 0;
+}
+\f
+
+/* recursively go down list of rolls, and mark the relevant GRPSYLs */
+
+static void
+do_a_roll(roll_p, mll_p)
+
+struct ROLLINFO *roll_p;       /* current roll */
+struct MAINLL *mll_p;          /* look from here to find appropriate staff */
+
+{
+       if (roll_p == (struct ROLLINFO *) 0) {
+               /* end recursion */
+               return;
+       }
+
+       /* recurse */
+       do_a_roll(roll_p->next, mll_p);
+
+       /* if error in early checking, ignore this one */
+       if (roll_p->error == NO) {
+       
+               /* find the relevant STAFF */
+               for (   ; mll_p != (struct MAINLL *) 0; mll_p = mll_p->prev) {
+                       if (mll_p->str == S_STAFF) {
+                               if (mll_p->u.staff_p->staffno ==
+                                                       roll_p->topstaff) {
+                                       break;
+                               }
+                       }
+               }
+
+               if (mll_p == (struct MAINLL *) 0) {
+                       pfatal("couldn't find staff information for roll");
+               }
+
+               /* mark the GRPSYLs */
+               roll(mll_p, roll_p, roll_p->offsets_p);
+       }
+
+       /* this one has been handled */
+       FREE(roll_p);
+}
+\f
+
+/* for a specific roll on a specific chord, fill in the roll parameters for
+ * all affected, visible groups */
+
+static void
+roll(mll_p, roll_p, offset_p)
+
+struct MAINLL *mll_p;          /* STAFF of top of roll */
+struct ROLLINFO *roll_p;       /* info about the roll */
+struct ROLLOFFSET *offset_p;   /* count offset at which to place roll */
+
+{
+       RATIONAL timeoffset;    /* time into measure of group getting rolled */
+       RATIONAL time1offset;   /* timeoffset of group in top voice of roll */
+       struct GRPSYL *gs_p;
+       struct GRPSYL *roll_grp_p;      /* group having roll */
+       struct GRPSYL *lastvisgrp_p;    /* most recent grp with roll that is
+                                        * on a visible staff */
+       int rollstate;                  /* STARTITEM, etc */
+       int staffno;
+       int voice;
+       double top_staffscale;  /* staffscale of staff at top of roll */
+
+
+       /* recurse */
+       if (offset_p == (struct ROLLOFFSET *) 0) {
+               return;
+       }
+       roll(mll_p, roll_p, offset_p->next);
+
+
+       /* find relevant group */
+       gs_p = mll_p->u.staff_p->groups_p [ roll_p->topvoice - 1 ];
+       roll_grp_p = closestgroup(offset_p->offset, gs_p, Score.timeden);
+
+       if (roll_grp_p->roll != NOITEM) {
+               l_yyerror(roll_p->inputfile, roll_p->lineno,
+                                       "overlapping rolls not allowed");
+               FREE(offset_p);
+               return;
+       }
+
+       /* a lot of the time, the top and bottom staff/voice of roll will
+        * be the same, meaning we have a LONEITEM. This is the easy case
+        * so handle that. */
+       if (roll_p->topstaff == roll_p->botstaff
+                               && roll_p->topvoice == roll_p->botvoice) {
+               if (svpath(roll_p->topstaff, VISIBLE)->visible == YES) {
+                       set_roll(roll_grp_p, LONEITEM, roll_p);
+               }
+               FREE(offset_p);
+               return;
+       }
+
+       /* we must have a roll that encompasses more than one voice */
+       lastvisgrp_p = (struct GRPSYL *) 0;
+
+       /* find group's actual RATIONAL time offset into the measure */
+       for (time1offset = Zero; gs_p != roll_grp_p; gs_p = gs_p->next) {
+               time1offset = radd(time1offset, gs_p->fulltime);
+       }
+
+       /* if the top voice is visible, mark it as the top of the roll.
+        * If not, make a note that we don't have a real top yet */
+       if (svpath(roll_p->topstaff, VISIBLE)->visible == YES) {
+               if (is_tab_staff(roll_grp_p->staffno) == YES) {
+                       l_yyerror(roll_p->inputfile, roll_p->lineno,
+                               "roll spanning multiple voices cannot include tab staff");
+                       return;
+               }
+               set_roll(roll_grp_p, STARTITEM, roll_p);
+               rollstate = INITEM;
+               lastvisgrp_p = roll_grp_p;
+       }
+       else {
+               rollstate = STARTITEM;
+       }
+
+       staffno = roll_p->topstaff;
+       voice = roll_p->topvoice;
+       top_staffscale = svpath(staffno, STAFFSCALE)->staffscale;
+
+       /* find all groups down to ending of roll */
+       for ( ; ; ) {
+
+               /* move to next voice, which may be on next staff */
+               if (++voice > MAXVOICES) {
+                       ++staffno;
+                       voice = 1;
+                       mll_p = mll_p->next;
+                       if (mll_p->str != S_STAFF ||
+                                       mll_p->u.staff_p->staffno != staffno) {
+                               pfatal("main list messed up while doing rolls");
+                       }
+               }
+
+               /* if no more voices on staff, no reason to check more */
+               if (voice > vscheme_voices(svpath(staffno, VSCHEME)->vscheme))  {
+                       continue;
+               }
+
+               /* find relevant group */
+               gs_p = mll_p->u.staff_p->groups_p[ voice - 1];
+               roll_grp_p = closestgroup(offset_p->offset, gs_p, Score.timeden);
+
+               if (is_tab_staff(roll_grp_p->staffno) == YES) {
+                       l_yyerror(roll_p->inputfile, roll_p->lineno,
+                               "roll spanning multiple voices cannot include tab staff");
+                       return;
+               }
+
+               if (svpath(roll_grp_p->staffno, STAFFSCALE)->staffscale !=
+                                                       top_staffscale) {
+                       l_yyerror(roll_p->inputfile, roll_p->lineno,
+                               "roll cannot span staffs with differing staffscale values");
+                       return;
+               }
+
+               if (roll_grp_p == (struct GRPSYL *) 0) {
+                       l_yyerror(roll_p->inputfile, roll_p->lineno,
+                                       "no chord associated with roll");
+                       return;
+               }
+
+               /* find group's actual RATIONAL time offset into the measure */
+               for (timeoffset = Zero; gs_p != roll_grp_p; gs_p = gs_p->next) {
+                       timeoffset = radd(timeoffset, gs_p->fulltime);
+               }
+
+               /* if this group's RATIONAL time isn't the same as
+                * the top group's, it doesn't get included in the roll */
+               if (EQ(timeoffset, time1offset)) {
+                       /* need roll on this group */
+                       if (roll_grp_p->grpcont == GC_NOTES) {
+                               set_roll(roll_grp_p, rollstate, roll_p);
+                               rollstate = INITEM;
+                               if (svpath(staffno, VISIBLE)->visible == YES) {
+                                       lastvisgrp_p = roll_grp_p;
+                               }
+                       }
+               }
+
+               /* check if at bottom of roll */
+               if (staffno == roll_p->botstaff && voice == roll_p->botvoice) {
+                       if (NE(timeoffset, time1offset)) {
+                               l_yyerror(roll_p->inputfile, roll_p->lineno,
+                                       "groups on top and bottom of roll are in different chords");
+                       }
+                       else if (svpath(staffno, VISIBLE)->visible == NO) {
+                               /* bottom staff of roll is invisible */
+                               if (lastvisgrp_p == (struct GRPSYL *) 0) {
+                                       /* no visible staffs in roll */
+                                       break;
+                               }
+
+                               /* change last visible staff included in the
+                                * roll, to be the end of the roll, or
+                                * set to LONEITEM if only visible */
+                               if (lastvisgrp_p->roll == STARTITEM) {
+                                       lastvisgrp_p->roll = LONEITEM;
+                               }
+                               else {
+                                       lastvisgrp_p->roll = ENDITEM;
+                               }
+                       }
+
+                       else if (lastvisgrp_p->roll == STARTITEM) {
+                               /* all but the last were invisible */
+                               roll_grp_p->roll = LONEITEM;
+                       }
+                       else {
+                               roll_grp_p->roll = ENDITEM;
+                       }
+                       break;
+               }
+       }
+
+       /* this one has been handled */
+       FREE(offset_p);
+}
+\f
+
+/* do final checking and actually fill in roll parameters in grpsyl */
+
+static void
+set_roll(gs_p, item, roll_p)
+
+struct GRPSYL *gs_p;           /* which GRPSYL to mark */
+int item;                      /* LONEITEM, STARTITEM, etc */
+struct ROLLINFO *roll_p;       /* info about roll associated with group */
+
+{
+       if (gs_p->grpcont != GC_NOTES) {
+               switch (item) {
+               case STARTITEM:
+                       l_yyerror(roll_p->inputfile, roll_p->lineno,
+                               "top visible chord of roll must not be rest or space");
+                       return;
+               case ENDITEM:
+                       l_yyerror(roll_p->inputfile, roll_p->lineno,
+                               "bottom visible chord of roll must not be rest or space");
+                       return;
+               case LONEITEM:
+                       l_yyerror(roll_p->inputfile, roll_p->lineno,
+                               "rolled chord must not be rest or space");
+                       return;
+               }
+       }
+
+       /* fill in values */
+       gs_p->roll = (short) item;
+       gs_p->rolldir = roll_p->rolldir;
+}
+\f
+
+/* print a roll */
+
+void
+print_roll(gs_p)
+
+struct GRPSYL *gs_p;   /* GRPSYL that might have a roll on it */
+
+{
+       struct GRPSYL *botgs_p;         /* bottom group of roll */
+       struct GRPSYL *prevgs_p;        /* chord above current chord */
+       float north;
+       float south;
+       float westmost;                 /* if voices overlap, the west of
+                                        * different groups in the chord may
+                                        * be different, so have to find
+                                        * whichever is farther west */
+
+       switch (gs_p->roll) {
+
+       case  LONEITEM:
+               draw_roll(gs_p->c[AW] + ROLLPADDING * Staffscale / 2.0,
+                               gs_p->notelist[0].c[AN],
+                               gs_p->notelist[ gs_p->nnotes - 1].c[AS],
+                               gs_p->rolldir);
+               return;
+
+       case STARTITEM:
+               /* normally, the north of the roll is the north of the top
+                * group. However, there is one special case. If the roll
+                * starts on voice 1 and goes through voice 2 on that staff,
+                * and the top note on voice 2 is higher than the top note
+                * on voice 1, need to start roll at the top note of voice 2 */
+               north = gs_p->notelist[0].c[AN];
+               if (gs_p->vno == 1 && gs_p->gs_p != (struct GRPSYL *) 0 &&
+                                       gs_p->gs_p->staffno == gs_p->staffno &&
+                                       gs_p->gs_p->grpsyl == GS_GROUP &&
+                                       gs_p->gs_p->grpcont == GC_NOTES) {
+                       if (gs_p->gs_p->notelist[0].c[AN] >
+                                               gs_p->notelist[0].c[AN]) {
+                               north = gs_p->gs_p->notelist[0].c[AN];
+                       }
+               }
+               
+               westmost = gs_p->c[AW];
+
+               /* find the bottom group of the roll */
+               prevgs_p = gs_p;
+               for (botgs_p = gs_p->gs_p; botgs_p != (struct GRPSYL *) 0;
+                                               botgs_p = botgs_p->gs_p) {
+
+                       if (botgs_p->grpsyl != GS_SYLLABLE &&
+                                               botgs_p->c[AW] < westmost) {
+                               westmost = botgs_p->c[AW];
+                       }
+
+                       if (botgs_p->roll == ENDITEM) {
+
+                               /* normally, the end of the roll is the bottom
+                                * note of the ending group. However, there is
+                                * one special case. If the roll ends on voice
+                                * 2, and the bottom note of voice 1 is lower
+                                * than the bottom note of voice 1, the south
+                                * of the roll is the bottom of voice 1 */
+                               south = botgs_p->notelist
+                                               [ botgs_p->nnotes - 1].c[AS];
+
+                               if (botgs_p->vno == 2 && prevgs_p->staffno
+                                               == botgs_p->staffno &&
+                                               prevgs_p->grpsyl == GS_GROUP) {
+
+                                       if (prevgs_p->nnotes > 0 &&
+                                                       prevgs_p->notelist[prevgs_p->nnotes-1].c[AS]
+                                                       < botgs_p->notelist
+                                                       [botgs_p->nnotes - 1]
+                                                       .c[AS]) {
+
+                                               south = prevgs_p->notelist
+                                                       [prevgs_p->nnotes - 1]
+                                                       .c[AS];
+                                       }
+                               }
+
+                               draw_roll(westmost +
+                                       ROLLPADDING * Staffscale / 2.0,
+                                       north, south, gs_p->rolldir);
+                               return;
+                       }
+                       prevgs_p = botgs_p;
+               }
+               pfatal("failed to find end of multi-voice roll");
+               break;
+
+       default:
+               /* nothing to do */
+               break;
+       }
+}
+\f
+
+/* Actually draw a roll at the given x from y1 to y2. If rolldir is DOWN,
+ * draw an arrow at the bottom; if it is UP draw an arrow at the top;
+ * if UNKNOWN don't draw any arrow. */
+
+static void
+draw_roll(x, y1, y2, rolldir)
+
+double x;              /* horizontal location of roll */
+double y1;             /* vertical location */
+double y2;
+int rolldir;           /* UP, DOWN, or UNKNOWN (i.e., UP but no arrow) */
+
+{
+       /* draw the roll itself */
+       draw_wavy(x, y1, x, y2);
+
+       /* If arrow was requested, draw it */
+       if (rolldir != UNKNOWN) {
+               float len;
+
+               /* draw arrow at bottom */
+               len = ROLLPADDING * Staffscale / 2.0 - Stdpad;
+               do_linetype(L_NORMAL);
+               if (rolldir == DOWN) {
+                       draw_line(x, y2 - Stepsize, x - (0.8 * len), y2 + len);
+                       draw_line(x, y2 - Stepsize, x + (0.8 * len), y2 + len);
+               }
+               else {
+                       draw_line(x, y1 + Stepsize, x - (0.8 * len), y1 - len);
+                       draw_line(x, y1 + Stepsize, x + (0.8 * len), y1 - len);
+               }
+       }
+}
+\f
+
+/* return YES if given group is the top group that gets a roll drawn by it,
+ * NO if not. This is called from the print phase */
+
+int
+gets_roll(gs_p, staff_p, v)
+
+struct GRPSYL *gs_p;           /* check if this group gets a roll */
+struct STAFF *staff_p; /* it's connected to this staff */
+int v;                 /* and is in this voice */
+
+{
+       float width1, width2;           /* widest note heads in each group */
+       float maxwide;                  /* widest notehead */
+       struct GRPSYL *othergs_p;       /* group in other voice */
+
+
+       if (gs_p->roll != STARTITEM && gs_p->roll != LONEITEM) {
+               return(NO);
+       }
+
+       /* check for strange case where we don't print a roll because groups
+        * are incompatible (had to be moved horizontally because they
+        * overlapped), and both have rolls. If the group's RX is greater
+        * than (maxwide - W_NORMAL * POINT) / 2 where
+        * maxwide is the maximum of width of the note head characters
+        * the two groups, then don't print the roll. */
+       if (svpath(staff_p->staffno, VSCHEME)->vscheme == V_1) {
+               /* strange case only happens with 2 voices */
+               return(YES);
+       }
+       else {
+               /* find width of widest note of this group */
+               width1 = widest_head(gs_p) * Staffscale;
+
+               /* find other group. If this is first voice,
+                * just look down the chord link */
+               if (v == 0) {
+                       othergs_p = gs_p->gs_p;
+               }
+               else {
+                       /* follow groups until we find the one linked to this
+                        * one */
+                       for (othergs_p = staff_p->groups_p[0];
+                                       othergs_p != (struct GRPSYL *) 0;
+                                       othergs_p = othergs_p->next) {
+                               if (othergs_p->gs_p == gs_p) {
+                                       break;
+                               }
+                       }
+               }
+
+               if (othergs_p != (struct GRPSYL *) 0 &&
+                               othergs_p->grpcont == GC_NOTES) {
+
+                       /* find width of widest note of the other group */
+                       width2 = widest_head(othergs_p) * Staffscale;
+
+                       maxwide = MAX(width1, width2);
+
+                       if (gs_p->c[RX] > ((maxwide - W_NORMAL * POINT) / 2.0)){
+                               /* we hit the strange case */
+                               return(NO);
+                       }
+               }
+       }
+       return(YES);
+}
diff --git a/mup/mup/setgrps.c b/mup/mup/setgrps.c
new file mode 100644 (file)
index 0000000..3f520bf
--- /dev/null
@@ -0,0 +1,2920 @@
+/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2004, 2005, 2006
+ * by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ * Name:       setgrps.c
+ *
+ * Description:        This file contains functions for setting the relative
+ *             horizontal coordinates of all groups that contain notes
+ *             (grpcont == GC_NOTES) and of all objects in these groups.
+ *             It also sets relative vertical coordinates for the dots
+ *             after notes.
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+struct NOTEPTRS {
+       struct NOTE *top_p;     /* point at a note in top group */
+       struct NOTE *bot_p;     /* point at same note in bottom group*/
+       float wid;              /* width of the note head */
+};
+
+static struct GRPSYL *procallvoices P((struct MAINLL *mll_p,
+               struct GRPSYL *gs_p));
+static void proc1or2voices P((struct MAINLL *mll_p, struct STAFF *staff_p,
+               struct GRPSYL *gs1_p, struct GRPSYL *gs2_p));
+static int compat P((struct NOTEPTRS noteptrs[], struct GRPSYL *gs1_p,
+               struct GRPSYL *gs2_p));
+static int can_overlap P((struct GRPSYL *gs1_p, struct GRPSYL *gs2_p));
+static void procsome P((struct NOTEPTRS noteptrs[], struct MAINLL *mll_p,
+               struct STAFF *staff_p, struct GRPSYL *gs1_p,
+               struct GRPSYL *gs2_p));
+static void procgrace P((struct NOTEPTRS noteptrs[], struct MAINLL *mll_p,
+               struct STAFF *staff_p, struct GRPSYL *gsnorm_p));
+static void procbunch P((struct NOTEPTRS noteptrs[], struct MAINLL *mll_p,
+               struct STAFF *staff_p, struct GRPSYL *gs1_p,
+               struct GRPSYL *gs2_p));
+static void doacc P((struct NOTEPTRS noteptrs[], double halfwide,
+               double halfhigh, int collinear));
+static int nextacc P((struct NOTEPTRS noteptrs[], int found));
+static void dodot P((struct STAFF *staff_p, struct GRPSYL *gs1_p,
+               struct GRPSYL *gs2_p, double halfwide, int collinear));
+static void dogrpdot P((struct STAFF *staff_p, struct GRPSYL *gs_p,
+               struct GRPSYL *ogs_p, double halfwide, int uppermost,
+               int lowermost, int push));
+static void westwith P((struct GRPSYL *gs_p));
+static void eastwith P((struct GRPSYL *gs_p));
+static void csbstempad P((struct MAINLL *mll_p, struct GRPSYL *gs_p));
+static void proctab P((struct MAINLL *mll_p, struct STAFF *staff_p,
+               struct GRPSYL *gs1_p));
+static void noterparen P((struct NOTEPTRS noteptrs[], struct GRPSYL *gs1_p,
+               struct GRPSYL *gs2_p, double halfwide, double halfhigh,
+               int collinear));
+\f
+/*
+ * Name:        setgrps()
+ *
+ * Abstract:   Find first group on each staff & call procallvoices to process.
+ *
+ * Returns:     void
+ *
+ * Description: This function goes through the chord lists, and for each chord,
+ *             the list of GRPSYLs hanging off it.  It finds the first group
+ *             on each staff, and calls procallvoices() to set the relative
+ *             horizontal coordinates of all the note groups on that staff.
+ */
+
+void
+setgrps()
+
+{
+       struct CHORD *ch_p;             /* point at a chord */
+       struct GRPSYL *gs1_p;           /* point at a group */
+       struct MAINLL *mainll_p;        /* point at items in main linked list*/
+       struct MAINLL *mstaff_p;        /* for looking for staff */
+
+
+       debug(16, "setgrps");
+       initstructs();          /* clean out old SSV info */
+
+       /*
+        * Loop down the main linked list looking for each chord list
+        * headcell.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               /* keep SSVs up to date */
+               if (mainll_p->str == S_SSV)
+                       asgnssv(mainll_p->u.ssv_p);
+
+               if (mainll_p->str != S_CHHEAD)
+                       continue;       /* skip everything but chord HC */
+
+               /*
+                * Loop through each chord in this list.
+                */
+               for (ch_p = mainll_p->u.chhead_p->ch_p; ch_p != 0;
+                                       ch_p = ch_p->ch_p) {
+                       /*
+                        * Loop through the linked list of GRPSYLs hanging off
+                        * this chord.  Skip the syllables; just deal with the
+                        * groups.  Upon finding the first group on a staff
+                        * (which could be for any of the voices, since not all
+                        * might be present in this chord), call procallvoices
+                        * to process all the note groups.
+                        */
+                       gs1_p = ch_p->gs_p;
+                       for (;;) {
+                               /* find first group on a staff */
+                               while (gs1_p != 0 &&
+                                               gs1_p->grpsyl == GS_SYLLABLE)
+                                       gs1_p = gs1_p->gs_p;
+                               if (gs1_p == 0)
+                                       break;
+
+                               /* find the staff's MLL structure */
+                               mstaff_p = chmgrp2staffm(mainll_p, gs1_p);
+
+                               /* set gs1_p to after this staff's groups */
+                               gs1_p = procallvoices(mstaff_p, gs1_p);
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        procallvoices()
+ *
+ * Abstract:    Process the groups for all the voices on one staff in a chord.
+ *
+ * Returns:     pointer to the first GRPSYL after these groups, 0 if none
+ *
+ * Description: This function is given the GRPSYL for the first (topmost) voice
+ *             that is on this staff in this chord.  It finds what other
+ *             GRPSYLs exist.  For each of them that is for notes (not rests
+ *             or spaces), it calls proc1or2voices() to process them together
+ *             and/or separately, as needed.  This file generally deals only
+ *             with notes, not rests or spaces.  But this function also deals
+ *             with rests to the following extent:  For both notes and rests,
+ *             there are situations where voice 3 should "stand in" for voice 1
+ *             or voice 2.  This function makes those decisions, and sets pvno.
+ */
+
+static struct GRPSYL *
+procallvoices(mll_p, gs_p)
+
+struct MAINLL *mll_p;          /* the MLL item the group is connected to */
+struct GRPSYL *gs_p;           /* point at first voice on this staff */
+
+{
+       struct STAFF *staff_p;          /* point at staff */
+       struct GRPSYL *g_p[MAXVOICES];  /* point at note groups */
+       struct GRPSYL *last_p;          /* point at last note group */
+       struct GRPSYL *g2_p[MAXVOICES]; /* point at note and rest groups */
+       struct GRPSYL *gs1_p;           /* remember first group */
+       struct GRPSYL *gs2_p;           /* another GRPSYL pointer */
+       int numnonspace;                /* number of nonspace GRPSYLs */
+       int numgrps;                    /* how many note groups are here */
+       int n;                          /* loop variable, voices processed */
+
+
+       staff_p = mll_p->u.staff_p;
+       numgrps = 0;                    /* no groups found yet */
+       last_p = 0;                     /* no note groups yet */
+       gs1_p = gs_p;                   /* remember first group */
+
+       /* find all groups in this chord on this staff; remember note groups */
+       while (gs_p != 0 && gs_p->staffno == staff_p->staffno &&
+                           gs_p->grpsyl == GS_GROUP) {
+               gs_p->pvno = gs_p->vno; /* init pseudo voice no. to voice no.*/
+               if (gs_p->grpcont == GC_NOTES) {
+                       g_p[numgrps++] = gs_p;
+                       last_p = gs_p;
+               }
+               gs_p = gs_p->gs_p;
+       }
+
+       /*
+        * Before continuing on to process note groups, change voice 3's pvno
+        * when appropriate.  First find all nonspace groups.
+        */
+       numnonspace = 0;                /* no nonspace groups found yet */
+       gs2_p = gs1_p;
+
+       /* find all nonspace groups in this chord on this staff */
+       while (gs2_p != 0 && gs2_p->staffno == staff_p->staffno &&
+                           gs2_p->grpsyl == GS_GROUP) {
+               if (gs2_p->grpcont != GC_SPACE) {
+                       g2_p[numnonspace++] = gs2_p;
+               } else {
+                       /*
+                        * This is a convenient, though somewhat inappropriate,
+                        * place to process grace groups that precede a space
+                        * group.  Ones that precede notes groups will be
+                        * processed in the normal flow, called from procsome.
+                        * They are not allowed before rest groups.
+                        */
+                       struct NOTEPTRS noteptrs[MAXHAND + 1];
+                       procgrace(noteptrs, mll_p, staff_p, gs2_p);
+               }
+               gs2_p = gs2_p->gs_p;
+       }
+
+       /*
+        * If the only nonspace voices are 1 and 3, or 2 and 3, and at least
+        * one of them is a rest and this is not a tab staff and "ho" was not
+        * used for either . . .
+        */
+       if (numnonspace == 2 && g2_p[1]->vno == 3 &&
+          (g2_p[0]->grpcont == GC_REST || g2_p[1]->grpcont == GC_REST) &&
+          ! is_tab_staff(staff_p->staffno) && g2_p[0]->ho_usage == HO_NONE &&
+          g2_p[1]->ho_usage == HO_NONE) {
+               /*
+                * If v1 is either a rest or stem-up notes and v3 is a rest or
+                * stem-down notes, let v3 stand in for v2.
+                */
+               if (g2_p[0]->vno == 1 && (g2_p[0]->grpcont == GC_NOTES &&
+                   g2_p[0]->stemdir == UP || g2_p[0]->grpcont == GC_REST) &&
+                   (g2_p[1]->grpcont == GC_NOTES && g2_p[1]->stemdir == DOWN ||
+                   g2_p[1]->grpcont == GC_REST)) {
+                       g2_p[1]->pvno = 2;
+               }
+               /*
+                * If v2 is either a rest or stem-down notes and v3 is a rest or
+                * stem-up notes, let v3 stand in for v1.
+                */
+               if (g2_p[0]->vno == 2 && (g2_p[0]->grpcont == GC_NOTES &&
+                   g2_p[0]->stemdir == DOWN || g2_p[0]->grpcont == GC_REST) &&
+                   (g2_p[1]->grpcont == GC_NOTES && g2_p[1]->stemdir == UP ||
+                   g2_p[1]->grpcont == GC_REST)) {
+                       g2_p[1]->pvno = 1;
+               }
+       }
+
+       /* if there were no note groups on this staff, nothing more to do */
+       if (numgrps == 0)
+               return (gs_p);
+
+       n = 0;          /* number of voices processed so far */
+
+       /*
+        * If voices 1 and 2 exist and are notes and do not have user specified
+        * horizontal offsets and this is not a tab staff, handle them together.
+        * If both voices 1 and 2 have a group here, they will be the first two
+        * found.  Tab staffs should be handled separately because their voices
+        * never conflict with each other (because of chktabcollision() in
+        * in setnotes.c).  Before checking the offsets, verify that they are
+        * legal and fix if not.
+        */
+       if (numgrps >= 2 && g_p[0]->vno == 1 && g_p[1]->vno == 2 &&
+                       ! is_tab_staff(staff_p->staffno)) {
+
+               vfyoffset(g_p);         /* verify and fix */
+
+               if (g_p[0]->ho_usage == HO_NONE && g_p[1]->ho_usage == HO_NONE){
+                       proc1or2voices(mll_p, staff_p, g_p[0], g_p[1]);
+                       n = 2;          /* processed 2 voices */
+               }
+       }
+
+       /*
+        * Else, if v1 and v3, or v2 and v3, are notes, and only those two
+        * exist, and they do not have user specified horizontal offsets and
+        * this is not a tab staff, and v3's stem dir is compatible, let v3
+        * "stand in" for v1 or v2, as the case may be.  Handle the two voices
+        * together.
+        */
+       else if (numgrps == 2 && numnonspace == 2 &&
+                       ! is_tab_staff(staff_p->staffno) && g_p[0]->ho_usage ==
+                       HO_NONE && g_p[1]->ho_usage == HO_NONE) {
+
+               if (g_p[0]->vno == 1 && g_p[0]->stemdir == UP &&
+                   g_p[1]->vno == 3 && g_p[1]->stemdir == DOWN) {
+
+                       g_p[1]->pvno = 2;
+                       proc1or2voices(mll_p, staff_p, g_p[0], g_p[1]);
+                       n = 2;          /* processed 2 voices */
+
+               } else if (g_p[0]->vno == 2 && g_p[0]->stemdir == DOWN &&
+                          g_p[1]->vno == 3 && g_p[1]->stemdir == UP) {
+
+                       g_p[1]->pvno = 1;
+                       proc1or2voices(mll_p, staff_p, g_p[1], g_p[0]);
+                       n = 2;          /* processed 2 voices */
+               }
+       }
+
+       /* process any remaining voices individually */
+       for ( ; n < numgrps; n++) {
+               proc1or2voices(mll_p, staff_p, g_p[n], (struct GRPSYL *)0);
+       }
+
+       /* return the first GRPSYL after the groups we processed */
+       return (gs_p);
+}
+\f
+/*
+ * Name:        proc1or2voices()
+ *
+ * Abstract:    Process a single voice, or voices 1 and 2 together.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given pointers to one or two groups on a
+ *             staff.  If it's just one (the second one is a null pointer),
+ *             that group is to be handled alone.  If it is two, they are
+ *             voices 1 and 2, since voice 3 is always handled separately.
+ *             (Except that voice 3 can sometimes "stand in" for v1 or v2.)
+ *             In any case, these are always note groups, not rest or space.
+ *
+ *             The function sets up an array (noteptrs) to point at each
+ *             note in the group(s), figuring out whether the groups overlap
+ *             and, if so, if they are compatible (see below for definition).
+ *             It calls procsome() to set relative horizontal coordinates for
+ *             some notes, which is done either separately for each group or
+ *             both at once, depending on the situation.
+ */
+
+static void
+proc1or2voices(mll_p, staff_p, gs1_p, gs2_p)
+
+struct MAINLL *mll_p;          /* the MLL item the group is connected to */
+struct STAFF *staff_p;                 /* the staff the groups are on */
+register struct GRPSYL *gs1_p, *gs2_p; /* point at groups in this hand */
+
+{
+       /*
+        * Each structure in this array points at a note.  Notes from gs1_p
+        * are pointed at by top_p, and, when both groups exist, notes
+        * from gs2_p are pointed at by bot_p.  If there's no overlap
+        * between the groups, there won't be any here either.  But if
+        * the groups "share" notes, the shared notes will be pointed
+        * at by both.  If the groups are "incompatible" (must be
+        * drawn shifted horizontally to avoid interference), they will
+        * be done separately and use this array separately, one at a time.
+        * And in that case, notes from both gs1_p and gs2_p will use top_p,
+        * in turn.
+        */
+       struct NOTEPTRS noteptrs[MAXHAND + 1];
+
+       float offset;           /* how far to offset incompatible groups */
+       int num1;               /* number of notes in top group */
+       int n;                  /* loop variable */
+       int incompat;           /* are groups incompatible (special case) */
+
+
+       /*
+        * For mrpt, we have nothing to do except set the horizontal group
+        * coordinates.  If the first group is a measure repeat, so is the
+        * second one, if it exists at all.  We set a very small width, as a
+        * placeholder, because if other staffs have normal notes, we don't
+        * want the first chord to be abnormally wide because of the mrpt
+        * symbol.  (It will be centered in the measure.)  If all the staffs
+        * have mrpt, abshorz.c will ensure that enough space is left for
+        * these symbols.
+        */
+       if (is_mrpt(gs1_p)) {
+               gs1_p->c[RX] = 0;
+               gs1_p->c[RE] = TEMPMRPTWIDTH / 2.0;
+               gs1_p->c[RW] = -TEMPMRPTWIDTH / 2.0;
+
+               if (gs2_p != 0) {
+                       gs2_p->c[RX] = 0;
+                       gs2_p->c[RE] = TEMPMRPTWIDTH / 2.0;
+                       gs2_p->c[RW] = -TEMPMRPTWIDTH / 2.0;
+               }
+               return;
+       }
+
+       /* clear out the array */
+       for (n = 0; n < NUMELEM(noteptrs); n++) {
+               noteptrs[n].top_p = 0;
+               noteptrs[n].bot_p = 0;
+               noteptrs[n].wid = 0.0;
+       }
+
+       num1 = gs1_p->nnotes;
+
+       /* set all the "top" group pointers */
+       for (n = 0; n < num1; n++)
+               noteptrs[n].top_p = &gs1_p->notelist[n];
+
+       /* if there is no "bottom" group, process the first bunch and quit */
+       if (gs2_p == 0) {
+               procsome(noteptrs, mll_p, staff_p, gs1_p, (struct GRPSYL *)0);
+
+               /* if group is rolled, allow room for the roll */
+               if (gs1_p->roll != NOITEM)
+                       gs1_p->c[RW] -= ROLLPADDING;
+               return;
+       }
+
+       /*
+        * If the lowest note of the top group is higher than the highest
+        * note of the bottom group, point at all the bottom notes,
+        * process both, and quit.  Exception:  if the inner notes of the
+        * two groups are on neighboring steps, and the top note of the
+        * bottom group is on a line and has a dot, and the top group has
+        * no dots, the groups are to be regarded as if overlapping and
+        * incompatible.  This is because there is no decent way to place
+        * the dots in this case otherwise.  But if, in this neighboring note
+        * situation, there are no problems with dots, the groups can still be
+        * handled together here; their stems will be made collinear.  When
+        * the notes are two or more steps apart, there's no problem at all,
+        * and the groups' X coordinates will line up and equal the chord's.
+        * Another exception ("else if") is that when the stem of either group
+        * has been forced the "wrong way" by the user, we require more
+        * vertical space between the groups.  Since we don't know the stem
+        * lengths yet, we can't do the full job, though.  The user may have to
+        * use "len" or "ho" to avoid a collision.
+        */
+       incompat = NO;
+       if (noteptrs[num1-1].top_p->stepsup > gs2_p->notelist[0].stepsup) {
+               if (noteptrs[num1-1].top_p->stepsup ==
+                               gs2_p->notelist[0].stepsup + 1 &&
+                               gs2_p->notelist[0].stepsup % 2 == 0 &&
+                               gs2_p->dots == 0 &&
+                               gs1_p->dots > 0) {
+                       incompat = YES;
+               } else if ((gs1_p->stemdir == DOWN || gs2_p->stemdir == UP) &&
+                               noteptrs[num1-1].top_p->stepsup <
+                               gs2_p->notelist[0].stepsup + 3) {
+                       incompat = YES;
+               } else {
+                       for (n = 0; n < gs2_p->nnotes; n++)
+                               noteptrs[num1+n].bot_p = &gs2_p->notelist[n];
+                       procsome(noteptrs, mll_p, staff_p, gs1_p, gs2_p);
+
+                       /* if a group is rolled, allow room for the roll */
+                       if (gs1_p->roll != NOITEM)
+                               gs1_p->c[RW] -= ROLLPADDING;
+                       if (gs2_p->roll != NOITEM)
+                               gs2_p->c[RW] -= ROLLPADDING;
+                       return;
+               }
+       }
+
+       /*
+        * There is overlap between the two groups.  See if they are
+        * compatible (also fills in group 2 in noteptrs).  If so,
+        * process the groups together, and return.
+        */
+       if (incompat == NO && compat(noteptrs, gs1_p, gs2_p) == YES) {
+               procsome(noteptrs, mll_p, staff_p, gs1_p, gs2_p);
+
+               /* if a group is rolled, allow room for the roll */
+               if (gs1_p->roll != NOITEM)
+                       gs1_p->c[RW] -= ROLLPADDING;
+               if (gs2_p->roll != NOITEM)
+                       gs2_p->c[RW] -= ROLLPADDING;
+               return;
+       }
+
+       /*
+        * The fact that we are here means the two groups are not compatible,
+        * meaning they overlap but can't share note heads.  Clear the array
+        * of any notes from the second group, in case compat() put some there.
+        */
+       for (n = 0; n < NUMELEM(noteptrs); n++)
+               noteptrs[n].bot_p = 0;
+
+       /*
+        * It is possible that the groups can at least be given collinear
+        * stems.  For this to be allowed, it must be that the bottom note of
+        * the top group is on the same step as the top note of the bottom
+        * group.  The top group's note can't have dots, the bottom group's
+        * can't have accidentals or a roll, and neither can have parentheses,
+        * because they couldn't be drawn decently.  Neither note can have
+        * another note on a neighboring step.
+        */
+       if (noteptrs[num1-1].top_p->stepsup == gs2_p->notelist[0].stepsup &&
+
+                       gs1_p->dots == 0 &&
+
+                       gs2_p->notelist[0].accidental == '\0' &&
+
+                       gs2_p->roll == NOITEM &&
+
+                       noteptrs[num1-1].top_p->note_has_paren == NO &&
+                       gs2_p->notelist[0].note_has_paren == NO &&
+
+                       (num1 == 1 || noteptrs[num1-2].top_p->stepsup
+                               > noteptrs[num1-1].top_p->stepsup + 1) &&
+
+                       (gs2_p->nnotes == 1 || gs2_p->notelist[0].stepsup
+                               > gs2_p->notelist[1].stepsup + 1) ) {
+               /*
+                * Since we are not sharing noteheads, the notes of the bottom
+                * group must be put after the notes of the top group in the
+                * noteptrs table.  Then process them together.
+                */
+               for (n = 0; n < gs2_p->nnotes; n++)
+                       noteptrs[num1+n].bot_p = &gs2_p->notelist[n];
+               procsome(noteptrs, mll_p, staff_p, gs1_p, gs2_p);
+
+               /* if top group is rolled, allow room for the roll */
+               if (gs1_p->roll != NOITEM)
+                       gs1_p->c[RW] -= ROLLPADDING;
+               return;
+       }
+
+       /*
+        * At this point we know we have to handle the groups separately, and
+        * then place them.  Process the top group now.
+        */
+       procsome(noteptrs, mll_p, staff_p, gs1_p, (struct GRPSYL *)0);
+
+       /*
+        * Clear the top group out of the array, and fill it with just the
+        * bottom group, to process them.  But mark them as if "top", to
+        * simplify procsome().
+        */
+       for (n = 0; n < NUMELEM(noteptrs); n++)
+               noteptrs[n].top_p = 0;
+
+       /* set all the "top" group pointers even though this is group 2 */
+       for (n = 0; n < gs2_p->nnotes; n++)
+               noteptrs[n].top_p = &gs2_p->notelist[n];
+
+       procsome(noteptrs, mll_p, staff_p, gs2_p, (struct GRPSYL *)0);
+
+       /*
+        * Now that we've figured out all the relative horizontal coords for
+        * the two groups (and everything in them) separately, we need to
+        * decide how to offset them so they don't overlap.  We'll offset
+        * each the same distance, one right and one left, and apply that
+        * offset to every horizontal coord of the groups.
+        */
+       /*
+        * If the groups can be placed so that their rectangles overlap, do it.
+        * Else if one of the groups is to be rolled and the other is not, the
+        * one to be rolled must be put on the left.  Otherwise, find which
+        * direction gives minimal offset, but bias the results (0.1) to favor
+        * putting the top group towards the left, so that the stems will be
+        * closer to lining up.  Set "offset" to the offset to be applied to
+        * group 1.  Group 2's will be -offset.
+        */
+       if (can_overlap(gs1_p, gs2_p) == YES) {
+               /* top group goes on right; top's offset > 0 */
+               if (allsmall(gs1_p, gs1_p) == allsmall(gs2_p, gs2_p)) {
+                       offset = 0.50 * STEPSIZE;
+               } else {
+                       offset = 0.75 * STEPSIZE;
+               }
+               if (gs2_p->roll != NOITEM)
+                       gs2_p->c[RW] -= ROLLPADDING;
+       } else if (gs1_p->roll != NOITEM && gs2_p->roll == NOITEM) {
+               /* only top group is rolled; it goes on left; its offset < 0 */
+               offset = ( gs2_p->c[RW] - gs1_p->c[RE] ) / 2;
+               gs1_p->c[RW] -= ROLLPADDING;
+       } else if (gs1_p->roll == NOITEM && gs2_p->roll != NOITEM) {
+               /* only bottom is rolled; top goes on right; top's offset > 0 */
+               offset = ( gs2_p->c[RE] - gs1_p->c[RW] ) / 2;
+               gs2_p->c[RW] -= ROLLPADDING;
+       } else {
+               /* either both are rolled or neither is; use other criterion */
+               if (gs1_p->c[RE] - gs2_p->c[RW] <
+                                       gs2_p->c[RE] - gs1_p->c[RW] + 0.1) {
+                       /* top group goes on left; its offset is negative */
+                       offset = ( gs2_p->c[RW] - gs1_p->c[RE] ) / 2;
+                       if (gs1_p->roll != NOITEM)
+                               gs1_p->c[RW] -= ROLLPADDING;
+               } else {
+                       /* top group goes on right; its offset is positive */
+                       offset = ( gs2_p->c[RE] - gs1_p->c[RW] ) / 2;
+                       if (gs2_p->roll != NOITEM)
+                               gs2_p->c[RW] -= ROLLPADDING;
+               }
+       }
+
+       /* apply offset to the groups and any preceding grace groups */
+       shiftgs(gs1_p, offset);
+       shiftgs(gs2_p, -offset);
+}
+\f
+/*
+ * Name:        compat()
+ *
+ * Abstract:    Determine whether two groups in a hand are "compatible".
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function is given pointers to the two groups in a hand,
+ *             in a situation where they overlap.  The noteptrs array has
+ *             just the top group filled in at this point.  The function
+ *             figures out whether the two groups are compatible (see block
+ *             comment below), or whether they must be drawn separately and
+ *             offset horizontally.  While doing this, it fills in the bottom
+ *             group part of noteptrs.  If it returns YES, this has been
+ *             completed.  If it returns NO, this may be partially done,
+ *             and the caller should clear out the partially complete bot_p
+ *             part of noteptrs.
+ */
+
+static int
+compat(noteptrs, gs1_p, gs2_p)
+
+struct NOTEPTRS noteptrs[];            /* array of ptrs to notes to process */
+register struct GRPSYL *gs1_p, *gs2_p; /* point at groups in this hand */
+
+{
+       int num1;               /* number of notes in top group */
+       register int n, k;      /* loop variables */
+
+
+       num1 = gs1_p->nnotes;
+
+       /*
+        * There is overlap between the two groups.  Try to match the bottom
+        * N notes of the top group with the top N notes of the bottom group.
+        * If all N are "compatible", we can "share" these notes.  For two
+        * groups to be compatible, they must meet the following conditions:
+        *      1) both basic time values must be half notes, or both must be
+        *         shorter than half notes
+        *      2) both have no dots or the same number of dots
+        *      3) the bottom N notes of the top group are the same letters
+        *         and octaves as the top N notes of the bottom group
+        *      4) no two of these N notes can be on neighboring letters
+        *      5) for each of the N pairs, the two notes have no accidental
+        *         or the same accidental
+        *      6) for each of the N pairs, the two notes must have the same
+        *         size and headshape
+        */
+       /* check rule 1 */
+       if (gs1_p->basictime < 2  || gs2_p->basictime < 2)
+               return (NO);
+       if (gs1_p->basictime == 2 && gs2_p->basictime != 2)
+               return (NO);
+       if (gs1_p->basictime != 2 && gs2_p->basictime == 2)
+               return (NO);
+
+       /* check rule 2 */
+       if (gs1_p->dots != gs2_p->dots)
+               return (NO);
+
+       /* check rules 3, 4, 5, and 6 together */
+       /* see if any note in the top group matches the top note in the other*/
+       for (n = 0; n < num1; n++) {
+               if (noteptrs[n].top_p->stepsup == gs2_p->notelist[0].stepsup)
+                       break;
+       }
+       if (n == num1)
+               return (NO);            /* didn't find any match */
+
+       /* starting with this note, verify that it and the rest match */
+       for (k = 0; n < num1; k++, n++) {
+               if (k >= gs2_p->nnotes) /* not enough notes in group 2? */
+                       return (NO);
+               if (gs2_p->notelist[k].stepsup != noteptrs[n].top_p->stepsup)
+                       return (NO);
+               if (k > 0 &&
+               gs2_p->notelist[k-1].stepsup - 1 == gs2_p->notelist[k].stepsup)
+                       return (NO);
+               if (gs2_p->notelist[k].accidental != noteptrs[n].top_p->accidental)
+                       return (NO);
+               if (gs2_p->notelist[k].notesize != noteptrs[n].top_p->notesize)
+                       return (NO);
+               if (gs2_p->notelist[k].headshape != noteptrs[n].top_p->headshape)
+                       return (NO);
+
+               /* this note matches; set up noteptrs */
+               noteptrs[n].bot_p = &gs2_p->notelist[k];
+       }
+
+       /*
+        * The fact that we made it to here means all the overlapping notes
+        * matched.  So fill the rest of group 2's note pointers.
+        */
+       for ( ; k < gs2_p->nnotes; k++, n++)
+               noteptrs[n].bot_p = &gs2_p->notelist[k];
+       /*
+        * It is possible that, although the overlapping notes' headshapes
+        * match, some of the characters are mirrors of each other due to the
+        * opposite stem dir.  In these cases, group 2 rules.  So overwrite the
+        * notes in group 1.  If the lowest note in group 1 has to be changed,
+        * that could affect the RS of group 1, so change that too.
+        * Also, while doing this, if any of these notes or their accs have
+        * parens in one group but not the other, erase those parens.
+        */
+       n -= k;
+       for (k = 0; n < num1; k++, n++) {
+               gs1_p->notelist[n].headchar = gs2_p->notelist[k].headchar;
+               gs1_p->notelist[n].headfont = gs2_p->notelist[k].headfont;
+               gs1_p->notelist[n].c[RN] = gs2_p->notelist[k].c[RN];
+               gs1_p->notelist[n].c[RS] = gs2_p->notelist[k].c[RS];
+
+               if (gs1_p->notelist[n].note_has_paren !=
+                   gs2_p->notelist[k].note_has_paren) {
+                       gs1_p->notelist[n].note_has_paren = NO;
+                       gs2_p->notelist[k].note_has_paren = NO;
+               }
+               if (gs1_p->notelist[n].acc_has_paren !=
+                   gs2_p->notelist[k].acc_has_paren) {
+                       gs1_p->notelist[n].acc_has_paren = NO;
+                       gs2_p->notelist[k].acc_has_paren = NO;
+               }
+       }
+       gs1_p->c[RS] = gs2_p->notelist[k - 1].c[RS];
+
+       return (YES);
+}
+\f
+/*
+ * Name:        can_overlap()
+ *
+ * Abstract:    Decides whether incompatible groups' rectangles can overlap.
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function is given two incompatible groups in a hand.  It
+ *             decides whether they can be placed such that their rectangles
+ *             overlap.  This arrangement is where the first group is to the
+ *             right of the second group, and the stems are about 3 stepsizes
+ *             apart.  The noteheads must be separated enough vertically so
+ *             that they don't collide, and various other things must also be
+ *             true for this to work.
+ */
+
+static int
+can_overlap(gs1_p, gs2_p)
+
+struct GRPSYL *gs1_p, *gs2_p;  /* point at group(s) in this hand */
+
+{
+       int notedist;           /* steps between two notes (absolute value) */
+       int n, k;               /* loop counters */
+
+
+       /*
+        * First, ensure that no note heads would collide.  We don't yet know
+        * whether any will be on the "wrong" side of their stem.  This is not
+        * too common and would rarely help things, so for now we assume the
+        * worst case, which is that all are on the "correct" side and thus
+        * have the potential of colliding with the other group's notes.
+        */
+       for (n = 0; n < gs1_p->nnotes; n++) {
+               for (k = 0; k < gs2_p->nnotes; k++) {
+                       notedist = abs(gs1_p->notelist[n].stepsup -
+                                      gs2_p->notelist[k].stepsup);
+
+                       /* never allow closer than 2 steps */
+                       if (notedist < 2)
+                               return (NO);
+
+                       /* if either is double whole, don't allow less than 3 */
+                       if ((gs1_p->basictime == 0 || gs2_p->basictime == 0) &&
+                                       notedist < 3)
+                               return (NO);
+               }
+       }
+
+       /* neither group can have slashes */
+       if (gs1_p->slash_alt > 0 || gs2_p->slash_alt > 0)
+               return (NO);
+
+       /* the first group can't have accidentals */
+       for (n = 0; n < gs1_p->nnotes; n++) {
+               if (gs1_p->notelist[n].accidental != '\0')
+                       return (NO);
+       }
+
+       /* the first group can't any preceding grace groups */
+       if (gs1_p->prev != 0 && gs1_p->prev->grpvalue == GV_ZERO)
+               return (NO);
+
+       /* the first group can't have a roll unless the second group has one */
+       if (gs1_p->roll != NOITEM && gs2_p->roll == NOITEM)
+               return (NO);
+
+       /* the second group can't have any dots */
+       if (gs2_p->dots > 0)
+               return (NO);
+
+       /* the second group can't have any flags */
+       if (gs2_p->basictime >= 8 && gs2_p->beamloc == NOITEM)
+               return (NO);
+
+       /* neither group can have a stem forced the "wrong" way */
+       if (gs1_p->stemdir == DOWN || gs2_p->stemdir == UP)
+               return (NO);
+
+       /*
+        * At this point we know we can overlap.
+        */
+       return (YES);
+}
+\f
+/*
+ * Name:        procsome()
+ *
+ * Abstract:    Sets coords for group(s) and their associated grace groups.
+ *
+ * Returns:     void
+ *
+ * Description: This function calls procbunch() to set the horizontal coords
+ *             for the given group(s) and their notes, etc.  Then it calls
+ *             procgrace() to deal with any grace groups preceding these
+ *             group(s) and adjust the main group(s)' west coordinates to.
+ *             contain the grace groups.
+ */
+
+static void
+procsome(noteptrs, mll_p, staff_p, gs1_p, gs2_p)
+
+struct NOTEPTRS noteptrs[];    /* array of ptrs to notes to process */
+struct MAINLL *mll_p;          /* the MLL item the group is connected to */
+struct STAFF *staff_p;         /* the staff the groups are connected to */
+struct GRPSYL *gs1_p, *gs2_p;  /* point at group(s) in this hand */
+
+{
+       /* process the normal group(s) */
+       procbunch(noteptrs, mll_p, staff_p, gs1_p, gs2_p);
+
+       /* process any grace groups preceding first normal group */
+       procgrace(noteptrs, mll_p, staff_p, gs1_p);
+
+       /* process any grace groups preceding second normal group, if exists */
+       if (gs2_p != 0)
+               procgrace(noteptrs, mll_p, staff_p, gs2_p);
+}
+\f
+/*
+ * Name:        procgrace()
+ *
+ * Abstract:    Sets coords for grace groups and adjusts normal group's west.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops leftward from the given normal group,
+ *             calling procbunch() for each grace group, and adjusting the
+ *             normal group's west coordinate accordingly.
+ */
+
+static void
+procgrace(noteptrs, mll_p, staff_p, gsnorm_p)
+
+struct NOTEPTRS noteptrs[];    /* array of ptrs to notes to process */
+struct MAINLL *mll_p;          /* the MLL item the group is connected to */
+struct STAFF *staff_p;         /* the staff the groups are connected to */
+struct GRPSYL *gsnorm_p;       /* point at the normal group to start from */
+
+{
+       struct GRPSYL *gs_p;    /* point at a grace group */
+       struct GRPSYL *right_p; /* point at the group to the right of this */
+       int n;                  /* loop variable */
+
+
+       /*
+        * Loop through any grace groups preceding the normal group, working
+        * right to left.  Call procbunch() for each.  Upon return, set
+        * the grace group's x,e,w relative to the normal group's x, and
+        * alter the west coordinate of the normal group to include them.
+        */
+       right_p = gsnorm_p;
+       for (gs_p = gsnorm_p->prev; gs_p != 0 && gs_p->grpvalue == GV_ZERO;
+                               gs_p = gs_p->prev) {
+               /* clear noteptrs, and resetup for this grace group */
+               /* note:  grace groups are always notes, not rests or spaces */
+               for (n = 0; n < MAXHAND + 1; n++) {
+                       noteptrs[n].top_p = 0;
+                       noteptrs[n].bot_p = 0;
+               }
+               /* set all the "top" group pointers */
+               for (n = 0; n < gs_p->nnotes; n++)
+                       noteptrs[n].top_p = &gs_p->notelist[n];
+
+               procbunch(noteptrs, mll_p, staff_p, gs_p, (struct GRPSYL *)0);
+
+               gs_p->c[RX] = right_p->c[RW] - gs_p->c[RE];
+               gs_p->c[RW] += gs_p->c[RX];
+               gs_p->c[RE] += gs_p->c[RX];
+
+               gsnorm_p->c[RW] = gs_p->c[RW];
+               right_p = gs_p;
+       }
+}
+\f
+/*
+ * Name:        procbunch()
+ *
+ * Abstract:    Sets relative horizontal coords of note heads, accs, & dots.
+ *
+ * Returns:     void
+ *
+ * Description: This function figures out which note heads in the given
+ *             group(s) need to be put on the "wrong" side of the stem to
+ *             avoid overlapping.  Then it sets all note heads' horizontal
+ *             coords.  It calls doacc() to find and store the positions
+ *             for the accidentals, dodot() for the dots.  It sets RW and
+ *             RE for the group(s), also taking flags into consideration.
+ */
+
+/*
+ * This macro checks the n'th structure in noteptrs.  If the top group has
+ * a note there, it returns a pointer to that note, else it returns the
+ * bottom pointer, which may or may not be 0.
+ */
+#define        GETPTR(n)       (noteptrs[n].top_p != 0 ?               \
+                       noteptrs[n].top_p : noteptrs[n].bot_p)
+
+static void
+procbunch(noteptrs, mll_p, staff_p, gs1_p, gs2_p)
+
+struct NOTEPTRS noteptrs[];    /* array of ptrs to notes to process */
+struct MAINLL *mll_p;          /* the MLL item the group is connected to */
+struct STAFF *staff_p;         /* the staff the groups are connected to */
+struct GRPSYL *gs1_p, *gs2_p;  /* point at group(s) in this hand */
+
+{
+       int normhead[MAXHAND + 1];      /* position of note heads */
+       float gwide;                    /* width of any note in these groups */
+       float nwide;                    /* width of a particular note */
+       float maxwide;                  /* max of gwide for the two groups */
+       float ghigh;                    /* height of any note in these groups*/
+       float nhigh;                    /* height of a particular note */
+       float g1wide, g2wide;           /* gwide for the two groups */
+       float maxhigh;                  /* max of ghigh for the two groups */
+       float flagwidth;                /* width of a flag */
+       float rh;                       /* relative horizontal of a note */
+       int collinear;                  /* are the 2 groups' stems collinear? */
+       register int k, n;              /* loop variables */
+       int size;
+
+
+       /*
+        * If this is a tablature staff, call a special function to handle it,
+        * and return.  Voices on tab staffs are handled one at a time, so
+        * gs2_p will never be used for them.
+        */
+       if (is_tab_staff(staff_p->staffno)) {
+               proctab(mll_p, staff_p, gs1_p);
+               return;
+       }
+
+       collinear = NO;                 /* assume not collinear stems */
+
+       /*
+        * "Normal" position of a note head means to the left of the stem
+        * for an upward stem, and right for downward.  When two notes in a
+        * group are on neighboring letters, one of the note heads has to be
+        * in "abnormal" position so that they don't collide.  Shared
+        * note heads must always be in normal position.  (The fact
+        * that no two of them can be on neighboring letters is enforced
+        * when checking for compatibility of groups.)
+        */
+       /*
+        * See if there are any shared notes first.
+        */
+       for (n = 0; noteptrs[n].top_p != 0; n++) {
+               if (noteptrs[n].bot_p != 0)
+                       break;          /* found a shared note */
+       }
+
+       if (noteptrs[n].top_p != 0) {
+               /*
+                * There are shared notes, and n indexes to the first one
+                * (starting from the top).  Set this first one to normal.
+                * First work upwards from there, reversing normality
+                * whenever there are neighboring notes, setting back to
+                * normal otherwise.  Then work downwards from there, doing
+                * the same.
+                */
+               normhead[n] = YES;
+               for (k = n - 1 ; k >= 0; k--) {
+                       if (noteptrs[k+1].top_p->stepsup ==
+                           noteptrs[ k ].top_p->stepsup - 1)
+                               normhead[k] = ! normhead[k+1];
+                       else
+                               normhead[k] = YES;
+               }
+               for (k = n + 1 ; noteptrs[k].bot_p != 0; k++) {
+                       if (noteptrs[k-1].bot_p->stepsup ==
+                           noteptrs[ k ].bot_p->stepsup + 1)
+                               normhead[k] = ! normhead[k-1];
+                       else
+                               normhead[k] = YES;
+               }
+       } else {
+               /*
+                * There are no shared notes.  It may even be that there's only
+                * one group.  In each group, the note that's opposite the stem
+                * must be normal, and then we go down the list of other notes
+                * in the group, reversing normality whenever there are
+                * neighboring notes, and setting back to normal otherwise.
+                * There's a special concern if the bottom note of the top
+                * group is on the neighboring letter to the top note of the
+                * bottom group, or if it is on the same letter.  In that case,
+                * we want to offset the groups slightly, such that their stems
+                * are collinear, so set that flag.
+                */
+               /* the first group's stem could go either way */
+               if (gs1_p->stemdir == UP) {
+                       normhead[n-1] = YES;    /* bottom note normal */
+                       for (k = n - 2; k >= 0; k--) {
+                               if (noteptrs[k+1].top_p->stepsup ==
+                                   noteptrs[ k ].top_p->stepsup - 1)
+                                       normhead[k] = ! normhead[k+1];
+                               else
+                                       normhead[k] = YES;
+                       }
+               } else {        /* stemdir == DOWN */
+                       normhead[0] = YES;      /* top note normal */
+                       for (k = 1; k < n; k++) {
+                               if (noteptrs[k-1].top_p->stepsup ==
+                                   noteptrs[ k ].top_p->stepsup + 1)
+                                       normhead[k] = ! normhead[k-1];
+                               else
+                                       normhead[k] = YES;
+                       }
+               }
+
+               /* the second group's stem (if it exists) must go down */
+               if (gs2_p != 0) {
+                       normhead[n] = YES;      /* top note normal */
+                       for (k = n + 1; noteptrs[k].bot_p != 0; k++) {
+                               if (noteptrs[k-1].bot_p->stepsup ==
+                                   noteptrs[ k ].bot_p->stepsup + 1)
+                                       normhead[k] = ! normhead[k-1];
+                               else
+                                       normhead[k] = YES;
+                       }
+
+                       collinear = (noteptrs[n-1].top_p->stepsup <=
+                                    noteptrs[ n ].bot_p->stepsup + 1);
+               }
+       }
+
+       /*
+        * Set gwide and ghigh to be the biggest values of any note in the top
+        * group, also storing the width of each note for later use.
+        */
+       gwide = ghigh = 0.0;
+       for (n = 0; noteptrs[n].top_p != 0; n++) {
+               size = noteptrs[n].top_p->notesize == GS_NORMAL ?
+                               DFLT_SIZE : SMALLSIZE;
+               nwide = width(noteptrs[n].top_p->headfont, size,
+                               noteptrs[n].top_p->headchar);
+               noteptrs[n].wid = nwide;
+               if (nwide > gwide) {
+                       gwide = nwide;
+               }
+               nhigh = height(noteptrs[n].top_p->headfont, size,
+                               noteptrs[n].top_p->headchar);
+               if (nhigh > ghigh) {
+                       ghigh = nhigh;
+               }
+       }
+
+       /* remember these values, for comparing to the other group (if any) */
+       maxwide = g1wide = gwide;       /* widest group so far */
+       maxhigh = ghigh;                /* highest group so far */
+
+       if (gs1_p->basictime <= 1) {
+               gs1_p->stemx = 0.0;     /* center the imaginary stem */
+       } else {
+               gs1_p->stemx = gs1_p->stemdir == UP ? gwide / 2 : -gwide / 2;
+       }
+
+       for (n = 0; noteptrs[n].top_p != 0; n++) {
+               nwide = noteptrs[n].wid;
+
+               if (normhead[n] == YES) {
+                       /*
+                        * The note head is in normal position, so usually its
+                        * relative x coord is 0, and west and east are half a
+                        * width off.  But if the note is smaller than the
+                        * group's max, and there is a stem, and the note is
+                        * not shared by the other group, the note needs to
+                        * be off center so that it touches the stem.
+                        */
+                       if (nwide != gwide && gs1_p->basictime >= 2 &&
+                                       noteptrs[n].bot_p == 0) {
+                               if (gs1_p->stemdir == UP) {
+                                       noteptrs[n].top_p->c[RE] = gwide / 2;
+                                       noteptrs[n].top_p->c[RX] =
+                                                       gwide / 2 - nwide / 2;
+                                       noteptrs[n].top_p->c[RW] =
+                                                       gwide / 2 - nwide;
+                               } else {        /* DOWN */
+                                       noteptrs[n].top_p->c[RW] = -gwide / 2;
+                                       noteptrs[n].top_p->c[RX] =
+                                                       -gwide / 2 + nwide / 2;
+                                       noteptrs[n].top_p->c[RE] =
+                                                       -gwide / 2 + nwide;
+                               }
+                       } else {
+                               noteptrs[n].top_p->c[RX] = 0;
+                               noteptrs[n].top_p->c[RW] = -nwide / 2;
+                               noteptrs[n].top_p->c[RE] = nwide / 2;
+                       }
+               } else {
+                       /*
+                        * The note head is in abnormal position.  Its relative
+                        * x coord, and west and east, depend on which way the
+                        * stem is going.  Smaller than normal notes need to
+                        * be placed differently regardless of whether stemed.
+                        * In all case, adjust by W_NORMAL*POINT, the width of
+                        * the stem, so that the note overlays the stem.
+                        */
+                       if (nwide != gwide) {
+                               if (gs1_p->stemdir == UP) {
+                                       noteptrs[n].top_p->c[RW] =
+                                               gwide / 2 - W_NORMAL * POINT;
+                                       noteptrs[n].top_p->c[RX] =
+                                               gwide / 2 + nwide / 2
+                                               - W_NORMAL * POINT;
+                                       noteptrs[n].top_p->c[RE] =
+                                               gwide / 2 + nwide
+                                               - W_NORMAL * POINT;
+                               } else {        /* DOWN */
+                                       noteptrs[n].top_p->c[RE] =
+                                               W_NORMAL * POINT - gwide / 2;
+                                       noteptrs[n].top_p->c[RX] =
+                                               W_NORMAL * POINT
+                                               - gwide / 2 - nwide /2;
+                                       noteptrs[n].top_p->c[RW] =
+                                               W_NORMAL * POINT
+                                               - gwide / 2 - nwide;
+                               }
+                       } else {
+                               if (gs1_p->stemdir == UP) {
+                                       noteptrs[n].top_p->c[RX] =
+                                               nwide - W_NORMAL * POINT;
+                                       noteptrs[n].top_p->c[RW] =
+                                               nwide * 0.5 - W_NORMAL * POINT;
+                                       noteptrs[n].top_p->c[RE] =
+                                               nwide * 1.5 - W_NORMAL * POINT;
+                               } else {        /* DOWN */
+                                       noteptrs[n].top_p->c[RX] =
+                                               W_NORMAL * POINT - nwide;
+                                       noteptrs[n].top_p->c[RW] =
+                                               W_NORMAL * POINT - nwide * 1.5;
+                                       noteptrs[n].top_p->c[RE] =
+                                               W_NORMAL * POINT - nwide * 0.5;
+                               }
+                       }
+               }
+       }
+
+       /*
+        * If there is a bottom group, get note head character width for
+        * it, find where in noteptrs that group starts, then loop through
+        * it, setting coords.  While doing this, set the group's
+        * horizontal coords.
+        */
+       g2wide = 0.0;   /* to avoid useless 'used before set' warning */
+       if (gs2_p != 0) {
+               /* skip by notes that are only in the top group */
+               for (n = 0; noteptrs[n].bot_p == 0; n++)
+                       ;
+               /*
+                * Set gwide and ghigh to be the biggest values of any note in
+                * the bottom group, also storing the width of each note for
+                * later use.  If the note is shared between groups, the width
+                * has already been stored in noteptrs[].wid, so we don't have
+                * to recalculate it.
+                */
+               gwide = ghigh = 0.0;
+               for ( ; noteptrs[n].bot_p != 0; n++) {
+                       size = noteptrs[n].bot_p->notesize == GS_NORMAL ?
+                                       DFLT_SIZE : SMALLSIZE;
+                       if (noteptrs[n].wid == 0.0) {
+                               nwide = width(noteptrs[n].bot_p->headfont, size,
+                                               noteptrs[n].bot_p->headchar);
+                               noteptrs[n].wid = nwide;
+                       } else {
+                               nwide = noteptrs[n].wid;
+                       }
+                       if (nwide > gwide) {
+                               gwide = nwide;
+                       }
+                       nhigh = height(noteptrs[n].bot_p->headfont, size,
+                                       noteptrs[n].bot_p->headchar);
+                       if (nhigh > ghigh) {
+                               ghigh = nhigh;
+                       }
+               }
+               g2wide = gwide;
+               if (gs2_p->basictime <= 1) {
+                       gs2_p->stemx = 0.0;     /* center the imaginary stem */
+               } else {
+                       gs2_p->stemx = gs2_p->stemdir == UP ? gwide / 2
+                                                          : -gwide / 2;
+               }
+
+               /* if groups have different note head sizes, adjust maxes */
+               if (gwide > maxwide)
+                       maxwide = gwide;
+               if (ghigh > maxhigh)
+                       maxhigh = ghigh;
+
+               for (n = 0; noteptrs[n].bot_p == 0; n++)
+                       ;
+               for ( ; noteptrs[n].bot_p != 0; n++) {
+                       nwide = noteptrs[n].wid;
+
+                       if (normhead[n] == YES) {
+                               /*
+                                * The note head is in normal position, so its
+                                * relative x coord is 0, and west and east are
+                                * half a width off.  But if the note is smaller
+                                * than the widest note in the group and there
+                                * is a stem, and the note is not shared by the
+                                * other group, the note needs to be off center
+                                * so that it touches the stem.
+                                */
+                               if (nwide != gwide && gs2_p->basictime >= 2 &&
+                                               noteptrs[n].top_p == 0) {
+                                       noteptrs[n].bot_p->c[RW] = -gwide / 2;
+                                       noteptrs[n].bot_p->c[RX] =
+                                                       -gwide / 2 + nwide / 2;
+                                       noteptrs[n].bot_p->c[RE] =
+                                                       -gwide / 2 + nwide;
+                               } else {
+                                       noteptrs[n].bot_p->c[RX] = 0;
+                                       noteptrs[n].bot_p->c[RW] = -nwide * 0.5;
+                                       noteptrs[n].bot_p->c[RE] = nwide * 0.5;
+                               }
+                       } else {
+                               /*
+                                * The note head is in abnormal position.  Its
+                                * relative x coord, and west and east, depend
+                                * on which way the stem is going, but the
+                                * stem must always be down in group 2.  Smaller
+                                * than normal notes need to be placed
+                                * differently regardless of whether stemed.
+                                */
+                               if (nwide != gwide) {
+                                       noteptrs[n].bot_p->c[RE] =
+                                               W_NORMAL * POINT - gwide / 2;
+                                       noteptrs[n].bot_p->c[RX] =
+                                               W_NORMAL * POINT
+                                               - gwide / 2 - nwide /2;
+                                       noteptrs[n].bot_p->c[RW] =
+                                               W_NORMAL * POINT
+                                               - gwide / 2 - nwide;
+                               } else {
+                                       noteptrs[n].bot_p->c[RX] =
+                                               W_NORMAL * POINT - nwide;
+                                       noteptrs[n].bot_p->c[RW] =
+                                               W_NORMAL * POINT - nwide * 1.5;
+                                       noteptrs[n].bot_p->c[RE] =
+                                               W_NORMAL * POINT - nwide * 0.5;
+                               }
+                       }
+               }
+       }
+
+       /* find position of accidentals */
+       doacc(noteptrs, maxwide / 2, maxhigh / 2, collinear);
+
+       /* find position of dots after notes */
+       dodot(staff_p, gs1_p, gs2_p, maxwide / 2, collinear);
+
+       /* find position of right parentheses around notes */
+       noterparen(noteptrs, gs1_p, gs2_p, maxwide/2, maxhigh/2, collinear);
+
+       /*
+        * Set RX for the group(s) to 0 for now if stems are offset (the
+        * normal case), or to the appropriate value if stems are collinear.
+        * If we only have one group it will thus be set to 0 now, though
+        * later, if there's an incompatible group next to it, this coord
+        * and all others will be adjusted.
+        */
+       if (collinear) {
+               gs1_p->c[RX] = (W_NORMAL * POINT - maxwide) / 2;
+               gs2_p->c[RX] = (maxwide - W_NORMAL * POINT) / 2;
+       } else {
+               gs1_p->c[RX] = 0;
+               if (gs2_p != 0)
+                       gs2_p->c[RX] = 0;
+       }
+
+       /*
+        * Set the western boundaries for the group(s).
+        */
+       /*
+        * Init the group's RW to 0.  Then loop through the notes, finding the
+        * westernmost thing associated with a note, and leaving the group's RW
+        * set to that.
+        */
+       gs1_p->c[RW] = 0;
+       for (k = 0; k < gs1_p->nnotes; k++) {
+               rh = notehorz(gs1_p, &gs1_p->notelist[k], RW);
+               if (rh < gs1_p->c[RW])
+                       gs1_p->c[RW] = rh;
+       }
+       /*
+        * If the stem is down on a half note or shorter that is to have
+        * slashes through its stem, make sure there is room for the slashes.
+        */
+       if (gs1_p->slash_alt > 0 && gs1_p->stemdir == DOWN &&
+                       gs1_p->basictime >= 2) {
+               gwide = g1wide;
+               /* if position of stem minus slash room < current west . . . */
+               if (-gwide / 2 - SLASHPAD < gs1_p->c[RW])
+                       gs1_p->c[RW] = -gwide / 2 - SLASHPAD;
+       }
+       westwith(gs1_p);                /* expand RW for "with" list if needbe*/
+       gs1_p->c[RW] -= gs1_p->padding; /* add user requested padding */
+
+       /* add the pad parameter that user wants for this voice */
+       gs1_p->c[RW] -= vvpath(gs1_p->staffno, gs1_p->vno, PAD)->pad;
+
+       csbstempad(mll_p, gs1_p);       /* cross staff beaming may need space */
+       gs1_p->c[RW] += gs1_p->c[RX];   /* shift by RX, in case RX isn't 0 */
+
+       /*
+        * If group 2 exists, do the same for it.  However, in the slash
+        * section, we know the stem must be down, so no need to check that.
+        */
+       if (gs2_p != 0) {
+               gs2_p->c[RW] = 0;
+               for (k = 0; k < gs2_p->nnotes; k++) {
+                       rh = notehorz(gs2_p, &gs2_p->notelist[k], RW);
+                       if (rh < gs2_p->c[RW])
+                               gs2_p->c[RW] = rh;
+               }
+               if (gs2_p->slash_alt > 0 && gs2_p->basictime >= 2) {
+                       gwide = g2wide;
+                       /* if pos of stem minus slash room < current west . .*/
+                       if (-gwide / 2 - SLASHPAD < gs2_p->c[RW])
+                               gs2_p->c[RW] = -gwide / 2 - SLASHPAD;
+               }
+               westwith(gs2_p);
+               gs2_p->c[RW] -= gs2_p->padding;
+               gs2_p->c[RW] -= vvpath(gs2_p->staffno, gs2_p->vno, PAD)->pad;
+               csbstempad(mll_p, gs2_p);
+               gs2_p->c[RW] += gs2_p->c[RX];
+       }
+
+       /*
+        * Set the eastern boundaries for the group(s).
+        */
+       /*
+        * Init the group's RE to 0.  Then loop through the notes, finding the
+        * easternmost thing associated with a note, and leaving the group's RE
+        * set to that.
+        */
+       gs1_p->c[RE] = 0;
+       for (k = 0; k < gs1_p->nnotes; k++) {
+               rh = notehorz(gs1_p, &gs1_p->notelist[k], RE);
+               if (rh > gs1_p->c[RE])
+                       gs1_p->c[RE] = rh;
+       }
+       /*
+        * Add in any padding needed for ties, slurs, and bends.  Also add room
+        * for alternations if there are any.
+        */
+       gs1_p->c[RE] += tieslurpad(staff_p, gs1_p);
+       if (gs1_p->slash_alt < 0 && gs1_p->beamloc == STARTITEM)
+               gs1_p->c[RE] += ALTPAD;
+       /*
+        * If the stem is up and a flag is needed, and the east boundary
+        * doesn't yet contain it, adjust the east boundary so the flag will
+        * fit.
+        */
+       if (gs1_p->stemdir == UP && gs1_p->basictime >= 8 &&
+                               gs1_p->beamloc == NOITEM) {
+               flagwidth = width(FONT_MUSIC, gs1_p->grpsize == GS_NORMAL ?
+                       DFLT_SIZE : SMALLSIZE, C_UPFLAG);
+               if (gs1_p->notelist[0].c[RE] + flagwidth > gs1_p->c[RE])
+                       gs1_p->c[RE] = gs1_p->notelist[0].c[RE] + flagwidth;
+       }
+       /*
+        * If the stem is up on a half note or shorter that is to have slashes
+        * through its stem, make sure there's room for the slashes.
+        */
+       if (gs1_p->slash_alt > 0 && gs1_p->stemdir == UP &&
+                       gs1_p->basictime >= 2) {
+               gwide = g1wide;
+               /* if position of stem plus slash room > current east . . . */
+               if (gwide / 2 + SLASHPAD > gs1_p->c[RE])
+                       gs1_p->c[RE] = gwide / 2 + SLASHPAD;
+       }
+       /*
+        * Expand RE some more if need be to accommodate the "with" list.  Then
+        * shift it over by RX, in case RX isn't 0.
+        */
+       eastwith(gs1_p);
+       gs1_p->c[RE] += gs1_p->c[RX];
+
+       /*
+        * If group 2 exists, do the same for it.  However, the stem is always
+        * down, so any flags will always already fit.  For the same reason,
+        * slashes don't need to be considered.
+        */
+       if (gs2_p != 0) {
+               gs2_p->c[RE] = 0;
+               for (k = 0; k < gs2_p->nnotes; k++) {
+                       rh = notehorz(gs2_p, &gs2_p->notelist[k], RE);
+                       if (rh > gs2_p->c[RE])
+                               gs2_p->c[RE] = rh;
+               }
+               gs2_p->c[RE] += tieslurpad(staff_p, gs2_p);
+               if (gs2_p->slash_alt < 0 && gs2_p->beamloc == STARTITEM)
+                       gs2_p->c[RE] += ALTPAD;
+               eastwith(gs2_p);
+               gs2_p->c[RE] += gs2_p->c[RX];
+       }
+}
+\f
+/*
+ * Name:        doacc()
+ *
+ * Abstract:    Finds horizontal position for each accidental in group(s).
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through all the accidentals belonging
+ *             to notes in the group(s) it is given.  It figures out where
+ *             to place them horizontally to avoid overlap, and stores the
+ *             relative west coord of each in NOTE.waccr.  For each group,
+ *             it uses the appropriate size of accidentals (based on normal
+ *             versus cue/grace), and places them appropriately, considering
+ *             also the size of the notes.  However, if there are two groups,
+ *             the note head sizes could be different.  The halfwide and
+ *             halfhigh passed in are supposed to be the right size for the
+ *             bigger of the two sizes, and accidentals will not be packed
+ *             as tightly against the other notes.  This doesn't hurt, and
+ *             isn't worth the trouble to do it "right".
+ *
+ *             This function takes into account parentheses around accidentals.
+ *             Its algorithm treats them as part of the accidental.  Also, when
+ *             there are parentheses around the note, it handles the left
+ *             parentheses the same way:  if there is also an accidental, it
+ *             treats it as part of it; otherwise the paren is handled like an
+ *             accidental itself.
+ */
+
+/* this fudge factor prevents roundoff error from causing overlap */
+#define        FUDGE           (.01)
+
+/* when CSS applies to a note or acc, move it by this much */
+#define CSS_OFF                (CSS_STEPS * STEPSIZE)
+
+static void
+doacc(noteptrs, halfwide, halfhigh, collinear)
+
+struct NOTEPTRS noteptrs[];    /* array of ptrs to notes to process */
+double halfwide;               /* half of max of width & height of (notes */
+double halfhigh;               /*  in group 1, notes in group 2) */
+int collinear;                 /* are stems collinear? */
+
+{
+       /*
+        * Each structure in this table represents either a note head that
+        * is farther left than normal, or an accidental.  A note head
+        * could be too far left for one of two reasons: either it was
+        * forced to be on the left ("wrong") side of a stem that points
+        * down, or it is a normal note in the top group when the stems are
+        * collinear.  In the collinear case, to make this function easier,
+        * we start out regarding the bottom group as being normal, and
+        * the top group as being shifted left one note head, and we figure
+        * everything relative to the bottom group.  But at the end we adjust
+        * waccr so that every accidental is relative to its own group, like
+        * it's supposed to be.
+        *
+        * The coordinates define the rectangle that surrounds the note or acc,
+        * including standard padding, even on note heads, which don't
+        * normally have padding.  First the notes are put into this table;
+        * then the accidentals, one at a time, making sure they don't
+        * overlap things already in the table.
+        * To see if the accidental being added overlaps, first its north
+        * and south are tested.  All previous rectangles that are "out of
+        * its way" vertically are marked not "relevant"; the others are
+        * marked "relevant".  As positions are tried, right to left, positions
+        * that fail to avoid overlap are marked "tried".
+        *
+        * After the correct position is found for an accidental, there is a
+        * special case for flats and double flats to take advantage of their
+        * shape and let them pack tighter.
+        */
+       struct {
+               float n, s, e, w;       /* boundaries of a rectangle */
+               short relevant;         /* is rectangle relevant? */
+               short tried;            /* have we tried this one yet? */
+       } rectab[2 * MAXHAND + 1];      /* enough for all notes & accidentals*/
+
+       struct NOTE *note_p;            /* point at a note */
+       int reclim;                     /* index after last rectangle in tab */
+       float north, south, east, west; /* relative coords of new accidental */
+       float accasc, accdesc;          /* ascent & descent of accidental */
+       float accwidth;                 /* width of new accidental */
+       float parenwidth;               /* width of note's left parenthesis */
+       float parenv;                   /* half the vertical size of paren */
+       float totwidth;                 /* width of acc plus paren */
+       int overlap;                    /* does our acc overlap existing ones*/
+       int try;                        /* which element of rectab to try */
+       int found;                      /* accs/parens found so far */
+       int k, j;                       /* loop variables */
+       int size;
+       float horfn, verfn;             /* horz & vert flat/nat notch sizes */
+       float savehorfn;                /* save original horfn */
+
+
+       reclim = 0;                     /* table initially empty */
+
+       /*
+        * Loop through noteptrs, finding all notes that are left of normal
+        * position, entering them in rectab.  Include padding around them.
+        * First loop through all notes, finding ones that are on the left
+        * side of a down stem; then, if stems are collinear, loop through
+        * the top group, finding all normal notes.
+        */
+       for (k = 0; (note_p = GETPTR(k)) != 0; k++) {
+               if (note_p->c[RX] < 0) {
+                       rectab[reclim].n = note_p->c[RY] + halfhigh + STDPAD;
+                       rectab[reclim].s = note_p->c[RY] - halfhigh - STDPAD;
+                       rectab[reclim].e = note_p->c[RE] + STDPAD;
+                       rectab[reclim].w = note_p->c[RW] - STDPAD;
+                       if (note_p->stepsup >= CSS_STEPS / 2) {
+                               rectab[reclim].n += CSS_OFF;
+                               rectab[reclim].s += CSS_OFF;
+                       } else if (note_p->stepsup <= -CSS_STEPS / 2) {
+                               rectab[reclim].n -= CSS_OFF;
+                               rectab[reclim].s -= CSS_OFF;
+                       }
+                       reclim++;
+               }
+       }
+       if (collinear) {
+               for (k = 0; (note_p = noteptrs[k].top_p) != 0; k++) {
+                       if (note_p->c[RX] == 0) {
+                               rectab[reclim].n = note_p->c[RY] + halfhigh
+                                               + STDPAD;
+                               rectab[reclim].s = note_p->c[RY] - halfhigh
+                                               - STDPAD;
+                               rectab[reclim].e = W_NORMAL * POINT
+                                               - halfwide + STDPAD;
+                               rectab[reclim].w = W_NORMAL * POINT
+                                               - 3 * halfwide - STDPAD;
+                               if (note_p->stepsup >= CSS_STEPS / 2) {
+                                       rectab[reclim].n += CSS_OFF;
+                                       rectab[reclim].s += CSS_OFF;
+                               } else if (note_p->stepsup <= -CSS_STEPS / 2) {
+                                       rectab[reclim].n -= CSS_OFF;
+                                       rectab[reclim].s -= CSS_OFF;
+                               }
+                               reclim++;
+                       }
+               }
+       }
+
+       /* prevent false "may be used before set" lint warning */
+       verfn = savehorfn = 0.0;
+
+       /*
+        * Loop through all notes, find the ones with accs or parens.  Find
+        * where the accs and parens will fit, storing that info in waccr, and
+        * adding them to rectab.  Call a function so that we loop in the
+        * proper order.
+        */
+       for (found = 0, k = nextacc(noteptrs, found);  k != -1;
+                               found++, k = nextacc(noteptrs, found)) {
+               note_p = GETPTR(k);
+               /* get dimensions of accidental if there is one */
+               if (note_p->accidental != '\0') {
+                       accdimen(note_p, &accasc, &accdesc, &accwidth);
+               } else {
+                       accwidth = accasc = accdesc = 0.0;
+               }
+               /* get dimensions of note's left paren, if there is one */
+               if (note_p->note_has_paren == YES) {
+                       size = (note_p->notesize == GS_NORMAL ?
+                                       DFLT_SIZE : SMALLSIZE);
+                       parenwidth = width(FONT_TR, size, '(');
+                       parenv = height(FONT_TR, size, '(') / 2.0;
+               } else {
+                       parenwidth = parenv = 0.0;
+               }
+               /* set the north, south, and width of what we have found */
+               north = note_p->c[RY] + MAX(accasc, parenv);
+               south = note_p->c[RY] - MAX(accdesc, parenv);
+               if (note_p->stepsup >= CSS_STEPS / 2) {
+                       north += CSS_OFF;
+                       south += CSS_OFF;
+               } else if (note_p->stepsup <= -CSS_STEPS / 2) {
+                       north -= CSS_OFF;
+                       south -= CSS_OFF;
+               }
+               totwidth = accwidth + parenwidth;
+
+               /*
+                * For each rectangle in rectab, decide whether (based on
+                * its vertical coords) it could possibly overlap with our
+                * new accidental.  If it's totally above or below ours, it
+                * can't.  We allow a slight overlap (FUDGE) so that round
+                * off errors don't stop us from packing things as tightly
+                * as possible.
+                */
+               for (j = 0; j < reclim; j++) {
+                       if (rectab[j].s + FUDGE > north ||
+                           rectab[j].n < south + FUDGE)
+                               rectab[j].relevant = NO;
+                       else
+                               rectab[j].relevant = YES;
+               }
+
+               /*
+                * Mark that none of the relevant rectangles' boundaries have
+                * been tried yet for positioning our acc.
+                */
+               for (j = 0; j < reclim; j++) {
+                       if (rectab[j].relevant == YES)
+                               rectab[j].tried = NO;
+               }
+
+               /*
+                * Set up first trial position for this acc., just to the
+                * left of normal notes, allowing padding.
+                */
+               east = - halfwide - STDPAD;
+               west = east - totwidth;
+
+               /*
+                * Keep trying positions for this acc, working right to
+                * left.  When we find one that doesn't overlap an existing
+                * rectangle, break.  This has to succeed at some point,
+                * at the leftmost rectangle position if not earlier.
+                */
+               for (;;) {
+                       overlap = NO;
+                       for (j = 0; j < reclim; j++) {
+                               /* ignore ones too far north or south */
+                               if (rectab[j].relevant == NO)
+                                       continue;
+
+                               /* if all west or east, okay; else overlap */
+                               if (rectab[j].w + FUDGE <= east &&
+                                   rectab[j].e >= west + FUDGE) {
+                                       overlap = YES;
+                                       break;
+                               }
+                       }
+
+                       /* if no rectangle overlapped, we found a valid place*/
+                       if (overlap == NO)
+                               break;
+
+                       /*
+                        * Something overlapped, so we have to try again.
+                        * Find the eastermost relevant west rectangle boundary
+                        * that hasn't been tried already, to use as the next
+                        * trial position for our acc's east.
+                        */
+                       try = -1;
+                       for (j = 0; j < reclim; j++) {
+                               /* ignore ones too far north or south */
+                               if (rectab[j].relevant == NO ||
+                                   rectab[j].tried == YES)
+                                       continue;
+
+                               /*
+                                * If this is the first relevant one we haven't
+                                * tried, or if this is farther east than the
+                                * easternmost so far, save it as being the
+                                * new easternmost so far.
+                                */
+                               if (try == -1 || rectab[j].w > rectab[try].w)
+                                       try = j;
+                       }
+
+                       if (try == -1)
+                               pfatal("bug in doacc()");
+
+                       /*
+                        * Mark this one as having been tried (for next time
+                        * around, if necessary).  Set new trial values for
+                        * east and west of our acc.
+                        */
+                       rectab[try].tried = YES;
+                       east = rectab[try].w;
+                       west = east - totwidth;
+
+               } /* end of while loop trying positions for this acc */
+
+               /*
+                * We found the correct position for the new acc.  However, for
+                * flats, double flats & nats, we would like a notch to be taken
+                * out of the upper right corner of their rectangle, in effect,
+                * since there's nothing there but white space.  This can only
+                * be done if the acc is not already right next to the group.
+                */
+               if (note_p->accidental == '&' || note_p->accidental == 'B' ||
+                                       note_p->accidental == 'n') {
+                       /* get notch size; if paren, add width to horz */
+                       if (note_p->accidental == 'n') {
+                               horfn = 1.4 * STEPSIZE; /* horizontal notch */
+                               verfn = 1.6 * STEPSIZE; /* vertical notch */
+                       } else {
+                               horfn = 1.5 * STEPSIZE; /* horizontal notch */
+                               verfn = 2.8 * STEPSIZE; /* vertical notch */
+                       }
+                       if (note_p->notesize == GS_SMALL) {
+                               horfn *= SM_FACTOR;
+                               verfn *= SM_FACTOR;
+                       }
+                       if (note_p->acc_has_paren) {
+                               size = (note_p->notesize == GS_NORMAL ?
+                                               DFLT_SIZE : SMALLSIZE);
+                               horfn += width(FONT_TR, size, ')');
+                       }
+                       savehorfn = horfn;      /* may need it later */
+                       /*
+                        * If notch width is bigger than the max possible dist
+                        * we could move the acc (we would overwrite the note),
+                        * reduce it to be the space available.
+                        */
+                       if (horfn > - east - halfwide - STDPAD)
+                               horfn = - east - halfwide - STDPAD;
+
+                       /* only attempt the shift if > 0 width available */
+                       if (horfn > 0.0) {
+                               /*
+                                * The useable notch size is horfn by verfn.
+                                * We'd like to move the acc to the right by
+                                * horfn.  We can only do this if the space is
+                                * unoccupied that is immediately to the right
+                                * of the acc, of width = horfn and height =
+                                * (height of acc) - verfn.  (If only part of
+                                * that space is available, we won't bother
+                                * trying to use it.)  So check whether any
+                                * existing rectangle overlaps that space.
+                                */
+                               overlap = NO;
+                               for (j = 0; j < reclim; j++) {
+                                       if (rectab[j].s + FUDGE <= north - verfn &&
+                                           rectab[j].n - FUDGE >= south &&
+                                           rectab[j].w + FUDGE <= east + horfn &&
+                                           rectab[j].e - FUDGE >= east) {
+                                               overlap = YES;
+                                               break;
+                                       }
+                               }
+                               /*
+                                * If the space is free, move the acc to the
+                                * right by HORFN.
+                                */
+                               if (overlap == NO) {
+                                       west += horfn;
+                                       east += horfn;
+                               } else {
+                                       /*
+                                        * All right, let's try again with 1/2
+                                        * of the previous horfn.
+                                        */
+                                       horfn /= 2.0;
+                                       overlap = NO;
+                                       for (j = 0; j < reclim; j++) {
+                                               if (rectab[j].s + FUDGE <= north - verfn &&
+                                                   rectab[j].n - FUDGE >= south &&
+                                                   rectab[j].w + FUDGE <= east + horfn &&
+                                                   rectab[j].e - FUDGE >= east) {
+                                                       overlap = YES;
+                                                       break;
+                                               }
+                                       }
+                                       if (overlap == NO) {
+                                               west += horfn;
+                                               east += horfn;
+                                       }
+                               }
+                       }
+               }
+
+               /*
+                * We have the final position for the new acc.  Enter it into
+                * rectab.  But for naturals, we don't want to reserve the
+                * lower left corner, where there is nothing but white space;
+                * so in that case, put two overlapping entries in rectab to
+                * account for the rest of the space.  Naturals are symmetrical,
+                * so we can use the same horfn and verfn as were calculated
+                * above for the upper right corner.
+                */
+               if (note_p->accidental == 'n') {
+                       /* upper part of natural */
+                       rectab[reclim].n = north;
+                       rectab[reclim].s = south + verfn;
+                       rectab[reclim].e = east;
+                       rectab[reclim].w = west;
+                       reclim++;
+
+                       /* right hand part of natural */
+                       rectab[reclim].n = north;
+                       rectab[reclim].s = south;
+                       rectab[reclim].e = east;
+                       rectab[reclim].w = west + savehorfn;
+               } else {
+                       /* some other accidental; reserve the whole rectangle*/
+                       rectab[reclim].n = north;
+                       rectab[reclim].s = south;
+                       rectab[reclim].e = east;
+                       rectab[reclim].w = west;
+               }
+               reclim++;
+
+               /*
+                * Store the acc's west in waccr in the NOTE structure for
+                * whichever groups have this note.  Store wlparen when there
+                * is a left paren on the note.
+                */
+               if (noteptrs[k].top_p != 0) {
+                       if (note_p->note_has_paren == YES)
+                               noteptrs[k].top_p->wlparen = west;
+                       if (note_p->accidental != '\0')
+                               noteptrs[k].top_p->waccr = west + parenwidth;
+               }
+               if (noteptrs[k].bot_p != 0) {
+                       if (note_p->note_has_paren == YES)
+                               noteptrs[k].bot_p->wlparen = west;
+                       if (note_p->accidental != '\0')
+                               noteptrs[k].bot_p->waccr = west + parenwidth;
+               }
+
+       } /* end of loop for each accidental */
+
+       /*
+        * Finally, if the stems were collinear, we have to adjust waccr for
+        * all the notes of the top group, so that it's relative to the top
+        * group instead of the bottom group.
+        */
+       if (collinear) {
+               for (k = 0; noteptrs[k].top_p != 0; k++) {
+                       if (noteptrs[k].top_p->note_has_paren == YES)
+                               noteptrs[k].top_p->wlparen += 2 * halfwide
+                                               - W_NORMAL * POINT;
+                       if (noteptrs[k].top_p->accidental != '\0')
+                               noteptrs[k].top_p->waccr += 2 * halfwide
+                                               - W_NORMAL * POINT;
+               }
+       }
+}
+\f
+/*
+ * Name:       nextacc()
+ *
+ * Abstract:   Find the next note that has an accidental to be processed.
+ *
+ * Returns:    Index to the NOTE, or -1 if no more.
+ *
+ * Description:        This function is called by doacc(), to return in the correct
+ *             order the notes that have accidentals to be processed.
+ *             (Actually, a note is to be processed not only if it has an
+ *             accidental, but also if it has parentheses.)  The first time in
+ *             here, count is 0, and it looks for the first eligible note (top
+ *             down).  The next time, count is 1, and it looks for the bottom-
+ *             most eligible note.  After that, it goes through the inner
+ *             notes, top down.  In the great majority of cases, this will
+ *             result in the most desirable packing of accidentals.
+ */
+
+static int
+nextacc(noteptrs, found)
+
+struct NOTEPTRS noteptrs[];    /* array of ptrs to notes to process */
+int found;                     /* no. of accidentals found already */
+
+{
+       struct NOTE *note_p;    /* point at a note */
+       static int previdx;     /* idx to note chosen the last time in here */
+       static int lastidx;     /* idx to the bottommost note chosen */
+       int n;                  /* loop counter */
+
+
+       /*
+        * If this is the first call for this group(s), find the topmost
+        * eligible note.
+        */
+       if (found == 0) {
+               for (n = 0; (note_p = GETPTR(n)) != 0; n++) {
+                       if (note_p->accidental != '\0' ||
+                                       note_p->note_has_paren == YES) {
+                               previdx = n;    /* remember it for next time */
+                               return (n);
+                       }
+               }
+               return (-1);    /* no notes have acc or parens */
+       }
+
+       /*
+        * If this is the second call, find the bottom of the list, then look
+        * backwards for the last eligible note.  Stop before finding the first
+        * note again.
+        */
+       if (found == 1) {
+               /* find the slot beyond the last note */
+               for (n = 0; (note_p = GETPTR(n)) != 0; n++) {
+                       ;
+               }
+               /* search from last note going backwards */
+               for (n-- ; n > previdx; n--) {
+                       note_p = GETPTR(n);
+                       if (note_p->accidental != '\0' ||
+                                       note_p->note_has_paren == YES) {
+                               lastidx = n;    /* remember it for next time */
+                               return (n);
+                       }
+               }
+               return (-1);    /* only 1 note has acc or parens */
+       }
+
+       /*
+        * Third or later call:  Scan inner notes top to bottom.
+        */
+       for (n = previdx + 1; n < lastidx; n++) {
+               note_p = GETPTR(n);
+               if (note_p->accidental != '\0' ||
+                               note_p->note_has_paren == YES) {
+                       previdx = n;
+                       return (n);
+               }
+       }
+       return (-1);            /* all eligible notes were already found */
+}
+\f
+/*
+ * Name:        dodot()
+ *
+ * Abstract:    Finds horizontal and vertical positions of dots.
+ *
+ * Returns:     void
+ *
+ * Description: This function figures out the limitations on where dots
+ *             can be put, for each group, and calls dogrpdot() for each
+ *             group that has dots, to figure their positions.
+ */
+
+static void
+dodot(staff_p, gs1_p, gs2_p, halfwide, collinear)
+
+struct STAFF *staff_p;         /* the staff the groups are connected to */
+register struct GRPSYL *gs1_p, *gs2_p; /* point at group(s) in this hand */
+double halfwide;                       /* half of max of width of notes */
+int collinear;                         /* are stems collinear? */
+
+{
+       /* the highest and lowest values of steps above the middle staff */
+       /* line that a dot is allowed to be for the given group */
+       int uppermost, lowermost;
+
+       int lowtopidx;          /* index to lowest note of top group */
+       int push;               /* steps to protruding note */
+       register int k;         /* loop variable */
+
+
+       lowtopidx = gs1_p->nnotes - 1;  /* for convenience */
+
+       /*
+        * For each group that needs dots, set the outer limits of where
+        * they are allowed.  If the other group doesn't need dots, we
+        * have to be careful to keep them out of its way.  Otherwise,
+        * don't worry about that; let them fall on top of each other if
+        * that would happen.
+        */
+
+       /*
+        * If the first group needs dots, find out how high and low they are
+        * allowed to be.  Also find out if nearby notes in the other group
+        * could be in the way of dots.  Call dogrpdot() with this info to
+        * find their positions.
+        */
+       if (gs1_p->dots > 0) {
+               /* upper limit is always as described above */
+               uppermost = gs1_p->notelist[0].stepsup;
+               if (uppermost % 2 == 0)         /* line note */
+                       uppermost++;
+
+               /* set lower limit as if no other group */
+               lowermost = gs1_p->notelist[lowtopidx].stepsup;
+               if (lowermost % 2 == 0)         /* line note */
+                       lowermost--;
+
+               /* but adjust if the other group exists & would interfere */
+               if (gs2_p != 0 && gs2_p->dots == 0 || collinear) {
+                       if (lowermost <= gs2_p->notelist[0].stepsup)
+                               lowermost += 2;
+               }
+
+               /*
+                * If the stems are collinear, bottom group notes that are
+                * in normal position for that group protrude to the right
+                * relative to the top group.  From top down, search for notes
+                * in the bottom group that are like this.  Set push to the
+                * first one.  If none are found, let push be 1000 to be out of
+                * the way.  In setting horizontal dot positions, dogrpdot()
+                * needs to know this.
+                */
+               push = 1000;
+               if ( gs2_p != 0 && collinear ) {
+                       for (k = 0; k < gs2_p->nnotes; k++) {
+                               if (gs2_p->notelist[k].c[RX] == 0) {
+                                       push = gs2_p->notelist[k].stepsup;
+                                       break;
+                               }
+                       }
+               }
+
+               /* do top group's dots */
+               dogrpdot(staff_p, gs1_p, (struct GRPSYL *)0, halfwide,
+                               uppermost, lowermost, push);
+       }
+
+       /*
+        * If the second group exists and needs dots, find out how high and
+        * low they are allowed to be, and find their positions.
+        */
+       if (gs2_p != 0 && gs2_p->dots > 0) {
+               /* set upper limit as if no other group */
+               uppermost = gs2_p->notelist[0].stepsup;
+               if (uppermost % 2 == 0)         /* line note */
+                       uppermost++;
+
+               /* but adjust if the other group would interfere */
+               if (gs1_p->dots == 0 || collinear) {
+                       if (uppermost >= gs1_p->notelist[lowtopidx].stepsup)
+                               uppermost -= 2;
+               }
+
+               /* lower limit is always as described above */
+               lowermost = gs2_p->notelist[ gs2_p->nnotes - 1 ].stepsup;
+               if (lowermost % 2 == 0)         /* line note */
+                       lowermost--;
+
+               /*
+                * Unless the stems are collinear, in which case no problem,
+                * from bottom up, search for notes in the top group that
+                * protrude towards the right.  Set push to the first one.
+                * If none are found, let push be 1000 to be out of the way.
+                * In setting horizontal dot positions, dogrpdot() needs to
+                * know this.
+                */
+               push = 1000;
+               if ( ! collinear ) {
+                       for (k = lowtopidx; k >= 0; k--) {
+                               if (gs1_p->notelist[k].c[RX] > 0) {
+                                       push = gs1_p->notelist[k].stepsup;
+                                       break;
+                               }
+                       }
+               }
+
+               /* do bottom group's dots */
+               dogrpdot(staff_p, gs2_p, gs1_p, halfwide, uppermost, lowermost,
+                               push);
+       }
+}
+\f
+/*
+ * Name:        dogrpdot()
+ *
+ * Abstract:    Finds horizontal and vertical positions of dots for one group.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through all the notes belonging to the
+ *             given group, setting the coords of the dots relative to it.
+ */
+
+/* recover dotsteps from ydotr, avoiding roundoff error */
+#define        DOTSTEPS(ydotr) (                               \
+       ydotr > 0.0 ?                                   \
+               (int)((ydotr + 0.001) / STEPSIZE)       \
+       :                                               \
+               -(int)((-ydotr + 0.001) / STEPSIZE)     \
+)
+
+static void
+dogrpdot(staff_p, gs_p, ogs_p, halfwide, uppermost, lowermost, push)
+
+struct STAFF *staff_p;         /* the staff the groups are connected to */
+register struct GRPSYL *gs_p;  /* point at group */
+struct GRPSYL *ogs_p;          /* if we're doing group 1 and 2 together, and
+                                * gs_p is group 2, ogs_p is group 1, else 0 */
+double halfwide;               /* half of max of width of notes */
+int uppermost;                 /* highest step where a dot is permitted */
+int lowermost;                 /* lowest step where a dot is permitted */
+int push;                      /* avoid protruding note at this position */
+
+{
+       float dotwidth;         /* width of a dot (includes padding) */
+       int normhorz;           /* use normal horizontal dot position? */
+       int notesteps;          /* steps note is above center line of staff */
+       int dotsteps;           /* steps dot is above center line of staff */
+       register int n, k;      /* loop variables */
+
+
+       /* until proven otherwise, assume normal horizontal dot position */
+       normhorz = YES;
+
+       /*
+        * The rules for vertical positioning of dots are as follows.
+        * For space notes, dots will be put in the same space.  For line
+        * notes we'd like them to be in the space directly above, except for
+        * voice 2 in vscheme=2o,3o or 2f,3f when voice 1 is not space, in
+        * which case we'd like them to be in the space below.  But if notes in
+        * a group are jammed onto neighboring steps, we may need to put some
+        * line note dots on the space below regardless; and we may
+        * even have to let some dots land on top of each other.  But in
+        * any case, never exceed the uppermost/lowermost bounds, which
+        * would interfere with the other group.
+        *
+        * The rules for horizontal positioning of dots are as follows.
+        * If the note on the dot's space, or either neighboring line,
+        * is in abnormal position to the right, the dot must be put
+        * farther right than normal.  The parameter "push" is the nearest
+        * note from the other group that protrudes this way.  And the dots
+        * of all the notes have to line up, so if any one has this problem,
+        * they must all be moved.
+        */
+
+       /*
+        * Loop through all notes in the group, setting dot positions.  At
+        * the top of the loop, "dotsteps" is the previous dot, but by the
+        * end it gets set to the current dot.
+        */
+       dotsteps = uppermost + 2;       /* pretend previous dot was here */
+
+       for (n = 0; n < gs_p->nnotes; n++) {
+
+               notesteps = gs_p->notelist[n].stepsup;
+
+               if (notesteps % 2 == 0) {
+                       /*
+                        * This note is on a line.  If the dot cannot be put
+                        * above the line, or if doing that would overlay the
+                        * previous dot and we are allowed to put it below
+                        * the line, then put it below the line.  Else, put
+                        * it above the line.  Notice that we're putting the
+                        * dot in the space above if at all possible; later on,
+                        * we'll make adjustments for voice 2 if appropriate.
+                        */
+                       if (notesteps + 1 > uppermost ||
+                          (notesteps + 1 == dotsteps &&
+                           notesteps - 1 >= lowermost)) {
+                               dotsteps = notesteps - 1;
+                       } else {
+                               dotsteps = notesteps + 1;
+                       }
+               } else {
+                       /*
+                        * This note is on a space.  The dot must be put in
+                        * this same space, regardless of anything else.
+                        */
+                       dotsteps = notesteps;
+               }
+
+               /* set relative y coord based on step position */
+               gs_p->notelist[n].ydotr = dotsteps * STEPSIZE;
+
+               /*
+                * Now see if this dot forces abnormal positioning.  "Push" may
+                * indicate a protruding note in the other group.  If this
+                * note is within 1 step of our dot, use abnormal positioning
+                * for the dot.  Else if the stem is down, all dots can be
+                * normal.  Else, we have to search for protruding notes to
+                * see where the dot can be.
+                */
+               if (normhorz == YES) {
+                       if (abs(dotsteps - push) <= 1) {
+                               normhorz = NO;
+                       } else if (gs_p->stemdir == UP) {
+                               for (k = 0; k < gs_p->nnotes; k++) {
+                                       notesteps = gs_p->notelist[k].stepsup;
+
+                                       if (gs_p->notelist[k].c[RE] >halfwide &&
+                                           notesteps <= dotsteps + 1 &&
+                                           notesteps >= dotsteps - 1) {
+
+                                               normhorz = NO;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /*
+        * Set horizontal dot positions, relative to the group.  STDPAD is
+        * needed because notehead characters don't include padding.  The
+        * abnormal case adds in one more notehead width, minus the width
+        * of the stem.  Since the dots for all notes line up vertically,
+        * xdotr is in GRPSYL instead of in each NOTE.
+        */
+       dotwidth = width(FONT_MUSIC, DFLT_SIZE, C_DOT);
+       gs_p->xdotr = halfwide + STDPAD + dotwidth / 2;
+       if (normhorz == NO) {
+               gs_p->xdotr += 2 * halfwide - W_NORMAL * POINT;
+       }
+
+       /*
+        * If this is voice 2, we may need to adjust the vertical position of
+        * nonshared line notes.  The same should happen if this is voice 3
+        * "standing in" for voice 2.
+        */
+       if (gs_p->pvno == 2) {
+               int trymove;            /* try to move dots? */
+               int vscheme;            /* voice scheme */
+               RATIONAL vtime;         /* time so far in this measure */
+               int prevdotsteps;       /* Y distance of prev note's dot */
+               struct GRPSYL *pgs_p;   /* point along GRPSYL list */
+               int onotesteps;         /* lowest note of voice 1 */
+
+               trymove = NO;           /* first assume leave them alone */
+               vscheme = svpath(gs_p->staffno, VSCHEME)->vscheme;
+               if (vscheme == V_2OPSTEM || vscheme == V_3OPSTEM) {
+                       /* always try to move if 2o or 3o */
+                       trymove = YES;
+               } else {
+                       /* 2f or 3f; move iff voice 1 is not all spaces here */
+                       vtime = Zero;   /* add up time of preceding groups */
+                       for (pgs_p = gs_p->prev; pgs_p != 0;
+                                       pgs_p = pgs_p->prev) {
+                               vtime = radd(vtime, pgs_p->fulltime);
+                       }
+                       if ( ! hasspace(staff_p->groups_p[0], vtime,
+                                       radd(vtime, gs_p->fulltime))) {
+                               /* not all space during duration of our group*/
+                               trymove = YES;
+                       }
+               }
+
+               if (trymove == YES) {
+                       /*
+                        * We need to try to move the dots of line notes from
+                        * the space above them to the space below them.  We
+                        * will work from bottom to top.  Initially, pretend
+                        * that the previous note is way low out of the way.
+                        * If a voice 1 group was being handled along with our
+                        * group, find the stepsup of its lowest note.
+                        */
+                       prevdotsteps = -1000;
+                       if (ogs_p != 0) {
+                               onotesteps = ogs_p->notelist[
+                                               ogs_p->nnotes - 1].stepsup;
+                       } else {
+                               onotesteps = 0; /* for lint; set before used */
+                       }
+                       for (n = gs_p->nnotes - 1; n >= 0; n--) {
+                               notesteps = gs_p->notelist[n].stepsup;
+                               /*
+                                * We want to stop if we run into notes shared
+                                * by group 1 if it exists.  ( > is defensive).
+                                */
+                               if (ogs_p != 0 && notesteps >= onotesteps)
+                                       break;
+                               /*
+                                * Recover our dotsteps from our dots coord
+                                * calculated earlier in this function.  Then,
+                                * consider moving our dot only if we are a
+                                * line note and our dot is currently in the
+                                * space above.  (It could already be below,
+                                * do to tightly packed notes.)
+                                */
+                               dotsteps = DOTSTEPS(gs_p->notelist[n].ydotr);
+                               if (notesteps % 2 == 0 &&
+                                               dotsteps == notesteps + 1) {
+                                       /*
+                                        * If the previous (lower) note is at
+                                        * least 2 steps away, we can certainly
+                                        * move our dot.  But also move it if
+                                        * we are the top note of group 2, and
+                                        * group 1 exists and has a note 2 steps
+                                        * away, and they don't have a dot at
+                                        * the same horz position; because our
+                                        * dot would be confusing if above.  If
+                                        * it make our dot land on top of the
+                                        * previous note's dot, tough.
+                                        */
+                                       if (prevdotsteps < notesteps - 1 ||
+                                           n == 0 && ogs_p != 0 &&
+                                           notesteps + 2 == onotesteps &&
+                                           ogs_p->xdotr != gs_p->xdotr) {
+
+                                               dotsteps -= 2;
+                                               gs_p->notelist[n].ydotr -=
+                                                       2.0 * STEPSIZE;
+                                       }
+                               }
+                               prevdotsteps = dotsteps;
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        westwith()
+ *
+ * Abstract:    Adjust west coord of a group to allow for its "with" lists.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given a GRPSYL whose relative horizontal
+ *             coords are set, relative to the center of the group, except
+ *             that "with" lists have not yet been considered.  It alters
+ *             gs_p->c[RW] if need be so that the group's rectangle includes
+ *             all "with" lists.
+ */
+
+static void
+westwith(gs_p)
+
+struct GRPSYL *gs_p;           /* point at this group */
+
+{
+       int n;                  /* loop through the "with" list items */
+       int font, size;         /* of the chars in the "with" list item */
+       int first_char;         /* first char of string to print */
+       char *str_p;            /* point into the item */
+       float x_offset;         /* half the width of the first char in item */
+
+
+       for (n = 0; n < gs_p->nwith; n++) {
+               /* should center first character on x */
+               font = gs_p->withlist[n][0];
+               size = gs_p->withlist[n][1];
+               str_p = gs_p->withlist[n] + 2;
+               first_char = next_str_char(&str_p, &font, &size);
+               x_offset = width(font, size, first_char) / 2.0;
+               if (-x_offset < gs_p->c[RW])
+                       gs_p->c[RW] = -x_offset;
+       }
+}
+\f
+/*
+ * Name:        eastwith()
+ *
+ * Abstract:    Adjust east coord of a group to allow for its "with" lists.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given a GRPSYL whose relative horizontal
+ *             coords are set, relative to the center of the group, except
+ *             that "with" lists have not yet been considered.  It alters
+ *             gs_p->c[RE] if need be so that the group's rectangle includes
+ *             all "with" lists.
+ */
+
+static void
+eastwith(gs_p)
+
+struct GRPSYL *gs_p;           /* point at this group */
+
+{
+       int n;                  /* loop through the "with" list items */
+       int font, size;         /* of the chars in the "with" list item */
+       int first_char;         /* first char of string to print */
+       char *str_p;            /* point into the item */
+       float x_offset;         /* half the width of the first char in item */
+
+
+       for (n = 0; n < gs_p->nwith; n++) {
+               /* should center first character on x */
+               font = gs_p->withlist[n][0];
+               size = gs_p->withlist[n][1];
+               str_p = gs_p->withlist[n] + 2;
+               first_char = next_str_char(&str_p, &font, &size);
+               x_offset = strwidth(gs_p->withlist[n]) -
+                               width(font, size, first_char) / 2.0;
+               if (x_offset > gs_p->c[RE])
+                       gs_p->c[RE] = x_offset;
+       }
+}
+\f
+/*
+ * Name:        csbstempad()
+ *
+ * Abstract:    Pad a group's RW for cross staff beaming if need be.
+ *
+ * Returns:     void
+ *
+ * Description: In cross staff beamed groups, where the beams are between the
+ *             staffs, and a note on the bottom staff is followed by a note on
+ *             the top staff, and the first note has no dots or anything else
+ *             that would force more space after it, and the top note has no
+ *             accidentals, graces, or anything that would force more space
+ *             before it, the stems of the two groups can be very close
+ *             together, too close.  This function checks for that case, and
+ *             when found, adds padding to the left of the top group.
+ */
+
+static void
+csbstempad(mll_p, gs_p)
+
+struct MAINLL *mll_p;          /* the MLL item the group is connected to */
+struct GRPSYL *gs_p;           /* point at the top staff's group */
+
+{
+       struct GRPSYL *gs2_p;           /* point at various GRPSYLs */
+       struct CHORD *ch_p, *pch_p;     /* our chord and preceding chord */
+       struct MAINLL *m2_p;            /* loop through MLL */
+       int k;                          /* loop through notelist */
+       int found;                      /* have we found our group? */
+
+
+       /* if this group is not a candidate for this, return */
+       if (gs_p->beamto != CS_BELOW)   /* must be CSB beamed with below */
+               return;
+       if (gs_p->stemdir == UP)        /* stem must be down */
+               return;
+       if (gs_p->beamloc == STARTITEM) /* must not be first item in CSB */
+               return;
+       if (gs_p->prev == 0)            /* (defensive) */
+               return;
+       if (gs_p->prev->grpcont != GC_SPACE)    /* prev must be a space */
+               return;
+
+       /*
+        * The notes should all have the same RW (even cues) unless a note is
+        * on the "wrong" side of the stem, because they are all supposed to
+        * touch the stem.  In the latter case, there's already enough space in
+        * the group to the left of the stem, so return.
+        */
+       for (k = 1; k < gs_p->nnotes; k++) {
+               if (ABSDIFF(gs_p->notelist[k].c[RW], gs_p->notelist[0].c[RW])
+                               > FUDGE)
+                       return;
+       }
+
+       /*
+        * If there's anything to the left of the notes' RWs (the stem
+        * position), it should be enough space, so return.
+        */
+       if (gs_p->c[RW] < gs_p->notelist[0].c[RW] - STDPAD - FUDGE)
+               return;
+
+       /* find the chord headcell for this measure */
+       for (m2_p = mll_p->prev; m2_p->str != S_CHHEAD; m2_p = m2_p->prev)
+               ;
+       /*
+        * Loop through the chords.  For each chord, loop through all its
+        * groups, trying to find our group.  It should be found.  At the point
+        * it is found, pch_p will point to the chord preceding the one that
+        * contains our group.
+        */
+       found = NO;
+       pch_p = 0;      /* to avoid useless 'used before set' warning */
+       for (ch_p = m2_p->u.chhead_p->ch_p; ch_p != 0;
+                               pch_p = ch_p, ch_p = ch_p->ch_p) {
+               for (gs2_p = ch_p->gs_p; gs2_p != 0; gs2_p = gs2_p->gs_p) {
+                       if (gs2_p == gs_p) {
+                               found = YES;
+                               break;
+                       }
+               }
+               if (found == YES)
+                       break;
+       }
+       if (found == NO)        /* defensive; this should never happen */
+               return;
+
+       /* find next visible staff after our staff */
+       for (m2_p = mll_p->next; m2_p->str == S_STAFF &&
+                       m2_p->u.staff_p->visible == NO; m2_p = m2_p->next)
+               ;
+       if (m2_p->str != S_STAFF)       /* defensive; should not happen */
+               return;
+
+       /*
+        * Loop down the preceding chord, looking for a group that is on the
+        * next visible staff after our staff and is CSB'ed to the staff above.
+        */
+       for (gs2_p = pch_p->gs_p; gs2_p != 0; gs2_p = gs2_p->gs_p) {
+
+               if (gs2_p->staffno == m2_p->u.staff_p->staffno &&
+                               gs2_p->beamto == CS_ABOVE) {
+                       /*
+                        * We found such a group; it must be the only one.
+                        * Check that it meets the conditions.
+                        */
+                       if (gs2_p->stemdir == DOWN)
+                               return;
+                       /*
+                        * The notes need to all have the same RE, analogous to
+                        * the earlier check on gs_p's RW.
+                        */
+                       for (k = 1; k < gs2_p->nnotes; k++) {
+                               if (ABSDIFF(gs2_p->notelist[k].c[RE], gs2_p->
+                                               notelist[0].c[RE]) > FUDGE)
+                                       return;
+                       }
+                       /*
+                        * If there's anything to the right of the notes' REs,
+                        * there's already enough space.
+                        */
+                       if (gs2_p->c[RE] > gs2_p->notelist[0].c[RE] +
+                                       STDPAD + FUDGE)
+                               return;
+
+                       /*
+                        * FINALLY!  We have established the need for more
+                        * space.  Append it to our group's RW.
+                        */
+                       gs_p->c[RW] -= STEPSIZE;
+                       return;
+               }
+       }
+
+       /* didn't find one; shouldn't happen, but just return */
+}
+\f
+/*
+ * Name:        proctab()
+ *
+ * Abstract:    Sets relative horizontal coords of fret numbers.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets all the horizontal coords of "notes" on a
+ *             tablature staff, which are actually fret numbers.  It sets RW
+ *             and RE for the group, too.  They also take bends into account.
+ */
+
+static void
+proctab(mll_p, staff_p, gs_p)
+
+struct MAINLL *mll_p;          /* the MLL item the group is connected to */
+struct STAFF *staff_p;         /* the staff the group is connected to */
+struct GRPSYL *gs_p;           /* point at this group */
+
+{
+       int n;                  /* loop through the "notes" in the group */
+       float halfwide;         /* half the width of a fret or bend number */
+       float maxhalffret;      /* half the max width of a fret number */
+       float maxhalfbend;      /* half the max width of a bend number */
+       float maxbend;          /* width of a bend number that sticks right */
+       struct GRPSYL *prevgs_p;/* point at previous group */
+       int center;             /* should bend string be centered? */
+       int k;                  /* loop variable */
+
+
+       maxhalffret = 0.0;
+       maxhalfbend = 0.0;
+       maxbend = 0.0;
+
+       prevgs_p = prevgrpsyl(gs_p, &mll_p);    /* in case we need it */
+
+       /* loop though all frets and bends in this group */
+       for (n = 0; n < gs_p->nnotes; n++) {
+               /*
+                * If there is a fret, find half the width of that number.  It
+                * should be centered on the center of the group.  Keep track
+                * of the maximum width so far.  Allow 1.5*STDPAD on each side
+                * of the fret number, since we don't ever want the numbers so
+                * close that they look like one number.
+                */
+               if (gs_p->notelist[n].FRETNO != NOFRET) {
+                       halfwide = strwidth(fret_string(&gs_p->notelist[n],
+                                       gs_p)) / 2.0;
+                       gs_p->notelist[n].c[RX] = 0.0;
+                       gs_p->notelist[n].c[RE] = halfwide;
+                       gs_p->notelist[n].c[RW] = -halfwide;
+                       maxhalffret = MAX(halfwide + 1.5*STDPAD, maxhalffret);
+               }
+
+               /*
+                * If there is a bend, figure out if it's the normal situation
+                * (centered on the group's X) or the the case where its left
+                * edge should be at the group's X (the case of a continuation
+                * bend where the previous group's bend was higher).  In the
+                * latter case, the string had to be shifted to avoid colliding
+                * with the arrow coming down from the previous group.
+                */
+               if (HASREALBEND(gs_p->notelist[n])) {
+                       center = YES;   /* first assume normal */
+
+                       /* search previous group, if any, for a bend */
+                       if (prevgs_p != 0) {
+                               for (k = 0; k < prevgs_p->nnotes; k++) {
+                                       if (HASREALBEND(prevgs_p->notelist[k]))
+                                               break;
+                               }
+                               /*
+                                * If previous group had a bend and its
+                                * distance was higher than the current group,
+                                * we have the special case.
+                                */
+                               if (k < prevgs_p->nnotes &&
+                                   GT( ratbend(&prevgs_p->notelist[k]),
+                                   ratbend(&gs_p->notelist[n]) ) ) {
+                                       center = NO;
+                               }
+                       }
+                       if (center == YES) {
+                               /*
+                                * Normal case of a bend string: centered at
+                                * group's X.  Maintain maxhalfbend as the
+                                * the widest so far.
+                                */
+                               halfwide = strwidth(bend_string(
+                                               &gs_p->notelist[n])) / 2.0;
+                               maxhalfbend = MAX(halfwide, maxhalfbend);
+                       } else {
+                               /*
+                                * A bend string that has its left edge at the
+                                * group's X.  There can only be one such,
+                                * since multiple continuation bends are not
+                                * allowed (other than releases).
+                                */
+                               maxbend = strwidth(bend_string(
+                                               &gs_p->notelist[n]));
+                       }
+               }
+       }
+
+       /*
+        * Set the group's relative horizontal coordinates.  On the east, add
+        * extra room if there are ties or slurs.  On the west, add any user
+        * requested padding.  Also adjust for "with" lists.  They can extend
+        * into tie/slur padding, but not into user requested padding.
+        */
+       gs_p->c[RX] = 0.0;
+
+       gs_p->c[RW] = -MAX(maxhalffret, maxhalfbend);
+       westwith(gs_p);
+       gs_p->c[RW] -= gs_p->padding;
+       gs_p->c[RW] -= vvpath(gs_p->staffno, gs_p->vno, PAD)->pad;
+
+       maxhalffret += tieslurpad(staff_p, gs_p);
+       gs_p->c[RE] = MAX(MAX(maxhalffret, maxhalfbend), maxbend);
+       eastwith(gs_p);
+}
+\f
+/*
+ * Name:        noterparen()
+ *
+ * Abstract:    Finds horizontal position notes' right parentheses.
+ *
+ * Returns:     void
+ *
+ * Description: If any of the notes in the given group(s) are to have
+ *             parentheses around them, this function finds the horizontal
+ *             positions of the right parentheses.  The left ones were done
+ *             in doacc() along with accidentals.  For each group, it uses
+ *             the appropriate size of parentheses (based on normal versus
+ *             cue/grace), and places them appropriately, considering also
+ *             the size of the notes.  However, if there are two groups,
+ *             the note head sizes could be different.  The halfwide and
+ *             halfhigh passed in are supposed to be the right size for the
+ *             bigger of the two sizes, and accidentals will not be packed
+ *             as tightly against the other notes.  This doesn't hurt, and
+ *             isn't worth the trouble to do it "right".
+ */
+
+static void
+noterparen(noteptrs, gs1_p, gs2_p, halfwide, halfhigh, collinear)
+
+struct NOTEPTRS noteptrs[];    /* array of ptrs to notes to process */
+struct GRPSYL *gs1_p, *gs2_p;  /* point at group(s) in this hand */
+double halfwide;               /* half of max of width & height of (notes */
+double halfhigh;               /*  in group 1, notes in group 2) */
+int collinear;                 /* are stems collinear? */
+
+{
+       /*
+        * Each structure in this table represents either a note head that is
+        * farther right than normal, note dot(s), or right paren.  A note head
+        * could be too far right for one of two reasons: either it was
+        * forced to be on the right ("wrong") side of a stem that points
+        * up, or it is a normal note in the bottom group when the stems are
+        * collinear.  In the collinear case, to make this function easier,
+        * we start out regarding the top group as being normal, and
+        * the bottom group as being shifted right one note head, and we figure
+        * everything relative to the top group.  But at the end we adjust
+        * so that every parenthesis is relative to its own group, like
+        * it's supposed to be.
+        *
+        * The coordinates define the rectangle that surrounds the note, dot(s),
+        * or paren, including standard padding, even on note heads, which don't
+        * normally have padding.  First the notes and dots are put into this
+        * table, just one rectangle for a sequence of dots; then the right
+        * parens one at a time, making sure they don't overlap things already
+        * in the table.
+        *
+        * To see if the parenthesis being added overlaps, first its north
+        * and south are tested.  All previous rectangles that are "out of
+        * its way" vertically are marked not "relevant"; the others are
+        * marked "relevant".  As positions are tried, left to right, positions
+        * that fail to avoid overlap are marked "tried".
+        */
+       struct {
+               float n, s, e, w;       /* boundaries of a rectangle */
+               short relevant;         /* is rectangle relevant? */
+               short tried;            /* have we tried this one yet? */
+       } rectab[2 * MAXHAND + 1];      /* enough for all notes & accidentals*/
+
+       struct NOTE *note_p;            /* point at a note */
+       int reclim;                     /* index after last rectangle in tab */
+       int parensexist;                /* does any note have parens? */
+       float north, south, east, west; /* relative coords of new accidental */
+       float parenwidth;               /* width of note's left parenthesis */
+       float parenv;                   /* half the vertical size of paren */
+       float dotoff;                   /* additional offset caused by dots */
+       float dotoff1, dotoff2;         /* same, for groups 1 and 2 */
+       int overlap;                    /* does our acc overlap existing ones*/
+       int try;                        /* which element of rectab to try */
+       int k, j;                       /* loop variables */
+       int size;
+
+
+       /*
+        * If no notes have parentheses, we can get out because there is
+        * nothing to do.
+        */
+       parensexist = NO;               /* init to no parens */
+       for (k = 0; (note_p = GETPTR(k)) != 0; k++) {
+               if (note_p->note_has_paren == YES)
+                       parensexist = YES;
+       }
+       if (parensexist == NO)
+               return;
+
+       reclim = 0;                     /* table initially empty */
+
+       /* set up dot offsets for both groups, zero if no dots */
+       dotoff1 = gs1_p->dots * (width(FONT_MUSIC,DFLT_SIZE,C_DOT) + 2*STDPAD);
+       dotoff2 = 0.0;          /* prevent useless 'used before set' warning */
+       if (gs2_p != 0) {
+               dotoff2 = gs2_p->dots * (width(FONT_MUSIC, DFLT_SIZE, C_DOT) +
+                               2 * STDPAD);
+       }
+
+       /*
+        * Loop through noteptrs, loading rectab with all the things that are
+        * already present that are to the right of the baseline.
+        */
+       for (k = 0; (note_p = GETPTR(k)) != 0; k++) {
+               /*
+                * If note exists in top group, use its dot offset, else use
+                * bottom's.  If it's in both, the results would be the same.
+                */
+               if (noteptrs[k].top_p != 0)
+                       dotoff = dotoff1;
+               else
+                       dotoff = dotoff2;
+
+               /* if note is right of normal position, put it in the table */
+               if (note_p->c[RX] > 0) {
+                       rectab[reclim].n = note_p->c[RY] + halfhigh + STDPAD;
+                       rectab[reclim].s = note_p->c[RY] - halfhigh - STDPAD;
+                       rectab[reclim].e = note_p->c[RE] + STDPAD;
+                       rectab[reclim].w = note_p->c[RW] - STDPAD;
+                       reclim++;
+               }
+
+               /* if collinear, bottom group's notes go into table if normal */
+               if (collinear && noteptrs[k].bot_p != 0) {
+                       if (note_p->c[RX] == 0) {
+                               rectab[reclim].n = note_p->c[RY] + halfhigh
+                                               + STDPAD;
+                               rectab[reclim].s = note_p->c[RY] - halfhigh
+                                               - STDPAD;
+                               rectab[reclim].e = W_NORMAL * POINT
+                                               + 3 * halfwide + STDPAD;
+                               rectab[reclim].w = W_NORMAL * POINT
+                                               + halfwide - STDPAD;
+                               reclim++;
+                       }
+               }
+
+               /* if this group has dots, do rectangle for dots */
+               if (dotoff > 0) {
+                       rectab[reclim].n = note_p->ydotr + STDPAD;
+                       rectab[reclim].s = note_p->ydotr - STDPAD;
+                       if (noteptrs[k].top_p != 0)
+                               rectab[reclim].e = gs1_p->xdotr + dotoff;
+                       else
+                               rectab[reclim].e = gs2_p->xdotr + dotoff;
+                       rectab[reclim].w = 0;
+                       reclim++;
+               }
+       }
+
+       /*
+        * Loop through all parentheses, finding where they will fit, storing
+        * that info in erparen, and adding them to rectab.
+        */
+       for (k = 0; (note_p = GETPTR(k)) != 0; k++) {
+
+               /* if no parens around the note, skip the note */
+               if (note_p->note_has_paren == NO)
+                       continue;
+
+               /* get dimensions of note's right paren */
+               size = (note_p->notesize == GS_NORMAL ? DFLT_SIZE : SMALLSIZE);
+               parenwidth = width(FONT_TR, size, ')');
+               parenv = height(FONT_TR, size, ')') / 2.0;
+
+               /* set the north and south of the paren */
+               north = note_p->c[RY] + parenv;
+               south = note_p->c[RY] - parenv;
+
+               /*
+                * For each rectangle in rectab, decide whether (based on
+                * its vertical coords) it could possibly overlap with our
+                * new paren.  If it's totally above or below ours, it
+                * can't.  We allow a slight overlap (FUDGE) so that round
+                * off errors don't stop us from packing things as tightly
+                * as possible.
+                */
+               for (j = 0; j < reclim; j++) {
+                       if (rectab[j].s + FUDGE > north ||
+                           rectab[j].n < south + FUDGE)
+                               rectab[j].relevant = NO;
+                       else
+                               rectab[j].relevant = YES;
+               }
+
+               /*
+                * Mark that none of the relevant rectangles' boundaries have
+                * been tried yet for positioning our paren.
+                */
+               for (j = 0; j < reclim; j++) {
+                       if (rectab[j].relevant == YES)
+                               rectab[j].tried = NO;
+               }
+
+               /*
+                * Set up first trial position for this paren, just to the
+                * right of normal notes, allowing padding.
+                */
+               west = halfwide + STDPAD;
+               east = west + parenwidth;
+
+               /*
+                * Keep trying positions for this paren, working left to
+                * right.  When we find one that doesn't overlap an existing
+                * rectangle, break.  This has to succeed at some point,
+                * at the rightmost rectangle position if not earlier.
+                */
+               for (;;) {
+                       overlap = NO;
+                       for (j = 0; j < reclim; j++) {
+                               /* ignore ones too far north or south */
+                               if (rectab[j].relevant == NO)
+                                       continue;
+
+                               /* if all west or east, okay; else overlap */
+                               if (rectab[j].w + FUDGE <= east &&
+                                   rectab[j].e >= west + FUDGE) {
+                                       overlap = YES;
+                                       break;
+                               }
+                       }
+
+                       /* if no rectangle overlapped, we found a valid place*/
+                       if (overlap == NO)
+                               break;
+
+                       /*
+                        * Something overlapped, so we have to try again.
+                        * Find the westermost relevant east rectangle boundary
+                        * that hasn't been tried already, to use as the next
+                        * trial position for our paren's west.
+                        */
+                       try = -1;
+                       for (j = 0; j < reclim; j++) {
+                               /* ignore ones too far north or south */
+                               if (rectab[j].relevant == NO ||
+                                   rectab[j].tried == YES)
+                                       continue;
+
+                               /*
+                                * If this is the first relevant one we haven't
+                                * tried, or if this is farther west than the
+                                * westernmost so far, save it as being the
+                                * new westernmost so far.
+                                */
+                               if (try == -1 || rectab[j].e < rectab[try].e)
+                                       try = j;
+                       }
+
+                       if (try == -1)
+                               pfatal("bug in noterparen()");
+
+                       /*
+                        * Mark this one as having been tried (for next time
+                        * around, if necessary).  Set new trial values for
+                        * east and west of our paren.
+                        */
+                       rectab[try].tried = YES;
+                       west = rectab[try].e;
+                       east = west + parenwidth;
+
+               } /* end of while loop trying positions for this acc */
+
+               /*
+                * We have the final position for the new paren.  Enter it into
+                * rectab.  Store its east in erparen in the NOTE structure for
+                * whichever groups have this note.
+                */
+               rectab[reclim].n = north;
+               rectab[reclim].s = south;
+               rectab[reclim].e = east;
+               rectab[reclim].w = west;
+               reclim++;
+               if (noteptrs[k].top_p != 0) {
+                       noteptrs[k].top_p->erparen = east;
+               }
+               if (noteptrs[k].bot_p != 0) {
+                       noteptrs[k].bot_p->erparen = east;
+               }
+
+       } /* end of loop for each accidental */
+
+       /*
+        * Finally, if the stems were collinear, we have to adjust erparen for
+        * all the notes of the bottom group, so that it's relative to the
+        * bottom group instead of the top group.
+        */
+       if (collinear) {
+               for (k = 0; (note_p = GETPTR(k)) != 0; k++) {
+                       if (noteptrs[k].bot_p != 0) {
+                               noteptrs[k].bot_p->erparen -= 2 * halfwide
+                                               - W_NORMAL * POINT;
+                       }
+               }
+       }
+}
diff --git a/mup/mup/setnotes.c b/mup/mup/setnotes.c
new file mode 100644 (file)
index 0000000..47155b1
--- /dev/null
@@ -0,0 +1,1783 @@
+/* Copyright (c) 1995, 1996, 1997, 1998, 2000, 2001, 2003, 2004, 2005, 2006
+ * by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ * Name:       setnotes.c
+ *
+ * Description:        This file contains functions for setting relative vertical
+ *             locations of notes.  It also sets relative vertical locations
+ *             of the groups that contain notes, considering only the notes.
+ *             It also sets the directions of stems.
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+static void locnotes P((void));
+static void locllnotes P((struct MAINLL *mll_p, int v,
+               struct MAINLL *nextbar_p));
+static void chktabcollision P((struct GRPSYL *start_p));
+static void intertab P((struct GRPSYL *gs_p, struct MAINLL *mll_p));
+static void setstems P((void));
+static void setonestem P((struct GRPSYL *gs_p));
+static void setopstem P((struct GRPSYL *gs1_p, struct GRPSYL *gs2_p));
+static void setfreestem P((struct GRPSYL *gs1_p, struct GRPSYL *gs2_p));
+static void set1freestem P((struct GRPSYL *this_p, struct GRPSYL *other_p,
+               int stemdir));
+static void setbeamedstem P((struct GRPSYL *start_p, int stemdir));
+static void dobunch P((struct GRPSYL *start_p, struct GRPSYL *end_p));
+static void dograce P((struct GRPSYL *gs1_p, struct GRPSYL *gs2_p));
+static int setv3stem P((struct GRPSYL *gs_p, int stemdir));
+static int dov3bunch P((struct GRPSYL *start_p, struct GRPSYL *end_p,
+               int stemdir));
+static void setheads P((void));
+static void setvoiceheads P((struct MAINLL *mll_p, struct GRPSYL *gs_p,
+               int stafflines, short *shapes, int is_tab, int allx_hsi,
+               int sharps, int keylet));
+static void fixoneline P((void));
+\f
+/*
+ * Name:        setnotes()
+ *
+ * Abstract:    Sets the relative vert coords of each note, and stem dir.
+ *
+ * Returns:     void
+ *
+ * Description: This function calls subroutines to set the relative vertical
+ *             coordinates of each note and each note group (considering only
+ *             the note heads in it at this point), stem directions, and which
+ *             notehead characters to use.
+ */
+
+void
+setnotes()
+
+{
+       debug(16, "setnotes");
+
+       locnotes();
+       setstems();
+       setheads();
+       fixoneline();
+}
+\f
+/*
+ * Name:        locnotes()
+ *
+ * Abstract:    Sets the relative vertical coordinates of each note.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through the main linked list, finding every
+ *             STAFF structure.  It calls a subroutine to process each list of
+ *             list of GRPSYLs for groups (not syllables).
+ */
+
+static void
+locnotes()
+
+{
+       register struct MAINLL *mainll_p; /* point item in main linked list */
+       int v;                          /* index to voice linked lists */
+       int did_a_voice;                /* have we processed a voice in meas?*/
+       struct TIMEDSSV *tssv_p;        /* point along a timed SSV list */
+       struct MAINLL *nextbar_p;       /* the next bar in the MLL */
+
+
+       debug(16, "locnotes");
+       initstructs();                  /* clean out old SSV info */
+
+       did_a_voice = NO;       /* prevent useless "used before set" warning */
+       nextbar_p = 0;          /* prevent useless "used before set" warning */
+
+       /*
+        * Loop through the main linked list, processing voices.  MLL SSVs are
+        * assigned when encountered.  But we also have to handle timed SSVs,
+        * because they may change the clef.  This algorithm would be simpler
+        * if we called setssvstate() after each voice (to undo the timed
+        * SSVs), and then always reapplied them when we get to the next bar.
+        * But to save time, we don't undo them after the last voice, and so
+        * usually don't have to reassign them at the bar (unless all the
+        * visible voices had measure repeats, and so we never assigned any).
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               switch (mainll_p->str) {
+               case S_SSV:
+                       asgnssv(mainll_p->u.ssv_p);
+                       break;
+
+               case S_CHHEAD:
+                       /* find the next bar line */
+                       for (nextbar_p = mainll_p; nextbar_p->str != S_BAR;
+                                       nextbar_p = nextbar_p->next) {
+                               ;
+                       }
+                       /* we haven't processed a voice in this measure yet */
+                       did_a_voice = NO;
+                       break;
+
+               case S_STAFF:
+                       /* if invisible, there is nothing to do */
+                       if (mainll_p->u.staff_p->visible == NO) {
+                               break;
+                       }
+
+                       /* loop through the voice(s), and process each list */
+                       for (v = 0; v < MAXVOICES && mainll_p->u.staff_p
+                                       ->groups_p[v] != 0; v++) {
+
+                               /* meas rpt/rest/space have no notes to do */
+                               if (mainll_p->u.staff_p->groups_p[v]->is_meas
+                                               == YES) {
+                                       continue;
+                               }
+
+                               /*
+                                * If this is not the first voice we've done in
+                                * this measure, and there are timed SSVs,
+                                * locllnotes() assigned them when we were in
+                                * there for the previous voice we did.  So set
+                                * the SSVs back to the state they were in at
+                                * the start of the measure.
+                                */
+                               if (did_a_voice == YES && nextbar_p->u.bar_p->
+                                                       timedssv_p != 0){
+                                       setssvstate(mainll_p);
+                               }
+                               locllnotes(mainll_p, v, nextbar_p);
+                               did_a_voice = YES;
+                       }
+                       break;
+
+               case S_BAR:
+                       if (did_a_voice == NO) {
+                               for (tssv_p = mainll_p->u.bar_p->timedssv_p;
+                                               tssv_p != 0;
+                                               tssv_p = tssv_p->next) {
+                                       asgnssv(&tssv_p->ssv);
+                               }
+                       }
+                       break;
+               }
+       }
+}
+\f
+/*
+ * Name:        locllnotes()
+ *
+ * Abstract:    Set the "stepsup" field for the notes in one GRPSYL list.
+ *
+ * Returns:     void
+ *
+ * Description: This function goes down one of the linked lists of GRPSYLs,
+ *             one that is for groups, not syllables, and sets the stepsup
+ *             value.
+ */
+
+static void
+locllnotes(mll_p, v, nextbar_p)
+
+struct MAINLL *mll_p;          /* point at the MLL struct voice hangs off */
+int v;                         /* voice to loop through */
+struct MAINLL *nextbar_p;      /* point at MLL for the next bar line */
+
+{
+       register int upfromc4;  /* steps up from middle C */
+       register int n;         /* loop through all notes in a group */
+       int s;                  /* staff number */
+       int slines;             /* lines in this staff */
+       int clef;               /* the clef currently in operation */
+       int newclef;            /* the new clef, in case it changes */
+       struct GRPSYL *gs_p;    /* starts pointing at first GRPSYL in list */
+       struct TIMEDSSV *tssv_p;/* point along a timed SSV list */
+       RATIONAL offset;        /* current group's offset into measure */
+
+
+       s = mll_p->u.staff_p->staffno;
+       debug(32, "locllnotes file=%s line=%d staff=%d vidx=%d",
+                       mll_p->inputfile, mll_p->inputlineno, s, v);
+       slines = svpath(s, STAFFLINES)->stafflines;
+
+       /* find the initial clef for this staff */
+       clef = svpath(s, CLEF)->clef;
+
+       /* point at the first timed SSV for this measure, if there is one */
+       tssv_p = nextbar_p->u.bar_p->timedssv_p;
+       offset = Zero;          /* first group's offset into measure */
+
+       /* loop through every group in this voice */
+       for (gs_p = mll_p->u.staff_p->groups_p[v]; gs_p != 0;
+                               gs_p = gs_p->next) {
+
+               /* if no timed SSVs, don't waste time doing the following */
+               if (tssv_p != 0) {
+                       /* assign timed SSVs before current offset */
+                       while (tssv_p != 0 && LT(tssv_p->time_off, offset)) {
+                               asgnssv(&tssv_p->ssv);
+                               tssv_p = tssv_p->next;
+                       }
+
+                       /* get clef state just before this group */
+                       clef = svpath(s, CLEF)->clef;
+
+                       /* assign timed SSVs at current offset */
+                       while (tssv_p != 0 && EQ(tssv_p->time_off, offset)) {
+                               asgnssv(&tssv_p->ssv);
+                               tssv_p = tssv_p->next;
+                       }
+
+                       /* get clef for this group */
+                       newclef = svpath(s, CLEF)->clef;
+
+                       /*
+                        * If the clef changed at this time, set it in GRPSYL.
+                        * This could happen with multiple voices on the staff.
+                        * If so, we'll later erase clef from all but one; but
+                        * the choice depends on the coords, which we don't
+                        * know yet, so that is done later.  The erasing is
+                        * done in eraseclef() in restsyl.c.
+                        */
+                       if (newclef != clef) {
+                               clef = newclef;
+                               gs_p->clef = clef;
+                       }
+
+                       /* add our group's dur to get ready for next iteration*/
+                       offset = radd(offset, gs_p->fulltime);
+               }
+
+               /* nothing more to do for rests or spaces */
+               if (gs_p->grpcont != GC_NOTES)
+                       continue;
+
+               /*
+                * We found a group consisting of notes, normal or tablature.
+                * First handle the tablature case.
+                */
+               if (clef == TABCLEF) {
+                       /*
+                        * Make sure this voice's notes don't collide with
+                        * some later voice's notes.
+                        */
+                       chktabcollision(gs_p);
+
+                       for (n = 0; n < gs_p->nnotes; n++) {
+                               /*
+                                * Set stepsup to be on the appropriate string.
+                                */
+                               /* calc steps up from middle of staff */
+                               gs_p->notelist[n].stepsup = slines
+                                       - 1 - 2 * gs_p->notelist[n].STRINGNO;
+
+                       }
+
+                       continue;
+               }
+
+               /*
+                * We found a non-tablature group consisting of notes.  For
+                * each note, find the number of steps it is up from middle C
+                * and from the center line of the staff.  (However, for 1-line
+                * staffs, we assume center line for now.)
+                * For CSS notes, we apply an offset to keep it far from the
+                * normal notes.  This is so that setgrps.c will understand
+                * that CSS and non-CSS notes in a group never interfere.
+                * Later, absvert.c will find the true stepsup on the other
+                * staff.
+                */
+               for (n = 0; n < gs_p->nnotes; n++) {
+                       /* set steps up from middle line of staff */
+                       if (slines == 5) {
+                               /* get steps up from middle C */
+                               upfromc4 = (gs_p->notelist[n].octave - 4) * 7 +
+                               Letshift[ gs_p->notelist[n].letter - 'a' ];
+
+                               gs_p->notelist[n].stepsup = upfromc4
+                                               + clef - ALTO;
+                               if (gs_p->stemto == CS_ABOVE &&
+                                               n <= gs_p->stemto_idx) {
+                                       gs_p->notelist[n].stepsup += CSS_STEPS;
+                               } else if (gs_p->stemto == CS_BELOW &&
+                                               n >= gs_p->stemto_idx) {
+                                       gs_p->notelist[n].stepsup -= CSS_STEPS;
+                               }
+                       } else {
+                               /* 1-line staff; assume center line for now */
+                               gs_p->notelist[n].stepsup = 0;
+                       }
+               }
+       }
+
+       /*
+        * Assign any timed SSVs that came after the last group, so that we are
+        * in the right state for the next measure (if we are the last voice).
+        */
+       while (tssv_p != 0) {
+               asgnssv(&tssv_p->ssv);
+               tssv_p = tssv_p->next;
+       }
+}
+\f
+/*
+ * Name:        chktabcollision()
+ *
+ * Abstract:    Error if this GRPSYL conflicts with others on this staff.
+ *
+ * Returns:     void
+ *
+ * Description: This function checks for collisions between notes in this
+ *             GRPSYL and notes in GRPSYLs of later voices in this chord on
+ *             this staff.  On a tab staff, no two voices are allowed to use
+ *             the same string at the same time.  If the frets are different,
+ *             it would be impossible to play, and it seems best to disallow
+ *             it even if they agreed.  So if this happens, do an l_ufatal.
+ */
+
+static void
+chktabcollision(start_p)
+
+struct GRPSYL *start_p;                /* first voice on this staff in this chord */
+
+{
+       int sv[MAXTABLINES];    /* which voice, if any, is using each string */
+       int sidx;               /* string index, starting at 0 */
+       struct GRPSYL *gs_p;    /* a GRPSYL on this staff in this chord */
+       int n;                  /* loop through notes (frets) in GRPSYL */
+
+
+       /* if this chord has no more voices on this staff, return */
+       if (start_p->gs_p == 0 ||
+           start_p->gs_p->grpsyl == GS_SYLLABLE ||
+           start_p->gs_p->staffno != start_p->staffno)
+               return;
+
+       /* we care only about notes (frets); rests and spaces are invisible */
+       if (start_p->grpcont != GC_NOTES)
+               return;
+
+       /* init each string to an invalid voice number */
+       for (sidx = 0; sidx < MAXTABLINES; sidx++) {
+               sv[sidx] = 0;
+       }
+
+       /*
+        * Loop from this voice through the last voice on this staff that has
+        * a GRPSYL in this chord.  Don't worry about preceding voices; they
+        * already were in here and were checked against all these voices.
+        */
+       for (gs_p = start_p; gs_p != 0 && start_p->gs_p->grpsyl == GS_GROUP &&
+                       gs_p->staffno == start_p->staffno; gs_p = gs_p->gs_p) {
+
+               /* put each note into array, checking if string already used */
+               for (n = 0; n < gs_p->nnotes; n++) {
+
+                       if (sv[(int)gs_p->notelist[n].STRINGNO] != 0) {
+
+                               l_ufatal(start_p->inputfile,
+                                        start_p->inputlineno,
+                                        "voices %d and %d on staff %d are using the \"%s\" string at the same time",
+                                        sv[(int)gs_p->notelist[n].STRINGNO],
+                                        gs_p->vno,
+                                        gs_p->staffno,
+                                        stringname(gs_p->notelist[n].STRINGNO,
+                                               gs_p->staffno));
+                       }
+
+                       sv[(int)gs_p->notelist[n].STRINGNO] = gs_p->vno;
+               }
+       }
+}
+\f
+/*
+ * Name:        intertab()
+ *
+ * Abstract:    Do additional work between tablature groups.
+ *
+ * Returns:     void
+ *
+ * Description: This function does checks to prevent certain bend sequences
+ *             on a tab staff.  (It's unclear how such things would be drawn.)
+ *             Also, when it finds the end of a single consecutive bend, it
+ *             alters the previously set northern group boundaries of the
+ *             groups, so that the arrows pointing at the bend strings will go
+ *             up and down appropriately.
+ *
+ *             This function is called only with groups that have real bends
+ *             (regular or prebends).
+ */
+#define        MAXBDIST        20      /* no. of unique bend distances in a sequence*/
+
+static void
+intertab(gs_p, mll_p)
+
+struct GRPSYL *gs_p;           /* point at current tablature group */
+struct MAINLL *mll_p;          /* point at the main LL struct it hangs off */
+
+{
+       RATIONAL bdist[MAXBDIST];       /* array of bend distances */
+       RATIONAL bd;                    /* a bend distance */
+       int bdidx;                      /* index into table of bend distances*/
+       struct GRPSYL *nextgs_p;        /* point at the next GRPSYL */
+       struct GRPSYL *gs2_p;           /* point at earlier GRPSYLs */
+       struct MAINLL *mll2_p;          /* needed for crossing bar lines */
+       int count, count2;              /* count numbers of bends */
+       int n, k, j;                    /* loop variables */
+       int idx;                        /* index into a notelist */
+       int bad;                        /* was a bad thing found? */
+
+
+       /* count how many nonnull bends end at this group, remember last one */
+       count = 0;
+       idx = 0;                /* prevent useless 'used before set' warning */
+       for (n = 0; n < gs_p->nnotes; n++) {
+               if (HASREALBEND(gs_p->notelist[n])) {
+                       count++;
+                       idx = n;                /* remember where bend is */
+               }
+       }
+
+       /* enforce restrictions on the following group, if there is one */
+       mll2_p = mll_p;         /* we don't want to disturb mll_p */
+       nextgs_p = nextgrpsyl(gs_p, &mll2_p);
+       count2 = 0;     /* how many nonnull nonprebend bends are in *nextgs_p */
+
+       if (nextgs_p != 0 && nextgs_p->grpcont == GC_NOTES) {
+
+               bad = NO;       /* init to "nothing is bad" */
+
+               for (n = 0; n < nextgs_p->nnotes; n++) {
+
+                       /* if this note has a nonnull nonprebend bend */
+                       if (HASREALBEND(nextgs_p->notelist[n]) &&
+                           nextgs_p->notelist[n].FRETNO == NOFRET) {
+
+                               count2++;
+                               if (count > 1) {
+                                       l_ufatal(gs_p->inputfile,
+                                               gs_p->inputlineno,
+                                               "no bend (other than a release) is allowed to follow a multiple string bend");
+                               }
+
+                               if (count2 > 1) {
+                                       l_ufatal(gs_p->inputfile,
+                                               gs_p->inputlineno,
+                                               "only single string bends are allowed to be consecutive");
+                               }
+
+                               if (nextgs_p->notelist[n].STRINGNO !=
+                                               gs_p->notelist[idx].STRINGNO) {
+                                       bad = YES;
+                               }
+                       }
+               }
+               /*
+                * We check "bad" here instead of inside the above loop,
+                * because we want to give priority to the "only single string
+                * bends . . ." message if that condition is happening.
+                */
+               if (bad == YES) {
+                       l_ufatal(gs_p->inputfile, gs_p->inputlineno,
+                               "consecutive bends must be on the same string");
+               }
+       }
+
+       /*
+        * We know the current group has bend(s).  If the following group has
+        * a nonnull nonprebend bend, just return now.  We will handle this
+        * bend sequence when we find the last nonnull bend in it.
+        */
+       if (count2 > 0)
+               return;
+
+       /*
+        * Loop backwards through the sequence of bends.  The start should be
+        * either a bend following no nonnull bend, or a prebend.  While
+        * searching, build a table of all the unique bend distances.  Usually
+        * we break out by finding a group with a nonnull bend, which means we
+        * went one too far with gs2_p, and gs_p is the start of the sequence.
+        * But if we hit the start, gs2_p will become 0 and we get out of the
+        * loop naturally.  Again, gs_p is the start of the sequence.
+        */
+       bdidx = 0;      /* number of unique bend distances found */
+       gs2_p = gs_p;
+       while (gs2_p != 0) {
+               /* find which note, if any, has the bend in this group */
+               for (n = 0; n < gs2_p->nnotes; n++) {
+                       if (HASREALBEND(gs2_p->notelist[n])) {
+                               bd = ratbend(&gs2_p->notelist[n]);
+                               break;
+                       }
+               }
+
+               if (n < gs2_p->nnotes) {
+                       /*
+                        * We found a nonnull bend.  Search the bdist array to
+                        * see if this value has already occurred.  Get out
+                        * when the value is found, or when we find a greater
+                        * value (the list is in ascending order).
+                        */
+                       for (k = 0; k < bdidx; k++) {
+                               if (GE(bdist[k], bd))
+                                       break;
+                       }
+                       if (k == bdidx) {
+                               /* bd > everything in the array */
+                               /* add it at the end */
+                               bdist[k] = bd;
+                               bdidx++;
+                       } else if (GT(bdist[k], bd)) {
+                               /* bd should be put at this position */
+                               /* move all later ones down a notch */
+                               for (j = bdidx - 1; j >= k; j--)
+                                       bdist[j+1] = bdist[j];
+                               bdist[k] = bd;
+                               bdidx++;
+                       }
+                       /* else bd is already in the table */
+
+                       if (bdidx >= MAXBDIST)
+                               pfatal("too many unique bend distances in sequence of bends");
+                       /* if this bend was a prebend, break */
+                       if (gs2_p->notelist[n].FRETNO != NOFRET) {
+                               gs_p = gs2_p;   /* series starts at prebend */
+                               break;
+                       }
+               } else {
+                       /* there was no bend; start at the following group; */
+                       /* gs_p is now the beginning of the sequence */
+                       break;
+               }
+
+               /*
+                * It was a nonprebend bend.  Point gs2_p to the preceding
+                * group, remember the one we just looked at in gs_p, and keep
+                * looping.
+                */
+               gs_p = gs2_p;
+               gs2_p = prevgrpsyl(gs2_p, &mll_p);
+       }
+
+       /*
+        * Loop forward through these groups.  For each one, alter its northern
+        * boundary according to where its bend distance occurs in the bdist
+        * table.  This will cause the print phase to print the bend strings
+        * at varying heights so that the arrows will bend up and down as
+        * appropriate.
+        */
+       while (gs_p != nextgs_p && gs_p != 0) {
+               /* find which note has the bend in this group, get distance */
+               for (n = 0; n < gs_p->nnotes; n++) {
+                       if (HASREALBEND(gs_p->notelist[n])) {
+                               bd = ratbend(&gs_p->notelist[n]);
+                               break;
+                       }
+               }
+               /* find distance in table, raise RN proportionally to index */
+               for (n = 0; n < bdidx; n++) {
+                       if (EQ(bdist[n], bd)) {
+                               gs_p->c[RN] += 3.0 * STEPSIZE * TABRATIO * n;
+                               break;
+                       }
+               }
+
+               gs_p = nextgrpsyl(gs_p, &mll_p);
+       }
+}
+\f
+/*
+ * Name:        setstems()
+ *
+ * Abstract:    Sets stem direction for each group.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets the stem direction for each group, based
+ *             on the voice scheme at the time and other factors.
+ */
+
+static void
+setstems()
+
+{
+       /* remember the previous stem direction of voice 3 on each staff */
+       short v3stemdir[MAXSTAFFS + 1];
+
+       int staffno;                    /* staff number */
+       int n;                          /* loop variable */
+       register struct MAINLL *mainll_p; /* point at main linked list item */
+       int vscheme;                    /* current voice scheme */
+
+
+       debug(16, "setstems");
+       initstructs();                  /* clean out old SSV info */
+
+       /* set initial default direction of voice 3 stems to be UP */
+       for (n = 1; n <= MAXSTAFFS; n++)
+               v3stemdir[n] = UP;
+
+       /*
+        * Loop once for each item in the main linked list.  Apply any SSVs
+        * that are found.  Call subroutines to process linked lists of
+        * groups.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+               if (mainll_p->str == S_SSV) {
+
+                       asgnssv(mainll_p->u.ssv_p);
+
+               } else if (mainll_p->str == S_STAFF &&
+                               mainll_p->u.staff_p->visible == YES &&
+                               ! is_mrpt(mainll_p->u.staff_p->groups_p[0])) {
+                       /*
+                        * We've found a visible staff, which will have one
+                        * or more voices, depending on the voice scheme.
+                        */
+                       staffno = mainll_p->u.staff_p->staffno;
+                       vscheme = svpath(staffno, VSCHEME)->vscheme;
+
+                       switch (vscheme) {
+                       case V_1:
+                               /*
+                                * There's only one voice on this staff, so
+                                * call a routine to decide which way to point
+                                * each stem.  It handles both grace & nongrace.
+                                */
+                               setonestem(mainll_p->u.staff_p->groups_p[0]);
+                               break;
+
+                       case V_2OPSTEM:
+                               /*
+                                * There are two voices on this staff, and
+                                * the stems are always supposed to point
+                                * opposite.  Call a routine to mark their
+                                * stem directions.  It handles both nongrace
+                                * and grace.
+                                */
+                               setopstem(mainll_p->u.staff_p->groups_p[0],
+                                         mainll_p->u.staff_p->groups_p[1]);
+                               break;
+
+                       case V_2FREESTEM:
+                               /*
+                                * There are two voices on this staff, and
+                                * the stems are free to point either way
+                                * when one voice is a space.  Call routines
+                                * to mark their stem directions; first
+                                * nongrace, then grace.
+                                */
+                               setfreestem(mainll_p->u.staff_p->groups_p[0],
+                                           mainll_p->u.staff_p->groups_p[1]);
+                               dograce(mainll_p->u.staff_p->groups_p[0],
+                                       mainll_p->u.staff_p->groups_p[1]);
+
+                               break;
+
+                       case V_3OPSTEM:
+                               /*
+                                * This is just like V_2OPSTEM for the first
+                                * two voices, but also allows a voice 3.
+                                */
+                               setopstem(mainll_p->u.staff_p->groups_p[0],
+                                         mainll_p->u.staff_p->groups_p[1]);
+                               v3stemdir[staffno] = setv3stem(
+                                       mainll_p->u.staff_p->groups_p[2],
+                                       v3stemdir[staffno]);
+                               break;
+
+                       case V_3FREESTEM:
+                               /*
+                                * This is just like V_2FREESTEM for the first
+                                * two voices, but also allows a voice 3.
+                                */
+                               setfreestem(mainll_p->u.staff_p->groups_p[0],
+                                           mainll_p->u.staff_p->groups_p[1]);
+                               dograce(mainll_p->u.staff_p->groups_p[0],
+                                       mainll_p->u.staff_p->groups_p[1]);
+                               v3stemdir[staffno] = setv3stem(
+                                       mainll_p->u.staff_p->groups_p[2],
+                                       v3stemdir[staffno]);
+
+                               break;
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        setonestem()
+ *
+ * Abstract:    Sets stem direction for each group in a linked list for V_1.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets the stem direction for each group in a
+ *             linked list for a voice/measure, for the case where there is
+ *             only one voice on the staff.
+ */
+
+static void
+setonestem(gs_p)
+
+struct GRPSYL *gs_p;   /* starts pointing at the first GRPSYL in a list */
+
+{
+       register struct GRPSYL *start_p, *end_p; /* first and last of a set */
+
+
+       debug(32, "setonestem file=%s line=%d", gs_p->inputfile,
+                       gs_p->inputlineno);
+       /*
+        * Loop once for each bunch of groups that must be stemmed the same
+        * way.  A beamed group must all be stemmed the same way, but nonbeamed
+        * notes are independent.
+        */
+       start_p = gs_p;
+       for (;;) {
+               /*
+                * Find next group that has nongrace notes.  While doing this,
+                * set the stemdir for any grace groups encountered.  For V_1,
+                * grace stems always go up.
+                */
+               while (start_p != 0 && (start_p->grpcont != GC_NOTES ||
+                                       start_p->grpvalue == GV_ZERO)) {
+                       if (start_p->grpcont == GC_NOTES) /* must be grace */
+                               start_p->stemdir = UP;
+                       start_p = start_p->next;
+               }
+               if (start_p == 0)       /* get out if no more this measure */
+                       break;
+
+               /* if this group is not beamed, handle it, and point at next */
+               if (start_p->beamloc == NOITEM) {
+                       dobunch(start_p, start_p->next);
+                       start_p = start_p->next;
+                       continue;
+               }
+
+               /*
+                * Find end of this beamed group, setting grace groups UP.  If
+                * this is a cross staff beamed group, we may be starting at an
+                * INITEM or even the ENDITEM, since on this staff STARTITEM
+                * may have been a space.  But that doesn't matter; we still
+                * look for ENDITEM, whether or not it's also a space; and
+                * dobunch handles these cases.
+                */
+               for (end_p = start_p; end_p != 0 &&
+               (end_p->grpvalue == GV_ZERO || end_p->beamloc != ENDITEM);
+               end_p = end_p->next) {
+                       if (end_p->grpvalue == GV_ZERO)
+                               end_p->stemdir = UP;
+               }
+               if (end_p == 0)
+                       pfatal("beamed group is not terminated");
+
+               /* handle this bunch of groups, and point at next */
+               dobunch(start_p, end_p->next);
+               start_p = end_p->next;
+       }
+}
+\f
+/*
+ * Name:        setopstem()
+ *
+ * Abstract:    Sets stemdir for v1 or v2 groups for V_2OPSTEM/V_3OPSTEM.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets the stem direction for each group in
+ *             2 linked lists for a staff/measure, for the case where
+ *             the linked list is for voice 1 or voice 2 and stems are always
+ *             supposed to be opposed.  This function does both grace and
+ *             nongrace groups.  For this vscheme, they act the same.
+ *             The user can force the stems against the normal direction,
+ *             except that the parse phase blocks any forcing of grace groups.
+ */
+
+static void
+setopstem(gs1_p, gs2_p)
+
+register struct GRPSYL *gs1_p; /* starts at first GRPSYL in voice 1 list */
+register struct GRPSYL *gs2_p; /* starts at first GRPSYL in voice 2 list */
+
+{
+       debug(32, "setopstem file=%s line=%d", gs1_p->inputfile,
+                       gs1_p->inputlineno);
+       /* mark first voice's stems up */
+       while (gs1_p != 0) {
+               /* if notes or starttime (needed for CSB), mark direction */
+               if (gs1_p->grpcont == GC_NOTES || gs1_p->beamloc == STARTITEM) {
+                       /* if grace, or not in beamed group, try to set UP */
+                       if (gs1_p->grpvalue == GV_ZERO ||
+                           gs1_p->beamloc == NOITEM) {
+                               /* if not forced by user, set UP */
+                               if (gs1_p->stemdir == UNKNOWN) {
+                                       gs1_p->stemdir = UP;
+                               }
+                       } else if (gs1_p->beamloc == STARTITEM) {
+                               /* do same for all groups in beamed set */
+                               setbeamedstem(gs1_p, UP);
+                       }
+               }
+               gs1_p = gs1_p->next;
+       }
+
+       /* mark second voice's stems down */
+       while (gs2_p != 0) {
+               /* if notes or starttime (needed for CSB), mark direction */
+               if (gs2_p->grpcont == GC_NOTES || gs2_p->beamloc == STARTITEM) {
+                       /* if grace, or not in beamed group, try to set DOWN */
+                       if (gs2_p->grpvalue == GV_ZERO ||
+                           gs2_p->beamloc == NOITEM) {
+                               /* if not forced by user, set DOWN */
+                               if (gs2_p->stemdir == UNKNOWN) {
+                                       gs2_p->stemdir = DOWN;
+                               }
+                       } else if (gs2_p->beamloc == STARTITEM) {
+                               /* do same for all groups in beamed set */
+                               setbeamedstem(gs2_p, DOWN);
+                       }
+               }
+               gs2_p = gs2_p->next;
+       }
+}
+\f
+/*
+ * Name:        setfreestem()
+ *
+ * Abstract:    Sets stemdir for each group in 2 linked lists for V_2FREESTEM.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets the stem direction for each (nongrace)
+ *             group in 2 linked lists for a staff/measure, for the case
+ *             where there are two voices on the staff and the stems are
+ *             allowed to point either way for one voice when the other
+ *             voice has a space.
+ */
+
+static void
+setfreestem(gs1_p, gs2_p)
+
+struct GRPSYL *gs1_p;  /* starts pointing at first GRPSYL in voice 1 list */
+struct GRPSYL *gs2_p;  /* starts pointing at first GRPSYL in voice 2 list */
+
+{
+       debug(32, "setfreestem file=%s line=%d", gs1_p->inputfile,
+                       gs1_p->inputlineno);
+       /* call to handle first voice, then call to handle second voice */
+       set1freestem(gs1_p, gs2_p, UP);
+       set1freestem(gs2_p, gs1_p, DOWN);
+}
+\f
+/*
+ * Name:        set1freestem()
+ *
+ * Abstract:    Sets stemdir for v1 or v2 groups for V_2FREESTEM/V_3FREESTEM.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets the stem direction for each (nongrace)
+ *             group in one linked list for a staff/measure, for the case
+ *             where the linked list is for voice 1 or voice 2 and stems are
+ *             allowed to point either way for one voice when the other
+ *             voice has a space.  The function sets the directions just
+ *             for "this" voice; the other voice is only used as a reference
+ *             (we need to check when it has spaces).
+ */
+
+static void
+set1freestem(this_p, other_p, stemdir)
+
+struct GRPSYL *this_p; /* starts pointing at first GRPSYL in linked list */
+                       /* for the voice whose stems we are now setting */
+struct GRPSYL *other_p;        /* starts pointing at first GRPSYL in linked list */
+                       /* for the other voice */
+int stemdir;           /* which way the stem must point if forced */
+
+{
+       register struct GRPSYL *start_p, *end_p; /* first and last of a set */
+       RATIONAL vtime, vtime2;         /* elapsed time this measure */
+
+
+       debug(32, "set1freestem file=%s line=%d stemdir=%d", this_p->inputfile,
+                       this_p->inputlineno, stemdir);
+       vtime = Zero;                   /* init to no time elapsed */
+
+       /*
+        * Loop once for each bunch of groups in this voice that must be
+        * stemmed the same way.  A beamed group must all be stemmed the same
+        * way, but nonbeamed notes are independent.
+        */
+       start_p = this_p;
+       for (;;) {
+               /*
+                * Find next group that has nongrace notes, accumulating
+                * elapsed time.  This code depends on grace notes having
+                * zero duration.
+                */
+               while (start_p != 0 && (start_p->grpcont != GC_NOTES ||
+                                       start_p->grpvalue == GV_ZERO)) {
+                       vtime = radd(vtime, start_p->fulltime);
+                       start_p = start_p->next;
+               }
+               if (start_p == 0)       /* get out if no more this measure */
+                       break;
+
+               /* if this group is not beamed, handle it, and point at next */
+               if (start_p->beamloc == NOITEM) {
+                       vtime2 = radd(vtime, start_p->fulltime);
+
+                       if (hasspace(other_p, vtime, vtime2)) {
+                               /* other voice has space; decide stem */
+                               dobunch(start_p, start_p->next);
+                       } else {
+                               /*
+                                * The other voice has notes/rests; force the
+                                * the direction, unless the user has already
+                                * forced it.
+                                */
+                               if (start_p->stemdir == UNKNOWN) {
+                                       start_p->stemdir = (short)stemdir;
+                               }
+                       }
+
+                       start_p = start_p->next;
+                       vtime = vtime2;
+                       continue;
+               }
+
+               /* find end of this beamed group, ignoring grace groups */
+               vtime2 = vtime;
+               for (end_p = start_p; end_p != 0 &&
+               (end_p->grpvalue == GV_ZERO || end_p->beamloc != ENDITEM);
+               end_p = end_p->next)
+                       vtime2 = radd(vtime2, end_p->fulltime);
+               if (end_p == 0)
+                       pfatal("beamed group is not terminated");
+               vtime2 = radd(vtime2, end_p->fulltime); /* add in final note */
+
+               /* handle this bunch of groups, and point at next */
+               if (hasspace(other_p, vtime, vtime2)) {
+                       /* other voice has space; decide our stems */
+                       dobunch(start_p, end_p->next);
+               } else {
+                       /* other voice has notes/rests; this forces ours */
+                       setbeamedstem(start_p, stemdir);
+               }
+
+               vtime = vtime2;
+               start_p = end_p->next;
+       }
+}
+\f
+/*
+ * Name:        setbeamedstem()
+ *
+ * Abstract:    Sets stem direction in beamed set, favoring one direction.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given the first group in a nongrace beamed
+ *             set.  It sets all the stem directions, the same way of course.
+ *             It sets them to the given stemdir, unless the user has
+ *             overridden the direction.
+ */
+
+static void
+setbeamedstem(start_p, stemdir)
+
+struct GRPSYL *start_p;        /* point at the first GRPSYL in beamed set */
+int stemdir;           /* which way we will try to point the stems */
+
+{
+       struct GRPSYL *g_p;             /* point into the set */
+       int forcedir;                   /* direction forced by user */
+
+
+       forcedir = UNKNOWN;             /* no forcing yet */
+
+       /* look for groups in this set where the user has forced stemdir */
+       for (g_p = start_p; g_p != 0; g_p = g_p->next) {
+               /* consider only nongrace note groups */
+               if (g_p->grpcont != GC_NOTES || g_p->grpvalue == GV_ZERO) {
+                       continue;
+               }
+               /* if user forced the stemdir */
+               if (g_p->stemdir != UNKNOWN) {
+                       if (forcedir == UNKNOWN) {
+                               /* first such occurrence; remember it */
+                               forcedir = g_p->stemdir;
+                       } else if (g_p->stemdir != forcedir) {
+                               /* any later occurrence must agree */
+                               l_warning(g_p->inputfile, g_p->inputlineno,
+                               "cannot have both 'up' and 'down' stem in same set of beamed or 'alt'-ed note groups");
+                               forcedir = g_p->stemdir; /* use latest */
+                       }
+               }
+               if (g_p->beamloc == ENDITEM) {
+                       break;
+               }
+       }
+
+       /* if user forced any stems, we'll go with that direction */
+       if (forcedir != UNKNOWN) {
+               stemdir = forcedir;
+       }
+
+       /* set all the stems in this set */
+       for (g_p = start_p; g_p != 0; g_p = g_p->next) {
+               if (g_p->grpcont != GC_NOTES || g_p->grpvalue == GV_ZERO) {
+                       continue;
+               }
+               g_p->stemdir = stemdir;
+               if (g_p->beamloc == ENDITEM) {
+                       break;
+               }
+       }
+}
+/*
+ * Name:        dobunch()
+ *
+ * Abstract:    Sets stem direction for a single group or a beamed set.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given a single (nongrace) group, or a set
+ *             of them that will be beamed together, for the case where
+ *             the stems are allowed to go either way.  It decides which
+ *             way is best, and sets the result.
+ */
+
+static void
+dobunch(start_p, end_p)
+
+struct GRPSYL *start_p;        /* starts pointing at the first GRPSYL in a bunch */
+struct GRPSYL *end_p;  /* starts pointing after the last GRPSYL in a bunch */
+
+{
+       register struct GRPSYL *gs_p;   /* point along list of them */
+       int lonesum;            /* sum of offsets of single notes from center*/
+       int topsum;             /* sum of offsets of top notes from center */
+       int botsum;             /* sum of offsets of bottom notes from center*/
+       int insum;              /* sum of offsets of inner notes from center */
+       int n;                  /* loop counter */
+       int stemdir;            /* answer of where stems should point */
+
+
+       /*
+        * Loop through all (nongrace) notes in these group(s), adding up
+        * the offsets of their outer notes from the center line.  For groups
+        * that have only one note, count this in lonesum.  For other groups,
+        * count the top notes and bottom notes separately.  We consider only
+        * outer notes in these counters, and we count single note groups
+        * separately to avoid counting the same note twice.  But to be able to
+        * breaks ties in the best way, we keep a separate counter for inner
+        * notes of groups that have 3 or more notes.
+        * While doing this, also keep track of whether the user requested a
+        * specific stem direction on any of these groups.  If so, there must
+        * not be any contradictions between what they asked for.
+        */
+       lonesum = topsum = botsum = insum = 0;
+       stemdir = UNKNOWN;      /* user hasn't asked for anything yet */
+       for (gs_p = start_p; gs_p != end_p; gs_p = gs_p->next) {
+               /*
+                * Consider only note groups.  Cross staff beaming can have
+                * spaces in the list of groups, and rests need to be skipped.
+                */
+               if (gs_p->grpcont == GC_NOTES && gs_p->grpvalue == GV_NORMAL) {
+                       if (gs_p->stemdir != UNKNOWN) {
+                               if (stemdir == UNKNOWN) {
+                                       stemdir = gs_p->stemdir;
+                               } else if (gs_p->stemdir != stemdir) {
+                                       l_warning(gs_p->inputfile,
+                                       gs_p->inputlineno,
+                                       "cannot have both 'up' and 'down' stem in same set of beamed or 'alt'-ed note groups");
+                                       stemdir = gs_p->stemdir;
+                               }
+                       }
+
+                       if (gs_p->nnotes == 1) {
+                               lonesum += gs_p->notelist[0].stepsup;
+                       } else {
+                               topsum += gs_p->notelist[0].stepsup;
+                               botsum += gs_p->notelist[ gs_p->nnotes - 1 ].
+                                               stepsup;
+                       }
+
+                       /* this loop happens only if >= 3 notes in the group */
+                       for (n = 1; n < gs_p->nnotes - 1; n++ ) {
+                               insum += gs_p->notelist[n].stepsup;
+                       }
+               }
+       }
+
+       /*
+        * If the user requested a stem direction, that's what they will get,
+        * for 5-line regular staffs, but for 1-line regular staffs stems are
+        * always UP and for tablature staffs, always DOWN.  For tab staffs, the
+        * parse phase blocks any user requests for stemdir, so we don't have
+        * to cover that in the warning and error messages here.
+        *
+        * For a regular 5-line staff where the user didn't specify, if we are
+        * involved in cross staff beaming, the direction defaults such that
+        * the beam ends up between the two staffs; else, these rules apply:
+        * If lonesum + topsum + botsum is positive, the "average" outer note
+        * in these group(s) is above the center line, so the stems should go
+        * down.  If negative, they should go up.  In case of tie, they should
+        * go down, unless we can break the tie by using the inner notes.
+        * For 1-line staff, the stem should go up, regardless.
+        */
+       if (svpath(start_p->staffno, STAFFLINES)->stafflines == 5 &&
+                       is_tab_staff(start_p->staffno) == NO) {
+               if (stemdir == UNKNOWN) {
+                       switch (start_p->beamto) {
+                       case CS_ABOVE:          /* bm with staff above */
+                               stemdir = UP;
+                               break;
+                       case CS_BELOW:          /* bm with staff below */
+                               stemdir = DOWN;
+                               break;
+                       case CS_SAME:           /* no cross staff beaming */
+                               /* normal case: base on note distances */
+                               if (lonesum + topsum + botsum > 0)
+                                       stemdir = DOWN;
+                               else if (lonesum + topsum + botsum < 0)
+                                       stemdir = UP;
+                               else
+                                       stemdir = insum >= 0 ? DOWN : UP;
+                               break;
+                       }
+               }
+       } else if (is_tab_staff(start_p->staffno) == YES) {
+               stemdir = DOWN;
+       } else {
+               if (stemdir == DOWN)
+                       l_ufatal(start_p->inputfile, start_p->inputlineno,
+                       "cannot specify 'down' stem on voice 1 or 2 of a one-line staff");
+               if (stemdir == UP)
+                       l_warning(start_p->inputfile, start_p->inputlineno,
+                       "stem direction should not be specified on voice 1 or 2 of a one-line staff");
+               stemdir = UP;   /* in case it was UNKNOWN */
+       }
+
+       /* mark all groups (doesn't hurt to mark rests and spaces too) */
+       for (gs_p = start_p; gs_p != end_p; gs_p = gs_p->next) {
+               if (gs_p->grpvalue == GV_NORMAL)
+                       gs_p->stemdir = (short)stemdir;
+       }
+}
+\f
+/*
+ * Name:        dograce()
+ *
+ * Abstract:    Sets stem direction for a single grace group.
+ *
+ * Returns:     void
+ *
+ * Description:        This function sets stem directions for grace groups when the
+ *             vscheme V_2FREESTEM.  (The V_1 and V_2OPSTEM cases were handled
+ *             along with nongrace groups.)  If the next nongrace group occurs
+ *             at a time when the other voice has a space, the grace stem goes
+ *             up (like V_1), else the same as the main group (like V_2OPSTEM).
+ *             For the first voice, these rules boil down to the fact that
+ *             graces stems are always up.  The second voice can end up
+ *             going either way.
+ */
+
+static void
+dograce(gs1_p, gs2_p)
+
+register struct GRPSYL *gs1_p; /* starts at first GRPSYL in voice 1 list */
+register struct GRPSYL *gs2_p; /* starts at first GRPSYL in voice 2 list */
+
+{
+       register struct GRPSYL *gs_p;   /* point along list of them */
+       RATIONAL vtime;                 /* elapsed time in measure */
+       static RATIONAL tiny = {1, 4 * MAXBASICTIME};
+
+
+       /* for the first voice, mark all grace stems up */
+       for (gs_p = gs1_p; gs_p != 0; gs_p = gs_p->next) {
+               if (gs_p->grpvalue == GV_ZERO)
+                       gs_p->stemdir = UP;
+       }
+
+       /*
+        * For the 2nd voice, loop though all groups.  For each nongrace group,
+        * accumulate the fulltime.  For each grace group, find out if the
+        * other voice has a space at the moment the following nongrace group
+        * starts.  If so, treat as V_1.  If not, treat as V_2OPSTEM.
+        */
+       vtime = Zero;
+       for (gs_p = gs2_p; gs_p != 0; gs_p = gs_p->next) {
+               if (gs_p->grpvalue == GV_NORMAL) {
+                       vtime = radd(vtime, gs_p->fulltime);
+               } else {
+                       /* does other voice have space? */
+                       if (hasspace(gs1_p, vtime, radd(vtime, tiny)) == YES) {
+                               gs_p->stemdir = UP;
+                       } else {
+                               gs_p->stemdir = DOWN;
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        setv3stem()
+ *
+ * Abstract:    Sets stem direction for each group in a linked list for voice 3.
+ *
+ * Returns:     default stem direction after this measure
+ *
+ * Description: This function sets the stem direction for each group in a
+ *             linked list for a voice/measure that is for voice 3.  Voice 3
+ *             ignores the other voices.
+ */
+
+static int
+setv3stem(gs_p, stemdir)
+
+struct GRPSYL *gs_p;   /* starts pointing at the first GRPSYL in a list */
+int stemdir;           /* stem direction of the previous group */
+
+{
+       register struct GRPSYL *start_p, *end_p; /* first and last of a set */
+
+
+       debug(32, "setv3stem file=%s line=%d", gs_p->inputfile,
+                       gs_p->inputlineno);
+       /*
+        * Loop once for each bunch of groups that must be stemmed the same
+        * way.  A beamed group must all be stemmed the same way, but nonbeamed
+        * notes are independent.
+        */
+       start_p = gs_p;
+       for (;;) {
+               /*
+                * Find next group that has nongrace notes.  While doing this,
+                * set the stemdir for any grace groups encountered.  For voice
+                * 3, grace stems always go up.
+                */
+               while (start_p != 0 && (start_p->grpcont != GC_NOTES ||
+                                       start_p->grpvalue == GV_ZERO)) {
+                       if (start_p->grpcont == GC_NOTES) /* must be grace */
+                               start_p->stemdir = UP;
+                       start_p = start_p->next;
+               }
+               if (start_p == 0)       /* get out if no more this measure */
+                       break;
+
+               /* if this group is not beamed, handle it, and point at next */
+               if (start_p->beamloc == NOITEM) {
+                       stemdir = dov3bunch(start_p, start_p->next, stemdir);
+                       start_p = start_p->next;
+                       continue;
+               }
+
+               /*
+                * Find end of this beamed group, setting grace groups UP.
+                * Note that voice 3 does not allow cross staff beaming.
+                */
+               for (end_p = start_p; end_p != 0 &&
+               (end_p->grpvalue == GV_ZERO || end_p->beamloc != ENDITEM);
+               end_p = end_p->next) {
+                       if (end_p->grpvalue == GV_ZERO)
+                               end_p->stemdir = UP;
+               }
+               if (end_p == 0)
+                       pfatal("beamed group is not terminated");
+
+               /* handle this bunch of groups, and point at next */
+               stemdir = dov3bunch(start_p, end_p->next, stemdir);
+               start_p = end_p->next;
+       }
+
+       return (stemdir);
+}
+\f
+/*
+ * Name:        dov3bunch()
+ *
+ * Abstract:    Sets stem dir for a single group or a beamed set on voice 3.
+ *
+ * Returns:     stem direction that was chosen
+ *
+ * Description: This function is given a single (nongrace) group, or a set
+ *             of them that will be beamed together, for voice 3.  It decides
+ *             which stemdir is needed, and sets it for each group.
+ */
+
+static int
+dov3bunch(start_p, end_p, stemdir)
+
+struct GRPSYL *start_p;        /* starts pointing at the first GRPSYL in a bunch */
+struct GRPSYL *end_p;  /* starts pointing after the last GRPSYL in a bunch */
+int stemdir;           /* stem direction of the previous group */
+
+{
+       register struct GRPSYL *gs_p;   /* point along list of them */
+       int userdir;                    /* stemdir requested by user */
+
+
+       /*
+        * Loop through all groups in this bunch, keeping track of any user-
+        * specified direction.  Grace groups are forced to UP but are other-
+        * wise ignored.  Nongrace groups could be rests, so ignore them.
+        */
+       userdir = UNKNOWN;      /* user hasn't asked for anything yet */
+       for (gs_p = start_p; gs_p != end_p; gs_p = gs_p->next) {
+               if (gs_p->grpvalue == GV_ZERO) {
+                       gs_p->stemdir = UP;     /* grace group */
+               } else if (gs_p->grpcont == GC_NOTES) {
+                       if (gs_p->stemdir != UNKNOWN) { /* user request */
+                               if (userdir == UNKNOWN) {
+                                       userdir = gs_p->stemdir;
+                               } else if (gs_p->stemdir != userdir) {
+                                       l_warning(gs_p->inputfile,
+                                       gs_p->inputlineno,
+                                       "cannot have both 'up' and 'down' stem in same set of beamed or 'alt'-ed note groups");
+                                       userdir = gs_p->stemdir;
+                               }
+                       }
+               }
+       }
+
+       /* if user requested a direction, we will use that, else keep previous*/
+       if (userdir != UNKNOWN)
+               stemdir = userdir;
+
+       /* mark all nongrace groups; it doesn't hurt to mark rests */
+       for (gs_p = start_p; gs_p != end_p; gs_p = gs_p->next) {
+               if (gs_p->grpvalue == GV_NORMAL)
+                       gs_p->stemdir = (short)stemdir;
+       }
+
+       return (stemdir);
+}
+\f
+/*
+ * Name:        setheads()
+ *
+ * Abstract:    Set headshape, headfont, headchar, and coords for all notes.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets the headshape, headfont, and headchar for
+ *             all notes.  (However, the headchar is changed later, in
+ *             setgrps.c, in certain cases where two GRPSYLs share a note.)
+ *             It also sets the relative vertical coords of the notes and
+ *             their groups.  We waited until now to do this so that stemdir
+ *             would be known.
+ */
+
+static void
+setheads()
+
+{
+       struct MAINLL *mainll_p;        /* point at main linked list item */
+       struct STAFF *staff_p;          /* point at a STAFF */
+       int stafflines;                 /* lines in a tablature staff */
+       int is_tab;                     /* is this a tablature staff? */
+       int sharps;                     /* in the key sig */
+       char keylet;                    /* letter of the key, assuming major */
+       short *shapes;                  /* 7 shapes for the 7 notes */
+       int vidx;                       /* voice index */
+       int allx_hsi;                   /* headshape index for allx */
+
+
+       debug(16, "setheads");
+       initstructs();                  /* clean out old SSV info */
+
+       /* just in case we'll need it later */
+       allx_hsi = get_shape_num("allx");
+
+       /*
+        * Loop once for each item in the main linked list.  Apply any SSVs
+        * that are found.  For each voice on each staff, call setvoiceheads
+        * to do the the work.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               if (mainll_p->str == S_SSV) {
+                       /* apply the SSV and go to the next item */
+                       asgnssv(mainll_p->u.ssv_p);
+                       continue;
+               }
+
+               /* deal only with visible staffs that aren't measure rpts */
+               if (mainll_p->str != S_STAFF ||
+                               mainll_p->u.staff_p->visible == NO ||
+                               is_mrpt(mainll_p->u.staff_p->groups_p[0])) {
+                       continue;
+               }
+
+               /*
+                * We found a staff to work on.  Set up some variables we'll
+                * be needing.
+                */
+               staff_p = mainll_p->u.staff_p;
+               stafflines = svpath(staff_p->staffno, STAFFLINES)->stafflines;
+               is_tab = svpath(staff_p->staffno, CLEF)->clef == TABCLEF;
+
+               /*
+                * Find the key letter.  We don't care about any sharp or flat
+                * in the key name, just the letter.  For tab it's meaningless,
+                * but that's okay.
+                */
+               sharps = eff_key(staff_p->staffno);
+               keylet = Circle[(sharps + 1 + 7) % 7];
+
+               /* loop through every possible voice on this staff */
+               for (vidx = 0; vidx < MAXVOICES; vidx++) {
+
+                       /* point at array of headshapes for this voice */
+                       shapes = vvpath(staff_p->staffno, vidx + 1,
+                                       NOTEHEADS)->noteheads;
+
+                       setvoiceheads(mainll_p, staff_p->groups_p[vidx],
+                               stafflines, shapes, is_tab, allx_hsi, sharps,
+                               keylet);
+               }
+       }
+}
+\f
+/*
+ * Name:        setvoiceheads()
+ *
+ * Abstract:    Set headshape, headfont, headchar, and coords for one GRPSYL.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets the headshape, headfont, and headchar for
+ *             one GRPSYL.  (However, the headchar is changed later, in
+ *             setgrps.c, in certain cases where two GRPSYLs share a note.)
+ *             It also sets the relative vertical coords of the notes and
+ *             the group.
+ */
+
+static void
+setvoiceheads(mll_p, gs_p, stafflines, shapes, is_tab, allx_hsi, sharps, keylet)
+
+struct MAINLL *mll_p;          /* point at the main LL struct gs_p hangs off */
+struct GRPSYL *gs_p;           /* starts at start of GRPSYL list */
+int stafflines;                        /* lines in a tablature staff */
+short *shapes;                 /* 7 shapes for the 7 notes */
+int is_tab;                    /* is this a tablature staff? */
+int allx_hsi;                  /* headshape index for allx */
+int sharps;                    /* in the key sig */
+int keylet;                    /* letter of the key, assuming major */
+
+{
+       float bendheight;               /* total height of bend numbers */
+       int havebend;                   /* any bends in this group? */
+       int n;                          /* loop variable */
+       int i;                          /* temp variable */
+       int hfont;                      /* font of note head */
+       int hchar;                      /* char of note head */
+       float vhalf;                    /* half the vert size of note head */
+       int stepsup;                    /* local copy */
+
+
+       /* loop through every GRPSYL in voice (may be none) */
+       for ( ; gs_p != 0; gs_p = gs_p->next) {
+
+               /* we only care about notes, not rest/space */
+               if (gs_p->grpcont != GC_NOTES) {
+                       continue;
+               }
+
+               bendheight = 0;         /* init to no bends */
+               havebend = NO;
+
+               /*
+                * Loop through every note in the GRPSYL, setting its
+                * headshape, head font/char, and coords.
+                */
+               for (n = 0; n < gs_p->nnotes; n++) {
+
+                       /* if there is no note-level override... */
+                       if (gs_p->notelist[n].headshape == HS_UNKNOWN) {
+
+                               /* set to group-level override if present */
+                               gs_p->notelist[n].headshape = gs_p->headshape;
+
+                               /*
+                                * If still no setting (which is the usual
+                                * case), set according to what the SSVs said.
+                                * Set i to how far note is above the tonic
+                                * (assuming a major key).  Tab uses tonic.
+                                * Then get shape from array.
+                                */
+                               if (gs_p->notelist[n].headshape == HS_UNKNOWN) {
+
+                                       if (is_tab) {
+                                               i = 0;  /* arbitrary */
+                                       } else {
+                                               i = (gs_p-> notelist[n].letter
+                                                       + 7 - keylet) % 7;
+                                       }
+
+                                       gs_p->notelist[n].headshape = shapes[i];
+                               }
+                       }
+
+                       /*
+                        * Now that we know the stepsup (set in locllnotes())
+                        * and the headshape, we can set the note's coords.
+                        */
+                       if (is_tab && gs_p->notelist[n].headshape != allx_hsi) {
+
+                               /* handle tab (except when it's an X) */
+
+                               gs_p->notelist[n].c[RY] = gs_p->notelist[n].
+                                       stepsup * TABRATIO * STEPSIZE;
+
+                               if (gs_p->notelist[n].FRETNO == NOFRET) {
+                                       /* set RN and RS the same as RY */
+                                       gs_p->notelist[n].c[RN] =
+                                               gs_p->notelist[n].c[RY];
+                                       gs_p->notelist[n].c[RS] =
+                                               gs_p->notelist[n].c[RY];
+                               } else {
+                                       /*
+                                        * Set vertical coordinates of the
+                                        * "note" (fret number).  It is to be
+                                        * centered on the appropriate line.
+                                        */
+                                       vhalf = strheight(fret_string(&gs_p->
+                                               notelist[n], gs_p)) / 2.0;
+                                       gs_p->notelist[n].c[RN] =
+                                               gs_p->notelist[n].c[RY] + vhalf;
+                                       gs_p->notelist[n].c[RS] =
+                                               gs_p->notelist[n].c[RY] - vhalf;
+                               }
+
+                       } else {
+
+                               /* handle non-tab and tab X-notes */
+
+                               /* find & store music font and char */
+                               hchar = nheadchar(gs_p->notelist[n].headshape,
+                                       gs_p->basictime, gs_p->stemdir, &hfont);
+                               gs_p->notelist[n].headchar = hchar;
+                               gs_p->notelist[n].headfont = hfont;
+
+                               /* half the height of the note head */
+                               vhalf = height(hfont, gs_p->notelist[n].notesize
+                                       == GS_NORMAL ? DFLT_SIZE : SMALLSIZE,
+                                       hchar) / 2;
+
+                               /*
+                                * Set actual relative vertical coords.  We need
+                                * to recalculate the original stepsup, which
+                                * was modified for CSS notes, because absvert.c
+                                * needs to know what the note's coords would
+                                * have been if it hadn't been CSS.  Sigh.
+                                */
+                               stepsup = gs_p->notelist[n].stepsup;
+                               switch (gs_p->stemto) {
+                               case CS_ABOVE:
+                                       if (n <= gs_p->stemto_idx) {
+                                               stepsup -= CSS_STEPS;
+                                       }
+                                       break;
+                               case CS_BELOW:
+                                       if (n >= gs_p->stemto_idx) {
+                                               stepsup += CSS_STEPS;
+                                       }
+                                       break;
+                               }
+                               gs_p->notelist[n].c[RY] = stepsup * STEPSIZE *
+                                       (is_tab ? TABRATIO : 1.0);
+
+                               gs_p->notelist[n].c[RN] =
+                                       gs_p->notelist[n].c[RY] + vhalf;
+
+                               gs_p->notelist[n].c[RS] =
+                                       gs_p->notelist[n].c[RY] - vhalf;
+                       }
+
+                       if (is_tab) {
+                               /*
+                                * If there was a real bend, add to total height
+                                * of the bend numbers.
+                                */
+                               if (HASREALBEND(gs_p->notelist[n])) {
+                                       bendheight += strheight(bend_string(
+                                               &gs_p->notelist[n])) + STDPAD;
+                               }
+
+                               /* if any bend at all, remember it */
+                               if (HASBEND(gs_p->notelist[n])) {
+                                       havebend = YES;
+                               }
+                       }
+               }
+
+               /*
+                * Set the group's coords.
+                */
+               if (is_tab) {
+                       /*
+                        * Set the group's north based on the top of the top
+                        * bend number if there is one, otherwise the top of
+                        * the top fret number.  We leave 3 "tab stepsizes" of
+                        * white space between the staff and the lowest bend
+                        * number, for the arrow.
+                        */
+                       if (havebend == NO) {   /* no bends present */
+                               /* there must be frets, since no bends */
+                               gs_p->c[RN] = gs_p->notelist[0].c[RN] + STDPAD;
+                       } else {                /* bend(s) present */
+                               gs_p->c[RN] = (stafflines + 2) *
+                                       STEPSIZE * TABRATIO + bendheight;
+                       }
+
+                       /*
+                        * Set the group's south based on the bottom of the
+                        * bottom fret number if there is one, otherwise the
+                        * middle of the staff.
+                        */
+                       if (gs_p->nnotes == 0) {        /* no frets present */
+                               gs_p->c[RS] = 0;
+                       } else {                        /* frets present */
+                               gs_p->c[RS] = gs_p->notelist
+                                       [ gs_p->nnotes - 1 ].c[RS] - STDPAD;
+                       }
+
+                       /* if bends, do work between this and other groups */
+                       if (bendheight > 0) {
+                               intertab(gs_p, mll_p);
+                       }
+               } else {
+                       /*
+                        * Non-tab: use the outermost non-CSS notes, but pad.
+                        * If all notes are CSS, then set RN and RS to zero.
+                        */
+                       switch (gs_p->stemto) {
+                       case CS_SAME:
+                               gs_p->c[RN] = gs_p->notelist
+                                       [0].c[RN] + STDPAD;
+                               gs_p->c[RS] = gs_p->notelist
+                                       [gs_p->nnotes-1].c[RS] - STDPAD;
+                               break;
+                       case CS_ABOVE:
+                               if (gs_p->stemto_idx == gs_p->nnotes - 1) {
+                                       gs_p->c[RN] = gs_p->c[RS] = 0.0;
+                               } else {
+                                       gs_p->c[RN] = gs_p->notelist
+                                          [gs_p->stemto_idx+1].c[RN] + STDPAD;
+                                       gs_p->c[RS] = gs_p->notelist
+                                          [gs_p->nnotes-1].c[RS] - STDPAD;
+                               }
+                               break;
+                       case CS_BELOW:
+                               if (gs_p->stemto_idx == 0) {
+                                       gs_p->c[RN] = gs_p->c[RS] = 0.0;
+                               } else {
+                                       gs_p->c[RN] = gs_p->notelist
+                                          [0].c[RN] + STDPAD;
+                                       gs_p->c[RS] = gs_p->notelist
+                                          [gs_p->stemto_idx-1].c[RS] - STDPAD;
+                               }
+                               break;
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        fixoneline()
+ *
+ * Abstract:    Fix stemsup and vertical coord for notes on one-line staffs.
+ *
+ * Returns:     void
+ *
+ * Description: stepsup and notes' vertical coords are set in locllnotes().
+ *             For one-line staffs, it assumes the notes are on the line.
+ *             But if the notes are not to be on the line, that isn't right.
+ *             It depends on which voice this is.  Now that we have set the
+ *             stem direction, we need to correct this info.
+ */
+
+static void
+fixoneline()
+
+{
+       struct MAINLL *mainll_p;        /* point at main linked list item */
+       struct STAFF *staff_p;          /* point at a STAFF */
+       struct GRPSYL *gs_p;            /* point along a GRPSYL list */
+       int v;                          /* voice number, 0 or 1 */
+
+
+       debug(16, "fixoneline");
+       initstructs();                  /* clean out old SSV info */
+
+       /*
+        * Loop once for each item in the main linked list.  Apply any SSVs
+        * that are found.  Move notes that are not to be on the line.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               if (mainll_p->str == S_SSV) {
+                       /* apply the SSV and go to the next item */
+                       asgnssv(mainll_p->u.ssv_p);
+                       continue;
+               }
+
+               /* deal only with visible staffs that aren't measure rpts */
+               if (mainll_p->str != S_STAFF ||
+                               mainll_p->u.staff_p->visible == NO ||
+                               is_mrpt(mainll_p->u.staff_p->groups_p[0])) {
+                       continue;
+               }
+
+               staff_p = mainll_p->u.staff_p;
+
+               /* deal only with non-tab one-line staffs */
+               if (svpath(staff_p->staffno, STAFFLINES)->stafflines != 1 ||
+                               svpath(staff_p->staffno, CLEF)->clef
+                               == TABCLEF) {
+                       continue;
+               }
+
+               /*
+                * Loop through voices 1 and 2, and process each list.  Note
+                * that voice 3 is always on the line, so we don't need to do
+                * anything to it.
+                */
+               for (v = 0; v < NORMVOICES && staff_p->groups_p[v] != 0; v++) {
+
+                       /* change stepsup from 0 only if notes not on the line*/
+                       if (vvpath(staff_p->staffno, v + 1, ONTHELINE)->
+                                       ontheline == YES) {
+                               continue;
+                       }
+
+                       for (gs_p = staff_p->groups_p[v]; gs_p != 0;
+                                       gs_p = gs_p->next) {
+
+                               /* only notes are to be changed */
+                               if (gs_p->grpcont != GC_NOTES) {
+                                       continue;
+                               }
+
+                               /* move up or down a step based on voice */
+                               if (gs_p->vno == 1) {
+                                       gs_p->notelist[0].stepsup = 1;
+                                       gs_p->notelist[0].c[RY] = STEPSIZE;
+                                       gs_p->notelist[0].c[RN] += STEPSIZE;
+                                       gs_p->notelist[0].c[RS] += STEPSIZE;
+                               } else {
+                                       gs_p->notelist[0].stepsup = -1;
+                                       gs_p->notelist[0].c[RY] = -STEPSIZE;
+                                       gs_p->notelist[0].c[RN] -= STEPSIZE;
+                                       gs_p->notelist[0].c[RS] -= STEPSIZE;
+                               }
+                       }
+               }
+       }
+}
diff --git a/mup/mup/ssv.c b/mup/mup/ssv.c
new file mode 100644 (file)
index 0000000..4ec37b2
--- /dev/null
@@ -0,0 +1,1420 @@
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ * 2006 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ * Name:       ssv.c
+ *
+ * Description:        This file defines the instances of score, staff, and voice
+ *             structures that are used for viewpathing.  It also contains
+ *             functions for accessing them.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "defines.h"
+#include "rational.h"
+#include "structs.h"
+#include "globals.h"
+
+/* define the default order of stacking for marks */
+static char Defmarkorder[] = {
+       1,      /* MK_MUSSYM    */
+       2,      /* MK_OCTAVE    */
+       3,      /* MK_DYN       */
+       3,      /* MK_OTHERTEXT */
+       3,      /* MK_CHORD     */
+       4,      /* MK_LYRICS    */
+       5,      /* MK_ENDING    */
+       6,      /* MK_REHEARSAL */
+       7,      /* MK_PEDAL     */
+};
+
+/* default timesig of 4/4 */
+static char Dflt_timerep[] = { 4, TSR_SLASH, 4, TSR_END };
+
+static void freestaffset P((int num, struct STAFFSET *ss_p));
+static void asgnstaffset P((int num, struct STAFFSET **new_p_p,
+               struct STAFFSET *old_p));
+static void setorder P((int place, struct SSV *i_p, struct SSV *f_p));
+\f
+/*
+ * Name:        initstructs()
+ *
+ * Abstract:    Init the fixed instances of the SSV structures.
+ *
+ * Returns:     void
+ *
+ * Description: This function initializes all the fixed structures Score,
+ *             Staff[s], and Voice[s][v].  This needs to be done before
+ *             scanning through the main linked list of user input
+ *             structures.
+ */
+
+void
+initstructs()
+
+{
+       int s;          /* staff number */
+       int v;          /* voice number */
+       int n;          /* another loop variable */
+       int p;          /* place (PL_*) */
+       int m;          /* mark (MK_*) */
+       int hs;         /* head shape number */
+
+
+       /*
+        * Call zapssv() to release any malloc'ed memory, if any of the
+        * structures have been used before, and mark all fields unused.
+        */
+       zapssv(&Score);
+
+       for (s = 0; s < MAXSTAFFS; s++) {
+               zapssv(&Staff[s]);
+               for (v = 0; v < MAXVOICES; v++)
+                       zapssv(&Voice[s][v]);
+       }
+
+       /*
+        * Fill the Score structure with the proper default values, and
+        * mark all its fields as used.
+        */
+       /* score context */
+       Score.scale_factor = DEFSCALE;
+       Score.units = INCHES;
+       Score.pageheight = DEFPAGEHEIGHT;
+       Score.pagewidth = DEFPAGEWIDTH;
+       Score.panelsperpage = DEFPANELSPERPAGE;
+       Score.topmargin = DEFVMARGIN;
+       Score.botmargin = DEFVMARGIN;
+       Score.leftmargin = DEFHMARGIN;
+       Score.rightmargin = DEFHMARGIN;
+       Score.restcombine = NORESTCOMBINE;
+       Score.firstpage = NOFIRSTPAGE;
+       Score.staffs = DEFSTAFFS;
+       Score.minscsep = DEFMINSCSEP;
+       Score.maxscsep = DEFMAXSCSEP;
+       Score.minscpad = DEFMINSCPAD;
+       Score.maxscpad = DEFMAXSCPAD;
+       Score.nbrace = 0;
+       Score.nbrack = 0;
+       Score.nbarst = 0;
+       Score.timerep = Dflt_timerep;
+       Score.timenum = 4;
+       Score.timeden = 4;
+       Score.time.n = 1;
+       Score.time.d = 1;
+       Score.division = DEFDIVISION;
+       Score.endingstyle = ENDING_TOP;
+       Score.gridsatend = NO;
+       Score.measnum = NO;
+       Score.measnumfamily = BASE_TIMES;
+       Score.measnumfont = FONT_TR;
+       Score.measnumsize = MNUM_SIZE;
+       Score.packfact = DFLTPACKFACT;
+       Score.packexp = DFLTPACKEXP;
+       Score.warn = YES;
+
+       /* score and staff context */
+       Score.staffscale = DEFSTFSCALE;
+       Score.visible = YES;
+       Score.hidesilent = NO;
+       Score.stafflines = 5;
+       Score.strinfo = 0;
+       Score.printclef = SS_NORMAL;
+       Score.gridswhereused = NO;
+       Score.gridscale = DEFGRIDSCALE;
+       Score.gridfret = DEFGRIDFRET;
+       Score.numbermrpt = YES;
+       Score.printmultnum = YES;
+       Score.restsymmult = NO;
+       Score.vscheme = V_1;
+       for (v = 0; v < MAXVOICES; v++) {
+               Score.vcombine[v] = 0;
+       }
+       Score.vcombinequal = VC_NOOVERLAP;
+       Score.sharps = DEFSHARPS;
+       Score.is_minor = NO;
+       Score.cancelkey = NO;
+       Score.inttype = PERFECT;
+       Score.intnum = 1;
+       Score.addinttype = PERFECT;
+       Score.addintnum = 1;
+       Score.clef = TREBLE;
+       Score.rehstyle = RS_BOXED;
+       Score.fontfamily = BASE_TIMES;
+       Score.font = FONT_TR;
+       Score.size = DFLT_SIZE;
+       Score.lyricsfamily = BASE_TIMES;
+       Score.lyricsfont = FONT_TR;
+       Score.lyricssize = DFLT_SIZE;
+       Score.lyricsalign = DEFLYRICSALIGN;
+       Score.sylposition = DEFSYLPOSITION;
+       Score.minstsep = DEFMINSTSEP;
+       Score.staffpad = DEFSTPAD;
+       for (p = 0; p < NUM_PLACE; p++) {
+               for (m = 0; m < NUM_MARK; m++) {
+                       Score.markorder[p][m] = Defmarkorder[m];
+               }
+       }
+       Score.pedstyle = P_LINE;
+       Score.chorddist = DEFCHORDDIST;
+       Score.dist = DEFDIST;
+       Score.dyndist = DEFDYNDIST;
+       Score.label = 0;
+       Score.label2 = 0;
+
+       /* score, staff, and voice context */
+       Score.nbeam = 0;
+       Score.nsubbeam = 0;
+       Score.beamfact = DEFBEAMFACT;
+       Score.beammax = DEFBEAMMAX;
+       Score.pad = DEFPAD;
+       Score.stemlen = DEFSTEMLEN;
+       Score.stemshorten = DEFSTEMSHORTEN;
+       Score.defoct = DEFOCTAVE;
+       Score.timeunit.n = 1;
+       Score.timeunit.d = 4;
+       Score.timelist_p = 0;
+       Score.swingunit = Zero;
+       Score.release = DEFRELEASE;
+       Score.ontheline = YES;
+       Score.tabwhitebox = NO;
+       hs = get_shape_num("norm");
+       for (n = 0; n < 7; n++) {
+               Score.noteheads[n] = hs;
+       }
+
+       for (n = 0; n < NUMFLDS; n++) {
+               Score.used[n] = YES;    /* all items will be set in Score */
+       }
+}
+\f
+/*
+ * Name:        zapssv()
+ *
+ * Abstract:    Init a fixed instance of the SSV structure to empty.
+ *
+ * Returns:     void
+ *
+ * Description: This function initializes a fixed SSV structure to say that
+ *             all fields are unused.
+ */
+
+void
+zapssv(s_p)
+
+struct SSV *s_p;               /* pointer to the structure to be zapped */
+
+{
+       int n;          /* loop variable */
+
+
+       /*
+        * If the structure has been used before, we first have to free any
+        * memory that was malloc'ed.  It's okay to check "used" the first
+        * time, because global variables are set to 0 by the compiler;
+        * thus, used[X] == NO.
+        */
+       if (s_p->used[BRACELIST] == YES) {
+               freestaffset(s_p->nbrace, s_p->bracelist);
+               s_p->bracelist = 0;
+       }
+       if (s_p->used[BRACKLIST] == YES) {
+               freestaffset(s_p->nbrack, s_p->bracklist);
+               s_p->bracklist = 0;
+       }
+       if (s_p->used[BARSTLIST] == YES && s_p->barstlist != 0) {
+               FREE(s_p->barstlist);
+               s_p->barstlist = 0;
+       }
+       if (s_p->used[LABEL] == YES && s_p->label != 0) {
+               FREE(s_p->label);
+               s_p->label = 0;
+       }
+       if (s_p->used[LABEL2] == YES && s_p->label2 != 0) {
+               FREE(s_p->label2);
+               s_p->label2 = 0;
+       }
+       if (s_p->used[BEAMSTLIST] == YES && s_p->beamstlist != 0) {
+               FREE(s_p->beamstlist);
+               s_p->beamstlist = 0;
+       }
+
+       /*
+        * Mark all fields unused.
+        */
+       for (n = 0; n < NUMFLDS; n++) {
+               s_p->used[n] = NO;
+       }
+}
+\f
+/*
+ * Name:        freestaffset()
+ *
+ * Abstract:    Free all malloc'ed memory associated with a staffset list.
+ *
+ * Returns:     void
+ *
+ * Description: This function frees staffset structures, along with their
+ *             labels if they exist.
+ */
+
+static void
+freestaffset(num, ss_p)
+
+int num;                       /* how many staffsets are in list? */
+struct STAFFSET *ss_p;         /* pointer to first staffset */
+
+{
+       int n;                  /* loop variable */
+
+
+       if (ss_p == 0)                  /* if there is no list, just return */
+               return;
+
+       /* for each staffset in the list, free labels if present */
+       for (n = 0; n < num; n++) {
+               if (ss_p[n].label != 0) {               /* if label, free it */
+                       FREE(ss_p[n].label);
+                       ss_p[n].label = 0;
+               }
+               if (ss_p[n].label2 != 0) {      /* if label2, free it */
+                       FREE(ss_p[n].label2);
+                       ss_p[n].label2 = 0;
+               }
+       }
+
+       FREE(ss_p);                     /* free the staffset list itself */
+}
+\f
+/*
+ * Name:        asgnstaffset()
+ *
+ * Abstract:    Set up a staffset list in another SSV structure.
+ *
+ * Returns:     void
+ *
+ * Description: This function sets up a new staffset list identical to
+ *             another one, including the labels if they exist.
+ */
+
+static void
+asgnstaffset(num, new_p_p, old_p)
+
+int num;                       /* how many staffsets are in list? */
+struct STAFFSET **new_p_p;     /* ptr to ptr to first staffset of new list */
+struct STAFFSET *old_p;                /* pointer to first staffset of old list */
+
+{
+       int n;          /* loop variable */
+
+
+       if (num == 0)           /* if there's no old list, nothing to do */
+               return;
+
+       /*
+        * Allocate the new list and point at it.
+        */
+       MALLOC(STAFFSET, *new_p_p, num);
+
+       /*
+        * Loop through the old list.  Wherever there is a label, allocate
+        * one for the new list.  When there isn't, set that pointer to null.
+        */
+       for (n = 0; n < num; n++) {
+               (*new_p_p)[n].topstaff = old_p[n].topstaff;
+               (*new_p_p)[n].botstaff = old_p[n].botstaff;
+
+               if (old_p[n].label != 0) {
+                       MALLOCA(char, (*new_p_p)[n].label,
+                                       strlen(old_p[n].label) + 1);
+                       (void)strcpy((*new_p_p)[n].label, old_p[n].label);
+               } else {
+                       (*new_p_p)[n].label = 0;
+               }
+
+               if (old_p[n].label2 != 0) {
+                       MALLOCA(char, (*new_p_p)[n].label2,
+                                       strlen(old_p[n].label2) + 1);
+                       (void)strcpy((*new_p_p)[n].label2, old_p[n].label2);
+               } else {
+                       (*new_p_p)[n].label2 = 0;
+               }
+       }
+}
+\f
+/*
+ * Name:        svpath()
+ *
+ * Abstract:    Find a field for a staff, using the viewpath.
+ *
+ * Returns:     pointer to structure containing correct field value
+ *
+ * Description: This function, given a staff number and a field number, looks
+ *             down the viewpath to find the first structure where the field
+ *             is set.  It returns a pointer to that structure.  (However, see
+ *             below for a special kluge for the "visible" field.)
+ *             Note:  0 is allowed for the staff number, and that means use
+ *             the Score value.
+ */
+
+struct SSV *
+svpath(s, field)
+
+int s;         /* staff number, 1 to MAXSTAFFS; or 0, meaning score */
+int field;     /* the defined symbol for the field desired */
+
+{
+       static struct SSV phony;        /* phony SSV; see below */
+
+
+       if (s == 0)
+               return (&Score);
+
+       /*
+        * For the "visible" field, special kluges are needed, for two reasons.
+        * One is that there is a command line option (-s) that overrides the
+        * visibility requests in the Mup input file.  The other is that, even
+        * though it is a score/staff/voice parameter, it is easier to manage
+        * visibility at the staff level than at the voice level.  Otherwise,
+        * to know if a staff should be drawn, we would have to check vscheme
+        * and the visibility state of each voice.
+        *
+        * The design is as follows:  in mkchords.c, if a voice is to be
+        * invisible, a measure space is put in place of its original GRPSYL
+        * list.  Users can use svpath() to check if a staff is visible
+        * instead of having to call vvpath() for its voice(s).  The field
+        * staff_p->visible is set by calling here, so that will also be
+        * consistent.
+        *
+        * If the -s option was used on the command line, only staffs/voices
+        * listed there are ever allowed to be visible.  So although SSVs are
+        * set as for other score/staff/voice parameters, the results from
+        * svpath() also consider what the -s option said.  In vvpath() this
+        * is also done.
+        */
+       if (field == VISIBLE) {
+               int num_voices;         /* how many voices on this staff */
+
+               /*
+                * In case we are going to return the phony SSV, load the
+                * hidesilent field into it.  Both visible and hidesilent are
+                * controlled by VISIBLE, but hidesilent is not to be affected
+                * by the kluges needed for "visible".
+                */
+               /* if the field is set in the staff structure, use that */
+               if (Staff[s-1].used[VISIBLE] == YES) {
+                       phony.hidesilent = Staff[s-1].hidesilent;
+               } else {
+                       /* use the score structure; it's always set there */
+                       phony.hidesilent = Score.hidesilent;
+               }
+
+               /* always return NO if the command line says staff invisible */
+               if (Staff_vis[s] == NO) {
+                       /* return phony SSV with NO, ignore real SSV */
+                       phony.visible = NO;
+                       return (&phony);
+               }
+
+               num_voices = vscheme_voices(svpath(s, VSCHEME)->vscheme);
+
+               /*
+                * If a voice that the command line is allowing to be visible
+                * was requested via an SSV to be visible, we must let the
+                * staff be visible.
+                */
+               if ((Voice_vis[s][1] == YES &&
+                    Voice[s-1][0].used[VISIBLE] == YES &&
+                    Voice[s-1][0].visible == YES) ||
+
+                   (num_voices >= 2 &&
+                    Voice_vis[s][2] == YES &&
+                    Voice[s-1][1].used[VISIBLE] == YES &&
+                    Voice[s-1][1].visible == YES) ||
+
+                   (num_voices >= 3 &&
+                    Voice_vis[s][3] == YES &&
+                    Voice[s-1][2].used[VISIBLE] == YES &&
+                    Voice[s-1][2].visible == YES)) {
+
+                       /* return phony SSV with YES, ignore real SSV */
+                       phony.visible = YES;
+                       return (&phony);
+               }
+
+               /*
+                * If, for each voice that exists, either the command line is
+                * forcing it to be invisible or else it was requested via an
+                * SSV to be invisible, then the staff must be invisible.
+                */
+               if ((Voice_vis[s][1] == NO ||
+                    Voice[s-1][0].used[VISIBLE] == YES &&
+                    Voice[s-1][0].visible == NO) &&
+
+                   (num_voices < 2 ||
+                    (Voice_vis[s][2] == NO ||
+                     Voice[s-1][1].used[VISIBLE] == YES &&
+                     Voice[s-1][1].visible == NO)) &&
+
+                   (num_voices < 3 ||
+                    (Voice_vis[s][3] == NO ||
+                     Voice[s-1][2].used[VISIBLE] == YES &&
+                     Voice[s-1][2].visible == NO))) {
+
+                       /* return phony SSV with NO, ignore real SSV */
+                       phony.visible = NO;
+                       return (&phony);
+               }
+
+               /*
+                * The command line and the voice(s) aren't forcing the issue.
+                * So fall through to determine the staff's visibility the
+                * normal way.
+                */
+       }
+
+       /* if the field is set in the staff structure, use that */
+       if (Staff[s-1].used[field] == YES)
+               return (&Staff[s-1]);
+
+       /* else use the score structure; it's always set there */
+       return (&Score);
+}
+\f
+/*
+ * Name:        vvpath()
+ *
+ * Abstract:    Find a field for a voice, using the viewpath.
+ *
+ * Returns:     pointer to structure containing correct field value
+ *
+ * Description: This function, given a staff number, voice number on that
+ *             staff, and a field number, looks down the viewpath to find
+ *             the first structure where the field is set.  It returns a
+ *             pointer to that structure.  (However, see below for a special
+ *             kluge for the "visible" field.)
+ *             Note:  0 is allowed for the voice number, and that means use
+ *             the staff's value.  If staff is 0, the Score is used,
+ *             regardless of the voice number.
+ */
+
+struct SSV *
+vvpath(s, v, field)
+
+int s;         /* staff number, 1 to MAXSTAFFS; or 0, meaning score */
+int v;         /* voice number, 1 to MAXVOICES; or 0, meaning staff */
+int field;     /* the defined symbol for the field desired */
+
+{
+       static struct SSV phony;        /* phony SSV; see below */
+
+
+       if (s == 0 || v == 0)
+               return (svpath(s, field));
+
+       /*
+        * See the comment in svpath() regarding the "visible" field.  There's
+        * probably no need to call vvpath() for "visible" after mkchords.c has
+        * run, since voices that are to be invisible are changed to measure
+        * spaces there.  But in mkchords.c itself, and earlier, there is
+        * sometimes a need.
+        *
+        * For the "visible" field, first check the command line to see if this
+        * voice or its staff must always be invisible.  If so, return a phony
+        * SSV that says that.  Otherwise fall through to handle the normal way.
+        */
+       if (field == VISIBLE && (Staff_vis[s] == NO || Voice_vis[s][v] == NO)) {
+               /*
+                * Since we are going to force visible to NO, it's irrelevant
+                * what hidesilent is, so don't bother setting it, unlike what
+                * we had to do in svpath().
+                */
+               phony.visible = NO;
+               return (&phony);
+       }
+
+       /* if the field is set in the voice structure, use that */
+       if (Voice[s-1][v-1].used[field] == YES)
+               return (&Voice[s-1][v-1]);
+
+       /* else if the field is set in the staff structure, use that */
+       if (Staff[s-1].used[field] == YES)
+               return (&Staff[s-1]);
+
+       /* else use the score structure; it's always set there */
+       return (&Score);
+}
+\f
+/*
+ * Name:        asgnssv()
+ *
+ * Abstract:    Assign fields from an input SSV to a fixed one.
+ *
+ * Returns:     void
+ *
+ * Description: This function is passed an input SSV structure (from an input
+ *             context).  For each field where "used" is YES in the input SSV,
+ *             it copies it to the appropriate fixed SSV and sets its "used"
+ *             flag to YES.  For each field where "used" is UNSET in the input
+ *             SSV, it sets "used" to NO in the appropriate fixed SSV.
+ *             In some cases, there are side effects, where it also
+ *             alters a lower level structure.  E.g., changing the number of
+ *             voices of a staff inits its voice structures.  In the case
+ *             of stafflines, setting a staff to be a tablature staff
+ *             automatically automatically forces some other fields to be set
+ *             not only in the given staff, but also in the preceding tabnote
+ *             staff.  Note also that the Score "used" flags are already
+ *             always set and don't need to be set here.  And Score fields can
+ *             never be unset.
+ */
+
+void
+asgnssv(i_p)
+
+struct SSV *i_p;       /* input SSV structure to be copied from */
+
+{
+       struct SSV *f_p;        /* ptr to fixed SSV structure to copy into */
+       int s, v;               /* used for looping through staffs & voices */
+       int start, stop;        /* loop limits */
+       int n;                  /* another loop variable */
+
+
+       f_p = 0;        /* to prevent "uninitialized variable" warnings */
+
+       /*
+        * Using the selector fields in the input structure, set a pointer to
+        * the fixed structure that is to be populated.
+        */
+       switch (i_p->context) {
+       case C_SCORE:
+               f_p = &Score;
+               break;
+       case C_STAFF:
+               /* silently ignore bogus staff no.; it is caught elsewhere */
+               if (i_p->staffno < 1 || i_p->staffno > MAXSTAFFS) {
+                       return;
+               }
+               f_p = &Staff[ i_p->staffno - 1 ];
+               break;
+       case C_VOICE:
+               /* silently ignore bogus staff/voice; it is caught elsewhere */
+               if (i_p->staffno < 1 || i_p->staffno > MAXSTAFFS ||
+                   i_p->voiceno < 1 || i_p->voiceno > MAXVOICES) {
+                       return;
+               }
+               f_p = &Voice[ i_p->staffno - 1 ][ i_p->voiceno - 1 ];
+               break;
+       }
+
+       /*
+        * ========== ITEMS FOR SCORE CONTEXT ONLY ===========
+        * There's no need to set f_p->used[] = YES here; since this is the
+        * score, those bits are already always YES.
+        */
+       if (i_p->used[SCALE_FACTOR] == YES) {
+               f_p->scale_factor = i_p->scale_factor;
+       }
+
+       if (i_p->used[UNITS] == YES) {
+               f_p->units = i_p->units;
+       }
+
+       /*
+        * PAGEHEIGHT, PAGEHEIGHT, and PANELSPERPAGE interact, because when the
+        * user sets PAGE*, they are referring to the paper, but internally we
+        * want page* to refer to one "panel" of music, which is a 90 degree
+        * rotated half of the sheet of paper when panelsperpage is 2.
+        */
+       if (i_p->used[PAGEHEIGHT] == YES) {
+               if (f_p->panelsperpage == 1) {
+                       f_p->pageheight = i_p->pageheight;
+               } else {
+                       f_p->pagewidth = i_p->pageheight / 2.0;
+               }
+       }
+
+       if (i_p->used[PAGEWIDTH] == YES) {
+               if (f_p->panelsperpage == 1) {
+                       f_p->pagewidth = i_p->pagewidth;
+               } else {
+                       f_p->pageheight = i_p->pagewidth;
+               }
+       }
+
+       if (i_p->used[PANELSPERPAGE] == YES) {
+               /* depending on how this is changing, flip height and width */
+               float oldwidth;
+               if (f_p->panelsperpage == 1 && i_p->panelsperpage == 2) {
+                       oldwidth = f_p->pagewidth;
+                       f_p->pagewidth = f_p->pageheight / 2.0;
+                       f_p->pageheight = oldwidth;
+               } else if (f_p->panelsperpage == 2 && i_p->panelsperpage == 1) {
+                       oldwidth = f_p->pagewidth;
+                       f_p->pagewidth = f_p->pageheight;
+                       f_p->pageheight = oldwidth * 2.0;
+               }
+               f_p->panelsperpage = i_p->panelsperpage;
+       }
+
+       if (i_p->used[TOPMARGIN] == YES) {
+               f_p->topmargin = i_p->topmargin;
+       }
+
+       if (i_p->used[BOTMARGIN] == YES) {
+               f_p->botmargin = i_p->botmargin;
+       }
+
+       if (i_p->used[LEFTMARGIN] == YES) {
+               f_p->leftmargin = i_p->leftmargin;
+       }
+
+       if (i_p->used[RIGHTMARGIN] == YES) {
+               f_p->rightmargin = i_p->rightmargin;
+       }
+
+       if (i_p->used[RESTCOMBINE] == YES) {
+               f_p->restcombine = i_p->restcombine;
+       }
+
+       if (i_p->used[FIRSTPAGE] == YES) {
+               f_p->firstpage = i_p->firstpage;
+       }
+
+       if (i_p->used[NUMSTAFF] == YES) {
+               f_p->staffs = i_p->staffs;
+
+               /* this destroys all staff and voice info */
+               for (s = 0; s < MAXSTAFFS; s++) {
+                       zapssv(&Staff[s]);
+                       for (v = 0; v < MAXVOICES; v++)
+                               zapssv(&Voice[s][v]);
+               }
+       }
+
+       if (i_p->used[MINSCSEP] == YES) {
+               f_p->minscsep = i_p->minscsep;
+       }
+
+       if (i_p->used[MAXSCSEP] == YES) {
+               f_p->maxscsep = i_p->maxscsep;
+       }
+
+       if (i_p->used[MINSCPAD] == YES) {
+               f_p->minscpad = i_p->minscpad;
+       }
+
+       if (i_p->used[MAXSCPAD] == YES) {
+               f_p->maxscpad = i_p->maxscpad;
+       }
+
+       if (i_p->used[BRACELIST] == YES) {
+               /* if it was already used, free old list if present */
+               if (f_p->used[BRACELIST] == YES) {
+                       freestaffset(f_p->nbrace, f_p->bracelist);
+                       f_p->bracelist = 0;
+               }
+
+               /* set up new list */
+               f_p->nbrace = i_p->nbrace;
+               asgnstaffset(f_p->nbrace, &f_p->bracelist, i_p->bracelist);
+       }
+
+       if (i_p->used[BRACKLIST] == YES) {
+               /* if it was already used, free old list if present */
+               if (f_p->used[BRACKLIST] == YES) {
+                       freestaffset(f_p->nbrack, f_p->bracklist);
+                       f_p->bracklist = 0;
+               }
+
+               /* set up new list */
+               f_p->nbrack = i_p->nbrack;
+               asgnstaffset(f_p->nbrack, &f_p->bracklist, i_p->bracklist);
+       }
+
+       if (i_p->used[BARSTLIST] == YES) {
+               /* if it was already used, free old list if present */
+               if (f_p->used[BARSTLIST] == YES && f_p->nbarst != 0)
+                       FREE(f_p->barstlist);
+
+               /* set up new list */
+               f_p->nbarst = i_p->nbarst;
+               /* the +1 is to guard against allocating 0 */
+               MALLOC(TOP_BOT, f_p->barstlist, f_p->nbarst + 1);
+               for (n = 0; n < f_p->nbarst; n++) {
+                       f_p->barstlist[n] = i_p->barstlist[n];
+               }
+       }
+
+       if (i_p->used[TIME] == YES) {
+               f_p->timenum  = i_p->timenum;
+               f_p->timeden  = i_p->timeden;
+               f_p->timevis  = i_p->timevis;
+               f_p->timerep  = i_p->timerep;
+               f_p->time     = i_p->time;
+
+               /*
+                * Changing the time sig forces a change in default time unit.
+                * Set it to one "beat" for the score, and unset it for all
+                * staffs and voices.
+                */
+               f_p->timeunit.n = 1;
+               f_p->timeunit.d = f_p->timeden;
+               f_p->timelist_p = 0;
+               for (s = 0; s < MAXSTAFFS; s++) {
+                       Staff[s].used[TIMEUNIT] = NO;
+                       for (v = 0; v < MAXVOICES; v++)
+                               Voice[s][v].used[TIMEUNIT] = NO;
+               }
+
+               /*
+                * Changing the time also destroys all beamstyle lists.
+                * However, the special empty beamstyle list that was set up
+                * for a tablature staff must be retained, so that it will
+                * continue to override any score beamstyle list that may be
+                * set up later on.
+                */
+               if (Score.used[BEAMSTLIST] == YES) {
+                       if (Score.nbeam != 0) {
+                               FREE(Score.beamstlist);
+                               Score.beamstlist = 0;
+                               Score.nbeam = 0;
+                               FREE(Score.subbeamstlist);
+                               Score.subbeamstlist = 0;
+                               Score.nsubbeam = 0;
+                       }
+               }
+               for (s = 0; s < MAXSTAFFS; s++) {
+                       if (Staff[s].used[BEAMSTLIST] == YES &&
+                           Staff[s].strinfo == 0) {    /* not tablature */
+                               if (Staff[s].nbeam != 0) {
+                                       FREE(Staff[s].beamstlist);
+                                       Staff[s].beamstlist = 0;
+                                       Staff[s].nbeam = 0;
+                                       FREE(Staff[s].subbeamstlist);
+                                       Staff[s].subbeamstlist = 0;
+                                       Staff[s].nsubbeam = 0;
+                               }
+                               Staff[s].used[BEAMSTLIST] = NO;
+                       }
+                       for (v = 0; v < MAXVOICES; v++) {
+                               if (Voice[s][v].used[BEAMSTLIST] == YES) {
+                                       if (Voice[s][v].nbeam != 0) {
+                                               FREE(Voice[s][v].beamstlist);
+                                               Voice[s][v].beamstlist = 0;
+                                               Voice[s][v].nbeam = 0;
+                                               FREE(Voice[s][v].subbeamstlist);
+                                               Voice[s][v].subbeamstlist = 0;
+                                               Voice[s][v].nsubbeam = 0;
+                                       }
+                                       Voice[s][v].used[BEAMSTLIST] = NO;
+                               }
+                       }
+               }
+       }
+
+       if (i_p->used[DIVISION] == YES) {
+               f_p->division = i_p->division;
+       }
+
+       if (i_p->used[ENDINGSTYLE] == YES) {
+               f_p->endingstyle = i_p->endingstyle;
+       }
+
+       if (i_p->used[GRIDSATEND] == YES) {
+               f_p->gridsatend = i_p->gridsatend;
+       }
+
+       if (i_p->used[MEASNUM] == YES) {
+               f_p->measnum = i_p->measnum;
+       }
+
+       if (i_p->used[MEASNUMFAMILY] == YES) {
+               f_p->measnumfamily = i_p->measnumfamily;
+       }
+
+       if (i_p->used[MEASNUMFONT] == YES) {
+               f_p->measnumfont = i_p->measnumfont;
+       }
+
+       if (i_p->used[MEASNUMSIZE] == YES) {
+               f_p->measnumsize = i_p->measnumsize;
+       }
+
+       if (i_p->used[PACKFACT] == YES) {
+               f_p->packfact = i_p->packfact;
+       }
+
+       if (i_p->used[PACKEXP] == YES) {
+               f_p->packexp = i_p->packexp;
+       }
+
+       if (i_p->used[WARN] == YES) {
+               f_p->warn = i_p->warn;
+       }
+
+       /*
+        * ========== ITEMS FOR SCORE AND STAFF CONTEXT ===========
+        */
+       /*
+        * Most parameters involve just a single field, and have no side
+        * effects.  For this, we can use the following switch statement to
+        * do the work, for parameters that can exist on staff or voice.
+        * (Score-only ones don't need it, since that can't be unset.)
+        */
+#define        SETPARM(name, NAME)                     \
+       switch (i_p->used[NAME]) {              \
+       case YES:                               \
+               f_p->name = i_p->name;          \
+               f_p->used[NAME] = YES;          \
+               break;                          \
+       case UNSET:                             \
+               f_p->used[NAME] = NO;           \
+               break;                          \
+       /* default is NO; do nothing */         \
+       }
+
+       SETPARM(staffscale, STAFFSCALE)
+
+       switch (i_p->used[STAFFLINES]) {
+       case YES: {
+               struct SSV *tabnote_p;  /* ptr to tabnote fixed SSV */
+               f_p->stafflines = i_p->stafflines;
+
+               if (i_p->strinfo != 0) {        /* tablature */
+                       struct SSV *voice_p;    /* ptr to a voice's fixed SSV*/
+
+                       /*
+                        * This is a tablature staff.  Set printclef to normal
+                        * (even though tab isn't particularly "normal").
+                        * Point f_p->strinfo at the same array that
+                        * i_p->strinfo points at.
+                        */
+                       f_p->printclef = SS_NORMAL;
+                       f_p->strinfo = i_p->strinfo;
+
+                       /*
+                        * Force some other score/staff items to fixed values
+                        * for tab.  The parser blocks the user from setting
+                        * these.  We need to set them here in the staff SSV to
+                        * override whatever may be in the score SSV.  This
+                        * will make it possible to avoid special checks for
+                        * tablature in many places; the right values will be
+                        * set for this staff.  Also force score/staff/voice
+                        * items here.
+                        */
+                       f_p->sharps = 0;
+                       f_p->is_minor = NO;
+                       f_p->used[SHARPS] = YES;
+
+                       f_p->inttype = PERFECT;
+                       f_p->intnum = 1;
+                       f_p->used[TRANSPOSITION] = YES;
+
+                       f_p->addinttype = PERFECT;
+                       f_p->addintnum = 1;
+                       f_p->used[ADDTRANSPOSITION] = YES;
+
+                       f_p->clef = TABCLEF;
+                       f_p->used[CLEF] = YES;
+
+                       if (f_p->used[BEAMSTLIST] == YES && f_p->nbeam != 0) {
+                               /* if already used, free old list if present */
+                               FREE(f_p->beamstlist);
+                               FREE(f_p->subbeamstlist);
+                       }
+                       f_p->nbeam = 0;
+                       f_p->beamstlist = 0;
+                       f_p->nsubbeam = 0;
+                       f_p->subbeamstlist = 0;
+                       f_p->used[BEAMSTLIST] = YES;
+
+                       f_p->defoct = 4;
+                       f_p->used[DEFOCT] = YES;
+
+                       /* blow away the following in tab staff's voices */
+                       for (v = 0; v < MAXVOICES; v++) {
+                               voice_p = &Voice[ i_p->staffno - 1][ v ];
+
+                               if (voice_p->used[BEAMSTLIST] == YES) {
+                                       if (voice_p->nbeam != 0) {
+                                               FREE(f_p->beamstlist);
+                                               FREE(f_p->subbeamstlist);
+                                       }
+                                       voice_p->used[BEAMSTLIST] = NO;
+                               }
+                               voice_p->used[DEFOCT] = NO;
+                       }
+
+                       /*
+                        * Force fields on the tabnote staff above this tab
+                        * staff.
+                        */
+                       tabnote_p = &Staff[ i_p->staffno - 2 ];
+
+                       /*
+                        * The parse phase wouldn't let this be another tab
+                        * staff, so we don't need to check for that.  But it
+                        * might be a 1-line staff.  If so, override it to 5
+                        * line.  If this parameter wasn't set, force printclef
+                        * to normal, but if it was, keep the old value.  (We
+                        * might as well allow 5n and 5 drum as well as 5,
+                        * though that would be a weird usage.)
+                        */
+                       tabnote_p->stafflines = 5;
+                       if (tabnote_p->used[STAFFLINES] == NO)
+                               tabnote_p->printclef = SS_NORMAL;
+                       tabnote_p->used[STAFFLINES] = YES;
+
+               } else {        /* not tablature */
+                       /*
+                        * If this staff used to be tablature, we need to unset
+                        * some "used" fields that were forced.
+                        */
+                       if (f_p->strinfo != 0) {
+                               f_p->used[SHARPS] = NO;
+                               f_p->used[TRANSPOSITION] = NO;
+                               f_p->used[ADDTRANSPOSITION] = NO;
+                               f_p->used[CLEF] = NO;
+                               f_p->used[BEAMSTLIST] = NO;
+                               f_p->used[DEFOCT] = NO;
+                               tabnote_p = &Staff[ i_p->staffno - 2 ];
+
+                               /* make it non-tablature */
+                               f_p->strinfo = 0;
+                       }
+
+                       f_p->printclef = i_p->printclef;
+               }
+               f_p->used[STAFFLINES] = YES;
+               } break;
+       case UNSET:
+               f_p->used[STAFFLINES] = NO;
+               break;
+       }
+
+       SETPARM(gridswhereused, GRIDSWHEREUSED)
+
+       SETPARM(gridscale, GRIDSCALE)
+
+       SETPARM(gridfret, GRIDFRET)
+
+       SETPARM(numbermrpt, NUMBERMRPT)
+
+       SETPARM(printmultnum, PRINTMULTNUM)
+
+       SETPARM(restsymmult, RESTSYMMULT)
+
+       switch (i_p->used[VSCHEME]) {
+       case YES:
+               /*
+                * If the vscheme change changes the *number* of voices, we
+                * have to wipe out the voice information, but otherwise not.
+                */
+               if (i_p->context == C_SCORE) {
+                       start = 0;              /* if score, do test for */
+                       stop = MAXSTAFFS - 1;   /*  all staffs */
+               } else {        /* C_STAFF */
+                       start = stop = i_p->staffno - 1; /* do just this one */
+               }
+
+               /* for each staff affected by this change . . . */
+               for (n = start; n <= stop; n++) {
+                       int oldvoices, newvoices; /* how many before & after */
+
+                       oldvoices = vscheme_voices(svpath(n + 1,
+                                       VSCHEME)->vscheme);
+                       newvoices = vscheme_voices(i_p->vscheme);
+
+                       if (oldvoices != newvoices) {
+
+                               for (v = 0; v < MAXVOICES; v++)
+                                       zapssv(&Voice[n][v]);
+                       }
+               }
+
+               f_p->vscheme = i_p->vscheme;
+               f_p->used[VSCHEME] = YES;
+               break;
+       case UNSET:
+               f_p->used[VSCHEME] = NO;
+               break;
+       }
+
+       switch (i_p->used[VCOMBINE]) {
+       case YES:
+               for (v = 0; v < MAXVOICES; v++) {
+                       f_p->vcombine[v] = i_p->vcombine[v];
+               }
+               f_p->vcombinequal = i_p->vcombinequal;
+               f_p->used[VCOMBINE] = YES;
+               break;
+       case UNSET:
+               f_p->used[VCOMBINE] = NO;
+               break;
+       }
+
+       switch (i_p->used[SHARPS]) {
+       case YES:
+               f_p->sharps = i_p->sharps;
+               f_p->is_minor = i_p->is_minor;
+               f_p->used[SHARPS] = YES;
+               break;
+       case UNSET:
+               f_p->used[SHARPS] = NO;
+               break;
+       }
+
+       SETPARM(cancelkey, CANCELKEY)
+
+       switch (i_p->used[TRANSPOSITION]) {
+       case YES:
+               f_p->inttype = i_p->inttype;
+               f_p->intnum = i_p->intnum;
+               f_p->used[TRANSPOSITION] = YES;
+               break;
+       case UNSET:
+               f_p->used[TRANSPOSITION] = NO;
+               break;
+       }
+
+       switch (i_p->used[ADDTRANSPOSITION]) {
+       case YES:
+               f_p->addinttype = i_p->addinttype;
+               f_p->addintnum = i_p->addintnum;
+               f_p->used[ADDTRANSPOSITION] = YES;
+               break;
+       case UNSET:
+               f_p->used[ADDTRANSPOSITION] = NO;
+               break;
+       }
+
+       switch (i_p->used[CLEF]) {
+       case YES:
+               f_p->clef = i_p->clef;
+               f_p->used[CLEF] = YES;
+
+               /*
+                * Reset the default octave so that the middle line of the
+                * staff lies within it.  If the user also set octave in
+                * this context, this will get changed again later in this
+                * function.
+                */
+               if (f_p->clef > ALTO)           /* lower than alto */
+                       f_p->defoct = 3;
+               else if (f_p->clef < TREBLE)    /* higher than treble */
+                       f_p->defoct = 5;
+               else
+                       f_p->defoct = 4;
+               f_p->used[DEFOCT] = YES;
+               break;
+       case UNSET:
+               f_p->used[DEFOCT] = NO;
+               break;
+       }
+
+       SETPARM(rehstyle, REHSTYLE)
+
+       SETPARM(fontfamily, FONTFAMILY)
+
+       SETPARM(font, FONT)
+
+       SETPARM(size, SIZE)
+
+       SETPARM(lyricsfamily, LYRICSFAMILY)
+
+       SETPARM(lyricsfont, LYRICSFONT)
+
+       SETPARM(lyricssize, LYRICSSIZE)
+
+       SETPARM(lyricsalign, LYRICSALIGN)
+
+       SETPARM(sylposition, SYLPOSITION)
+
+       SETPARM(minstsep, MINSTSEP)
+
+       SETPARM(staffpad, STAFFPAD)
+
+       switch (i_p->used[ABOVEORDER]) {
+       case YES:
+               setorder(PL_ABOVE, i_p, f_p);
+               f_p->used[ABOVEORDER] = YES;
+               break;
+       case UNSET:
+               f_p->used[ABOVEORDER] = NO;
+               break;
+       }
+
+       switch (i_p->used[BELOWORDER]) {
+       case YES:
+               setorder(PL_BELOW, i_p, f_p);
+               f_p->used[BELOWORDER] = YES;
+               break;
+       case UNSET:
+               f_p->used[BELOWORDER] = NO;
+               break;
+       }
+
+       switch (i_p->used[BETWEENORDER]) {
+       case YES:
+               setorder(PL_BETWEEN, i_p, f_p);
+               f_p->used[BETWEENORDER] = YES;
+               break;
+       case UNSET:
+               f_p->used[BETWEENORDER] = NO;
+               break;
+       }
+
+       SETPARM(pedstyle, PEDSTYLE)
+
+       SETPARM(chorddist, CHORDDIST)
+
+       SETPARM(dist, DIST)
+
+       SETPARM(dyndist, DYNDIST)
+
+       switch (i_p->used[LABEL]) {
+       case YES:
+               /* if it was already used, free old label */
+               if (f_p->used[LABEL] == YES && f_p->label != 0) {
+                       FREE(f_p->label);
+                       f_p->label = 0;
+               }
+
+               /* set up new label */
+               MALLOCA(char, f_p->label, strlen(i_p->label) + 1);      
+               (void)strcpy(f_p->label, i_p->label);
+
+               f_p->used[LABEL] = YES;
+               break;
+       case UNSET:
+               /* if it was already used, free old label */
+               if (f_p->used[LABEL] == YES && f_p->label != 0) {
+                       FREE(f_p->label);
+                       f_p->label = 0;
+               }
+               f_p->used[LABEL] = NO;
+               break;
+       }
+
+       switch (i_p->used[LABEL2]) {
+       case YES:
+               /* if it was already used, free old label2 */
+               if (f_p->used[LABEL2] == YES && f_p->label2 != 0) {
+                       FREE(f_p->label2);
+                       f_p->label2 = 0;
+               }
+
+               /* set up new label */
+               MALLOCA(char, f_p->label2, strlen(i_p->label2) + 1);
+               (void)strcpy(f_p->label2, i_p->label2);
+
+               f_p->used[LABEL2] = YES;
+               break;
+       case UNSET:
+               /* if it was already used, free old label2 */
+               if (f_p->used[LABEL2] == YES && f_p->label2 != 0) {
+                       FREE(f_p->label2);
+                       f_p->label2 = 0;
+               }
+               f_p->used[LABEL2] = NO;
+               break;
+       }
+
+       /*
+        * ========== ITEMS FOR SCORE, STAFF, AND VOICE CONTEXT ===========
+        */
+       switch (i_p->used[VISIBLE]) {
+       case YES:
+               f_p->visible = i_p->visible;
+               f_p->hidesilent = i_p->hidesilent;
+               f_p->used[VISIBLE] = YES;
+               break;
+       case UNSET:
+               f_p->used[VISIBLE] = NO;
+       }
+
+       switch (i_p->used[BEAMSTLIST]) {
+       case YES:
+               /* if it was already used, free old list if present */
+               if (f_p->used[BEAMSTLIST] == YES && f_p->nbeam != 0) {
+                       FREE(f_p->beamstlist);
+                       FREE(f_p->subbeamstlist);
+                       f_p->beamstlist = 0;
+                       f_p->subbeamstlist = 0;
+               }
+
+               /* set up new list */
+               f_p->nbeam = i_p->nbeam;
+               f_p->beamrests = i_p->beamrests;
+               f_p->beamspaces = i_p->beamspaces;
+               f_p->nsubbeam = i_p->nsubbeam;
+               /* the +1 is to guard against allocating 0 */
+               MALLOCA(RATIONAL, f_p->beamstlist, f_p->nbeam + 1);
+               MALLOCA(RATIONAL, f_p->subbeamstlist, f_p->nsubbeam + 1);
+               for (n = 0; n < f_p->nbeam; n++) {
+                       f_p->beamstlist[n] = i_p->beamstlist[n];
+               }
+               for (n = 0; n < f_p->nsubbeam; n++) {
+                       f_p->subbeamstlist[n] = i_p->subbeamstlist[n];
+               }
+
+               f_p->used[BEAMSTLIST] = YES;
+               break;
+       case UNSET:
+               /* if it was already used, free old list if present */
+               if (f_p->used[BEAMSTLIST] == YES && f_p->nbeam != 0) {
+                       FREE(f_p->beamstlist);
+                       FREE(f_p->subbeamstlist);
+                       f_p->beamstlist = 0;
+                       f_p->subbeamstlist = 0;
+               }
+               f_p->used[BEAMSTLIST] = NO;
+               break;
+       }
+
+       switch (i_p->used[BEAMSLOPE]) {
+       case YES:
+               f_p->beamfact = i_p->beamfact;
+               f_p->beammax = i_p->beammax;
+               f_p->used[BEAMSLOPE] = YES;
+               break;
+       case UNSET:
+               f_p->used[BEAMSLOPE] = NO;
+               break;
+       }
+
+       SETPARM(pad, PAD)
+
+       SETPARM(stemlen, STEMLEN)
+
+       SETPARM(stemshorten, STEMSHORTEN)
+
+       SETPARM(defoct, DEFOCT)
+
+       switch (i_p->used[TIMEUNIT]) {
+       case YES:
+               f_p->timeunit = i_p->timeunit;
+               f_p->timelist_p = i_p->timelist_p;
+               f_p->used[TIMEUNIT] = YES;
+               break;
+       case UNSET:
+               f_p->used[TIMEUNIT] = NO;
+       }
+
+       SETPARM(swingunit, SWINGUNIT)
+
+       SETPARM(release, RELEASE)
+
+       SETPARM(ontheline, ONTHELINE)
+
+       SETPARM(tabwhitebox, TABWHITEBOX)
+
+       switch (i_p->used[NOTEHEADS]) {
+       case YES:
+               for (n = 0; n < 7; n++) {
+                       f_p->noteheads[n] = i_p->noteheads[n];
+               }
+               f_p->used[NOTEHEADS] = YES;
+               break;
+       case UNSET:
+               f_p->used[NOTEHEADS] = NO;
+               break;
+       }
+}
+\f
+/*
+ * Name:        setssvstate()
+ *
+ * Abstract:    Set the static SSVs to the state for a given place in the MML.
+ *
+ * Returns:     void
+ *
+ * Description: This function, given any structure from the main linked list,
+ *             initializes the static SSVs, and then runs through the MLL up
+ *             to just before that point, assigning SSVs.  It assigns not only
+ *             the SSVs in the MLL, but also the timed SSVs hanging off
+ *             barlines.  You can pass a null pointer, and then it will go
+ *             through the whole MLL.
+ */
+
+void
+setssvstate(mainll_p)
+
+struct MAINLL *mainll_p;       /* place in the MLL to stop */
+
+{
+       struct MAINLL *mll_p;           /* for looping through MLL */
+       struct TIMEDSSV *tssv_p;        /* for looping through TIMEDSSV lists*/
+
+
+       initstructs();
+       for (mll_p = Mainllhc_p; mll_p != 0 && mll_p != mainll_p;
+                       mll_p = mll_p->next) {
+               switch (mll_p->str) {
+               case S_SSV:
+                       /* assign this normal input SSV */
+                       asgnssv(mll_p->u.ssv_p);
+                       break;
+               case S_BAR:
+                       /* assign each timed SSV, if any */
+                       for (tssv_p = mll_p->u.bar_p->timedssv_p; tssv_p != 0;
+                                       tssv_p = tssv_p->next) {
+                               asgnssv(&tssv_p->ssv);
+                       }
+                       break;
+               }
+       }
+}
+\f
+/*
+ * Name:        setorder()
+ *
+ * Abstract:    Assign an "order" field from an input SSV to a fixed one.
+ *
+ * Returns:     void
+ *
+ * Description: This function is called by asgnssv() to assign to the
+ *             appropriate part of the markorder array, based on above, below,
+ *             or between.
+ */
+
+static void
+setorder(place, i_p, f_p)
+
+int place;             /* PL_* */
+struct SSV *i_p;       /* input SSV structure to be copied from */
+struct SSV *f_p;       /* ptr to fixed SSV structure to copy into */
+
+{
+       int m;          /* mark (MK_*) */
+       int stk;        /* stacking order */
+
+
+       /*
+        * First assign all the marks' stacking orders as given.  Keep track of
+        * the highest stacking order number found.
+        */
+       stk = 0;
+       for (m = 0; m < NUM_MARK; m++) {
+               f_p->markorder[place][m] = i_p->markorder[place][m];
+
+               if (f_p->markorder[place][m] > stk)
+                       stk = f_p->markorder[place][m];
+       }
+
+       /*
+        * For every mark type that the user didn't list, the stacking order is
+        * now 0.  Set all these to default settings, higher than all the ones
+        * the user listed, but in the same order as Defmarkorder.  They will
+        * all be separate numbers, none set equal, unlike Defmarkorder, where
+        * some are equal.
+        */
+       for (m = 0; m < NUM_MARK; m++) {
+               if (f_p->markorder[place][m] == 0) {
+                       f_p->markorder[place][m] = ++stk;
+               }
+       }
+}
diff --git a/mup/mup/ssvused.h b/mup/mup/ssvused.h
new file mode 100644 (file)
index 0000000..24141f0
--- /dev/null
@@ -0,0 +1,104 @@
+/* Copyright (c) 2001, 2003, 2004, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+#ifndef _SSVUSED_H
+#define _SSVUSED_H
+
+/*
+ * This file contains the array subscript definitions for the used[] array
+ * of an SSV struct. An SSV contains parameters associated with a
+ * Score, Staff, or Voice.  The used[] array is a set of flags which say
+ * whether a given parameter is actually populated in the SSV instance.
+ * In the "score" SSV, all used flags are always set true.  In SSVs for
+ * a staff or voice, a "used" flag is only set to true if the user
+ * specified a value for the parameter in that staff or voice context.
+ *
+ * The actual values are machine-generated so they get automatically
+ * renumbered if parameters are added or deleted or rearranged.
+ *
+ * We try to put things that are logically similar close together in
+ * this list, but they could be in any order, other than that NUMFLDS
+ * _must_ be last.
+ */
+
+#define        SCALE_FACTOR            (0)
+#define        UNITS                   (1)
+#define        PAGEHEIGHT              (2)
+#define        PAGEWIDTH               (3)
+#define        PANELSPERPAGE           (4)
+#define        TOPMARGIN               (5)
+#define        BOTMARGIN               (6)
+#define        LEFTMARGIN              (7)
+#define        RIGHTMARGIN             (8)
+#define        RESTCOMBINE             (9)
+#define        FIRSTPAGE               (10)
+#define        NUMSTAFF                (11)
+#define        MINSCSEP                (12)
+#define        MAXSCSEP                (13)
+#define        MINSCPAD                (14)
+#define        MAXSCPAD                (15)
+#define        BRACELIST               (16)
+#define        BRACKLIST               (17)
+#define        BARSTLIST               (18)
+#define        TIME                    (19)
+#define        DIVISION                (20)
+#define        ENDINGSTYLE             (21)
+#define        GRIDSATEND              (22)
+#define        MEASNUM                 (23)
+#define        MEASNUMFAMILY           (24)
+#define        MEASNUMFONT             (25)
+#define        MEASNUMSIZE             (26)
+#define        PACKFACT                (27)
+#define        PACKEXP                 (28)
+#define        WARN                    (29)
+#define        STAFFSCALE              (30)
+#define        VISIBLE                 (31)
+#define        STAFFLINES              (32)
+#define        GRIDSWHEREUSED          (33)
+#define        GRIDSCALE               (34)
+#define        GRIDFRET                (35)
+#define        NUMBERMRPT              (36)
+#define        PRINTMULTNUM            (37)
+#define        RESTSYMMULT             (38)
+#define        VSCHEME                 (39)
+#define        VCOMBINE                (40)
+#define        SHARPS                  (41)
+#define        CANCELKEY               (42)
+#define        TRANSPOSITION           (43)
+#define        ADDTRANSPOSITION        (44)
+#define        CLEF                    (45)
+#define        REHSTYLE                (46)
+#define        FONTFAMILY              (47)
+#define        FONT                    (48)
+#define        SIZE                    (49)
+#define        LYRICSFAMILY            (50)
+#define        LYRICSFONT              (51)
+#define        LYRICSSIZE              (52)
+#define        LYRICSALIGN             (53)
+#define        SYLPOSITION             (54)
+#define        MINSTSEP                (55)
+#define        STAFFPAD                (56)
+#define        ABOVEORDER              (57)
+#define        BELOWORDER              (58)
+#define        BETWEENORDER            (59)
+#define        PEDSTYLE                (60)
+#define        CHORDDIST               (61)
+#define        DIST                    (62)
+#define        DYNDIST                 (63)
+#define        LABEL                   (64)
+#define        LABEL2                  (65)
+#define        BEAMSTLIST              (66)
+#define        BEAMSLOPE               (67)
+#define        PAD                     (68)
+#define        STEMLEN                 (69)
+#define        STEMSHORTEN             (70)
+#define        DEFOCT                  (71)
+#define        TIMEUNIT                (72)
+#define        SWINGUNIT               (73)
+#define        RELEASE                 (74)
+#define        ONTHELINE               (75)
+#define        TABWHITEBOX             (76)
+#define        NOTEHEADS               (77)
+#define        NUMFLDS                 (78)
+
+#endif
diff --git a/mup/mup/structs.h b/mup/mup/structs.h
new file mode 100644 (file)
index 0000000..3c2c197
--- /dev/null
@@ -0,0 +1,1423 @@
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ * 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ *     structs.h
+ *
+ *     This file defines the structures needed for the Mup program.
+ */
+
+#ifndef _STRUCTS
+#define _STRUCTS
+
+#include <stdio.h>
+#include "defines.h"
+#include "rational.h"
+
+/*
+ * Define a structure for holding coordinates as input.  These are always
+ * relative to something, either a real object, _page (the whole sheet of
+ * paper), _win (this context's window: header, footer, or center region),
+ * or _cur (the current position).
+ *
+ * Both the horizonal and vertical elements have a pointer to some
+ * object's coordinates, and a type, which tells what part of the object is
+ * to be used.  The type is RX (relative X), AE (absolute east), etc.  For
+ * horizontal this would be one of [RA][XEW].  For y this would be one
+ * of [RA][YNS].  Both hor and vert also have a fixed offset that is to be
+ * added in (could be 0), measured in step sizes.  Finally, hor also has a
+ * counts value, which translates to a width, based on the 13th coordinate
+ * (INCHPERWHOLE) of the thing this structure is attached to.  This field is
+ * not allowed in headers and footers.
+ */
+struct INPCOORD {
+       float *hor_p;
+       short htype;
+       float hsteps;
+       float counts;
+
+       float *vert_p;
+       short vtype;
+       float vsteps;
+};
+
+/*
+ * We save a linked list of the addresses of tag references, so that if a tag
+ * is moved, we can update its references.
+ */
+struct COORD_REF {
+       float **ref_p_p;                /* address of tag reference */
+       struct COORD_REF *next;         /* for linked list */
+};
+
+/*
+ * For each coodinate that is pointed to by some location variable, we
+ * need a bunch of information about it, such as whether it's from a NOTE,
+ * BAR, builtin variable, or GRPSYL. If not a builtin varaible, we'll need
+ * to know what page, score, and (if GRPSYL) staff, it is associated with
+ * in order to figure out how to split things that end up on different
+ * scores and/or pages.
+ */
+struct COORD_INFO {
+       float *coordlist_p;             /* address of the coordinate */
+       short flags;                    /* if CT_NOTE, CT_BAR, etc */
+       short page;                     /* which page it's on */
+       short scorenum;                 /* which score on the page */
+       short staffno;                  /* which staff (CT_GRPSYL only) */
+       struct MAINLL *mll_feed_p;  /* the feed info about the score it's on */
+       struct BAR *pseudo_bar_p;       /* if this is a CT_BAR that happens
+                                        * to fall at the end of a score,
+                                        * this field will contain a pointer
+                                        * to the pseudo bar at the beginning
+                                        * of the following score */
+       struct COORD_REF *ref_list_p;   /* list of references to this coord */
+       struct COORD_INFO *next;        /* linked list off hash table */
+};
+
+/*
+ * Define a structure to be used to hold two staff numbers, and pointers
+ * to strings to be malloc'ed to hold labels, if desired.  This is to
+ * be used for brace and bracket info.
+ */
+struct STAFFSET {
+       short topstaff;         /* first staff joined by brace or bracket */
+       short botstaff;         /* last staff joined by brace or bracket */
+       char *label;            /* label to be used on first score */
+       char *label2;           /* label to be used on later scores */
+};
+
+/*
+ * Define a structure to be used to hold top and bottom of a range of staffs
+ */
+struct TOP_BOT {
+       short top;
+       short bottom;
+};
+
+/*
+ * Define headcell structure pointing off at linked list of structures
+ * holding information about an instance of one of the contexts of the
+ * C_BLOCKHEAD class.
+ */
+struct BLOCKHEAD {
+       struct PRINTDATA *printdata_p;  /* point at first item in list */
+       float c[NUMCTYPE];              /* for _win */
+       float height;                   /* of the context instance in inches */
+};
+
+/*
+ * Define a structure for the above linked list, holding information
+ * about printing.  Can also be on a list off of a PRHEAD struct.
+ */
+struct PRINTDATA {
+       struct INPCOORD location;       /* input coordinates */
+       float width;                    /* of string in inches */
+       short justifytype;              /* J_LEFT, etc. */
+       char *string;                   /* malloc'ed string to print */
+       short isPostScript;             /* is this for raw PostScript? */
+       char *inputfile;                /* file this print command came from */
+       short inputlineno;              /* line number in inputfile */
+       struct PRINTDATA *next;         /* for linked list */
+};
+
+/*
+ * Information about the size of each character in FONTFACTORs of an inch.
+ * Note that we don't explicitly store descent; it is (height - ascent).  Also
+ * info is only stored about the size of DFLT_SIZE characters; those in other
+ * sizes are assumed to be proportional.
+ */
+struct FONTINFO {
+       short   ch_width[CHARS_IN_FONT];
+       short   ch_height[CHARS_IN_FONT];
+       short   ch_ascent[CHARS_IN_FONT];
+       char    *ps_name;       /* PostScript name of font */
+       FILE    *fontfile;      /* User's PostScript defn of font, if any  */
+       short   is_ital;        /* is this an italic font? */
+};
+
+/* mapping of user names for non-ascii characters to internal code numbers */
+struct SPECCHAR {
+       char *charname;         /* name user would use inside \(  )  */
+       short code;             /* internal code, like the ASCII code would
+                                * be for a text font */
+};
+
+/*
+ * Store info about a string, for tablature.  The parse phase fills in an array
+ * of these, one for each string, for each tablature staff.
+ */
+struct STRINGINFO {
+       char letter;            /* 'a' to 'g' */
+       char accidental;        /* '\0', '#', '&' */
+       short nticks;           /* 0 or more */
+       short octave;           /* MINOCTAVE to MAXOCTAVE */
+};
+
+/*
+ * Define structure holding information about these three contexts:
+ *
+ *     score           the whole score
+ *     staff           a staff
+ *     voice           a voice
+ *
+ * Every field used by voice is also used by staff and score.  Every field
+ * used by staff is also used by score.
+ *
+ * Except for the selector and "used" fields, every field is numbered.
+ * Each item in the map "used" tells whether the corresponding field is
+ * currently being used in this instance of the structure.  Fields that are
+ * always set at the same time may be numbered as a group.
+ *
+ * Instances of this structure are used in two ways.
+ *
+ * First, whenever the user's input contains a context of score, staff, or
+ * voice, a "struct MAINLL", which contains one of these structures, is
+ * allocated and put in the main linked list.  For each item the user sets,
+ * the corresponding field is set in this structure and its "used" bit is
+ * set to YES.  If the user sets a parameter during the course of the input for
+ * a voice, using the <<....>> construct, the SSV will be put in a TIMEDSSV
+ * structure and linked off the following BAR line.
+ * 
+ * Second, a structure is allocated statically (global variable) for each
+ * possible score, staff, and voice.  Each time the program scans through
+ * the main linked list, it starts off by populating the (one and only)
+ * score structure with default values for everything, and setting all its
+ * "used" bits to YES.  It sets all the "used" bits for the staff and voice
+ * structures to NO.  As it scans through the main linked list, whenever it
+ * finds one of these structures, it copies all the fields whose "used" bits
+ * are YES in that structure, to the appropriate fixed structure, and sets
+ * its "used" bit to YES there.  The selector and linkage items are not used
+ * in these fixed structures.
+ * 
+ * Whenever the program needs to know the current value of a field for a
+ * given voice, staff, and score, it uses a viewpath through the corresponding
+ * three fixed structures, in that order, using the "used" bits to see if
+ * the field is filled in.  Note that the score structure is always fully
+ * populated, so the info will be found then, if not earlier.
+ */
+
+/* define the indices to the "used" field */
+#include "ssvused.h"
+
+struct SSV {
+       /* ======== SELECTOR ITEMS (ONLY SET FOR USER INPUT STRUCTS) ======= */
+       short context;  /* which context is it for? (used by all) */
+       short staffno;  /* staff no. (used by staff & voice); 1 to MAXSTAFFS */
+       short voiceno;  /* voice no. (used by voice); 1 to MAXVOICES */
+
+       /* ======== USED FLAGS ======== */
+       char used[NUMFLDS];     /* map of which fields below are being used */
+
+       /* ======== ITEMS FOR SCORE CONTEXT ONLY ======== */
+       float scale_factor;     /* scale the whole output by this amount */
+
+       float units;            /* INCHES or CM */
+
+       float pageheight;       /* size of the paper, in inches */
+       float pagewidth;
+
+       short panelsperpage;    /* print how many panels on each page of paper*/
+
+       float topmargin;        /* the four margins, in inches */
+       float botmargin;
+       float leftmargin;
+       float rightmargin;
+
+       short restcombine;      /* min. no. of mr to combine, like -c option */
+       short firstpage;        /* page number for first page, like -p option*/
+
+       short staffs;           /* no. of staffs, 1 to MAXSTAFFS */
+
+       /*
+        * The following vertical distances are in units of stepsizes.
+        * They are as follows:  minscsep is the smallest distance ever allowed
+        * between the bottom line of the bottom staff of one score, and the
+        * top of the top of the next.  (The program distributes extra space
+        * on the page between scores.)  maxscsep is the farthest distance
+        * allowed here, unless things sticking out force it farther.
+        * scorepad is the mininum distance allowed between the outermost
+        * things on neighboring scores.
+        */
+       short minscsep;
+       short maxscsep;
+       short minscpad;
+       short maxscpad;
+
+       /*
+        * A brace scheme is either "none" (nbrace == 0), or a list of pairs
+        * of staff numbers and optional labels.  Braces are to be drawn
+        * joining each pair of staffs at the start of each score.  The staffs
+        * in a pair may be the same; (3,3) means a brace is put on staff 3.
+        * If nbrace != 0, an array must be malloc'ed for bracelist to point
+        * at, so it can be treated as an array.  If labels are to be printed
+        * for the group of staffs, a place must be malloc'ed for them, and
+        * the pointers in the "struct STAFFSET" must be set.  Otherwise,
+        * those pointers must be set to null.
+        *
+        * A bracket scheme works exactly the same, using nbrack and bracklist.
+        * 
+        * Barcon refers to which staffs are to be connected by bar lines.
+        * This also works the same way, except that if staff N does not
+        * fall within any of the ranges, it still will have bar lines, as
+        * if (N,N) had been listed explicity.  Also, no labels are allowed.
+        */
+       short nbrace;                   /* brace ranges in list */
+       struct STAFFSET *bracelist;     /* pointer to list */
+       short nbrack;                   /* bracket ranges in list */
+       struct STAFFSET *bracklist;     /* pointer to list */
+       short nbarst;                   /* bar-connected ranges in list */
+       struct TOP_BOT *barstlist;      /* pointer to list */
+
+       /* 
+        * Common and cut time are noted as such in timetype, but in all other
+        * ways are treated as 4/4 and 2/2 respectively.
+        */
+       short timetype;         /* time signature type */
+       short timenum;          /* time sig numerator, 1 to 99 */
+       short timeden;          /* time sig denominator, power of 2 */
+                               /* from 1 to 64 */
+       char *timerep;          /* representation of time signature */
+       short timevis;          /* is time sig visible (YES or NO) */
+       RATIONAL time;          /* time signature in lowest terms */
+
+       short division;         /* clock ticks per 1/4 note (used by midi) */
+       short endingstyle;      /* where ending brackets are to be drawn */
+       short gridsatend;       /* print chord grids at end of song? */
+       short measnum;          /* should measure numbers be printed? */
+       short measnumfamily;    /* font family for measnum */
+       short measnumfont;      /* font for measnum */
+       short measnumsize;      /* point size for measnum */
+       float packfact;         /* horizontal packing factor */
+       float packexp;          /* horizontal packing expansion (exponent) */
+
+       short warn;             /* should warnings be printed (YES/NO)? */
+
+       /* ======== ITEMS FOR SCORE AND STAFF CONTEXT ======== */
+       float staffscale;       /* scale staff by this, relative to score */
+       short stafflines;       /* number of lines in staff (normally 5) */
+       struct STRINGINFO *strinfo;     /* iff tab staff, malloc'ed array */
+       short printclef;        /* SS_* (shares staffline's "used" flag) */
+       short gridswhereused;   /* print grids by chords where used? */
+       float gridscale;        /* scale chord grids by this times staffscale*/
+       short gridfret;         /* min fret to print next to chord grid */
+       short numbermrpt;       /* should mrpt have number printed above? */
+       short printmultnum;     /* should multirests have no. printed above? */
+       short restsymmult;      /* draw multirests using rest chars? (YES/NO)*/
+       short vscheme;          /* voice scheme */
+       short vcombine[MAXVOICES]; /* voices to be combined if possible, in the
+                                   * order to try the combining */
+       short vcombinequal;     /* vcombine qualifer (see definition of VC_*) */
+       short sharps;           /* no. of sharps, -7 to 7 */
+       short is_minor;         /* minor key (YES/NO)? (used by MIDI) */
+       short cancelkey;        /* should old key sig be canceled with nats? */
+       short inttype;          /* transpose: interval type (MINOR, ...) */
+       short intnum;           /* transpose: interval number, neg means down*/
+       short addinttype;       /* same as inttype but for addtranspose */
+       short addintnum;        /* same as intnum but for addtranspose */
+       short clef;             /* which clef is it? */
+       short rehstyle;         /* what should reh marks be enclosed in? */
+       short fontfamily;       /* font family for text other than lyrics */
+       short font;             /* font for text other than lyrics */
+       short size;             /* point size for text other than lyrics */
+       short lyricsfamily;     /* font family for lyrics */
+       short lyricsfont;       /* font for lyrics */
+       short lyricssize;       /* point size for lyrics */
+       float lyricsalign;      /* fraction of syl to the left of chord center*/
+       short sylposition;      /* points left of chord center to start syl
+                                * (overrides lyricsalign if used) */
+
+       /*
+        * minstsep is the distance between bottom line of this staff and top
+        * line of the first visible staff below it, unless things sticking out
+        * force them to be farther apart.
+        */
+       short minstsep;
+
+       /*
+        * staffpad is the mininum distance allowed between the outermost
+        * things on neighboring staffs.  It can be negative, to allow
+        * overlapping.
+        */
+       short staffpad;
+
+       /*
+        * markorder, for each "place", contains the stacking priority of each
+        * MK_* (mark type).  Priority 1 get stack first, then 2, etc.  This
+        * should really be "short" (a number, not a char), but it would waste
+        * too much space.
+        */
+       char markorder[NUM_PLACE][NUM_MARK];
+
+       short pedstyle;         /* type of pedal marks to draw */
+       short chorddist;        /* min dist between chord & staff, STEPSIZEs */
+       short dist;             /* min dist between stuff & staff, STEPSIZEs */
+       short dyndist;          /* min dist between dyn & staff, STEPSIZEs */
+
+       /* must malloc a place to store these strings, else set to null */
+       char *label;            /* label on first score */
+       char *label2;           /* label on later scores */
+
+       /* ======== ITEMS FOR SCORE, STAFF, AND VOICE CONTEXT ======== */
+       /*
+        * Although "visible" applies to score, staff, and voice, it is handled
+        * specially; see svpath() in ssv.c.  The "visible" parameter sets both
+        * the "visible" and "hidesilent" fields, as follows:
+        *      visible parameter       visible field           hidesilent field
+        *              "n"                     NO                      NO
+        *              "whereused"             YES                     YES
+        *              "y"                     YES                     NO
+        * The whereused value is not allowed for voice.  As soon as the all
+        * the scorefeeds are known (after abshorz.c), new SSVs are inserted to
+        * make the appropriate staffs invisible "for real" (using "visible").
+        */
+       short visible;          /* is the voice visible? */
+       short hidesilent;       /* if normally visible, hide when not used? */
+       /*
+        * A beam scheme is either "none" (nbeam == 0), or a list of note
+        * durations adding up to a full measure.  nbeam is how many durations
+        * in the list.  If nbeam != 0, an array must be malloc'ed for
+        * beamstlist to point at, so it can be treated as an array.
+        * Some of these durations can be parenthesized sublists of durations.
+        * If not, then nsubbeam == nbeam and subbeamstlist is the same as
+        * beamstlist.  But if so, the "sub" items count and list each
+        * individual duration, regardless of whether it's a stand-alone
+        * duration, or a member of a sublist; and nbeam and beamstlist give
+        * the combined version, where the durations of each sublist are added
+        * up and are regarded as a single duration.
+        * When nbeam != 0, beamrests tells whether the "r" flag was given;
+        * otherwise, beamrests is garbage.
+        * When nbeam != 0, beamspaces tells whether the "s" flag was given;
+        * otherwise, beamspaces is garbage.
+        */
+       short nbeam;            /* durations in list */
+       RATIONAL *beamstlist;   /* pointer to list */
+       short beamrests;        /* YES or NO:  beam across rests? */
+       short beamspaces;       /* YES or NO:  beam across spaces? */
+       short nsubbeam;         /* durations in list */
+       RATIONAL *subbeamstlist; /* pointer to list */
+
+       /* these are controlled by BEAMSLOPE */
+       float beamfact;         /* beam angle = this * regression angle */
+       float beammax;          /* maximum beam angle allowed (degrees) */
+
+       float pad;              /* apply on left of each group (stepsizes) */
+                               /* internal value = external - 1/3 */
+       float stemlen;          /* stem length in inches */
+       float stemshorten;      /* how much beamed stems can be shortened */
+                               /*  (in stepsizes) */
+
+       short defoct;           /* default octave number, 0 to 9 */
+       RATIONAL timeunit;      /* note length to use when none specified */
+       struct TIMELIST *timelist_p;    /* LL of additional times for timeunit*/
+       RATIONAL swingunit;     /* duration within which notes are to "swing" */
+       short release;          /* internote space for MIDI, in milliseconds */
+       short ontheline;        /* put notes on the one-line staff line? */
+       short tabwhitebox;      /* print white rectangle under fret numbers? */
+       short noteheads[7];     /* headshapes to be used for each scale degree*/
+};
+
+/*
+ * Define a structure for timed SSVs.  These represent parameters that are set
+ * in the course of the input for a voice, using the <<....>> construct rather
+ * than being set the usual way in a score, staff, or voice context.  They are
+ * put in a linked list hanging off the next BAR structure.  They are stored in
+ * user input order, except that they are sorted by time_off.
+ */
+struct TIMEDSSV {
+       struct SSV ssv;         /* all the normal contents of an SSV */
+       RATIONAL time_off;      /* time offset into the measure where it is */
+       struct GRPSYL *grpsyl_p;/* the group before which the <<....>> was */
+       struct TIMEDSSV *next;  /* link to the next one */
+};
+
+/*
+ * If the user enters times to be added together, like 2.+16, a linked list of
+ * these structs keeps track of the added times.
+ */
+struct TIMELIST {
+       int             basictime;
+       RATIONAL        fulltime;       /* like fulltime in struct GRPSYL */
+       struct TIMELIST *next;          /* for linked list */
+};
+
+/*
+ * Define structure pointing to the list of chords in a measure.
+ */
+struct CHHEAD {
+       struct CHORD *ch_p;     /* point at a linked list of chords */
+};
+
+/*
+ * Define structure pointing a list of things to print.  It is used for
+ * prints that occur in the "music" context.
+ */
+struct PRHEAD {
+       struct PRINTDATA *printdata_p;  /* point at first item in list */
+};
+
+/*
+ * Define a structure containing a coordinate for an ending or rehearsal mark.
+ * The coordinate given is the south edge of the item's rectangle.
+ */
+struct MARKCOORD {
+       short staffno;          /* which staff has the ending and/or rehear */
+       float ry;               /* vertical coord rel to center line of staff */
+       struct MARKCOORD *next; /* for linked list */
+};
+
+/*
+ * Define structure holding info about a bar line.
+ */
+struct BAR {
+       short bartype;          /* type of bar line */
+       short linetype;         /* type of line (L_*) */
+
+       /*
+        * When a repeatstart occurs at the end of a line, it gets moved to the
+        * pseudobar on the next line.  Where it used to be, a new bar line is
+        * supplied.  The type of that new bar line is specified by precbartype.
+        * It defaults to singlebar.
+        */
+       short precbartype;
+
+       /*
+        * The bar line's coordinates have the following meanings.
+        * X is the middle of the bar line (even if it's a repeat sign, etc.).
+        * Y is the middle line of the top staff.
+        * W and E allow standard padding.  (The leftmost "bar line" on a score
+        * is not considered to be a bar line at all, but is just drawn as
+        * part of the score.)
+        * N is the top line of the top staff; S is the bottom line of the
+        * bottom staff.
+        */
+       float c[NUMCTYPE];      /* coordinates */
+
+       float padding;          /* extra space to allow */
+
+       /*
+        * Define whether the user used "hidechanges" on this bar, which
+        * prevents changes of clef, key, and time from printing out after this
+        * bar if it ends up being the last bar on a score.
+        */
+       short hidechanges;      /* YES or NO */
+
+       /*
+        * Define position (*ITEM) relative to an ending, and what the label
+        * should say.  The label is meaningful only for the first bar of
+        * the ending (STARTITEM).  ENDITEM is used for the bar after the
+        * last measure of the ending.
+        */
+       short endingloc;        /* position within (or not) an ending */
+       char *endinglabel;      /* malloc'ed string to label the ending */
+
+       short reh_type;         /* REH_* */
+       char *reh_string;       /* string to print as rehearsal mark; should */
+                               /* be null if reh_type != REH_STRING */
+       short dist;             /* overrides SSV dist for the reh mark */
+       short dist_usage;       /* was dist used, and was it forced? (SD_*) */
+
+       short mnum;             /* measure number, 0 unless set by the user */
+
+       /*
+        * These start linked lists, one structure for each staff at this
+        * bar line that needs to have coordinates stored for an ending mark
+        * or a rehearsal mark above it.  A coord is given for an ending
+        * mark only at the bar line where it begins.
+        */
+       struct MARKCOORD *ending_p;     /* LL for ending marks */
+       struct MARKCOORD *reh_p;        /* LL for rehearsal marks */
+
+       /*
+        * There is also a linked list holding SSVs for parameters that were
+        * set during the input for a voice rather than in their own context.
+        */
+       struct TIMEDSSV *timedssv_p;
+};
+
+/*
+ * Define structure for a line.
+ */
+struct LINE {
+       short linetype;                 /* type of line */
+       struct INPCOORD start, end;     /* start and end points */
+       char *string;                   /* malloc; to be printed by the line */
+};
+
+/*
+ * Define structure for a curve.  There are two input formats for a curve.  The
+ * first type gives 3 or more coordinates, but no bulge distances.  For that
+ * type ncoord tells how many coordinates, the coordinates are given by
+ * coordlist, nbulge is zero, and bulgelist is not allocated.  For the other
+ * type of curve, 2 points (the endpoints) are given, and 1 or more bulge
+ * distances are given, in stepsize units.
+ */
+struct CURVE {
+       short curvetype;                /* type of curve */
+       short ncoord;                   /* number of coords in the following */
+       struct INPCOORD *coordlist;     /* array of coords to be malloc'ed */
+       short nbulge;                   /* number of bulge distances given */
+       float *bulgelist;               /* array of them to be malloc'ed */
+};
+
+/*
+ * Define a structure for score and page feeds.  The parser puts these in
+ * the main linked list when it sees the user's "newscore" and "newpage"
+ * directives, and the placement phase puts additional ones there as needed.
+ */
+struct FEED {
+       short pagefeed;         /* YES=score & page feed, NO=scorefeed only */
+
+       /* the following are set to -1.0 when they aren't being used */
+       float leftmargin;       /* override param on score after the feed */
+       float rightmargin;      /* override param on score before the feed */
+
+       /*
+        * If this is a pagefeed, there may be blockhead contexts of some or
+        * all of these four types that we need to point at.  When the user
+        * uses one of these contexts, it forces a pagefeed (whether they
+        * explicitly requested it or not), and the parse phase sets the
+        * pointer to a malloc'ed area.  Later, in absvert.c, these pointer
+        * values are carried forward to subsequent pagefeeds.
+        */
+       struct BLOCKHEAD *top_p, *top2_p, *bot_p, *bot2_p;
+
+       short firstvis;         /* first visible staff number in this score */
+       short lastvis;          /* last visible staff number in this score */
+       float lastdist;         /* distance from bottom line of last visible */
+                               /*  staff to the southernmost extent of score*/
+
+       /*
+        * The following are the coordinates of the score that follows.
+        * W and E are the margins, which it always extends out to when you
+        * consider labels and everything (no padding).
+        * N and S are just far enough out to include every rectangle,
+        * every staff, and every clef, with standard padding.
+        * X is the the X of the line left of the clefs.
+        * Y is the middle line of the top visible staff.
+        */
+       float c[NUMCTYPE];      /* coordinates of the score that follows */
+};
+
+
+/*
+ * Define structure telling whether to print clef, key signatures, or
+ * time signatures.
+ */
+struct CLEFSIG {
+       short prclef[MAXSTAFFS + 1];    /* print clef this staff? (YES/NO) */
+       short clefsize;                 /* print them DFLT_SIZE or SMALLSIZE */
+       /*
+        * sharps tells how many sharps to print in the key sig.  If negative,
+        * it means flats.  naturals means how many sharps are to be cancelled
+        * with natural signs.  If negative, it means we are cancelling flats.
+        * Based on these numbers and on music theory, the print phase knows
+        * which ones to print.  If both are zero, no key sig is to be printed.
+        */
+       short sharps[MAXSTAFFS + 1];
+       short naturals[MAXSTAFFS + 1];
+       short prtimesig;                /* print time signature? (YES/NO) */
+       float wclefsiga;                /* absolute west coord of clefsig */
+       float effwidth;                 /* width that can't overlap chords */
+                                       /* (used only by user clefsigs) */
+       float widestclef;               /* width of widest clef to print */
+                                       /* (used only by user clefsigs) */
+       short hide;                     /* should be hidden (hidechanges)? */
+       short multinum;                 /* number of measures in the multirest
+                                        * that follows, 0 if no multirest */
+
+       /*
+        * The following is a pointer to a BAR that gets malloc'ed for
+        * CLEFSIGs that occur after FEEDs (at the start of a score).  This
+        * represents the special, pseudo bar line at the start of a score.
+        * This pseudo bar comes immediately after the other clefsig items.
+        * It actually gets drawn only if it happens to be a REPEATSTART.
+        */
+       struct BAR *bar_p;
+};
+
+
+/*
+ * Define a structure describing a staff for one measure, which points off to
+ * linked lists of GRPSYLs and STUFFs.
+ */
+struct STAFF {
+       short staffno;                  /* staff number */
+       short visible;                  /* is this staff visible? */
+
+       /*
+        * Coordinates for the location of the staff.  The relative horizontal
+        * ones are never set, but the absolute horizonal ones are set to meet
+        * the surrounding bar lines.  The vertical ones are the same for
+        * all STAFFs for the same staff number for a given score.  (For each
+        * staff number, the packing of rectangles is done across the whole
+        * score, and the same resulting vertical coords are stored in each
+        * measure's STAFF.)  The relative vertical coords start out relative
+        * to the center line of the staff, so at that time RY is 0.  Later,
+        * they are changed to be relative to the score.
+        */
+       float c[NUMCTYPE];              /* location of staff */
+
+       struct GRPSYL *groups_p[MAXVOICES]; /* linked list(s) of voices */
+
+       /*
+        * Following is syls_p, a malloc'ed array of headcells of linked lists
+        * of GRPSYLs for verses.  There are "nsyllists" lists, which is
+        * "Maxverses" or less.  The parallel array sylplace tells whether
+        * each list of syllables is above this staff, below it, or centered
+        * between this staff and the next staff number.  The verse numbers do
+        * not have to equal the index into syls_p.  Lists for the three
+        * places can be mixed together, alternating or whatever.  But the
+        * verse numbers of each given place are in increasing order.  Any
+        * verses may be missing, but then they won't have entries in syls_p.
+        */
+       short nsyllists;
+       short *sylplace;
+       struct GRPSYL **syls_p;
+
+       /*
+        * Following is the headcell for the linked list of other "stuff"
+        * associated with this staff; above, below, and between mixed together
+        * any which way.  Actually, they are in user input order for below,
+        * and reversed for above and between, and that's the order in which
+        * their surrounding rectangles will be packed together.  Thus, on the
+        * page things will end up placed in agreement with user input order.
+        */
+       struct STUFF *stuff_p;
+
+       /*
+        * Centered between this staff and the next we may have lyrics and/or
+        * "stuff".  The rectangles for all this are packed together against
+        * a base line, and then the total height of all that is stored here.
+        */
+       float heightbetween;
+
+       /*
+        * In an mrpt measure, this holds the number that is to be printed
+        * above the measure (2 at the first mrpt, then increment).  For other
+        * measures it is 0.
+        */
+       short mrptnum;
+};
+
+
+/*
+ * Define a structure that hold information about a chord grid.
+ */
+struct GRID {
+       char *name;             /* internal chord name string (malloc) */
+
+       /*
+        * positions[0] is the fret for the first string, positions[1] is the
+        * second, etc.  0 means draw an "o" above this string, -1 means draw
+        * an "x".  -2 means draw nothing.
+        */
+       short positions[MAXTABLINES];   /* slot for each string possible */
+       short numstr;                   /* number of strings used */
+
+       /*
+        * Numbers of the left and right strings to which the curved line
+        * extends.  The first string is 1, not 0.  0 means no curved line.
+        */
+       short curvel, curver;
+
+       short used;                     /* was this grid used in this song? */
+};
+
+
+/*
+ * Define a structure that describes an item to be drawn other than music and
+ * lyrics.  A linked list of these can hang off a STAFF structure.
+ */
+struct STUFF {
+#ifdef BIGMEM  /* the way we'd define things, if we had plenty of memory */
+
+       short inputlineno;      /* which input line this structure came from */
+       char *inputfile;        /* which file this came from (malloc'ed) */
+       char *string;           /* usual convention of 1st 2 bytes = font/size*/
+       short all;              /* does this STUFF actually belong to "all" */
+                               /* (the score), not a particular staff? YES/NO*/
+
+       /*
+        * Define start and end times for the stuff.  "start" and "end.count"
+        * range from 0 to (numerator_of_time_sig + 1).  They can be any float
+        * within that range; they don't have to line up with any group.
+        * However, if gracebackup is not 0, it means the stuff is to start at
+        * that many grace notes before the normal group that is closest to
+        * "start".  Also, if the stuff is a phrase mark, both ends of it are
+        * set to the nearest group that is not rest or space, even if grace-
+        * backup is 0.  (If it is nonzero, it then works the same way.)
+        * In any case, after the start position is determined as described
+        * above, the "steps" offset is applied to it, which can be positive,
+        * negative, or (usually) zero.
+        */
+       struct {
+               float count;    /* counts into measure where the thing begins*/
+               float steps;    /* offset in stepsizes */
+       } start;
+       struct {
+               int bars;       /* how many bar lines it crosses */
+               float count;    /* count (in whichever measure) where it ends */
+       } end;                  /* both are 0 if no "til" clause */
+       short gracebackup;      /* how many graces before "start" to start at */
+
+       short stuff_type;       /* ST_CRESC, etc. */
+       short modifier;         /* if text, is it chord, etc. (TM_*)? */
+                               /* if phrase, what type of line (L_*)? */
+       short place;            /* PL_ABOVE, etc. */
+       short dist;             /* overrides SSV dist/chorddist/dyndist */
+       short dist_usage;       /* was dist used, and was it forced? (SD_*) */
+       short carryin;          /* is this a continuation from last score? */
+       short carryout;         /* does this continue onto the next score? */
+       struct STUFF *costuff_p;/* for tie/slur/bend carryin stuff, point at 
+                                * corresponding carryout stuff */
+
+       /*
+        * The following group of variables is used only for ST_PHRASE and/or
+        * ST_TIESLUR.
+        *
+        * Phrases use them as follows:
+        * A phrase must be assigned to apply to a particular voice on the
+        * staff.  Unlike other STUFF, the endpoints of a phrase mark need to
+        * get associated with GRPSYLs.  These pointers get set to point at
+        * them.  If it crosses score feeds, carry ins and outs will have a
+        * pointer to the first and last GRPSYL of the score, respectively.
+        * The crvlist_p is the headcell of the linked list of points forming
+        * a phrase mark.  begnote_p is not used.
+        *
+        * Ties and slurs use them as follows:
+        * A tie/slur is not input the same as other STUFF.  The user's input
+        * sets its starting note.  The STUFF structure is not allocated until
+        * stuff.c.  At that point, vno, beggrp_p, and begnote_p are set, and
+        * crvlist_p is set up like for phrases.  If it crosses a scorefeed,
+        * carry in and out are used, and the "beg" pointers for the second
+        * half of the tie/slur point at the end group and note.  In any case,
+        * curveno tells which tie/slur this STUFF refers to, since a tie and
+        * multiple slurs can start at the same note.  endgrp_p isn't used.
+        */
+       short vno;                      /* voice phrase applies to (1 or 2) */
+       struct GRPSYL *beggrp_p;        /* beginning GRPSYL */
+       struct GRPSYL *endgrp_p;        /* ending GRPSYL */
+       struct CRVLIST *crvlist_p;      /* headcell of linked list of coords */
+       struct NOTE *begnote_p;         /* beginning NOTE */
+       short curveno;                  /* idx into slurtolist; -1 for tie */
+
+       /*
+        * For above and below stuff, the relative vertical coords are
+        * relative to the staff's center line.  For between stuff, they end
+        * up being relative to the center line of the above staff, but at
+        * first they are relative to the base line that the between stuff is
+        * piled on.  (Not used for phrase marks.)
+        */
+       float c[NUMCTYPE];      /* where item is placed */
+
+       struct STUFF *next;     /* for linked list */
+
+#else          /* the same as above, optimized for space */
+
+       char *inputfile;
+       char *string;
+       struct GRPSYL *beggrp_p;
+       struct GRPSYL *endgrp_p;
+       struct CRVLIST *crvlist_p;
+       struct NOTE *begnote_p;
+       struct STUFF *next;
+       struct STUFF *costuff_p;
+       float c[NUMCTYPE];
+       struct {
+               float count;
+               float steps;
+       } start;
+       struct {
+               float count;
+               short bars;
+       } end;
+       short inputlineno;
+       short gracebackup;
+       short vno;
+       short curveno;
+       short dist;
+       unsigned dist_usage     : 2;
+       unsigned all            : 1;
+       unsigned stuff_type     : 4;
+       unsigned modifier       : 3;
+       unsigned place          : 2;
+       unsigned carryin        : 1;
+       unsigned carryout       : 1;
+#endif
+};
+
+/*
+ * Define a structure for forming linked lists of coordinates making up the
+ * curve of a phrase mark.  Each structure has the coordinates of one point.
+ */
+struct CRVLIST {
+       float x;                /* absolute X */
+       float y;                /* Y initially rel to staff, later absolute */
+       struct CRVLIST *next;   /* doubly linked list */
+       struct CRVLIST *prev;
+};
+
+/*
+ * Define struct to save lists of staff number or vno (voice or verse) ranges.
+ */
+struct RANGELIST {
+       short   begin;          /* first number in range */
+       short   end;            /* last number in range. Must be >= begin */
+       short   all;            /* is this staff no. actually "all" (the */
+                               /* score), not a particular staff? YES/NO */
+       short   place;          /* PL_*   */
+       struct RANGELIST *next; /* for linked list */
+};
+
+/*
+ * Define a struct to save a list of pairs of staff and voice range lists.
+ */
+struct SVRANGELIST {
+       struct RANGELIST *stafflist_p;
+       struct RANGELIST *vnolist_p;
+       struct SVRANGELIST *next;       /* linked list */
+};
+
+/*
+ * Define a structure for stating the note that a given note is slurred to.
+ */
+struct SLURTO {
+       char letter;            /* a to g */
+       short octave;           /* 0 to 9 */
+       short slurstyle;        /* what type slur: L_[NORMAL|DOTTED|DASHED] */
+       short slurdir;          /* should slur bulge UP or DOWN? */
+};
+
+/*
+ * Define the structure for holding information concerning a note.  Much of
+ * the info you might expect to be here actually applies to the whole "group",
+ * and so is in the group/syllable structure below.
+ * NOTE:  When adding fields to this structure, update function map1note().
+ */
+struct NOTE {
+       /*
+        * Define the coords x, y, north, south, east, west, both relative
+        * and absolute.  The relative coords are relative to the group's
+        * (x, y). The NSEW coords define a rectangle surrounding the note
+        * head.  XY are the center of the note head.
+        */
+       float *c;               /* must malloc array; see comment in */
+                               /*  grpsyl.c, add_note() for why */
+
+       float waccr;            /* relative coord:  w(accidental)-x(group) */
+       float ydotr;            /* relative coord:  y(dot)-y(group) */
+
+       /* these next two are used when note_has_paren is YES */
+       float wlparen;          /* relative coord:  w(left paren)-x(group) */
+       float erparen;          /* relative coord:  e(right paren)-x(group) */
+
+       /*
+        * nslurto says how many notes of the following group this note is
+        * slurred to.  If it is greater than 0, an array of that many SLURTO
+        * structures must be malloc'ed and slurtolist set to point at it.
+        */
+       struct SLURTO *slurtolist;
+       short nslurto;
+
+       char letter;            /* a to g */
+       char accidental;        /* '\0', 'x', '#', 'n', '&', 'B'(double flat)*/
+       short octave;           /* 0 to 9 */
+       short stepsup;          /* how many steps above middle line is note? */
+       char headfont;          /* music char font of this note head */
+       char headchar;          /* music char number of this note head */
+#ifdef BIGMEM  /* the way we'd define things, if we had plenty of memory */
+       short headshape;        /* shape type of this note head */
+       short notesize;         /* size of the note head */
+       short tie;              /* if YES, tie this note to the same note in
+                                * the next note group */
+       short tiestyle;         /* what type of tie: L_[NORMAL|DOTTED|DASHED] */
+       short tiedir;           /* should tie bulge UP or DOWN? */
+       short acc_has_paren;    /* does the accidental have () around it? */
+       short note_has_paren;   /* does the entire note have () around it? */
+       short is_bend;          /* does slurto list really contain a "bend"? */
+
+       /*
+        * On a tabnote staff, when there is a bend of <= 1/4 steps, the bent-
+        * to note isn't drawn.  Instead, smallbend is set to YES, and a small,
+        * curved line gets drawn.  In the input, the user specifies this by
+        * saying ^/ after the note.
+        */
+       short smallbend;
+
+#else          /* the same as above, optimized for space */
+       unsigned notesize       : 1;
+       unsigned tie            : 1;
+       unsigned tiestyle       : 3;
+       unsigned tiedir         : 2;
+       unsigned acc_has_paren  : 1;
+       unsigned note_has_paren : 1;
+       unsigned is_bend        : 1;
+       unsigned smallbend      : 1;
+       unsigned headshape      : 5;
+#endif
+};
+/*
+ * For tablature, the items above are used differently from the usual meaning.
+ * Accidentals are never printed, so their coordinates are not used.  letter
+ * is used to store the string number.  accidental is used to store the fret
+ * number.  Inside the octave field three bit fields are used to store the bend
+ * distance, as follows from high bits to low bits:
+ *     integer part of bend; if no integer, store 0.
+ *     numerator part of bend; if no fraction, store 0.
+ *     denominator part of bend; if no fraction, store 0.
+ *     If "full", store as if the integer 1 were given for bend (1-0-0).
+ * The following macros are used for accessing these fields.  acc_has_paren is
+ * used to indicate parentheses around the fret number, so an alternate name is
+ * defined for it.  stepsup is used, in the parse phase only, to store number
+ * of tick marks and fret values; see grpsyl.c for the details.  In later
+ * phases it is set to its usual meaning, but note that middle of the staff
+ * will not be a line if there are an even number of lines.
+ */
+#define        STRINGNO                letter
+#define        FRETNO                  accidental
+#define        BEND                    octave
+#define        BENDINT(note)           (((note).BEND >> \
+                               (BENDNUMBITS + BENDDENBITS)) & MAXBENDINT)
+#define        BENDNUM(note)           (((note).BEND >> BENDDENBITS) & MAXBENDNUM)
+#define        BENDDEN(note)           (((note).BEND >> 0) & MAXBENDDEN)
+#define        TABOCT(inte, num, den)  (((inte) << (BENDNUMBITS + BENDDENBITS)) | \
+                               ((num) << BENDDENBITS) | ((den) << 0))
+#define HASBEND(note)          ((note).BEND != 0)
+#define HASNULLBEND(note)      ((note).BEND == 1)
+#define HASREALBEND(note)      (HASBEND(note) && ! HASNULLBEND(note))
+#define FRET_HAS_PAREN         acc_has_paren
+/*
+ * During parsing, we temporarily save nticks and fret in the stepsup field.
+ * Bits 0-8 hold the fret, bits 9-12 hold the nticks.  Any changes to MAXFRET
+ * or MAXTICKS would have to be coordinated here.  These things are stored
+ * temporarily in these fields since when we are doing parsing, we still need
+ * to remember the pitch and accidental information, so can't put them in their
+ * final place till a bit later.
+ */
+#define TMP_SAVE(note_p, nticks, fret)  \
+               (note_p)->stepsup = (((nticks) & 0xf) << 8) | ((fret) & 0xff)
+#define TMP_NTICKS(note_p)     (((note_p)->stepsup >> 8) & 0xf)
+#define TMP_FRET(note_p)       ((note_p)->stepsup & 0xff)
+
+/*
+ * Define the structure for holding information concerning a "group", which
+ * consists of either a space, a rest, or a list of notes stemmed together
+ * (or which would be stemmed together if they were shorter than whole notes);
+ * or a syllable of lyrics.
+ * NOTE:  When adding fields to this structure, update function map1note().
+ */
+struct GRPSYL {
+#ifdef BIGMEM  /* the way we'd define things, if we had plenty of memory */
+
+       /* ======== ITEMS FOR GROUPS AND SYLLABLES ======== */
+       short inputlineno;      /* which input line this structure came from */
+       char *inputfile;        /* which file this came from (malloc'ed) */
+       short staffno;          /* staff number */
+       short vno;              /* voice (1 to MAXVOICES) or verse number */
+       short grpsyl;           /* is it group or syllable? */
+
+       /*
+        * Define the coords x, y, north, south, east, west, both relative
+        * and absolute.  The vertical relative coords are relative to the
+        * center line of the staff.  The horizontal relative coords are
+        * relative to the chord's x.  The NSEW coords define a rectangle
+        * surrounding the group; for groups, X goes through the center of
+        * the (normal) note heads; Y is the middle line of the staff.
+        * For syllables, Y is the baseline and X is the place that should
+        * line up with the chord, which is part way from the left edge toward
+        * the right edge based on lyricsalign, not counting any characters in
+        * <angle brackets> that precede or follow the real syllable.
+        *
+        * WARNING:  for groups, during the time when positions of phrase
+        * marks are being figured out, AN and AS are used in a strange way,
+        * denoting the offset from RN or RS where the phrase is.  But later
+        * they get set to their normal values.
+        */
+       float c[NUMCTYPE];      /* coordinates */
+
+       /*
+        * The basic time value is one of the following: -1, 0, power of 2 from
+        * 1 to 256, or less than -1.  For normal (is_meas==NO) groups, -1
+        * means quadruple whole, 0 means double whole, 1 is whole, 2 is half,
+        * etc.  Less than -1 means a multirest of (-basictime) measures.  For
+        * is_meas==YES groups, basictime is the same as the preceding for
+        * measure rests, where it just tells which rest to draw, but for ms
+        * and mrpt it is arbitrarily set to -1.
+        */
+       short basictime;
+
+       /*
+        * is_meas tells whether an "m" was used with the time in the input.
+        * This is used for "measure" rests, spaces, or repeats (mr, ms, mrpt).
+        * (Only mr can have a normal time value in addition to the "m"; it is
+        * stored as the basictime (defaults to 1) and tells which rest to
+        * draw.)  Their fulltime is the time signature.  mr and mrpt are
+        * centered in the measure.
+        */
+       short is_meas;
+
+       short dots;             /* number of dots applied to time value */
+
+       short tuploc;           /* none, start, inner, end, lone (for tuplet) */
+       short tupcont;          /* number to print for the tuplet */
+
+       /*
+        * Full time is basic time modified by dots, tuplets, etc.  It's the
+        * actual time duration, and thus for grace it's always 0.
+        */
+       RATIONAL fulltime;
+
+       float padding;          /* extra space to allow */
+
+       /* ======== ITEMS FOR GROUPS ONLY ======== */
+       short pvno;             /* pseudo voice number: normally equals vno,
+                                * but when voice 3 is treated like voice 1 or
+                                * or 2, that number is stored here */
+                               /* also used as scratch area in mkchords.c */
+       short grpcont;          /* note(s), rest, or space; although normally
+                                * meaningful only for groups, gram.y uses it
+                                * as scratch while processing syllables */
+       short grpvalue;         /* normal time value; or zero for grace group
+                                * or for all-space chords in MIDI */
+       short grpsize;          /* size of items in group */
+       short headshape;        /* default shape of noteheads in group */
+       short uncompressible;   /* is this space a "us" (used for space only)*/
+
+       short beamloc;          /* none, start, inner, end (only note groups)*/
+       float beamslope;        /* user specified angle of beam in degrees */
+
+       /*
+        * Stem length applies to groups shorter than a whole note and groups
+        * joined by "alternation" beams.  It starts out based only on
+        * basictime and grpsize, but due to a beam or override, it could be
+        * changed.  Direction is up or down, and applies to all groups, even
+        * whole note groups (useful for figuring ties).   stemx is the
+        * horizontal position of the stem, relative to the X of the GRPSYL.
+        * These fields are valid only for note groups.
+        */
+       float stemlen;
+       short stemdir;          /* up or down */
+       float stemx;
+
+       /*
+        * beamto is always CS_SAME, except when this group is a notes or
+        * space group and is involved in cross staff beaming.  It then tells
+        * whether we are beamed with the staff above us or below us.  It is
+        * set for all the note and space groups on both staffs in the set.
+        * So on the top staff it's set to CS_BELOW, and on the bottom staff
+        * it's set to CS_ABOVE.
+        */
+       short beamto;
+
+       /*
+        * stemto is always CS_SAME, except when this group is a notes group
+        * and is involved in cross staff steming.  It then tells whether we
+        * are stemmed with the staff above us or below us.  When stemto is not
+        * CS_SAME, stemto_idx is an index into notelist[].  For CS_ABOVE,
+        * it indexes to the last note that is on the above staff.  For
+        * CS_BELOW, it indexes to the first note that is on the below staff.
+        */
+       short stemto;
+       short stemto_idx;
+
+       /* YES if the last group in a subbeam */
+       short breakbeam;
+
+       /*
+        * printtup tells whether the user wants a tuplet number and bracket to
+        * be printed next to a note group.  If PT_NEITHER, neither will be.
+        * If PT_BOTH, both will be.  If PF_DEFAULT, at least the number will
+        * be.  The bracket will be too, unless the tuplet contains only one
+        * group, or if all the groups' beamlocs are equal to their tuplocs
+        * (the groups are already beamed as a unit).  If PT_NUMBER, the number
+        * (and only the number) will be printed.  In any case, printtup
+        * is set for each group in the tuplet.
+        *
+        * tupextend is set only for the groups of a tuplet of notes that has
+        * printtup == Y.  It is the vertical offset of where the tuplet
+        * bracket would be, from the AN or AS of the groups, as the case may
+        * be.  If the bracket would be above the groups, it is positive and
+        * relative to AN; else it is negative and relative to AS.  It is set
+        * even for the case where the bracket is not going to be printed, so
+        * that the tuplet number can still be placed as halfway between the
+        * invisible bracket's endpoints.
+        */
+       short printtup;
+       float tupextend;
+       short tupside;          /* should number & bracket be above or below?*/
+
+       short phraseside;       /* relevant side(s) for phrase mark space */
+
+       /*
+        * nnotes says how many notes there are in the group.  An array of
+        * that many note structures must be malloc'ed and notelist set to
+        * point at it.  The notes are stored in order of descending pitch,
+        * regardless of the user's input ordering.  These fields are valid
+        * only for note groups.
+        * But for measure repeats (mrpt), even though they are GC_NOTES,
+        * nnotes is 0 and notelist is a null pointer.
+        */
+       short nnotes;           /* no. of notes in group */
+       struct NOTE *notelist;  /* list of notes in group */
+
+       /*
+        * If tie is set to YES, all notes in the group are to be tied to
+        * corresponding notes in the following group. The "tie" flag will
+        * also be set on each individual note in its NOTE struct, but it
+        * turns out to be handy to have the whole group marked here too.
+        * This field is valid only for note groups.
+        */
+       short tie;
+
+       /*
+        * The slash_alt field is used for slashes on a group or between
+        * pairs of groups (for tremolo, or just dividing the time value of
+        * the group(s).  0 means normal group; >0 means draw that many
+        * slashes through the stem of this group (or, if basictime < 2, where
+        * the stem would have been); <0 means draw negative that many slashes
+        * between this and the next group.  This field is valid only for note
+        * groups.
+        */
+       short slash_alt;
+
+       /*
+        * On a tablature staff, when an entire group is tied to the following
+        * group, the second group normally should not be printed.  (Its
+        * corresponding tabnote group will be, though.)  This flag says not to
+        * print this group.  This is set by the parse phase when the preceding
+        * tab group is tied.  It is cleared by the placement phase after
+        * scorefeeds.
+        */
+       short inhibitprint;
+
+       /*
+        * This is used for rests only.  If not used, it is NORESTDIST.
+        * Otherwise, it is the vertical offset of the "center" of the rest
+        * (the part that normally is on the center line) from the center line.
+        * The rest is forced there.
+        */
+       short restdist;
+
+       /*
+        * These are for the user-specified horizontal offset of the group from
+        * the chord's X.  The value is in stepsizes; negative to the left, and
+        * positive to the right.
+        */
+       short ho_usage;         /* HO_* */
+       float ho_value;         /* value to use when ho_usage is HO_VALUE */
+
+
+       /* the X positions of dots are the same for every note in the group */
+       float xdotr;            /* relative coord of dots:  x(dot)-x(group) */
+       /*
+        * When symbols are to be drawn "with" a group, they are stored
+        * in the list below in order, starting from the group and moving
+        * outwards.  When nwith is 0, there is no list.  Otherwise, a
+        * list must be malloc'ed and the pointer must be set to point at
+        * it.  Each item in the list is a pointer to a string, which must
+        * also be malloc'ed.  Normally, the "with" items are on the note side
+        * of the group, but if there are two voices, they might need to be
+        * put on the stem side, so normwith says which side they go on.
+        * These fields are valid only for note groups.
+        */
+       short nwith;            /* no. of symbols with group */
+       char **withlist;        /* list of symbols with group */
+       short normwith;         /* does it go on the normal (note) end of grp?*/
+
+       short roll;             /* where is this group in a roll, if at all? */
+       short rolldir;          /* is the roll's arrow UP, DOWN, or UNKNOWN? */
+                               /*  (with UNKNOWN, roll is up, but no arrow) */
+
+       short clef;             /* clef to be printed before this group */
+
+       /* ======== ITEMS FOR SYLLABLES ONLY ======== */
+       char *syl;              /* malloc a place for the syllable */
+       short sylposition;      /* points left of chord's X to start syl */
+
+       /* ======== LINKAGE ======== */
+       struct GRPSYL *prev;    /* point at previous group/syl in voice/verse*/
+       struct GRPSYL *next;    /* point at next group/syl in voice/verse */
+       struct GRPSYL *gs_p;    /* point at next group/syl in chord */
+
+#else          /* the same as above, optimized for space */
+
+       RATIONAL fulltime;
+       float c[NUMCTYPE];
+       float padding;
+       float stemlen;
+       float stemx;
+       float tupextend;
+       float ho_value;
+       float xdotr;
+       float beamslope;
+       char *inputfile;
+       char **withlist;
+       char *syl;
+       struct GRPSYL *prev;
+       struct GRPSYL *next;
+       struct GRPSYL *gs_p;
+       struct NOTE *notelist;
+       short inputlineno;
+       short staffno;
+       short vno;
+       short basictime;
+       short dots;
+       short tupcont;
+       short pvno;
+       short nnotes;
+       short slash_alt;
+       short nwith;
+       short restdist;
+       short sylposition;
+       short clef;
+       short headshape;
+       short stemto_idx;
+       unsigned ho_usage       : 2;
+       unsigned is_meas        : 1;
+       unsigned grpsyl         : 1;
+       unsigned tuploc         : 3;
+       unsigned grpcont        : 2;
+       unsigned grpvalue       : 1;
+       unsigned grpsize        : 1;
+       unsigned uncompressible : 1;
+       unsigned beamloc        : 3;
+       unsigned stemdir        : 2;
+       unsigned tupside        : 2;
+       unsigned phraseside     : 2;
+       unsigned printtup       : 2;
+       unsigned tie            : 1;
+       unsigned normwith       : 1;
+       unsigned roll           : 3;
+       unsigned rolldir        : 2;
+       unsigned inhibitprint   : 1;
+       unsigned beamto         : 2;
+       unsigned stemto         : 2;
+       unsigned breakbeam      : 1;
+#endif
+};
+
+/*
+ * Define the structure for a chord.
+ */
+struct CHORD {
+       /*
+        * Define the coords of a CHORD.  For vertical, only the absolute ones
+        * are set.  They are set the same as the FEED for this score, and they
+        * are used only for drawing bounding boxes with MUP_BB.  As for
+        * horizontal, the relative coords are relative to the score's
+        * (x, y).  Basically, west and east are set out just far enough to
+        * hold the biggest GRPSYL in the CHORD.  However, for both groups and
+        * syllables there is special code that allows parts of them to stick
+        * out, when the overlap would be harmless even if the CHORDs end up
+        * being packed tightly together.
+        */
+       float c[NUMCTYPE];      /* coordinates */
+       float width;            /* c[RE] - c[RW], which equals c[AE] - c[AW] */
+       float fullwidth;        /* dist from c[RX] of this chord to c[RX] of */
+                               /*  next (or to bar line if last in measure) */
+
+       RATIONAL starttime;     /* starting time of chord within its measure */
+       RATIONAL duration;      /* duration of the chord */
+       float pseudodur;        /* a function of duration; proportional to */
+                               /* width this chord will "deserve" */
+
+       struct CHORD *ch_p;     /* point at next chord in list */
+       struct GRPSYL *gs_p;    /* point at first group or syllable in chord */
+};
+
+/*
+ * Define the structure that contains info concerning chord grids that are
+ * going to be printed at the end of the song.  Only one instance of this
+ * structure exists.
+ */
+struct ATEND_INFO {
+       /* number of different grids actually used in the song */
+       int grids_used;
+
+       /*
+        * Must grid dictionary be put on a separate page, following the last
+        * page of music (because it doesn't fit with the music)?  YES or NO.
+        */
+       int separate_page;
+
+       /*
+        * This is a malloc'ed array of pointers to the grids to be printed.
+        * Placement sets it up and sorts it.
+        */
+       struct GRID **grid_p;
+
+       int grids_per_row;      /* no. of grids to print per row */
+       int rows_per_page;      /* no. of rows of grids allowed on one page */
+       float firstgrid_x;      /* X coord of grids in the first column */
+       float firstgrid_y;      /* Y coord of grids in the first row */
+       float horz_sep;         /* dist between X of neighboring grids */
+       float vert_sep;         /* dist between Y of neighboring grids */
+};
+
+/*
+ * Define a symbol for each structure type that can be inside a union, so
+ * that we can record which member of the union is being used.
+ */
+#define        S_SSV           (0)
+#define        S_FEED          (1)
+#define        S_CLEFSIG       (2)
+#define        S_PRHEAD        (3)
+#define        S_CHHEAD        (4)
+#define        S_STAFF         (5)
+#define S_LINE         (6)
+#define S_CURVE                (7)
+#define        S_BAR           (8)
+#define        S_BLOCKHEAD     (9)
+
+/*
+ * The following contains a union of all the structures that can occur in the
+ * main linked list, set up by yyparse().
+ */
+struct MAINLL {
+       short str;      /* which structure in the union is now being used? */
+       short inputlineno; /* which input line this structure came from */
+       char *inputfile;        /* which file this came from (malloc'ed) */
+       union {                 /* malloc'ed structures to be pointed at */
+               struct SSV *ssv_p;      /* score/staff/voice context info */
+               struct FEED *feed_p;    /* score and/or page feed */
+               struct CLEFSIG *clefsig_p;    /* print clef and/or sigs? */
+               struct PRHEAD *prhead_p;/* head of list to print things */
+               struct CHHEAD *chhead_p;/* head of chord list for a measure */
+               struct STAFF *staff_p;  /* staff info from data context */
+               struct LINE *line_p;    /* line info */
+               struct CURVE *curve_p;  /* curve info */
+               struct BAR *bar_p;      /* bar line info from data context */
+               struct BLOCKHEAD *blockhead_p;  /* info for a "block" context */
+       } u;
+       struct MAINLL *prev;    /* previous structure in linked list */
+       struct MAINLL *next;    /* next structure in linked list */
+};
+/*
+ * The structures in the main linked list must occur in the order as shown
+ * below, by the end of the placement phase.  There are optional initial SSVs,
+ * then two alternative sets of structures that repeat, then some optional
+ * final structures.  The list shows [in brackets] which phase of Mup inserts
+ * the structure:  parse or placement.  (The third phase, print, doesn't insert
+ * any structures; nor does the midi phase, which can replace the print phase.)
+ *
+ * 0 or more SSVs [parse]
+ * LOOP 1 or more times:
+ *    EITHER a measure:
+ *       0 or 1 FEED; 1 is required in 1st measure & after block[parse or place]
+ *       0 or 1 CLEFSIG (at start of a score); 1 iff a FEED precedes [place]
+ *       1 CHHEAD [place]
+ *       1 or more STAFFs.  They are ordered by staff number. [parse]
+ *       0 or more LINEs and/or CURVEs and/or PRHEADs, any order[parse or place]
+ *       1 BAR [parse]
+ *       0 or more SSVs [parse or place]
+ *       0 or 1 CLEFSIG (after a bar line, not at start of a score) [place]
+ *    OR a block:
+ *       1 FEED [parse]
+ *       1 BLOCKHEAD [parse]
+ *       0 or more SSVs [parse]
+ *    END_EITHER
+ * END_LOOP
+ * 0 or more LINEs and/or CURVEs and/or PRHEADs and 1 optional FEED; the FEED
+ *                     is required if a block preceeds [parse]
+ */
+#endif
diff --git a/mup/mup/stuff.c b/mup/mup/stuff.c
new file mode 100644 (file)
index 0000000..08a2259
--- /dev/null
@@ -0,0 +1,2255 @@
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ * Name:       stuff.c
+ *
+ * Description:        This file contains functions for handling "stuff".
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+/* for STUFF, apply appropriate staffscale, based on "all" */
+#define STUFFSTEP(stuff_p)     ((stuff_p)->all == YES ?        \
+                               Score.staffscale * STEPSIZE : stepsize);
+
+static void normalizestuff P((void));
+static void movestuff P((struct STAFF *staff1_p, struct STAFF *staff2_p,
+               struct STUFF *stuff_p));
+static void setphrases P((void));
+static void phrasestuff P((struct MAINLL *msbeg_p, struct STUFF *stuff_p));
+static void set1phrase P((struct MAINLL *msbeg_p, struct STUFF *stuff_p,
+               int v));
+static void rmstuff P((struct STAFF *staff_p, struct STUFF *stuff_p));
+static void breakstuff P((void));
+static struct STUFF *prevstuff P((struct MAINLL *mainll_p,
+               struct STUFF *stuff_p));
+static void breakone P((struct MAINLL *m2_p, struct STUFF *stuff_p,
+               int timenum, char *origstr_p, int depth));
+static void contpedal P((void));
+static void setstuff P((void));
+static double count2coord P((double count, struct BAR *bar_p,
+               struct CHHEAD *chhead_p, int timeden));
+static int geteast P((struct STUFF *stuff_p, struct MAINLL *m2_p,
+               short *timeden2_p, struct CHHEAD **chhead2_p_p,
+               struct BAR **bar2_p_p));
+static int setmrferm P((struct STAFF *staff_p, struct STUFF *stuff_p));
+static int trygrid P((struct MAINLL *mainll_p, struct STUFF *stuff_p));
+static void tieslurstuff P((void));
+static void mktieslurstuff P((struct MAINLL *mllstaff_p, struct GRPSYL *gs_p,
+               int n, int s));
+static void mkextrastuff P((struct MAINLL *mll_p, struct STUFF *origstuff_p,
+               struct GRPSYL *gs_p, int n, int s, int stufftype));
+\f
+/*
+ * Name:        stuff()
+ *
+ * Abstract:    Perform all necessary horizontal operations on STUFF.
+ *
+ * Returns:     void
+ *
+ * Description: This function calls subroutines to do all necessary horizontal
+ *             operations on STUFF.
+ */
+
+void
+stuff()
+{
+       debug(16, "stuff");
+       normalizestuff();
+       setphrases();
+       breakstuff();
+       contpedal();
+       setstuff();
+       tieslurstuff();
+}
+\f
+/*
+ * Name:        normalizestuff()
+ *
+ * Abstract:   Normalize STUFF starting at count N + 1 before a FEED.
+ *
+ * Returns:     void
+ *
+ * Description: This function looks for all STUFF structures that start at
+ *             count N + 1 (where N is the numerator of the time signature)
+ *             in measures preceding a score feed.  These things really
+ *             should be drawn at the start of the next score, so this
+ *             function moves them to be at count 0 of the next measure.
+ *             However, if the staff involved is invisible on the next score,
+ *             it doesn't move the STUFF.  Also, fermatas and the pedal marks
+ *             PEDAL and ENDPED are not moved.
+ *             Only start.count is used; the policy is to apply start.steps
+ *             only after everything else is done.
+ */
+
+static void
+normalizestuff()
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct MAINLL *m2_p, *m3_p;     /* secondary & tertiary MLL pointers */
+       struct STUFF *stuff_p;          /* point at a STUFF structure */
+       struct STUFF *next_p;           /* point at the next STUFF structure */
+
+
+       debug(16, "normalizestuff");
+       initstructs();
+
+       /*
+        * Loop through the main linked list, looking for BARs that immediately
+        * precede a FEED.  When found, adjust the start count of STUFFs in the
+        * preceding measure if necessary.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               switch (mainll_p->str) {
+               case S_SSV:
+                       /* keep SSVs up to date; we need to know time sig */
+                       asgnssv(mainll_p->u.ssv_p);
+                       continue;
+
+               case S_BAR:
+                       /* break out to handle this BAR */
+                       break;
+
+               default:
+                       /* nothing to do, skip to next loop */
+                       continue;
+               }
+
+               /*
+                * Find out if this is a bar that immediately precedes a FEED.
+                * If not, there is no need to adjust any stuff, so continue.
+                */
+               for (m2_p = mainll_p; m2_p != 0 && m2_p->str != S_FEED &&
+                               m2_p->str != S_CHHEAD; m2_p = m2_p->next)
+                       ;
+               if (m2_p == 0 || m2_p->str == S_CHHEAD)
+                       continue;
+
+               /*
+                * This bar immediately precedes a FEED.  Make sure the number
+                * of staffs doesn't change across this FEED.  (And if what
+                * follows are blocks, continue looking until we find a FEED
+                * that is not a block.)  If it does, don't move any STUFF.
+                */
+               for (m2_p = mainll_p; m2_p->next != 0; m2_p = m2_p->next) {
+                       /* break out if a FEED that is not followed by block */
+                       if (m2_p->str == S_FEED &&
+                                       m2_p->next->str != S_BLOCKHEAD)
+                               break;
+                       /* break out if SSV changes number of staffs */
+                       if (m2_p->str == S_SSV && 
+                                       m2_p->u.ssv_p->used[NUMSTAFF] == YES)
+                               break;
+               }
+               /* if at end of list or staffs changed, don't move stuff */
+               if (m2_p->next == 0 || m2_p->str == S_SSV)
+                       continue;
+
+               /*
+                * Search back to the CHHEAD of the preceding measure.
+                */
+               for (m2_p = mainll_p; m2_p->str != S_CHHEAD; m2_p = m2_p->prev)
+                       ;
+
+               /*
+                * Loop through all the staffs in this preceding measure,
+                * adjusting STUFF when need be.
+                */
+               for (m2_p = m2_p->next; m2_p->str == S_STAFF;
+                               m2_p = m2_p->next) {
+
+                       if (m2_p->u.staff_p->visible == NO)
+                               continue;
+
+                       /*
+                        * Find the matching STAFF in the next measure.  If we
+                        * can't find it (like end of MLL) or it's not visible,
+                        * forget this staff.
+                        */
+                       for (m3_p = mainll_p->next; m3_p != 0 &&
+                                       m3_p->str != S_BAR; m3_p = m3_p->next) {
+                               if (m3_p->str == S_STAFF &&
+                                               m3_p->u.staff_p->staffno ==
+                                               m2_p->u.staff_p->staffno)
+                                       break;
+                       }
+                       if (m3_p == 0 || m3_p->str != S_STAFF ||
+                                       m3_p->u.staff_p->visible == NO)
+                               continue;
+
+                       /*
+                        * Loop through all the stuff on this staff in the
+                        * preceding measure, normalizing it.  That is, if it
+                        * starts at count N + 1 (where N is the numerator of
+                        * the time signature), change it to start at count 0
+                        * of the next bar line.  However, don't move fermatas
+                        * or pedal "bounce" or "ending" marks.
+                        */
+                       for (stuff_p = m2_p->u.staff_p->stuff_p;
+                                       stuff_p != 0; stuff_p = next_p) {
+                               /*
+                                * Remember next one in case we have to move
+                                * this one to the next measure's linked list.
+                                */
+                               next_p = stuff_p->next;
+
+                               if (stuff_p->start.count == Score.timenum + 1 &&
+                               string_is_sym(stuff_p->string, C_PEDAL, FONT_MUSIC) == NO &&
+                               string_is_sym(stuff_p->string, C_ENDPED, FONT_MUSIC) == NO &&
+                               string_is_sym(stuff_p->string, C_FERM, FONT_MUSIC) == NO &&
+                               string_is_sym(stuff_p->string, C_UFERM, FONT_MUSIC) == NO) {
+                                       /*
+                                        * Move this stuff from preceding to
+                                        * following measure's linked list.
+                                        */
+                                       movestuff(m2_p->u.staff_p,
+                                                 m3_p->u.staff_p, stuff_p);
+                                       /*
+                                        * Set start count to 0.  If there is a
+                                        * "til" clause, bars would have to be
+                                        * greater than 0, since count can't
+                                        * refer to a count in this measure
+                                        * (can't be greater than N + 1).  So
+                                        * we only need to check bars to see if
+                                        * there's a "til" clause.  If there
+                                        * is, decrement it.
+                                        */
+                                       stuff_p->start.count = 0;
+                                       if (stuff_p->end.bars > 0)
+                                               stuff_p->end.bars--;
+                               }
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        movestuff()
+ *
+ * Abstract:    Move a STUFF from one linked list to another.
+ *
+ * Returns:     void
+ *
+ * Description: This function, given two staff pointers, finds the given STUFF
+ *             in the first one's linked list of STUFF.  It removes it from
+ *             there and adds it to the start of the second staff's list.
+ */
+
+static void
+movestuff(staff1_p, staff2_p, stuff_p)
+
+struct STAFF *staff1_p;                /* first STAFF */
+struct STAFF *staff2_p;                /* second STAFF */
+struct STUFF *stuff_p;         /* the STUFF to be moved */
+
+{
+       struct STUFF *s_p;      /* loop pointer */
+
+
+       debug(32, "movestuff file=%s line=%d", stuff_p->inputfile,
+                       stuff_p->inputlineno);
+       if (staff1_p->stuff_p == stuff_p) {
+               /*
+                * This STUFF is the first one in the first STAFF's linked
+                * list.  Change the headcell to point at the next one (which
+                * removes it from this list).  This "next one" could be null.
+                */
+               staff1_p->stuff_p = stuff_p->next;
+       } else {
+               /*
+                * Find which STUFF in the first STAFF's list points at the one
+                * we want to move.  Make it point at the following one.
+                */
+               for (s_p = staff1_p->stuff_p; s_p->next != stuff_p;
+                                       s_p = s_p->next)
+                       ;
+               s_p->next = stuff_p->next;
+       }
+
+       /*
+        * Make the STUFF we are moving point at what used to be the first
+        * one in the second STAFF's linked list.  Make the second STAFF's
+        * headcell point at the STUFF we are moving.
+        */
+       stuff_p->next = staff2_p->stuff_p;
+       staff2_p->stuff_p = stuff_p;
+}
+\f
+/*
+ * Name:        setphrases()
+ *
+ * Abstract:    Find endpoints and direction of all phrase marks.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through the main linked list and all STUFF,
+ *             looking for phrase marks.  For each phrase mark, it calls
+ *             phrasestuff() to find out the horizontal positioning of the
+ *             endpoints and whether the phrase mark should be above or below.
+ */
+
+static void
+setphrases()
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct STUFF *stuff_p;          /* point at a STUFF structure */
+       struct STUFF **phrasearray;     /* malloc array of pointers to stuff */
+       int numphrases;                 /* number of phrases in linked list */
+       int n;                          /* loop through phrasearray */
+
+
+       debug(16, "setphrases");
+       initstructs();
+
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               switch (mainll_p->str) {
+               case S_SSV:
+                       /* keep SSVs up to date; we need to know time sig */
+                       asgnssv(mainll_p->u.ssv_p);
+                       continue;
+
+               case S_STAFF:
+                       /* break out to handle this STAFF */
+                       break;
+
+               default:
+                       /* nothing to do, skip to next loop */
+                       continue;
+               }
+
+               /*
+                * For each phrase in this staff's stuff list, we need to
+                * determine whether it should print 0, 1, or 2 phrase marks,
+                * and the direction and endpoints of each.  We can't simply
+                * loop through the linked list, because the list gets altered
+                * by the subroutines we call, which can add and delete phrases
+                * from the list.  So we copy the pointers to an array first.
+                */
+               /* count how many phrases are in this staff's stuff list */
+               numphrases = 0;
+               for (stuff_p = mainll_p->u.staff_p->stuff_p; stuff_p != 0;
+                                       stuff_p = stuff_p->next) {
+                       if (stuff_p->stuff_type == ST_PHRASE)
+                               numphrases++;
+               }
+
+               /* if no phrases, nothing to do */
+               if (numphrases == 0)
+                       continue;
+
+               /* allocate an array to hold pointer(s) to the phrase(s) */
+               MALLOCA(struct STUFF *, phrasearray, numphrases);
+
+               /* fill the array with pointers to each phrase */
+               n = 0;
+               for (stuff_p = mainll_p->u.staff_p->stuff_p; stuff_p != 0;
+                                       stuff_p = stuff_p->next) {
+                       if (stuff_p->stuff_type == ST_PHRASE)
+                               phrasearray[n++] = stuff_p;
+               }
+
+               /* find endpoints and direction of phrase(s) from each stuff */
+               for (n = 0; n < numphrases; n++) {
+                       phrasestuff(mainll_p, phrasearray[n]);
+               }
+
+               FREE(phrasearray);
+       }
+}
+\f
+/*
+ * Name:        phrasestuff()
+ *
+ * Abstract:    Find endpoints and direction of phrase(s) from one STUFF.
+ *
+ * Returns:     void
+ *
+ * Description: This function decides whether the given phrase STUFF should
+ *             try to generate one or two phrase marks above, below, or both.
+ *             If it's both, it inserts a new STUFF in the list for it.  Then
+ *             it calls set1phrase() for each desired phrase to find endpoints
+ *             and set the place if it's unknown.
+ */
+
+static void
+phrasestuff(msbeg_p, stuff_p)
+
+struct MAINLL *msbeg_p;        /* point at main linked list where phrase starts */
+struct STUFF *stuff_p; /* point at STUFF structure for start of phrase */
+
+{
+       struct STUFF *stuff2_p;         /* if we need to create a 2nd phrase */
+
+
+       debug(32, "phrasestuff file=%s line=%d", stuff_p->inputfile,
+                       stuff_p->inputlineno);
+       switch (svpath(msbeg_p->u.staff_p->staffno, VSCHEME)->vscheme) {
+       case V_1:               /* one voice */
+               /* do phrase mark for first (only) voice if possible */
+               set1phrase(msbeg_p, stuff_p, 0);
+               break;
+
+       case V_2FREESTEM:       /* two voices that are free if one is space */
+       case V_3FREESTEM:       /* same as above; STUFF ignores voice 3 */
+               if (chkallspace(msbeg_p, stuff_p, 0) == YES) {
+                       /* first voice all spaces, apply phrase to second */
+                       set1phrase(msbeg_p, stuff_p, 1);
+                       break;
+               } else if (chkallspace(msbeg_p, stuff_p, 1) == YES) {
+                       /* second voice all spaces, apply phrase to first */
+                       set1phrase(msbeg_p, stuff_p, 0);
+                       break;
+               }
+               /* FALL THROUGH to handle like V_2OPSTEM */
+
+       case V_2OPSTEM:         /* two voices that always oppose */
+       case V_3OPSTEM:         /* same as above; STUFF ignores voice 3 */
+               switch (stuff_p->place) {
+
+               case PL_ABOVE:
+                       /* phrase requested only for top voice */
+                       set1phrase(msbeg_p, stuff_p, 0);
+                       break;
+
+               case PL_BELOW:
+                       /* phrase requested only for bottom voice */
+                       set1phrase(msbeg_p, stuff_p, 1);
+                       break;
+
+               default:
+                       /*
+                        * We're going to have two phrase marks, one above the
+                        * first voice and one below the second voice.  Let the
+                        * current STUFF be for the top one, and create a new
+                        * STUFF for the bottom one.
+                        */
+                       stuff_p->place = PL_ABOVE;
+                       stuff2_p = newSTUFF((char *)0,
+                                       stuff_p->dist,
+                                       stuff_p->dist_usage,
+                                       stuff_p->start.count,
+                                       stuff_p->start.steps,
+                                       stuff_p->gracebackup,
+                                       stuff_p->end.bars, stuff_p->end.count,
+                                       ST_PHRASE, NO, PL_BELOW,
+                                       stuff_p->inputfile,
+                                       stuff_p->inputlineno);
+                       stuff2_p->next = stuff_p->next;
+                       stuff_p->next = stuff2_p;
+
+                       set1phrase(msbeg_p, stuff_p, 0);
+                       set1phrase(msbeg_p, stuff2_p, 1);
+                       break;
+               }
+               break;
+       }
+}
+\f
+/*
+ * Name:        set1phrase()
+ *
+ * Abstract:    Find endpoints and direction of one phrase.
+ *
+ * Returns:     void
+ *
+ * Description: This function, given a STUFF for a single phrase mark and the
+ *             voice it should apply to, finds the endpoint GRPSYLs for the
+ *             phrase.  If it can't find valid GRPSYLs, it removes the phrase
+ *             and prints a warning.  Otherwise, it also decides whether the
+ *             phrase should be above or below, if that is not already known.
+ */
+
+static void
+set1phrase(msbeg_p, stuff_p, v)
+
+struct MAINLL *msbeg_p;        /* point at MLL (staff) where phrase begins */
+struct STUFF *stuff_p; /* point at STUFF structure for start of phrase */
+int v;                 /* which voice to attach the phrase to */
+
+{
+       struct MAINLL *msend_p; /* MLL (staff) where phrase ends */
+       struct MAINLL *mll_p;   /* for looping through MLL */
+       struct GRPSYL *beggrp_p;/* (eventually is) beginning of phrase */
+       struct GRPSYL *endgrp_p;/* (eventually is) end of phrase */
+       struct GRPSYL *gs_p;    /* for looping through GRPSYL lists */
+       int staffno;            /* the staff this phrase is on */
+       int timeden;            /* denominator of time sig at end of phrase */
+       int up, down;           /* count stem directions */
+       int n;                  /* loop variable */
+
+
+       debug(32, "set1phrase file=%s line=%d v=%d", stuff_p->inputfile,
+                       stuff_p->inputlineno, v);
+       stuff_p->vno = v + 1;   /* translate voice numbers 0, 1 to 1, 2 */
+       staffno = msbeg_p->u.staff_p->staffno;
+
+       /*
+        * Find what measure this phrase mark ends in.  Along the way, keep
+        * track of the time signature denominator, in case it changes.  If
+        * getendstuff() returns 0, it means the phrase runs into a multirest,
+        * which is not allowed.  If the phrase is supposed to be attached to
+        * the bottom voice, but it ends in a measure where the vscheme is 1,
+        * we must also throw it away.  (This condition is signaled by the
+        * groups_p[v] being a null pointer.)
+        */
+       msend_p = getendstuff(msbeg_p, stuff_p, &timeden);
+
+       if (msend_p == 0) {
+               l_warning(stuff_p->inputfile, stuff_p->inputlineno,
+                       "removing invalid phrase (runs into multirest)");
+               rmstuff(msbeg_p->u.staff_p, stuff_p);
+               return;
+       }
+       if (msend_p->u.staff_p->groups_p[v] == 0) {
+               l_warning(stuff_p->inputfile, stuff_p->inputlineno,
+               "removing invalid phrase (covers no notes in last measure)");
+               rmstuff(msbeg_p->u.staff_p, stuff_p);
+               return;
+       }
+
+       /*
+        * Find the GRPSYLs that are closest, timewise, to the requested
+        * beginning and ending times of the phrase mark.
+        */
+       beggrp_p = closestgroup(stuff_p->start.count,
+                               msbeg_p->u.staff_p->groups_p[v], Score.timeden);
+       endgrp_p = closestgroup(stuff_p->end.count,
+                               msend_p->u.staff_p->groups_p[v], timeden);
+
+       /*
+        * It's possible that *beggrp_p is a rest or a space, but a phrase must
+        * start on a note group.  So search forward, if necessary, to the first
+        * note group after this point.  If there is none in this measure, this
+        * is an illegal phrase mark.  Also, if the phrase begins and ends in
+        * the same measure, check that we don't go past the end in doing this
+        * search.  A phrase is not allowed to begin and end at the same group.
+        * But the two groups can be the same if gracebackup is being used,
+        * because in that case the beginning group is really a grace group
+        * before the ending group.  In any case, apply gracebackup if
+        * requested.
+        */
+       while (beggrp_p != 0 && beggrp_p->grpcont != GC_NOTES) {
+               if (beggrp_p == endgrp_p)
+                       break;
+               beggrp_p = nextnongrace(beggrp_p);
+       }
+       if (beggrp_p == 0) {
+               l_warning(stuff_p->inputfile, stuff_p->inputlineno,
+               "removing invalid phrase (covers no notes in first measure)");
+
+               rmstuff(msbeg_p->u.staff_p, stuff_p);
+               return;
+       }
+       if (beggrp_p == endgrp_p && stuff_p->gracebackup == 0) {
+               l_warning(stuff_p->inputfile, stuff_p->inputlineno,
+               "removing invalid phrase (need multiple notes)");
+
+               rmstuff(msbeg_p->u.staff_p, stuff_p);
+               return;
+       }
+       /* found a valid starting point; back up grace notes if requested */
+       for (n = 0; n < stuff_p->gracebackup; n++) {
+               beggrp_p = beggrp_p->prev;
+               if (beggrp_p == 0 || beggrp_p->grpvalue != GV_ZERO) {
+                       l_ufatal(stuff_p->inputfile, stuff_p->inputlineno,
+                       "not enough grace groups to back up to for phrase");
+               }
+       }
+
+       /*
+        * Do the equivalent thing with the end of the phrase mark, except that
+        * we don't have to deal with gracebackup.
+        */
+       while (endgrp_p != 0 && endgrp_p->grpcont != GC_NOTES &&
+                       beggrp_p != endgrp_p) {
+               endgrp_p = prevnongrace(endgrp_p);
+       }
+       if (beggrp_p == endgrp_p) {
+               l_warning(stuff_p->inputfile, stuff_p->inputlineno,
+               "removing invalid phrase (need multiple notes)");
+
+               rmstuff(msbeg_p->u.staff_p, stuff_p);
+               return;
+       }
+       if (endgrp_p == 0) {
+               l_warning(stuff_p->inputfile, stuff_p->inputlineno,
+               "removing invalid phrase (covers no notes in last measure)");
+
+               rmstuff(msbeg_p->u.staff_p, stuff_p);
+               return;
+       }
+
+       /*
+        * We have now determined the correct beginning and ending GRPSYLs for
+        * the phrase.  Store them for later use.
+        */
+       stuff_p->beggrp_p = beggrp_p;
+       stuff_p->endgrp_p = endgrp_p;
+
+       /*
+        * If we don't know yet whether the phrase should be drawn above or
+        * below the staff, decide that now.  We will put it on the side that
+        * has more note heads than stems.  So loop through all GRPSYLs within
+        * this phrase, counting.  Ignore grace groups.
+        */
+       if (stuff_p->place == PL_UNKNOWN) {
+               up = down = 0;
+               mll_p = msbeg_p;
+               gs_p = beggrp_p;
+               if (gs_p->grpvalue == GV_ZERO)
+                       gs_p = nextnongrace(gs_p);
+               while (gs_p != endgrp_p) {
+                       if (gs_p->grpcont == GC_NOTES) {
+                               if (gs_p->stemdir == UP)
+                                       up++;
+                               else
+                                       down++;
+                       }
+
+                       gs_p = nextnongrace(gs_p);
+
+                       /* if we hit the end of a measure, find start of next */
+                       if (gs_p == 0) {
+                               for (mll_p = mll_p->next;
+                                       mll_p->str != S_STAFF ||
+                                       mll_p->u.staff_p->staffno != staffno;
+                                       mll_p = mll_p->next)
+                                       ;
+                               gs_p = mll_p->u.staff_p->groups_p[v];
+                       }
+               }
+               /* count final group in phrase (must be GC_NOTES) */
+               if (gs_p->stemdir == UP)
+                       up++;
+               else
+                       down++;
+
+               /*
+                * Put phrase opposite the majority of the stems.  If it's a
+                * tie, base it on the first group.
+                */
+               if (up > down)
+                       stuff_p->place = PL_BELOW;
+               else if (up < down)
+                       stuff_p->place = PL_ABOVE;
+               else if (beggrp_p->stemdir == UP)
+                       stuff_p->place = PL_BELOW;
+               else
+                       stuff_p->place = PL_ABOVE;
+       }
+}
+\f
+/*
+ * Name:        rmstuff()
+ *
+ * Abstract:    Remove a STUFF from a linked list, and free it.
+ *
+ * Returns:     void
+ *
+ * Description: This function removes the given STUFF from the linked list
+ *             hanging off the given staff, and frees it.
+ */
+
+static void
+rmstuff(staff_p, stuff_p)
+
+struct STAFF *staff_p;         /* the staff that the stuff hangs off of */
+struct STUFF *stuff_p;         /* the stuff to be removed */
+
+{
+       struct STUFF *stuff2_p;         /* point along STUFF list */
+
+
+       debug(32, "rmstuff file=%s line=%d", stuff_p->inputfile,
+                       stuff_p->inputlineno);
+       if (staff_p->stuff_p == stuff_p) {
+               /* the given stuff is the first one in the list */
+               staff_p->stuff_p = stuff_p->next;
+       } else {
+               /* find which stuff in list points at the one to be removed */
+               for (stuff2_p = staff_p->stuff_p; stuff2_p->next != stuff_p;
+                               stuff2_p = stuff2_p->next)
+                       ;
+               stuff2_p->next = stuff_p->next;
+       }
+
+       FREE(stuff_p);
+}
+\f
+/*
+ * Name:        breakstuff()
+ *
+ * Abstract:    Break all "stuff" that crosses scorefeeds.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through the main linked list and all STUFF,
+ *             looking for stuff that crosses score feeds.  When it finds such
+ *             stuff, it breaks them at that point.
+ */
+
+static void
+breakstuff()
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct STUFF *stuff_p;          /* point at a STUFF structure */
+
+
+       debug(16, "breakstuff");
+       initstructs();
+
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               switch (mainll_p->str) {
+               case S_SSV:
+                       /* keep SSVs up to date; we need to know time sig */
+                       asgnssv(mainll_p->u.ssv_p);
+                       continue;
+
+               case S_STAFF:
+                       /* break out to handle this STAFF */
+                       break;
+
+               default:
+                       /* nothing to do, skip to next loop */
+                       continue;
+               }
+
+               /*
+                * Loop through all the stuff on this staff.  Do it in reverse
+                * order so that when stuff gets broken, the new STUFFs end up
+                * in the correct order.
+                */
+               if (mainll_p->u.staff_p->stuff_p != 0) {
+
+                       stuff_p = mainll_p->u.staff_p->stuff_p;
+                               while (stuff_p->next != 0)
+                                       stuff_p = stuff_p->next;
+                       /* now stuff_p points at the last one in the list */
+
+                       for ( ; stuff_p != 0; stuff_p = prevstuff(mainll_p,
+                                       stuff_p)) {
+                               /*
+                                * If there's a "til" clause, and it crosses
+                                * bar lines, call a function to see if it
+                                * needs to be broken, and if so, break it.
+                                */
+                               if (stuff_p->end.bars > 0)
+                                       breakone(mainll_p, stuff_p,
+                                                       Score.timenum,
+                                                       stuff_p->string, 1);
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        prevstuff()
+ *
+ * Abstract:    Find stuff preceding the given one.
+ *
+ * Returns:     pointer to previous stuff, or 0 if none
+ *
+ * Description: This function is given a pointer to a staff mainll item and a
+ *             stuff in that list.  It finds the preceding stuff, returning
+ *             it, or 0 if none.  If stuff linked lists were doubly linked,
+ *             we wouldn't have to go through this aggravation.
+ */
+
+static struct STUFF *
+prevstuff(mainll_p, stuff_p)
+
+struct MAINLL *mainll_p;       /* ptr to MLL item for a stuff */
+struct STUFF *stuff_p;         /* ptr to current stuff */
+
+{
+       register struct STUFF *prevstuff_p;
+
+
+       prevstuff_p = mainll_p->u.staff_p->stuff_p; /* get 1st stuff in list */
+
+       /* if current stuff is first stuff, there is none before it */
+       if (prevstuff_p == stuff_p)
+               return (0);
+
+       /* loop until we find it, then return */
+       while (prevstuff_p->next != stuff_p)
+               prevstuff_p = prevstuff_p->next;
+       return (prevstuff_p);
+}
+\f
+/*
+ * Name:        breakone()
+ *
+ * Abstract:    Break one "stuff" item if it crosses scorefeeds.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given a STUFF with a "til" clause that crosses
+ *             bar line(s).  It finds out if the STUFF crosses the FEED at the
+ *             end of the score.  If so, it stops the current stuff there, and
+ *             starts a continuation on the next score.  If there are more bar
+ *             lines yet to be crossed, it calls itself recursively.
+ */
+
+static void
+breakone(mllstaff_p, stuff_p, timenum, origstr_p, depth)
+
+struct MAINLL *mllstaff_p;     /* point at MLL struct holding stuff's staff */
+struct STUFF *stuff_p;         /* point at a STUFF structure */
+int timenum;                   /* numerator of current time sig */
+char *origstr_p;               /* original string, from first score of stuff */
+int depth;                     /* depth of recursion */
+
+{
+       /*
+        * Make the local variables static, to use less stack when making
+        * recursive calls.  We can get away with this because the recursive
+        * call is at the end of the function, and the variables aren't used
+        * after that.
+        */
+       static struct MAINLL *m2_p;     /* point along main linked list */
+       static struct MAINLL *m3_p;     /* point along main linked list */
+       static struct MAINLL *m4_p;     /* point along main linked list */
+       static struct STUFF *s_p;       /* point at a new STUFF */
+       static struct GRPSYL *gs_p;     /* point along a GRPSYL list */
+       static int bars;                /* count how many bars long it is */
+       static int otimenum;            /* num of time sig before last bar */
+       static float endcount;          /* count where the stuff ends */
+
+
+       debug(32, "breakone file=%s line=%d timenum=%d origstr_p=\"%s\"",
+                       stuff_p->inputfile, stuff_p->inputlineno, timenum,
+                       origstr_p == 0 ? "" : origstr_p);
+       /*
+        * Save how many bars this stuff crosses (initially, before any
+        * breaking), and the count where it ends.
+        */
+       bars = stuff_p->end.bars;
+       endcount = stuff_p->end.count;
+
+       /*
+        * Loop forward until crossing the given number of bars, or hitting a
+        * FEED, whichever comes first.  Keep the timenum updated.  At each
+        * bar line, save what it was before in otimenum.
+        */
+       for (m2_p = mllstaff_p; bars >= 0 && m2_p != 0 && m2_p->str != S_FEED;
+                       m2_p = m2_p->next) {
+
+               switch (m2_p->str) {
+               case S_SSV:
+                       if (m2_p->u.ssv_p->used[TIME] == YES)
+                               timenum = m2_p->u.ssv_p->timenum;
+                       break;
+
+               case S_BAR:
+                       otimenum = timenum;
+                       bars--;
+                       break;
+
+               case S_STAFF:
+                       /*
+                        * If this is the first staff of a measure, check the
+                        * first voice to see if it's a multirest.  (If it is,
+                        * all voices on all staffs would be.)  If so, decrement
+                        * the bars remaining appropriately.  It could end up
+                        * less than 0.  That's okay; we won't be breaking it.
+                        */
+                       if (m2_p->u.staff_p->staffno == 1 &&
+                       m2_p->u.staff_p->groups_p[0]->basictime < -1) {
+
+                               bars += 1 + m2_p->u.staff_p->
+                                               groups_p[0]->basictime;
+                       }
+                       break;
+               }
+       }
+
+       /*
+        * If bars <= -1, this stuff doesn't reach the end of this score, so
+        * just return.  If we hit the end of the piece, end the stuff at the
+        * last count of the last measure (thus the last bar line).  The
+        * parser has already put out a warning for this.
+        * If the stuff ends at the pseudobar of the next score, make it end at
+        * the last bar of this score instead.  However, phrases should not be
+        * adjusted this way, because under these conditions they will get
+        * pulled to the note at count 1.
+        */
+       if (bars <= -1)
+               return;
+       if (m2_p == 0 || bars == 0 && stuff_p->end.count == 0 &&
+                       stuff_p->stuff_type != ST_PHRASE) {
+               stuff_p->end.bars -= bars + 1;
+               stuff_p->end.count = timenum + 1;
+               return;
+       }
+
+       /*
+        * At this point we know that the stuff truly crosses the FEED we're
+        * at, and we're going to have to break it.  First, terminate the part
+        * of the stuff on this score and mark the carryout.  (However, if the
+        * next staff starts with a multirest that fully contains the rest of
+        * the stuff, we'll cancel the carryout later and not insert a new
+        * stuff for continuation.)
+        */
+       stuff_p->end.bars -= bars + 1;          /* only cross this many bars */
+       stuff_p->end.count = otimenum + 1;      /* end at end of last measure*/
+       stuff_p->carryout = YES;
+
+       /*
+        * Find the matching STAFF in the next measure.  It might not exist
+        * due to blocks.
+        */
+       for (m3_p = m2_p->next; m3_p != 0 && m3_p->str != S_BAR;
+                       m3_p = m3_p->next) {
+               if (m3_p->str == S_STAFF && m3_p->u.staff_p->staffno ==
+                                           mllstaff_p->u.staff_p->staffno)
+                       break;
+       }
+       if (m3_p == 0) {
+               return;
+       }
+       if (m3_p->str != S_STAFF)
+               pfatal("can't find staff in main linked list [breakone]");
+
+       /*
+        * If the staff has a multirest that's longer than the remaining
+        * length of the stuff, don't insert a new stuff; just get out now.
+        */
+       if (m3_p->u.staff_p->groups_p[0]->basictime < -1) {
+               if (bars < -(m3_p->u.staff_p->groups_p[0]->basictime)) {
+                       stuff_p->carryout = NO; /* cancel the carryout */
+                       return;
+               }
+       }
+
+       /*
+        * Create a new STUFF starting at count 0 of the new measure.  Link it
+        * in to its STAFF and set fields appropriately.
+        */
+       s_p = newSTUFF(origstr_p, stuff_p->dist, stuff_p->dist_usage,
+                       (double)0, (double)0, (short)0, bars, endcount,
+                       stuff_p->stuff_type, stuff_p->modifier, stuff_p->place,
+                       stuff_p->inputfile, stuff_p->inputlineno);
+       s_p->next = m3_p->u.staff_p->stuff_p;
+       m3_p->u.staff_p->stuff_p = s_p;
+       s_p->carryin = YES;
+       s_p->vno = stuff_p->vno;        /* actually only needed for phrases */
+
+       switch (s_p->stuff_type) {
+       case ST_ROM:
+       case ST_BOLD:
+       case ST_ITAL:
+       case ST_BOLDITAL:
+               /*
+                * If this staff was visible on the previous score, we just
+                * want the continuation dashes on this score, not the original
+                * string, so we change the string in that case.  (If the staff
+                * is also invisible on this score, we don't care what happens,
+                * so don't even check for that.)  Otherwise, leave it alone.
+                * Also, all other types that have strings should always repeat
+                * them on each score, so leave them alone.
+                */
+               if (mllstaff_p->u.staff_p->visible == YES)
+                       s_p->string = dashstr(stuff_p->string);
+               break;
+       case ST_PHRASE:
+               /*
+                * The new (2nd half of the) phrase mark has as its first group
+                * its voice's first GRPSYL in the new score.  Its last group
+                * is the last GRPSYL of the entire phrase.  The last group of
+                * the old (1st half of the) phrase mark is the last GRPSYL on
+                * that score for this voice.
+                */
+               s_p->beggrp_p = m3_p->u.staff_p->groups_p[ stuff_p->vno - 1 ];
+               s_p->endgrp_p = stuff_p->endgrp_p;
+               /* find matching staff in the measure before the FEED */
+               for (m4_p = m2_p; m4_p->str != S_STAFF ||
+                               m4_p->u.staff_p->staffno !=
+                               mllstaff_p->u.staff_p->staffno;
+                               m4_p = m4_p->prev)
+                       ;
+               /* find last group in the measure in that voice */
+               for (gs_p = m4_p->u.staff_p->groups_p[ stuff_p->vno - 1 ];
+                               gs_p->next != 0; gs_p = gs_p->next)
+                       ;
+               stuff_p->endgrp_p = gs_p;
+               break;
+       }
+
+       /*
+        * If there are still more bars to be crossed, call ourselves
+        * recursively to break the stuff again if necessary.  But first check
+        * to see we aren't too deep in recursion, using too much stack.
+        */
+       if (s_p->end.bars > 0) {
+               if (depth >= 300)
+                       l_ufatal(stuff_p->inputfile, stuff_p->inputlineno,
+                       "stuff crosses more than 300 scores (break into shorter pieces)");
+               breakone(m3_p, s_p, timenum, origstr_p, depth + 1);
+       }
+}
+\f
+/*
+ * Name:        contpedal()
+ *
+ * Abstract:    Insert pedal continuation STUFFs when needed.
+ *
+ * Returns:     void
+ *
+ * Description: When a pedal is to be held down through a score feed, the
+ *             print phase needs to know where (vertically) to draw the pedal
+ *             line on the new score.  There might not occur another pedal
+ *             character in the first measure there, or even on that whole
+ *             score.  So whenever this happens, regardless of whether there
+ *             are already pedal characters on the new score, this function
+ *             inserts a new STUFF with a special, null pedal indication, at
+ *             count 0 of the first measure of the new score.
+ */
+
+static void
+contpedal()
+
+{
+       short inpedal[MAXSTAFFS + 1];   /* does this staff have pedal on now?*/
+       short snappedal[MAXSTAFFS + 1]; /* same, when an ending is entered */
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct MAINLL *m2_p;            /* another pointer along MLL */
+       struct STUFF *stuff_p;          /* point at a STUFF structure */
+       struct STUFF *stuff2_p;         /* point at new STUFF structure */
+       struct BAR *bar_p;              /* point at a bar line */
+       int inending;                   /* are we now in an ending? */
+       int s;                          /* staff number */
+
+
+       debug(16, "contpedal");
+       /* init pedal state to NO for all staffs */
+       for (s = 1; s <= MAXSTAFFS; s++)
+               inpedal[s] = NO;
+
+       inending = NO;
+
+       /*
+        * Loop through main linked list.  For each STAFF found, update pedal
+        * state when necessary.  For each FEED found, if there's a pedal
+        * crossing it, insert a pedal continuation.  There is special work to
+        * do when endings are encountered, since this can change pedal states.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               switch (mainll_p->str) {
+
+               case S_STAFF:
+                       /*
+                        * Loop through all the stuff on this staff.  Whenever
+                        * there's a pedal mark, update the state for that
+                        * staff, except that pedal up/down is irrelevant.
+                        */
+                       for (stuff_p = mainll_p->u.staff_p->stuff_p;
+                                       stuff_p != 0; stuff_p = stuff_p->next) {
+
+                               if (stuff_p->stuff_type != ST_PEDAL)
+                                       continue;
+
+                               if (string_is_sym(stuff_p->string,
+                                               C_BEGPED, FONT_MUSIC) == YES)
+                                       inpedal[mainll_p->u.staff_p->
+                                                       staffno] = YES;
+
+                               else if (string_is_sym(stuff_p->string,
+                                               C_ENDPED, FONT_MUSIC) == YES)
+                                       inpedal[mainll_p->u.staff_p->
+                                                       staffno] = NO;
+                       }
+                       break;
+
+               case S_BAR:
+                       /*
+                        * When entering a second or later ending, the state of
+                        * all pedals must be set back to what they were when
+                        * entering the first ending.
+                        * First deal with the case where an ending starts at
+                        * the pseudobar after a feed.  In that case, we need
+                        * to ignore any endending on the previous real bar.
+                        */
+                       bar_p = mainll_p->u.bar_p;
+                       for (m2_p = mainll_p->next; m2_p != 0 &&
+                                       m2_p->str != S_BAR &&
+                                       (m2_p->str != S_CLEFSIG ||
+                                       m2_p->u.clefsig_p->bar_p == 0);
+                                       m2_p = m2_p->next)
+                               ;
+                       if (m2_p != 0 && m2_p->str == S_CLEFSIG) {
+                               /*
+                                * If an ending starts at this pseudobar,
+                                * substitute this pseudobar for the real one.
+                                */
+                               if (m2_p->u.clefsig_p->bar_p->endingloc
+                                                       == STARTITEM)
+                                       bar_p = m2_p->u.clefsig_p->bar_p;
+                       }
+
+                       switch (bar_p->endingloc) {
+                       case STARTITEM:
+                               if (inending == NO) {
+                                       /* entering first ending */
+                                       /* snapshot pedal states here */
+                                       for (s = 1; s <= MAXSTAFFS; s++)
+                                               snappedal[s] = inpedal[s];
+                                       inending = YES;
+                               } else {
+                                       /* entering a later ending */
+                                       /* restore snapshotted state */
+                                       for (s = 1; s <= MAXSTAFFS; s++)
+                                               inpedal[s] = snappedal[s];
+                               }
+                               break;
+
+                       case ENDITEM:
+                               /* leaving the last ending */
+                               inending = NO;
+                               break;
+                       }
+                       break;
+
+               case S_FEED:
+                       /* only consider FEEDs that are before music */
+                       if ( ! IS_CLEFSIG_FEED(mainll_p)) {
+                               break;
+                       }
+
+                       /*
+                        * For every staff where the pedal is now down, find
+                        * the structure for that staff in the first measure,
+                        * and insert a STUFF to indicate the continuation of
+                        * the pedal mark line.
+                        */
+                       for (s = 1; s <= MAXSTAFFS; s++) {
+
+                               if (inpedal[s] == NO)
+                                       continue;
+
+                               for (m2_p = mainll_p; m2_p != 0 &&
+                                               (m2_p->str != S_STAFF ||
+                                               m2_p->u.staff_p->staffno != s);
+                                               m2_p = m2_p->next)
+                                       ;
+                               if (m2_p == 0)
+                                       pfatal("couldn't find staff in contpedal");
+                               /* pedal continuation at count 0, w/ null str */
+                               stuff2_p = newSTUFF((char *)0, 0, SD_NONE,
+                                       (double)0, (double)0, (short)0, 0,
+                                       (double)0, ST_PEDAL, NO, PL_BELOW,
+                                       (char *)0, -1);
+
+                               /* put at beginning of staff's linked list */
+                               stuff2_p->next = m2_p->u.staff_p->stuff_p;
+                               m2_p->u.staff_p->stuff_p = stuff2_p;
+                       }
+                       break;
+               }
+       }
+}
+\f
+/*
+ * Name:        setstuff()
+ *
+ * Abstract:    Set horizontal absolute coordinates of "stuff".
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through the main linked list.  For every
+ *             visible staff, it loops through its list of STUFF structures,
+ *             setting all their absolute horizontal coordinates.
+ */
+
+static void
+setstuff()
+
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct CHHEAD *chhead_p;        /* chord headcell of current measure */
+       struct BAR *bar_p;              /* [pseudo] bar before current meas */
+       struct STUFF *stuff_p;          /* point at a STUFF structure */
+       struct MAINLL *m2_p;            /* MLL for end of stuff */
+       short timeden2;                 /* time sig denom at end of stuff */
+       struct CHHEAD *chhead2_p;       /* chord headcell for end of stuff */
+       struct BAR *bar2_p;             /* bar line for end of stuff */
+       struct GRPSYL *gs_p;            /* used for gracebackup */
+       float stepsize;                 /* STEPSIZE scaled by staffscale */
+       float leftwid;                  /* width of string left of align pt. */
+       float streast;                  /* east end of a string */
+       int ret;                        /* return code from geteast */
+       int v;                          /* voice associated with */
+       int n;                          /* loop variable */
+
+
+       debug(16, "setstuff");
+       initstructs();
+
+       chhead_p = 0;           /* prevent useless 'used before set' warning */
+       bar_p = 0;              /* prevent useless 'used before set' warning */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+               /*
+                * Do various set up work per structure type.  If it's a
+                * visible staff, break and go do the rest of this loop.
+                * Otherwise, "continue" on to the next structure.
+                */
+               switch (mainll_p->str) {
+               case S_SSV:
+                       /* keep SSVs up to date; we need to know timeden */
+                       asgnssv(mainll_p->u.ssv_p);
+                       continue;
+
+               case S_CHHEAD:
+                       /* always remember preceding chord headcell */
+                       chhead_p = mainll_p->u.chhead_p;
+                       continue;
+
+               case S_BAR:
+                       /* always remember where the preceding bar was */
+                       bar_p = mainll_p->u.bar_p;
+                       continue;
+
+               case S_CLEFSIG:
+                       /*
+                        * The pseudo bar that's in a clefsig following a
+                        * scorefeed overrides the real bar at the end of the
+                        * previous score.
+                        */
+                       if (mainll_p->u.clefsig_p->bar_p != 0)
+                               bar_p = mainll_p->u.clefsig_p->bar_p;
+                       continue;
+
+               case S_STAFF:
+                       /* visible staff breaks out to do rest of the loop */
+                       if (mainll_p->u.staff_p->visible == YES)
+                               break;
+                       continue;
+
+               default:
+                       continue;
+               }
+
+               /* get stepsize for this staff */
+               stepsize = STEPSIZE * svpath(mainll_p->u.staff_p->staffno,
+                               STAFFSCALE)->staffscale;
+
+               /*
+                * Loop through all the stuff on this staff.
+                */
+               for (stuff_p = mainll_p->u.staff_p->stuff_p; stuff_p != 0;
+                               stuff_p = stuff_p->next) {
+                       /*
+                        * Handle the special case of a fermata on a measure
+                        * rest.  No matter what count the user requested,
+                        * we're going to center it above or below the measure
+                        * rest character.  We also assume there is no "til"
+                        * clause.
+                        */
+                       if (string_is_sym(stuff_p->string, C_FERM, FONT_MUSIC) == YES ||
+                           string_is_sym(stuff_p->string, C_UFERM, FONT_MUSIC) == YES) {
+
+                               if (setmrferm(mainll_p->u.staff_p, stuff_p)
+                                               == YES)
+                                       continue;
+                               /*
+                                * The fermata is not on a measure rest.  Fall
+                                * through to handle like any normal stuff.
+                                */
+                       }
+
+                       /*
+                        * Set c[AX] for the stuff.
+                        */
+                       if (stuff_p->gracebackup == 0) {
+                               /*
+                                * Use the c[INCHPERWHOLE] coordinate of the
+                                * chord or bar line that is at or before its
+                                * "start".
+                                */
+                               stuff_p->c[AX] = count2coord(
+                                       stuff_p->start.count, bar_p, chhead_p,
+                                       Score.timeden) +
+                                       stuff_p->start.steps *
+                                       STUFFSTEP(stuff_p);
+                       } else {
+                               /*
+                                * Since we have to back up by some number of
+                                * grace notes, we have to find a group to
+                                * associate the STUFF with.  Then we can back
+                                * up from there.
+                                */
+                               v = 0;  /* avoid 'used before set' warning */
+                               switch (svpath(mainll_p->u.staff_p->staffno,
+                                                       VSCHEME)->vscheme) {
+                               case V_1:               /* 1 */
+                                       v = 0;  /* only one voice, use it */
+                                       break;
+                               case V_2FREESTEM:       /* 2f */
+                               case V_3FREESTEM:       /* 3f */
+                                       if (chkallspace(mainll_p, stuff_p, 0)
+                                                       == YES) {
+                                               /* first voice all spaces */
+                                               /* apply stuff to second */
+                                               v = 1;
+                                               break;
+                                       } else if (chkallspace(mainll_p,
+                                                       stuff_p, 1) == YES) {
+                                               /* second voice all spaces */
+                                               /* apply stuff to first */
+                                               v = 0;
+                                               break;
+                                       }
+                                       /* FALL THROUGH;handle like V_2OPSTEM */
+                               case V_2OPSTEM:         /* 2o */
+                               case V_3OPSTEM:         /* 3o */
+                                       v = stuff_p->place == PL_ABOVE ? 0 : 1;
+                                       break;
+                               }
+
+                               /* find closest note group in this voice */
+                               gs_p = closestgroup(stuff_p->start.count,
+                                       mainll_p->u.staff_p->groups_p[v],
+                                       Score.timeden);
+
+                               /* back up right number of grace groups */
+                               for (n = 0; n < stuff_p->gracebackup; n++) {
+                                       gs_p = gs_p->prev;
+                                       if (gs_p == 0 || gs_p->grpvalue
+                                                               != GV_ZERO)
+                                               l_ufatal(stuff_p->inputfile,
+                                                       stuff_p->inputlineno,
+                                                       "not enough grace groups to back up to for stuff");
+                               }
+
+                               /*
+                                * Put the stuff at this grace group, except
+                                * that the steps offset must be applied.
+                                */
+                               stuff_p->c[AX] = gs_p->c[AX] +
+                                       stuff_p->start.steps *
+                                       STUFFSTEP(stuff_p);
+                       }
+
+                       /*
+                        * If this stuff has a "til" clause, find where the
+                        * ending point is and set c[AE] to that.  If this
+                        * stuff also has a string, and the string extends
+                        * beyond the point that the "til" clause asks for,
+                        * c[AE] will be changed later to agree with the string.
+                        */
+                       if (stuff_p->end.bars != 0 || stuff_p->end.count != 0) {
+                               /*
+                                * Init variables to the current position
+                                * (beginning of the stuff).  If the stuff is   
+                                * supposed to extend across one or more bar
+                                * lines, geteast() will alter them to the
+                                * correct values for the bar where the stuff
+                                * ends.  It will blow away the 'til' clause in
+                                * certain multirest scenarios.
+                                */
+                               m2_p = mainll_p;        /* this stuff's staff*/
+                               timeden2 = Score.timeden;
+                               chhead2_p = chhead_p;
+                               bar2_p = bar_p;
+
+                               ret = geteast(stuff_p, m2_p, &timeden2,
+                                                        &chhead2_p, &bar2_p);
+
+                               switch (ret) {
+                               case 1:
+                                       /*
+                                        * Set c[AE] for the stuff, using the
+                                        * c[INCHPERWHOLE] coordinate of the
+                                        * chord or bar line that precedes or
+                                        * is at the end of it.
+                                        */
+                                       stuff_p->c[AE] = count2coord(
+                                               stuff_p->end.count,
+                                               bar2_p, chhead2_p, timeden2);
+                                       break;
+                               case 2:
+                                       /* end the stuff a little beyond the */
+                                       /* barline at the start of the stuff */
+                                       stuff_p->c[AE] = bar2_p->c[AX]
+                                               + STUFFSTEP(stuff_p);
+                                       break;
+                               case 3:
+                                       /* no "til" clause anymore */
+                                       /* set to 0 temporarily */
+                                       stuff_p->c[AE] = 0;
+                                       break;
+                               }
+                               /*
+                                * If there is still a "til" clause (it wasn't
+                                * blown away), make sure AE isn't left of AX.
+                                * Although the parse phase checks the bars and
+                                * counts for this, it could still happen here
+                                * if start.steps is too big.  If it happens,
+                                * warn, and set AE to AX.
+                                */
+                               if (stuff_p->end.bars != 0 ||
+                                               stuff_p->end.count != 0) {
+                                       if (stuff_p->c[AE] < stuff_p->c[AX]) {
+                                               l_warning(stuff_p->inputfile,
+                                               stuff_p->inputlineno,
+                                               "mark begins after 'til' position; moving 'til' position to the right");
+                                               stuff_p->c[AE] = stuff_p->c[AX];
+                                       }
+                               }
+                       } else {
+                               /* no "til" clause; set to 0 temporarily */
+                               stuff_p->c[AE] = 0;
+                       }
+
+                       /*
+                        * Set c[AW] for all stuff types, and c[AE] for ones
+                        * that don't have a "til" clause.  Reset c[AE] for
+                        * ones that have a "til" clause, if they have a string
+                        * that sticks out farther than that.
+                        */
+                       switch (stuff_p->stuff_type) {
+                       case ST_ROM:
+                       case ST_BOLD:
+                       case ST_ITAL:
+                       case ST_BOLDITAL:
+                       case ST_MUSSYM:
+                       case ST_PEDAL:
+                       case ST_OCTAVE:
+                               /*
+                                * These types (and only these) have a string.
+                                * (However, pedal continuations don't, so
+                                * treat them specially.)  Set c[AW] such that
+                                * the first character will be centered at
+                                * c[AX].
+                                */
+                               if (stuff_p->string == 0) {
+                                       /* must be a pedal continuation; */
+                                       /*  these have no width */
+                                       stuff_p->c[AW] = stuff_p->c[AE] =
+                                                       stuff_p->c[AX];
+                                       break;
+                               }
+
+                               /* not a pedal continuation */
+
+                               /*
+                                * If this is a chord with a grid, handle it
+                                * all in the subroutine.
+                                */
+                               if (stuff_p->modifier == TM_CHORD && trygrid(
+                                               mainll_p, stuff_p) == YES) {
+                                       break;
+                               }
+
+                               leftwid = left_width(stuff_p->string);
+                               stuff_p->c[AW] = stuff_p->c[AX] - leftwid;
+
+                               /* find the initial east of the string */
+                               streast = stuff_p->c[AW] +
+                                               strwidth(stuff_p->string);
+                               /*
+                                * If the string would go beyond the right
+                                * margin, try to split it onto multiple lines,
+                                * and reset the string's east.  Don't do this
+                                * for chord/analysis/figbass.
+                                */
+                               if (streast > PGWIDTH -
+                                               eff_rightmargin(mainll_p) &&
+                                  ! IS_CHORDLIKE(stuff_p->modifier)) {
+                                       stuff_p->string = split_string(
+                                               stuff_p->string, PGWIDTH -
+                                               eff_rightmargin(mainll_p) -
+                                               stuff_p->c[AW]);
+                                       streast = stuff_p->c[AW] +
+                                               strwidth(stuff_p->string);
+                               }
+
+                               /*
+                                * If this east is beyond the east given by the
+                                * "til" clause (if any), use it for the AE.
+                                */
+                               if (streast > stuff_p->c[AE])
+                                       stuff_p->c[AE] = streast;
+
+                               break;
+
+                       case ST_CRESC:
+                       case ST_DECRESC:
+                       case ST_PHRASE:
+                       case ST_TIESLUR: /* due to carry-in into ending */
+                       case ST_TABSLUR: /* due to carry-in into ending */
+                       case ST_BEND:    /* due to carry-in into ending */
+                               /*
+                                * These types (and only these) have no string.
+                                * Set c[AW] the same as c[AX].  These always
+                                * have "til" clauses, so c[AE] is already set.
+                                * (Actually, c[AE] is not set for TIESLUR,
+                                * TABSLUR, or BEND, but no one uses it anyhow.)
+                                */
+                               stuff_p->c[AW] = stuff_p->c[AX];
+                               break;
+
+                       case ST_MIDI:
+                               /* this file doesn't deal with MIDI at all */
+                               break;
+
+                       default:
+                               pfatal("unknown stuff type %d", 
+                                               stuff_p->stuff_type);
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        count2coord()
+ *
+ * Abstract:    Convert a count in a measure to the absolute horizontal coord.
+ *
+ * Returns:     coordinate corresponding to the given count
+ *
+ * Description: This function, given a count number in a measure, and the
+ *             preceding bar line, chord head cell, and time signature
+ *             denominator, calculates and returns the absolute horizonal
+ *             coordinate of that place.  In a measure, the preceding bar line
+ *             (or pseudo bar line, if this is the first measure of a score)
+ *             is regarded as count 0, and the following bar line is regarded
+ *             as count N + 1, where N is the numerator of the time signature.
+ *             Between any adjacent chords, or chord and bar line, time is
+ *             treated as proportional to distance.
+ */
+
+static double
+count2coord(count, bar_p, chhead_p, timeden)
+
+double count;          /* count in measure */
+struct BAR *bar_p;     /* bar at start of measure (pseudobar if 1st in score)*/
+struct CHHEAD *chhead_p;/* chord headcell for this measure */
+int timeden;           /* denominator of time signature in this measure */
+
+{
+       struct CHORD *ch_p, *nch_p;     /* point at CHORD structures */
+       float frac;             /* what fraction of a whole it starts at */
+       float coord;            /* the answer */
+
+
+       if (count < 1) {
+               /*
+                * The stuff is before the first chord ("count 1").  So we
+                * consider the preceding bar line to be count 0, and allocate
+                * time proportionally.
+                */
+               coord = bar_p->c[AX] + (count / timeden) *
+                               bar_p->c[INCHPERWHOLE];
+       } else {
+               /*
+                * Convert the "count" where this stuff begins to what fraction
+                * of a whole it starts at.
+                */
+               frac = (count - 1) / timeden;
+
+               /*
+                * In this loop, ch_p starts at the first chord and nch_p is
+                * the next chord.  They move forward in parallel.  We get out
+                * either when nch_p is 0 (ch_p is the last chord), or when
+                * nch_p is beyond the place where our stuff goes (the stuff
+                * goes at or following ch_p).
+                */
+               for (ch_p = chhead_p->ch_p, nch_p = ch_p->ch_p;
+                    nch_p != 0 && RAT2FLOAT(nch_p->starttime) <= frac;
+                    ch_p = nch_p, nch_p = nch_p->ch_p)
+                       ;
+
+               /*
+                * Subtract to find how far (timewise) the stuff is after chord
+                * ch_p.  Then allocate space proportionally.
+                */
+               coord = ch_p->c[AX] + (frac - RAT2FLOAT(ch_p->starttime)) *
+                               ch_p->c[INCHPERWHOLE];
+       }
+
+       return (coord);
+}
+\f
+/*
+ * Name:        geteast()
+ *
+ * Abstract:    Point variables at things relevant to the east end of a STUFF.
+ *
+ * Returns:     1 if count2coord() should be used to find AE of stuff
+ *             2 if AE of stuff should be near *bar_p_p due to multirest
+ *             3 if 'til' clause is being blown away due to multirest
+ *
+ * Description: This function is given pointers pertaining to a measure where
+ *             a STUFF begins.  It searches forward to the end of the stuff,
+ *             according to the given number of measures.  It sets *timeden2_p,
+ *             *chhead2_p_p, and *bar2_p_p to the values they should be for
+ *             the end of the stuff, if the return code is 1 (the usual case).
+ *             For 2 and 3, only *bar2_p_p is guaranteed to be meaningful.
+ */
+
+static int
+geteast(stuff_p, m2_p, timeden2_p, chhead2_p_p, bar2_p_p)
+
+struct STUFF *stuff_p;         /* pointer to the stuff */
+struct MAINLL *m2_p;           /* starts at start of stuff, change to end */
+short *timeden2_p;             /* starts at start of stuff, change to end */
+struct CHHEAD **chhead2_p_p;   /* starts at start of stuff, change to end */
+struct BAR **bar2_p_p;         /* starts at start of stuff, change to end */
+
+{
+       int blimit;             /* number of bars to search forward past */
+       int timenum;            /* numerator of time signature */
+       int b;                  /* count bar lines */
+
+
+       blimit = stuff_p->end.bars;     /* number of bars to cross */
+
+       /* if all within one bar, return right away */
+       if (blimit == 0) {
+               /* if starts and ends inside multirest, blow away 'til' clause*/
+               if (m2_p->u.staff_p->groups_p[0]->basictime < -1) {
+                       stuff_p->end.count = 0;
+                       return (3);
+               }
+
+               return (1);     /* normal case; retain 'til' clause */
+       }
+
+       timenum = Score.timeden;        /* keep track of time sig numerator */
+
+       /*
+        * The input parameters point at values that are for the beginning of
+        * the stuff.  Loop forward the requested number of bars to get to the
+        * end of the stuff.  While doing this, keep those variables updated.
+        * By the end of this function, they will be correct for the end of
+        * the stuff.
+        */
+       b = 0;
+       /* if it starts at a multirest, account for that */
+       if (m2_p->u.staff_p->groups_p[0]->basictime < -1) {
+               /* if it ends inside the multirest, point at previous bar, */
+               /*  blow away 'til' clause, and get out */
+               if (-(m2_p->u.staff_p->groups_p[0]->basictime) > blimit) {
+                       *bar2_p_p = m2_p->u.bar_p;
+                       stuff_p->end.bars = 0;
+                       stuff_p->end.count = 0;
+                       return (3);
+               }
+
+               b = -1 - m2_p->u.staff_p->groups_p[0]->basictime;
+       }
+       for ( ; b < blimit; b++) {
+               for (m2_p = m2_p->next; m2_p != 0 && m2_p->str != S_BAR;
+                                       m2_p = m2_p->next) {
+
+                       switch (m2_p->str) {
+                       case S_SSV:
+                               if (m2_p->u.ssv_p->used[TIME] == YES) {
+                                       timenum = m2_p->u.ssv_p->timenum;
+                                       *timeden2_p = m2_p->u.ssv_p->timeden;
+                               }
+                               break;
+
+                       case S_STAFF:
+                               /* multirests count as multiple measures */
+                               if (m2_p->u.staff_p->staffno == 1 &&
+                               m2_p->u.staff_p->groups_p[0]->basictime < -1) {
+
+                                       /* add (multi - 1) to no. of bars */
+                                       b -= 1 + m2_p->u.staff_p->
+                                                       groups_p[0]->basictime;
+
+                                       /*
+                                        * If the stuff doesn't make it into
+                                        * the last measure, or doesn't make it
+                                        * to the last measure's bar line, make
+                                        * it stop at the bar before multirest.
+                                        */
+                                       if (b > blimit || b == blimit &&
+                                       stuff_p->end.count < timenum + 1) {
+                                               return (2);
+                                       }
+
+                                       /*
+                                        * If it ends at the bar after the
+                                        * multirest, move forward to that bar
+                                        * and end the stuff there.
+                                        */
+                                       if (b == blimit) {
+                                               while (m2_p->str != S_BAR)
+                                                       m2_p = m2_p->next;
+                                               *bar2_p_p = m2_p->u.bar_p;
+                                               return (2);
+                                       }
+                               }
+                               break;
+                       }
+               }
+
+               if (m2_p == 0)
+                       pfatal("'til' clause extends beyond end of the piece [geteast1]");
+
+               *bar2_p_p = m2_p->u.bar_p;
+       }
+
+       /*
+        * m2_p points at the bar line preceding or at the place where the
+        * stuff ends.  Continue forward to be pointing at the CHHEAD of that
+        * measure and also do final variable updates.
+        */
+       for ( ; m2_p != 0 && m2_p->str != S_CHHEAD;
+                       m2_p = m2_p->next) {
+
+               switch (m2_p->str) {
+               case S_SSV:
+                       if (m2_p->u.ssv_p->used[TIME] == YES)
+                               *timeden2_p = m2_p->u.ssv_p->timeden;
+                       break;
+               case S_CLEFSIG:
+                       if (m2_p->u.clefsig_p->bar_p != 0)
+                               *bar2_p_p = m2_p->u.clefsig_p->bar_p;
+                       break;
+               }
+       }
+
+       if (m2_p == 0)
+               pfatal("'til' clause extends beyond end of the piece [geteast2]");
+
+       /*
+        * If the first staff in this measure has a multirest, return that fact
+        * and have the stuff end at this bar line.
+        */
+       if (m2_p->next->u.staff_p->groups_p[0]->basictime < -1)
+               return (2);
+
+       *chhead2_p_p = m2_p->u.chhead_p;
+
+       return (1);             /* didn't end during a multirest */
+}
+\f
+/*
+ * Name:        setmrferm()
+ *
+ * Abstract:    Set absolute horizonal coords of a fermata on measure rest/rpt.
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function is given a staff and a stuff for a fermata there.
+ *             It decides whether the fermata applies to a measure rest or a
+ *             measure repeat.  If it does, it sets its coords to align with
+ *             the symbol and returns YES.  Otherwise it returns NO.
+ */
+
+static int
+setmrferm(staff_p, stuff_p)
+
+struct STAFF *staff_p;
+struct STUFF *stuff_p;
+
+{
+       struct GRPSYL *gs_p;    /* point at the relevant grpsyl list */
+       float fermx;            /* the center of the fermata */
+       float fermwidth;        /* width of the fermata */
+       int font, size, code;   /* of the fermata */
+       char *s_p;              /* point into the string holding the fermata */
+
+
+       debug(32, "setmrferm file=%s line=%d", stuff_p->inputfile,
+                       stuff_p->inputlineno);
+       /*
+        * Who knows why the user would put a fermata between two staffs, but
+        * if they did, treat it as normal stuff.
+        */
+       if (stuff_p->place == PL_BETWEEN)
+               return (NO);
+
+       /*
+        * Figure out which voice this fermata is meant to apply to.  It could
+        * be that one voice has a measure rest and the other doesn't.  For
+        * measure repeats, both would have it, so we wouldn't care which
+        * voice, but we might as well fall through the same code.  Point
+        * at the first GRPSYL in that voice's list.
+        */
+       gs_p = 0;               /* prevent useless 'used before set' warning */
+       switch (svpath(staff_p->staffno, VSCHEME)->vscheme) {
+       case V_1:
+               /* only 1 voice, this must be it */
+               gs_p = staff_p->groups_p[0];
+               break;
+
+       case V_2OPSTEM:
+       case V_3OPSTEM:
+               /*
+                * Technically we should attach the fermata to the voice it is
+                * next to.  But if that voice is all spaces, that wouldn't
+                * make much sense.  So fall through and handle the same as
+                * the freestem cases.
+                */
+
+       case V_2FREESTEM:
+       case V_3FREESTEM:
+               /* apply it to the nearest voice, unless it's all spaces */
+               if (stuff_p->place == PL_ABOVE) {
+                       if ( ! hasspace(staff_p->groups_p[0], Zero, Score.time))
+                               gs_p = staff_p->groups_p[0];
+                       else
+                               gs_p = staff_p->groups_p[1];
+               } else {
+                       if ( ! hasspace(staff_p->groups_p[1], Zero, Score.time))
+                               gs_p = staff_p->groups_p[1];
+                       else
+                               gs_p = staff_p->groups_p[0];
+               }
+               break;
+       }
+
+       /*
+        * If the relevant voice is not a measure rest or measure repeat, don't
+        * do anything more.  Just return and let the normal "stuff" code
+        * handle this fermata.
+        */
+       if (gs_p->is_meas == NO)
+               return (NO);
+
+       /*
+        * This fermata is on a measure rest/repeat.  We can't rely on the AX
+        * of this; it's offset like a whole rest would be.  We have to
+        * average the AW and AE to know where the center should be.
+        * If the user requested a stepsize offset, we will apply it to the
+        * result, so in that case it won't really be centered after all.
+        */
+       fermx = (gs_p->c[AW] + gs_p->c[AE]) / 2 +
+                               stuff_p->start.steps * STEPSIZE;
+
+       /* find width of fermata */
+       font = stuff_p->string[0];
+       size = stuff_p->string[1];
+       s_p = &stuff_p->string[2];
+       code = next_str_char(&s_p, &font, &size);
+       fermwidth = width(font, size, code);
+
+       /* set the absolute horizontal coords */
+       stuff_p->c[AX] = fermx;
+       stuff_p->c[AW] = fermx - fermwidth / 2;
+       stuff_p->c[AE] = fermx + fermwidth / 2;
+
+       return (YES);
+}
+\f
+/*
+ * Name:        trygrid()
+ *
+ * Abstract:   Handle a chord STUFF if there are chord grids.
+ *
+ * Returns:     YES if a grid will be printed with this chord, NO if not
+ *
+ * Description: If there are to be chord grids printed at the end of the song,
+ *             this function sets the "used" flag.  If a grid should be
+ *             printed here (where the chord is used), it sets the coordinates
+ *             of this STUFF appropriately.
+ */
+
+static int
+trygrid(mainll_p, stuff_p)
+
+struct MAINLL *mainll_p;       /* MLL struct for this chord stuff */
+struct STUFF *stuff_p;         /* the chord stuff */
+
+{
+       int gridswhereused;     /* YES or NO for this staff */
+       struct GRID *grid_p;    /* point to the grid definition */
+       char *asciichord_p;     /* point at ASCII version of chord */
+       float geast, gwest;     /* relative coords of the grid */
+       float hstrw;            /* half the width of the chord string */
+
+
+       gridswhereused = svpath(mainll_p->u.staff_p->staffno,
+                               GRIDSWHEREUSED)->gridswhereused;
+
+       if (Score.gridsatend == NO && gridswhereused == NO) {
+               return (NO);
+       }
+
+       grid_p = findgrid(stuff_p->string);
+
+       /* if grid was never defined, warn and return no grid here */
+       if (grid_p == 0) {
+               asciichord_p = ascii_str(stuff_p->string, YES, NO, TM_CHORD);
+               l_warning(stuff_p->inputfile, stuff_p->inputlineno,
+                               "no grid defined for chord %s", asciichord_p);
+               return (NO);
+       }
+
+       if (Score.gridsatend == YES) {          /* grids print at end of song*/
+               /* mark grid as used if it hasn't been, and keep count */
+               if (grid_p->used == NO) {
+                       grid_p->used = YES;
+                       Atend_info.grids_used++;
+               }
+       }
+
+       /* if no grid is to be printed here, get out */
+       if (gridswhereused == NO)
+               return (NO);
+
+       /* we only need east & west here */
+       gridsize(grid_p, stuff_p->all ? 0 : mainll_p->u.staff_p->staffno,
+                       (float *)0, (float *)0, &geast, &gwest);
+       hstrw = strwidth(stuff_p->string) / 2.0;
+
+       /*
+        * The stuff extends as far as necessary to contain both the string and
+        * the grid.  Unlike for other string stuffs, the string is centered at
+        * this count.  (So is the grid, if you ignore any "X fr" string on its
+        * right side.)  Note:  "til" clauses are not allowed on chords.
+        */
+       stuff_p->c[AE] = stuff_p->c[AX] + MAX(geast, hstrw);
+       stuff_p->c[AW] = stuff_p->c[AX] + MIN(gwest, -hstrw);
+
+       return (YES);           /* grid gets printed here */
+}
+\f
+/*
+ * Name:        tieslurstuff()
+ *
+ * Abstract:   Create STUFF structures for all ties, slurs, and bends.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts ST_TIESLUR, ST_TABSLUR, and ST_BEND STUFF
+ *             structures in the linked lists.  Unlike for the other stuff
+ *             types, the parser never does this.  So up until now, there have
+ *             been none of these in the linked lists.  More than one STUFF is
+ *             needed if there the tie/slur/bend is across a bar line into
+ *             endings, or across a scorefeed.
+ */
+
+static void
+tieslurstuff()
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct GRPSYL *gs_p;            /* point at a group */
+       int v;                          /* voice number, 0 or 1 */
+       int n, k;                       /* loop variables */
+
+
+       debug(16, "tieslurstuff");
+       initstructs();
+
+       /*
+        * Loop through main linked list, looking for visible STAFFs.
+        */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               if (mainll_p->str == S_SSV) {
+                       /* keep SSVs up to date for benefit of l_warning */
+                       asgnssv(mainll_p->u.ssv_p);
+                       continue;
+               }
+
+               if (mainll_p->str != S_STAFF ||
+                   mainll_p->u.staff_p->visible == NO)
+                       continue;
+
+               /*
+                * Loop through all voices on this staff.
+                */
+               for (v = 0; v < MAXVOICES && mainll_p->u.staff_p->
+                               groups_p[v] != 0; v++) {
+                       /*
+                        * Loop through the groups in this voice.  Ignore rests
+                        * and spaces.
+                        */
+                       for (gs_p = mainll_p->u.staff_p->groups_p[v];
+                                       gs_p != 0; gs_p = gs_p->next) {
+
+                               if (gs_p->grpcont != GC_NOTES)
+                                       continue;
+
+                               /*
+                                * For each note in this group, for each tie
+                                * and slur starting at it, call a function to
+                                * allocate a STUFF for it (more if into an
+                                * ending or scorefeed).  However, do not do
+                                * this for ties on a tablature staff.  They
+                                * are not to be printed.
+                                */
+                               for (n = 0; n < gs_p->nnotes; n++) {
+                                       if (gs_p->notelist[n].tie == YES &&
+                                                       ! is_tab_staff(mainll_p
+                                                       ->u.staff_p->staffno))
+                                               mktieslurstuff(mainll_p,
+                                                       gs_p, n, -1);
+
+                                       for (k = 0; k < gs_p->notelist[n].
+                                                               nslurto; k++) {
+                                               mktieslurstuff(mainll_p,
+                                                       gs_p, n, k);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        mktieslurstuff()
+ *
+ * Abstract:   Create STUFF structure(s) for one tie/slur/bend.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts ST_TIESLUR, ST_TABSLUR, or ST_BEND STUFF
+ *             structure(s) in the linked list for one tie or slur curve.
+ *             Normally only one is needed, but if it crosses a scorefeed
+ *             two are needed, and if it crosses into a first ending, one is
+ *             needed for each following ending.
+ */
+
+static void
+mktieslurstuff(mllstaff_p, gs_p, n, s)
+
+struct MAINLL *mllstaff_p;     /* MLL of staff where tie/slur/bend starts */
+struct GRPSYL *gs_p;           /* ptr to group where tie/slur/bend starts */
+int n;                         /* index to note in notelist where it starts */
+int s;                         /* index into slurtolist, or -1 for tie */
+
+{
+       struct STUFF *stuff_p;          /* point at a STUFF structure */
+       struct STAFF *staff_p;          /* point at staff of mllstaff */
+       struct MAINLL *mll_p;           /* point along MLL */
+       struct MAINLL *mll2_p;          /* another pointer along MLL */
+       struct BAR *bar_p;              /* point to a bar or pseudobar */
+       struct MAINLL *ebmll_p;         /* end bar MLL struct */
+       int endingloc;                  /* ending location */
+       int stufftype;                  /* which of the stuff types is it? */
+
+
+       staff_p = mllstaff_p->u.staff_p;
+
+       if (s == -1) {                                  /* tie */
+               stufftype = ST_TIESLUR;
+       } else if (gs_p->notelist[n].is_bend == YES) {  /* bend */
+               stufftype = ST_BEND;
+       } else if (is_tab_staff(staff_p->staffno) ||    /* slur on tab or */
+                  is_tab_staff(staff_p->staffno + 1)) { /* tabnote staff */
+               stufftype = ST_TABSLUR;
+       } else {                                        /* slur on other staff*/
+               stufftype = ST_TIESLUR;
+       }
+
+       /* allocate a STUFF structure for this tie/slur/bend */
+       stuff_p = newSTUFF((char *)0, 0, SD_NONE, (double)0, (double)0, 0, 0,
+                       (double)0, stufftype, NO, PL_UNKNOWN, (char *)0, 0);
+
+       /* fill in additional items needed for tie/slur */
+       stuff_p->vno = gs_p->vno;
+       stuff_p->beggrp_p = gs_p;
+       stuff_p->begnote_p = &gs_p->notelist[n];
+       stuff_p->curveno = (short)s;
+
+       /* put the new STUFF into this staff's stuff list, at start of list */
+       stuff_p->next = staff_p->stuff_p;
+       staff_p->stuff_p = stuff_p;
+
+       /* if this is not the last group in measure, no more STUFFs needed */
+       if (gs_p->next != 0)
+               return;
+
+       /* if this is a slur to/from nowhere, no second piece needed */
+       if (s >= 0 && (stufftype == ST_TABSLUR || stufftype == ST_TIESLUR) &&
+                       IS_NOWHERE(gs_p->notelist[n].slurtolist[s].octave))
+               return;
+
+       /*
+        * We might need more STUFF(s), either because of a scorefeed, or
+        * because of endings.  First check for the scorefeed case.
+        */
+       /* find bar line at end of measure */
+       for (ebmll_p = mllstaff_p; ebmll_p != 0 && ebmll_p->str != S_BAR;
+                       ebmll_p = ebmll_p->next)
+               ;
+       if (ebmll_p == 0)
+               pfatal("final measure has no bar line");
+
+       /* does a feed occur before next staff? */
+       for (mll_p = ebmll_p; mll_p != 0 && mll_p->str != S_FEED &&
+                       mll_p->str != S_STAFF; mll_p = mll_p->next)
+               ;
+       if (mll_p == 0)
+               return;
+
+       if (mll_p->str == S_FEED) {
+               /* found a feed, so try to make the extra STUFF */
+               stuff_p->carryout = YES;
+               mkextrastuff(mll_p, stuff_p, gs_p, n, s, stufftype);
+       }
+
+       /*
+        * Find whether we need to check for endings.  This is true when we are
+        * at the start of a first ending.  So endingloc has to be STARTITEM,
+        * and the previous bar must not be in an ending.  If we are at a FEED,
+        * look at the pseudobar's endingloc, else look at the previous real
+        * bar.  In any case, search back from the real bar.
+        */
+       if (mll_p->str == S_FEED) {
+               /*
+                * Find the next CLEFSIG.  Normally it's the next thing after
+                * this FEED, but it's possible there are block(s) here and so
+                * it will be after some later FEED.
+                */
+               while (mll_p != 0 && mll_p->str != S_CLEFSIG)
+                       mll_p = mll_p->next;
+               if (mll_p == 0)
+                       return; /* there must not be any more music */
+               bar_p = mll_p->u.clefsig_p->bar_p;
+       } else {
+               bar_p = ebmll_p->u.bar_p;
+       }
+       if (bar_p->endingloc != STARTITEM)
+               return;
+       for (mll2_p = ebmll_p->prev; mll2_p != 0 && mll2_p->str != S_BAR;
+                       mll2_p = mll2_p->prev)
+               ;
+       if (mll2_p != 0 && (mll2_p->u.bar_p->endingloc == STARTITEM ||
+                           mll2_p->u.bar_p->endingloc == INITEM))
+               return;
+
+       /*
+        * The curve was into a first ending.  So we have to loop forward,
+        * looking for the bar lines at the start of each ending, and try to
+        * make another STUFF for the curve carrying into that ending.
+        */
+       for ( ; mll_p != 0; mll_p = mll_p->next) {
+
+               if (mll_p->str != S_BAR)
+                       continue;
+
+               /* see if a pseudo bar occurs before the next staff */
+               for (mll2_p = mll_p; mll2_p != 0 && mll2_p->str != S_STAFF &&
+                               (mll2_p->str != S_CLEFSIG ||
+                                mll2_p->u.clefsig_p->bar_p == 0);
+                               mll2_p = mll2_p->next)
+                       ;
+               if (mll2_p == 0 || mll2_p->str == S_STAFF) {
+                       /* normal case, no pseudobar */
+                       endingloc = mll_p->u.bar_p->endingloc;
+               } else {
+                       /* found pseudobar; use it instead of normal bar */
+                       endingloc = mll2_p->u.clefsig_p->bar_p->endingloc;
+               }
+
+               switch (endingloc) {
+
+
+               case NOITEM:
+               case ENDITEM:
+                       /* out of all endings, we're done */
+                       return;
+
+               case STARTITEM:
+                       /*
+                        * We are at a bar that begins another ending.  Try to
+                        * find the matching staff in this measure.
+                        */
+                       mkextrastuff(mll_p, stuff_p, gs_p, n, s, stufftype);
+               }
+       }
+}
+\f
+/*
+ * Name:        mkextrastuff()
+ *
+ * Abstract:   Create STUFF extra structure(s) for one tie/slur/bend.
+ *
+ * Returns:     void
+ *
+ * Description: This function puts ST_TIESLUR, ST_TABSLUR, or ST_BEND STUFF
+ *             structure(s) in the linked list for the ending piece of a tie,
+ *             slur, or bend that is broken across a scorefeed or into a
+ *             second or later ending.
+ */
+
+static void
+mkextrastuff(mll_p, origstuff_p, gs_p, n, s, stufftype)
+
+struct MAINLL *mll_p;          /* starts before first staff in measure */
+struct STUFF *origstuff_p;     /* original STUFF for this curve */
+struct GRPSYL *gs_p;           /* GRPSYL where curve started */
+int n;                         /* index to note in notelist where it starts */
+int s;                         /* index into slurtolist, or -1 for tie */
+int stufftype;                 /* which of the stuff types is it? */
+
+{
+       struct STUFF *stuff_p;          /* new stuff */
+       struct GRPSYL *endgs_p;         /* group where tie/slur/bend ends */
+       int k;                          /* loop variable */
+
+
+       /* find first staff */
+       for ( ; mll_p != 0 && mll_p->str != S_STAFF;
+                       mll_p = mll_p->next)
+               ;
+
+       /* find matching staff */
+       for ( ; mll_p != 0 && mll_p->str == S_STAFF &&
+                       mll_p->u.staff_p->staffno !=
+                       gs_p->staffno; mll_p = mll_p->next)
+               ;
+       if (mll_p == 0)
+               pfatal("last bar missing in main linked list [mkextrastuff]");
+       if (mll_p->str != S_STAFF)      /* number of staffs changed? */
+               return;
+
+
+       /* allocate a STUFF structure second half of tie/slur/bend */
+       stuff_p = newSTUFF((char *)0, 0, SD_NONE, (double)0, (double)0, 0, 0,
+                       (double)0, stufftype, NO, PL_UNKNOWN, (char *)0, 0);
+
+       stuff_p->carryin = YES;
+       stuff_p->costuff_p = origstuff_p;
+
+       /* fill in additional items needed for tie/slur */
+       stuff_p->vno = gs_p->vno;
+       endgs_p = mll_p->u.staff_p->groups_p[gs_p->vno - 1];
+       stuff_p->beggrp_p = endgs_p;    /* "beg" is really set to the end here*/
+
+       /* begnote_p must be pointed at the note where tie/slur ends; find it */
+       for (k = 0; k < endgs_p->nnotes; k++) {
+               if (s == -1) {
+                       /* tie; check for matching note */
+                       if (endgs_p->notelist[k].letter ==
+                                       gs_p->notelist[n].letter
+                        && endgs_p->notelist[k].octave ==
+                                       gs_p->notelist[n].octave)
+                               break;
+               } else {
+                       /* slur/bend; check for note we're slurring/bending to*/
+                       if (endgs_p->notelist[k].letter ==
+                                       gs_p->notelist[n].slurtolist[s].letter
+                        && endgs_p->notelist[k].octave ==
+                                       gs_p->notelist[n].slurtolist[s].octave)
+                               break;
+               }
+       }
+       if (k == endgs_p->nnotes) {
+               l_warning(endgs_p->inputfile, endgs_p->inputlineno,
+                       "can't find note being tied, slurred, or bent to");
+               FREE(stuff_p);
+               return;
+       }
+
+       stuff_p->begnote_p = &endgs_p->notelist[k];     /* end of tie/slur */
+       stuff_p->curveno = (short)s;    /* same as for the carryout stuff */
+
+       /* put the new STUFF into this staff's stuff list, at start of list */
+       stuff_p->next = mll_p->u.staff_p->stuff_p;
+       mll_p->u.staff_p->stuff_p = stuff_p;
+}
diff --git a/mup/mup/symtbl.c b/mup/mup/symtbl.c
new file mode 100644 (file)
index 0000000..ed03155
--- /dev/null
@@ -0,0 +1,1332 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* This file contains functions for dealing with symbol tables.
+ * There is a symbol table that maps the names of location variables
+ * to the addresses of their array of coordinate info,
+ * a symbol table to map headshape names to the list of shapes,
+ * a table to map time signatures to beamstyle and/or timeunit values,
+ * and a symbol table to map grid names to definitions of the grids.
+ * Symbol names are hashed for fast lookup.
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+/* shapes for quarter and shorter, half, whole, double whole */
+#define MAX_SHAPE_DURS (4)
+/* UP and DOWN */
+#define MAX_STEM_DIRS  (2)
+
+/* First index of headchar and headfont is based on stem direction;
+ * also index of ystem_off. */
+#define STEMINDEX(stemdir)             ( (stemdir) == UP ? 0 : 1 )
+/* Second index of headchar and headfont is based on basictime */
+#define HCDUR(basictime)       ( (basictime) > 2 ? 0 : 3 - (basictime) )
+/* First index of Nhead_map */
+#define FONTINDEX(font)                (font - FONT_MUSIC)
+/* Second index of Nhead_map */
+#define CHARINDEX(ch)          (ch - FIRST_CHAR)
+
+struct HDSHAPEINFO {
+       /* We give each headshape instance a unique index number,
+        * as a compact way to refer to it. */
+       short   index;
+
+       /* This says what notehead characters to use for this shape.
+        * The first dimension is for stem direction, the second for
+        * duration (quarter and shorter, half, whole, double whole).
+        */
+       char    headchar[MAX_STEM_DIRS][MAX_SHAPE_DURS];
+       /* This array parallels the notehead array, saying which music
+        * font the character is in. */
+       char    headfont[MAX_STEM_DIRS][MAX_SHAPE_DURS];
+};
+
+/* How many "headshape" entries we allow. This must be small enough to
+ * fit in the number of bits allowed for shape indexes in GRPSYL and NOTE.
+ * Entry 0 isn't used since we need an "unknown" value.
+ */
+#define MAX_SHAPE_ENTRIES      (32)
+
+/* These are the predefined headshape entries. Users can define more.
+ * We define them here using the same syntax as user would, so we can
+ * use the same code to add to our internal table. */
+struct SHAPENAMES {
+       char *clan_name;        /* name for the set of shapes */
+       char *member_names;     /* The names of the 4 shapes in the set */
+} Predef_shape_names[] = {
+       { "norm",       "4n 2n 1n dblwhole" },
+       { "x",          "xnote diamond diamond dwhdiamond" },
+       { "allx",       "xnote xnote xnote xnote" },
+       { "diam",       "filldiamond diamond diamond dwhdiamond" },
+       { "blank",      "blankhead blankhead blankhead blankhead" },
+       { "righttri",   "u?fillrighttriangle u?righttriangle u?righttriangle u?dwhrighttriangle" },
+       { "isostri",    "fillisostriangle isostriangle isostriangle dwhisostriangle" },
+       { "rect",       "fillrectangle rectangle rectangle dwhrectangle" },
+       { "pie",        "fillpiewedge piewedge piewedge dwhpiewedge" },
+       { "semicirc",   "fillsemicircle semicircle semicircle dwhsemicircle" },
+       { "allslash",   "fillslashhead fillslashhead fillslashhead fillslashhead" },
+       { "slash",      "fillslashhead slashhead slashhead dwhslashhead" },
+       { 0, 0 }
+};
+
+/* Information about characters that are allowed to be noteheads */
+struct HEADINFO {
+       char ch;        /* code number 32-127 */
+       char font;      /* FONT_MUSIC*  */
+       float ystem_off[MAX_STEM_DIRS]; /* stepsizes from y to end stem */
+};
+
+/* Predefined note head music characters and their attributes. */
+struct HEADDATA {
+       char *name;
+       struct HEADINFO info;
+} Predef_headinfo[] = {
+  { "dblwhole",                { C_DBLWHOLE,           FONT_MUSIC, { 0.0, 0.0 } } },
+  { "1n",              { C_1N,                 FONT_MUSIC, { 0.0, 0.0 } } },
+  { "2n",              { C_2N,                 FONT_MUSIC, { 0.25, -0.25 } } },
+  { "4n",              { C_4N,                 FONT_MUSIC, { 0.25, -0.25 } } },
+  { "xnote",           { C_XNOTE,              FONT_MUSIC, { 1.0, -1.0 } } },
+  { "dwhdiamond",      { C_DWHDIAMOND,         FONT_MUSIC, { 0.0, 0.0 } } },
+  { "diamond",         { C_DIAMOND,            FONT_MUSIC, { 0.0, 0.0 } } },
+  { "filldiamond",     { C_FILLDIAMOND,        FONT_MUSIC, { 0.0, 0.0 } } },
+  { "dwhrighttriangle",        { C_DWHRIGHTTRIANGLE,   FONT_MUSIC2, { 0.0, 0.0 } } },
+  { "righttriangle",   { C_RIGHTTRIANGLE,      FONT_MUSIC2, { 0.0, 0.9 } } },
+  { "fillrighttriangle",{ C_FILLRIGHTTRIANGLE, FONT_MUSIC2, { 0.0, 0.9 } } },
+  { "udwhrighttriangle",{ C_UDWHRIGHTTRIANGLE, FONT_MUSIC2, { 0.0, 0.9 } } },
+  { "urighttriangle",  { C_URIGHTTRIANGLE,     FONT_MUSIC2, { -0.9, 0.0 } } },
+  { "ufillrighttriangle",{ C_UFILLRIGHTTRIANGLE,FONT_MUSIC2, { -0.9, 0.0 } } },
+  { "dwhrectangle",    { C_DWHRECTANGLE,       FONT_MUSIC2, { -0.9, 0.0 } } },
+  { "rectangle",       { C_RECTANGLE,          FONT_MUSIC2, { 0.0, 0.0 } } },
+  { "fillrectangle",   { C_FILLRECTANGLE,      FONT_MUSIC2, { 0.0, 0.0 } } },
+  { "dwhisostriangle", { C_DWHISOSTRIANGLE,    FONT_MUSIC2, { -0.8, -0.8 } } },
+  { "isostriangle",    { C_ISOSTRIANGLE,       FONT_MUSIC2, { -0.8, -0.8 } } },
+  { "fillisostriangle",        { C_FILLISOSTRIANGLE,   FONT_MUSIC2, { -0.8, -0.8 } } },
+  { "dwhpiewedge",     { C_DWHPIEWEDGE,        FONT_MUSIC2, { 0.1, 0.2 } } },
+  { "piewedge",                { C_PIEWEDGE,           FONT_MUSIC2, { 0.1, 0.2 } } },
+  { "fillpiewedge",    { C_FILLPIEWEDGE,       FONT_MUSIC2, { 0.1, 0.2 } } },
+  { "dwhsemicircle",   { C_DWHSEMICIRCLE,      FONT_MUSIC2, { 0.8, 0.8 } } },
+  { "semicircle",      { C_SEMICIRCLE,         FONT_MUSIC2, { 0.8, 0.8 } } },
+  { "fillsemicircle",  { C_FILLSEMICIRCLE,     FONT_MUSIC2, { 0.8, 0.8 } } },
+  { "blankhead",       { C_BLANKHEAD,          FONT_MUSIC2, { 0.0, 0.0 } } },
+  { "slashhead",       { C_SLASHHEAD,          FONT_MUSIC2, { 1.8, -1.8 } } },
+  { "fillslashhead",   { C_FILLSLASHHEAD,      FONT_MUSIC2, { 1.8, -1.8 } } },
+  { "dwhslashhead",    { C_DWHSLASHHEAD,       FONT_MUSIC2, { 1.8, -1.8 } } },
+  { 0,                 { 0,                    0,           { 0.0, 0.0 } } }
+};
+
+/*
+ * This struct provides a mapping from a time signature to all the
+ * beamstyle and timeunit values to be associated with that time signature.
+ *
+ * The [0][0] entry is used for the C_SCORE value.
+ * The entries [0][1] through [0][MAXVOICES+1] are unused.
+ * The [s][0] entries are used for C_STAFF values where 1 <= s <= MAXSTAFFS
+ * The [s][v] entries are used for C_VOICE values where 1 <= s <= MAXSTAFFS
+ *                     and 1 <= v <= MAXVOICES
+ * There will be one of these allocated for each time signature used in the
+ * input, if and only if the user also specified at least one beamstyle
+ * or timeunit while that time signature was in effect.
+ */
+struct SSVTABLES {
+       struct SSV *beamstyle_table[MAXSTAFFS+1][MAXVOICES+1];
+       struct SSV *timeunit_table[MAXSTAFFS+1][MAXVOICES+1];
+};
+
+
+/* information about a symbol: its name and current value.
+ * This is used for location tags, chord grids, headshapes, and time signatures.
+ * Note that in the case of location tags,
+ * if the same name is used in a later measure, just the coordlist_p will
+ * change, and when the symbol table is queried for the value of a symbol,
+ * it will get the current value for that symbol */
+struct Sym {
+       char    *symname;
+       union {
+               float   *coordlist_p;   /* when used for location tags, this is
+                                        * where its AX, RX, etc values are */
+               struct GRID *grid_p;    /* when used for grids */
+               struct HDSHAPEINFO *shapeinfo_p;/* when used for headshapes */
+               struct HEADINFO *noteinfo_p;    /* when used for note head info */
+               /* Info about beamstyles and/or timeunits associated with
+                * the time signature given by the symname. */
+               struct SSVTABLES *ssvtables_p;
+       } val;
+       struct Sym *next;               /* for collision chain off hash table */
+};
+
+/* symbol hash table size-- if this changes, hash() has to change accordingly */
+#define SYMTBLSIZE     (128)
+
+/* this is the symbol table for location tags */
+static struct Sym *Tag_table[SYMTBLSIZE];
+
+/* this is the symbol table for guitar grids. It is malloc-ed at runtime
+ * only if needed */
+static struct Sym **Grid_table;
+
+/* This is the symbol table for headshapes */
+static struct Sym *Shape_table[SYMTBLSIZE];
+
+/* This maps headshape indexes to the corresponding info.
+ * Element 0 is unused, since index 0 means "unknown" shape.
+ */
+static struct Sym *Shape_map[MAX_SHAPE_ENTRIES];
+/* How many Shape_map entries are actually used */
+static short Shape_entries = 0;
+
+/* This is the symbol table for noteheads, to get stem offsets */
+static struct Sym  *Nhead_table[SYMTBLSIZE];
+
+/* This maps notehead character codes to the stem offset info */
+static struct HEADINFO *Nhead_map[NUM_MFONTS][CHARS_IN_FONT];
+
+/* This is used to remember what beamstyle and/or timeunit values were
+ * associated with time signatures. This is really only needed during parse,
+ * and then only if user specifies beamstyle or timeunit somewhere.
+ */
+static struct Sym *Time_map[SYMTBLSIZE];
+
+/* Internal name for tag used to store the virtual _win coords for blocks */
+char Blockwin[] = "~blockwin";
+/* This points to where in the symbol table
+ * to save the pointer to the coord array for blocks.
+ * Having this pointer is a speed optimization,
+ * to save us from having to look it up every time. */
+float **Blockcoord_p_p;
+
+
+/* static functions */
+static struct GRID *parse_grid P((char *griddef));
+static struct Sym *add2tbl P((char *symname, struct Sym **table));
+static struct Sym *findSym P((char *symname, struct Sym **table));
+static int hash P((char *string));
+static int coordhash P((float *key));
+static void rep_ref P((float **old_ref_p_p, float **new_ref_p_p));
+static void delete_coord P((float *coord_p));
+static int is_valid_notehead P((int ch, int font));
+static void add_head P((char *name, struct HEADINFO *info_p));
+
+
+/* size of Coordinfo hash table. Should be prime */
+#define COORDTBLSIZE  (271)
+
+static struct COORD_INFO *Coord_table[COORDTBLSIZE];
+\f
+
+/* Add predefined values to the symbol tables */
+
+void
+init_symtbl()
+
+{
+       struct Sym *sym_p;
+       int i;
+
+       addsym("_page", _Page, CT_BUILTIN);
+       addsym("_cur", _Cur, CT_BUILTIN);
+
+       /* Blocks each have their own virtual _win,
+        * so we put a placeholder in the symbol table
+        * and save a pointer to its tag's coord pointer.
+        * Then we can update the coords via set_win_coords().
+        */
+       addsym(Blockwin, 0, CT_BUILTIN);
+       sym_p = findSym(Blockwin, Tag_table);
+       if (sym_p == 0) {
+               pfatal("couldn't find %s coord right after inserting it!",
+                                                       Blockwin);
+       }
+       Blockcoord_p_p = &(sym_p->val.coordlist_p);
+
+       /* Put the predefined notehead shapes into table. */
+       for (i = 0; Predef_headinfo[i].name != 0; i++) {
+               add_head(Predef_headinfo[i].name, &(Predef_headinfo[i].info));
+       }
+
+       /* Put the predefined head shapes in the shapes table */
+       for (i = 0; Predef_shape_names[i].clan_name != 0; i++) {
+               add_shape(Predef_shape_names[i].clan_name,
+                                       Predef_shape_names[i].member_names);
+       }
+}
+\f
+
+/* add a symbol to the table if not already there and fill in its coordlist_p
+ * in symbol table. */
+
+void
+addsym(symname, coordlist_p, coordtype)
+
+char *symname;         /* what to add to table */
+float *coordlist_p;    /* set of 13 coordinates associated with symbol */
+int coordtype;         /* CT_BAR, CT_GRPSYL, etc */
+
+{
+       struct Sym *sym_p;      /* pointer to info about symbol in hash tbl */
+
+
+       debug(4, "addsym(symname=%s coordlist_p=0x%lx, coordtype=%d)",
+                                       symname, coordlist_p, coordtype);
+
+       /* find in symbol table or add if not yet there */
+       sym_p = add2tbl(symname, Tag_table);
+
+       /* fill in coordlist pointer */
+       sym_p->val.coordlist_p = coordlist_p;
+
+       /* put entry in coord table */
+       add_coord(coordlist_p, coordtype);
+}
+\f
+
+/* add a symbol to the specified hash table */
+
+static struct Sym *
+add2tbl(symname, table)
+
+char *symname;         /* what to add */
+struct Sym **table;    /* which table to add to */
+
+{
+       struct Sym *sym_p;
+       int h;                  /* hash number of symbol */
+
+       if ((sym_p = findSym(symname, table)) == (struct Sym *) 0) {
+
+               /* not in list before. Add it */
+               MALLOC(Sym, sym_p, 1);
+               MALLOCA(char, sym_p->symname, strlen(symname) + 1);
+               (void) strcpy(sym_p->symname, symname);
+               h = hash(symname);
+
+               /* link onto front of list off hash table */
+               sym_p->next = table[h];
+               table[h] = sym_p;
+       }
+       return(sym_p);
+}
+\f
+
+/* given a symbol name, return pointer to its symbol table entry, or NULL
+ * if none */
+
+static struct Sym *
+findSym(symname, table)
+
+char *symname;         /* which symbol to look for */
+struct Sym **table;    /* which table to look in */
+
+{
+       struct Sym *sym_p;      /* symbol info currently being checked
+                                * for match with symname */
+       int h;                  /* hash number */
+
+
+       h = hash(symname);
+       /* go down the linked list (of hash collisions) off the table
+        * searching for match */
+       for (sym_p = table[h]; sym_p != (struct Sym *) 0;
+                                               sym_p = sym_p->next) {
+               if (strcmp(sym_p->symname, symname) == 0) {
+                       return(sym_p);
+               }
+       }
+       return((struct Sym *) 0);
+}
+\f
+
+/* For top/bot/top2/bot2/block we temporarily set the ~blockwin tag to point
+ * to the appropriate blockhead's coord array. Before doing a set_win for
+ * any of those, this function should be called to set things up, and
+ * it should be called again afterwards with 0 to mark we are no longer
+ * inside a block.
+ */
+
+void
+set_win_coord(coord_p)
+
+float *coord_p;
+
+{
+       *Blockcoord_p_p = coord_p;
+}
+\f
+
+/* Given a tag name, return its value (a pointer to the coordinate array
+ * containing the AX, AY, etc of the variable).
+ * If the tag is not found, an error is printed and 0 is returned.
+ * If the ref_p_p is non-null,
+ * save that value as something that references the tag. That way if the
+ * tag gives moved somewhere else, we can update all the references.
+ * If referencing the value of a coord that can never move (a builtin coord
+ * like _win), ref_p_p may be null.
+ */
+
+float *
+symval(symname, ref_p_p)
+
+char *symname;         /* which symbol to look up */
+float **ref_p_p;       /* address of reference to the tag */
+
+{
+       struct Sym *sym_p;      /* symbol info currently being checked */
+
+
+       /* _win is a special case: its actual symbol depends on context */
+       if (strcmp(symname, "_win") == 0) {
+               /* If we're inside a block, use its coord,
+                * else use the global _Win */
+               if (*Blockcoord_p_p != 0) {
+                       return(*Blockcoord_p_p);
+               }
+               else {
+                       return(_Win);
+               }
+       }
+       
+       /* find the symbol table entry */
+       if ((sym_p = findSym(symname, Tag_table)) != (struct Sym *) 0) {
+               if (sym_p->val.coordlist_p != (float *) 0) {
+                       /* save reference information */
+                       if (ref_p_p != 0) {
+                               struct COORD_INFO *coordinfo_p;
+                               struct COORD_REF *ref_p;
+                               CALLOC(COORD_REF, ref_p, 1);
+                               ref_p->ref_p_p = ref_p_p;
+                               /* link onto reference list */
+                               coordinfo_p = find_coord(sym_p->val.coordlist_p);
+                               ref_p->next = coordinfo_p->ref_list_p;
+                               coordinfo_p->ref_list_p = ref_p;
+                       }
+                       return(sym_p->val.coordlist_p);
+               }
+       }
+
+       /* whoops! not in table */
+       l_yyerror(Curr_filename, yylineno,
+                       "reference to uninitialized location tag '%s'",
+                       symname);
+       return((float *) 0);
+}      
+\f
+
+/* add item to grid table if not already there. */
+
+void
+add_grid(name, griddef)
+
+char *name;            /* chord name */
+char *griddef;         /* user's definition of the grid */
+
+{
+       char *internal_name;    /* internal format name */
+       char *grid_name;        /* permanent copy of internal_name */
+       char *symname;          /* ASCII-ized name */
+       char *key;              /* permanent copy of symname, key into hash tbl */
+       struct Sym *sym_p;
+       struct GRID *grid_p;
+
+
+       /* if table doesn't exist yet, create it */
+       if (Grid_table == 0) {
+               int g;
+
+               MALLOCA(struct Sym *, Grid_table, SYMTBLSIZE);
+               for (g = 0; g < SYMTBLSIZE; g++) {
+                       Grid_table[g] = 0;
+               }
+       }
+
+       /* Do all the transforms to get into internal form with
+        * accidentals as music characters. For historical reasons,
+        * this has to be done in several steps, in just the right order. */
+       internal_name = modify_chstr(name, TM_CHORD);
+       internal_name = fix_string(internal_name, Score.font, Score.size,
+                                               Curr_filename, yylineno);
+       /* convert accidentals, then convert to all ASCII */
+       grid_name = tranchstr(internal_name, -1);
+       symname = ascii_str(grid_name, YES, NO, TM_CHORD);
+
+       if (strlen(symname) == 0) {
+               yyerror("empty grid name not allowed");
+               return;
+       }
+
+       if ((sym_p = findSym(symname, Grid_table)) != 0) {
+               l_warning(Curr_filename, yylineno,
+                       "duplicate definition of grid for '%s', discarding previous",
+                       symname);
+               /* discard old definition, use new one */
+               if (sym_p->val.grid_p != 0) {
+                       if (sym_p->val.grid_p->name != 0) {
+                               FREE(sym_p->val.grid_p->name);
+                       }
+                       FREE(sym_p->val.grid_p);
+                       sym_p->val.grid_p = 0;
+               }
+               key = sym_p->symname;
+       }
+       else {
+               /* make permanent copy of key */
+               MALLOCA(char, key, strlen(symname) + 1);
+               (void) strcpy(key, symname);
+       }
+
+       if ((grid_p = parse_grid(griddef)) != 0) {
+               /* it's good, so put in hash table */
+               sym_p = add2tbl(key, Grid_table);
+
+               /* fill in the name and grid pointer */
+               grid_p->name = grid_name;
+               sym_p->val.grid_p = grid_p;;
+               {
+                       /* buffer--2 digits and a space for each string, plus null */
+                       char fretlist[3 * MAXTABLINES + 1];
+                       int f;
+                       for (f = 0; f < grid_p->numstr; f++) {
+                               (void) sprintf(fretlist + 3 * f, "%3d",
+                                                        grid_p->positions[f]);
+                       }
+                       fretlist[sizeof(fretlist) - 1] = '\0';
+                       debug(4, "added grid '%s' key '%s' with %d strings: %s curve %d to %d",
+                                       name, key,
+                                       grid_p->numstr, fretlist,
+                                       grid_p->curvel, grid_p->curver);
+               }
+       }
+}
+\f
+
+/* take the user's grid definition, like "2 (3 1) o x -"
+ * and populate a GRID struct with the info. If not parse-able,
+ * return 0 */
+
+static struct GRID *
+parse_grid(griddef)
+
+char *griddef; /* user's definition of the grid */
+
+{
+       struct GRID *grid_p;    /* the malloc-ed grid to populate & return */
+       int error = NO;
+       int value;
+
+       MALLOC(GRID, grid_p, 1);
+       grid_p->numstr = 0;
+       grid_p->curvel = grid_p->curver = 0;
+       grid_p->used = NO;
+       /* the +2 is to skip the font/size bytes */
+       for (griddef += 2; *griddef != '\0' && error == NO; griddef++) {
+               /* init to something illegal */
+               value = -1000;
+
+               while (*griddef == ' ' || *griddef == '\t') {
+                       griddef++;
+               }
+               if (*griddef == '\0') {
+                       break;
+               }
+
+               if ( isdigit(*griddef) ) {
+                       value = *griddef - '0';
+                       if (isdigit(*(griddef+1))) {
+                               value *= 10;
+                               griddef++;
+                               value += *griddef - '0';
+                       }
+                       if (value == 0) {
+                               yyerror("fret of zero not allowed; use 'o' for open or '-' for nothing");
+                               error = YES;
+                       }
+               }
+               else if (*griddef == '(') {
+                       if (grid_p->curvel != 0) {
+                               yyerror("only one '(' allowed in grid definition");
+                               error = YES;
+                       }
+                       else {
+                               grid_p->curvel = grid_p->numstr + 1;
+                       }
+               }
+               else if (*griddef == ')') {
+                       if (grid_p->curver != 0) {
+                               yyerror("only one ')' allowed in grid definition");
+                               error = YES;
+                       }
+                       else if (grid_p->curvel == 0) {
+                               yyerror("missing '(' in grid definition");
+                               error = YES;
+                       }
+                       else if (grid_p->curvel == grid_p->numstr) {
+                               yyerror("curve in grid definition must encompass more than one string");
+                               error = YES;
+                       }
+                       else {
+                               grid_p->curver = grid_p->numstr;
+                       }
+               }
+               else if (*griddef == 'o') {
+                       value = 0;
+               }
+               else if (*griddef == 'x') {
+                       value = -1;
+               }
+               else if (*griddef == '-') {
+                       value = -2;
+               }
+               else {
+                       yyerror("invalid grid specification");
+                       FREE(grid_p);
+                       return (0);
+               }
+
+               if (value >= -2) {
+                       /* We found a fret value (not parentheses).
+                        * Next better be white space sort of thing */
+                       char c;
+                       c = *(griddef + 1);
+                       if (c != ' ' && c != '\t' && c != '(' && c != ')'
+                                                       && c != '\0') {
+                               yyerror("missing white space in grid specification");
+                               error = YES;
+                       }
+                       else if (grid_p->numstr < MAXTABLINES) {
+                               /* all is well; save info for current string */
+                               grid_p->positions[grid_p->numstr] = value;
+                               (grid_p->numstr)++;
+                       }
+                       else {
+                               yyerror("too many strings in grid specification");
+                               error = YES;
+                       }
+               }
+       }
+
+       if (error == NO && grid_p->curvel != 0 && grid_p->curver == 0) {
+               yyerror("missing ')' in grid specification");
+               error = YES;
+       }
+       
+       if (grid_p->numstr < 1) {
+               yyerror("grid must include at least one string");
+               error = YES;
+       }
+
+       /* every curve must have at least one real fret in it */
+       if (grid_p->curvel != 0) {
+               int s;
+               /* the -1 is because curves start at 1, but positions at 0 */
+               for (s = grid_p->curvel - 1; s <= grid_p->curver - 1; s++) {
+                       if (grid_p->positions[s] > 0) {
+                               break;
+                       }
+               }
+               if (s == grid_p->curver) {
+                       yyerror("grid curve must include at least one fret number, not just x, o, and -");
+                       error = YES;
+               }
+       }
+
+       if (error == YES) {
+               /* clean up */
+               FREE(grid_p);
+               grid_p = 0;
+       }
+       return(grid_p);
+}
+\f
+
+/* Locate a named GRID in the grid hash table. Returns 0 if not found,
+ * else pointer to desired GRID. */
+
+struct GRID *
+findgrid(name)
+
+char *name;    /* find GRID with this chord name */
+
+{
+       struct Sym *sym_p;
+       char *ascii_name;
+       int length;
+       int first_char;
+
+       if (Grid_table == 0) {
+               /* no grids defined */
+               return((struct GRID *) 0);
+       }
+
+       ascii_name = ascii_str(name, YES, NO, TM_CHORD);
+       /* Chord names in STUFF have a space padding at the end of them
+        * unless they are in a box or circle, so strip that off for matching
+        * the name. We store the grid name without the space, because for
+        * grid printing, we want the name centered without end padding. */
+       length = strlen(ascii_name);
+       first_char = ((int)*(name+2)) & 0xff;
+       if (first_char != STR_BOX && first_char != STR_CIR
+                                       && ascii_name[length-1] == ' ') {
+               ascii_name[length-1] = '\0';
+       }
+
+       /* look it up */
+       sym_p = findSym(ascii_name, Grid_table);
+
+       return (sym_p ? sym_p->val.grid_p : 0);
+}
+\f
+
+/* Function to iterate through all the GRIDs. First time, call it with
+ * argument of zero, and it returns the first GRID it finds. To walk
+ * through the list, call it repeatedly, each time passing the GRID
+ * you got the last time.  When you get back a zero, the list is done.
+ * Restrictions: you must either call with zero or the last one you got.
+ * You can't remember some previous value and use that to try to jump
+ * to elsewhere on the list, or have multiple walks going on at once.
+ * Caller should assume values are returned in arbitrary order.
+ */
+
+struct GRID *
+nextgrid(grid_p)
+
+struct GRID *grid_p;
+
+{
+       static int tbl_index = -1;
+       static struct Sym *last_sym_p = 0;      /* remember where we were the
+                                                * last time we were called */
+
+       if (grid_p == 0) {
+               /* starting at beginning */
+               tbl_index = -1;
+               last_sym_p = 0;
+       }
+       else if (last_sym_p == 0 || grid_p != last_sym_p->val.grid_p) {
+               pfatal("nextgrid called incorrectly");
+       }
+
+       /* if there is another on the current collision chain, use that */
+       if (last_sym_p != 0) {
+               last_sym_p = last_sym_p->next;
+       }
+
+       /* if none, either if just starting, or if ran off the end
+        * of a collision chain, find next chain. */
+       if (last_sym_p == 0) {
+               for (tbl_index++; tbl_index <  SYMTBLSIZE; tbl_index++) {
+                       if (Grid_table[tbl_index] != 0) {
+                               /* found a populated chain */
+                               last_sym_p = Grid_table[tbl_index];
+                               break;
+                       }
+               }
+       }
+
+       return(last_sym_p == 0 ? 0 : last_sym_p->val.grid_p);
+}
+\f
+
+/* return a hash number from a string. XOR the bytes together */
+
+static int
+hash(string)
+
+char *string;  /* hash this string */
+
+{
+       int h;  /* hash number */
+
+       for (h = 0; *string != '\0'; string++) {
+               h ^= *string;
+       }
+       /* return hash number between 0 and 127 */
+       return(h & 0x7f);
+}
+\f
+
+/* add entry to COORD_INFO table */
+
+void
+add_coord(coordlist_p, coordtype)
+
+float *coordlist_p;    /* address of set of 13 coordinates to add to tbl */
+int coordtype;         /* CT_GRPSYL, etc */
+
+{
+       struct COORD_INFO *new_p;       /* space for saving coord info */
+       int h;                          /* hash number */
+
+
+       /* if not already in table, add it */
+       if (find_coord(coordlist_p) == (struct COORD_INFO *) 0) {
+
+               /* get space, fill in coord type, and link into hash table */
+               CALLOC(COORD_INFO, new_p, 1);
+
+               new_p->coordlist_p = coordlist_p;
+               new_p->flags = (short) coordtype;
+
+               h = coordhash(coordlist_p);
+               new_p->next = Coord_table[h];
+               Coord_table[h] = new_p;
+       }
+}
+\f
+
+/* Given an address of an array of floats (a coordinate array), return a hash
+ * number, which is modulo of the Coord_table table size */
+
+static int
+coordhash(key)
+
+float *key;    /* hash this number */
+
+{
+       return ((int) ( (unsigned long) key % COORDTBLSIZE));
+}
+\f
+
+/* Given a coordinate (pointer to array of floats), return the location of
+ * the info about it in the Coord_table, or 0 if not in table */
+
+struct COORD_INFO *
+find_coord(key)
+
+float *key;            /* look up this key in hash table */
+
+{
+       int h;                  /* hash number */
+       struct COORD_INFO *c_p;
+
+
+       /* search hash table for matching entry */
+       h = coordhash(key);
+       for (c_p = Coord_table[h]; c_p != (struct COORD_INFO *) 0;
+                                                       c_p = c_p->next) {
+               if (key == c_p->coordlist_p) {
+                       return(c_p);
+               }
+       }
+       return( (struct COORD_INFO *) 0);
+}
+\f
+
+/* Given an existing INPCOORD, and a new INPCOORD that is to replace it,
+ * adjust any tag references (hor_p or vert_p) to point to the new one. */
+
+void
+rep_inpcoord(old_inpcoord_p, new_inpcoord_p)
+
+struct INPCOORD *old_inpcoord_p;
+struct INPCOORD *new_inpcoord_p;
+
+{
+       rep_ref( &(old_inpcoord_p->hor_p), &(new_inpcoord_p->hor_p) );
+       rep_ref( &(old_inpcoord_p->vert_p), &(new_inpcoord_p->vert_p) );
+       
+}
+
+/* Given an existing reference to a tag in an INPCOORD, replace that
+ * reference with the new reference. This is for when transferring a
+ * temporary INPCOORD to a permanent one.
+ */
+
+static void
+rep_ref(old_ref_p_p, new_ref_p_p)
+
+float **old_ref_p_p;
+float **new_ref_p_p;
+
+{
+       struct COORD_INFO *coordinfo_p;
+       struct COORD_REF *ref_p;
+
+       if (*old_ref_p_p == 0) {
+               /* This can happen if user references uninitialized tag.
+                * We already give error message elsewhere for that. */
+               return;
+       }
+       if (*new_ref_p_p == 0) {
+               pfatal("attempt to replace tag reference with null.");
+               return;
+       }
+
+       /* Find this information about the coordinate */
+       if ((coordinfo_p = find_coord(*old_ref_p_p)) == 0) {
+               /* Must have been earlier user error. */
+               return;
+       }
+
+       /* Find any references matching the old and update them.
+        * Really should be only one, but seems safer to check all.
+        */
+       for (ref_p = coordinfo_p->ref_list_p; ref_p != 0; ref_p = ref_p->next) {
+               if (ref_p->ref_p_p == old_ref_p_p) {
+                       ref_p->ref_p_p = new_ref_p_p;
+               }
+       }
+}
+\f
+
+/* Given an existing coord array address and an address it is being moved to,
+ * update all references to the old to point to the new, and update our
+ * hash table to insert the old and delete the old.
+ */
+
+void
+upd_ref(oldcoord_p, newcoord_p)
+
+float * oldcoord_p;
+float * newcoord_p;
+
+{
+       struct COORD_INFO *coordinfo_p; /* existing info about oldcoord_p */
+       struct COORD_INFO *newcoordinfo_p;      /* for info about newcoord_p */
+       struct COORD_REF *ref_p;        /* for walking through ref list */
+
+       if ((coordinfo_p = find_coord(oldcoord_p)) == 0) {
+               /* apparently no tags associated with this coord array */
+               return;
+        }
+       /* update all the references to the tag with the new value */
+        for (ref_p = coordinfo_p->ref_list_p; ref_p != 0; ref_p = ref_p->next) {
+                *(ref_p->ref_p_p) = newcoord_p;
+        }
+
+       /* Now need to create new entry for the new coord, and delete old */
+       add_coord(newcoord_p, coordinfo_p->flags);
+       /* Append reference list to new coord info */
+       if ((newcoordinfo_p = find_coord(newcoord_p)) != 0) {
+               /* Should always get here; the 'if' is to just paranoia
+                * to be sure to avoid null pointer deference. */
+               /* If coord already existed before, because one coord is
+                * being combined with another, we want to concatenate the
+                * reference list, so find end to append to. */
+               struct COORD_REF **append_p_p;
+               for (append_p_p = &(newcoordinfo_p->ref_list_p);
+                                       *append_p_p != 0;
+                                       append_p_p = &((*append_p_p)->next)) {
+                       ;
+               }
+
+               *append_p_p = coordinfo_p->ref_list_p;
+               coordinfo_p->ref_list_p = 0;
+       }
+       delete_coord(oldcoord_p);
+}
+\f
+
+/* Delete the given coordinate information */
+
+static void
+delete_coord(coord_p)
+
+float * coord_p;
+
+{
+       int h;                  /* hash number */
+       struct COORD_INFO **c_p_p;
+
+       /* search hash table for matching entry and delete it */
+       h = coordhash(coord_p);
+       for (c_p_p = &(Coord_table[h]); *c_p_p != 0; *(c_p_p) = (*c_p_p)->next) {
+               if ((*c_p_p)->coordlist_p == coord_p) {
+                       struct COORD_INFO * to_delete_p;
+                       to_delete_p = *c_p_p;
+                       *c_p_p = (*c_p_p)->next;
+                       FREE(to_delete_p);
+                       return;
+               }
+       }
+}
+\f
+
+/* Given a shape name and string containing the 4 note heads to use for it,
+ * as would exist in a line of "headshapes" context, parse the
+ * string with the noteheads and save all the information
+ * in the shapes hash table.
+ */
+
+void
+add_shape(name, shapes)
+
+char *name;    /* name of the list of shapes */
+char *shapes;  /* list of 4 shape names */
+
+{
+       struct Sym *sym_p;              /* where added into Shape_table */
+       struct HDSHAPEINFO *shapeinfo_p;/* internal format for shape data */
+       int i;                  /* index through shapes */
+       int d;                  /* index through durations */
+       int nameleng;           /* length of one name in shapes list */
+       char namebuff[40];      /* one of the names in shapes list.
+                                * Needs to be big enough to hold longer
+                                * name of any valid note head character. */
+       char ch;                /* music character corresponding to head name */
+       int font;               /* which font FONT_MUSIC*  */
+       int size;               /* not really needed here, but function we
+                                * call expect it */
+       short flips;            /* YES if stem down uses upside down version */
+
+       debug(4, "add_shape name='%s' shapes='%s'", name, shapes);
+
+       /* Add to symbol table */
+       sym_p = add2tbl(name, Shape_table);
+       MALLOC(HDSHAPEINFO, shapeinfo_p, 1);
+       sym_p->val.shapeinfo_p = shapeinfo_p;
+
+       /* Allocate an index and fill in the index-to-info mapping array */
+       shapeinfo_p->index = ++Shape_entries;
+       if (Shape_entries >= MAX_SHAPE_ENTRIES) {
+               yyerror("Too many headshapes");
+               return;
+       }
+       else {
+               Shape_map[Shape_entries] = sym_p;
+       }
+
+       /* Parse the list of 4 shapes and save their info */
+       size = DFLT_SIZE;
+       for (d = i = 0; shapes[i] != '\0';  ) {
+               /* Skip white space */
+               if (isspace(shapes[i])) {
+                       i++;
+                       continue;
+               }
+
+               /* Make sure user didn't give too many shapes */
+               if (d >= MAX_SHAPE_DURS) {
+                       l_yyerror(Curr_filename, yylineno,
+                               "Too many shapes for headshape '%s' (%d expected, %d found)\n",
+                               name, MAX_SHAPE_DURS, d);
+                       return;
+               }
+
+               /* Check if stem down gets a flipped character */
+               if (shapes[i] == 'u' && shapes[i+1] == '?') {
+                       flips = YES;
+                       i += 2;
+               }
+               else {
+                       flips = NO;
+               }
+
+               /* get copy of current head name, and look up its character */
+               nameleng = strcspn(shapes + i, " \t\r\n");
+               /* leave room for null and 'u' for upsidedown */
+               if (nameleng > sizeof(namebuff) - 2) {
+                       ufatal("head shape name too long");
+               }
+               if (nameleng == 0 && flips == YES) {
+                       l_yyerror(Curr_filename, yylineno,
+                               "'u?' must be followed immediately by a note head character name");
+                       return;
+               }
+               strncpy(namebuff, shapes + i, nameleng);
+               namebuff[nameleng] = '\0';
+               ch = mc_name2num(namebuff, Curr_filename, yylineno, &size, &font);
+               if (is_valid_notehead(ch, font) == NO) {
+                       l_yyerror(Curr_filename, yylineno,
+                               "'%s' is not a valid note head name", namebuff);
+                       return;
+               }
+                       
+               shapeinfo_p->headchar[STEMINDEX(UP)][d] = ch;
+               shapeinfo_p->headfont[STEMINDEX(UP)][d] = font;
+
+               /* If flips, get upside down version. Else use same again */
+               if (flips == YES) {
+                       namebuff[0] = 'u';
+                       strncpy(namebuff + 1, shapes + i, nameleng);
+                       namebuff[nameleng+1] = '\0';
+                       ch = mc_name2num(namebuff, Curr_filename, yylineno, &size, &font);
+                       if (is_valid_notehead(ch, font) == NO) {
+                               l_yyerror(Curr_filename, yylineno,
+                                       "'%s' is not a valid note head name", namebuff);
+                               return;
+                       }
+               }
+               shapeinfo_p->headchar[STEMINDEX(DOWN)][d] = ch;
+               shapeinfo_p->headfont[STEMINDEX(DOWN)][d] = font;
+
+               /* Prepare for next in the list, if any */
+               d++;
+               i += nameleng;
+       }
+       if (d < MAX_SHAPE_DURS) {
+               l_yyerror(Curr_filename, yylineno,
+                       "Too few shapes for headshape '%s' (%d expected, %d found)\n",
+                       name, MAX_SHAPE_DURS, d);
+       }
+}
+\f
+
+/* Given a head shape index, stemdir, and basictime, return the notehead
+ * character to use and (via font_p pointer)
+ * which music font that notehead character is in.
+ */
+
+int
+nheadchar(headshape, basictime, stemdir, font_p)
+
+int headshape;         /* head shape index */
+int basictime;         /* 8 for eighth, 2 for half, etc */
+int stemdir;           /* UP or DOWN */
+int *font_p;           /* FONT_MUSIC* is returned here */
+
+{
+       struct Sym *info_p;     /* shape to character map */
+       int dir;                /* first index into headchar */
+       int dur;                /* second index into headchar */
+
+       if (headshape == HS_UNKNOWN || headshape > Shape_entries) {
+               pfatal("illegal headshape index to nheadchar (%d)", headshape);
+       }
+
+       info_p = Shape_map[headshape];
+
+       dir = STEMINDEX(stemdir);
+       dur = HCDUR(basictime);
+       *font_p = info_p->val.shapeinfo_p->headfont[dir][dur];
+       return(info_p->val.shapeinfo_p->headchar[dir][dur]);
+}
+\f
+
+/* Given a head shape name, return the internal index number we use
+ * to refer to that shape.
+ */
+
+int
+get_shape_num(shapename)
+
+char *shapename;
+
+{
+       struct Sym *sym_p;
+
+       if ((sym_p = findSym(shapename, Shape_table)) != 0) {
+               return(sym_p->val.shapeinfo_p->index);
+       }
+       return(HS_UNKNOWN);
+}
+\f
+
+/* Return YES if given character is a valid note head character, else NO */
+
+static int
+is_valid_notehead(ch, font)
+
+int ch;                /* character code */
+int font;      /* FONT_MUSIC*  */
+
+{
+       if ( IS_MUSIC_FONT(font) == NO || ch < 0 || ch >= CHARS_IN_FONT) {
+               /* If caller passes us the return from mc_name2num(),
+                * that could return BAD_CHAR, so we don't pfatal here,
+                * but do return right away, so we don't do an illegal
+                * array index below.
+                */
+               return(NO);
+       }
+       return (Nhead_map[FONTINDEX(font)][CHARINDEX(ch)] == 0 ? NO : YES);
+}
+\f
+
+/* Save note head information in table */
+/** If we allow users to supply their own some day,
+ * would need a function that allocates and fills in a HEADINFO,
+ * and then calls this one. */
+
+static void
+add_head(name, info_p)
+
+char *name;    /* music character name */
+struct HEADINFO *info_p;       /* char/font/stem offset */
+
+{
+       struct Sym *sym_p;
+
+       
+       sym_p = add2tbl(name, Nhead_table);
+       sym_p->val.noteinfo_p = info_p;
+
+       /* Fill in reverse lookup map */
+       Nhead_map[FONTINDEX(info_p->font)][CHARINDEX(info_p->ch)] = info_p;
+}
+\f
+
+/* Given a note head character and stem direction,
+ * return the y offset for the stem to end, in stepsizes.
+ */
+
+double
+stem_yoff(headch, font, stemdir)
+
+int headch;    /* music character code */
+int font;      /* FONT_MUSIC*   */
+int stemdir;   /* UP or DOWN */
+
+{
+       struct HEADINFO *info_p;
+
+       if ( IS_MUSIC_FONT(font) == NO || headch < 0 || headch >= CHARS_IN_FONT) {
+               pfatal("invalid argument: stem_yoffset(%d, %d, stemdir)",
+                                                       headch, font, stemdir);
+       }
+       info_p = Nhead_map[FONTINDEX(font)][CHARINDEX(headch)];
+       if (info_p == 0) {
+               pfatal("No notehead map for ch=%d, font=%d", headch, font);
+       }
+       if (stemdir == UNKNOWN) {
+               pfatal("stem_yoff called with unknown stemdir");
+       }
+       return(info_p->ystem_off[STEMINDEX(stemdir)]);
+}
+\f
+
+/* This should be called when an SSV has been collected by the user.
+ * If the user set beamstyle and/or timeunit in the SSV,
+ * create a mapping between the current time signature and that beamstyle
+ * and/or timeunit, so that if the user later sets the same time signature,
+ * they don't have to set the other things too.
+ * If they set time signature, see if we have a mapping
+ * for that time signature. If so, set the beamstyles and timeunits
+ * from that mapping.
+ */
+
+void
+remember_tsig_params(mll_p)
+
+struct MAINLL *mll_p;  /* contains SSV */
+
+{
+       struct SSV *ssv_p;      /* the SSV to process */
+       char *timesig;          /* current time signature representation */
+       struct Sym *entry;      /* entry in time sig info mapping table */
+
+
+       if (mll_p->str != S_SSV) {
+               pfatal("remember_tsig_params got bad str value %d", mll_p->str);
+       }
+       ssv_p = mll_p->u.ssv_p;
+
+       if (ssv_p->used[TIME] == NO && ssv_p->used[BEAMSTLIST] == NO &&
+                                       ssv_p->used[TIMEUNIT] == NO) {
+               /* nothing of interest in this SSV */
+               return;
+       }
+
+       /* If user set time signature in this SSV, that's the time sig
+        * of interest, otherwise use the current time signature */
+       timesig = (ssv_p->used[TIME] == YES ? ssv_p->timerep : Score.timerep);
+       if ((entry = findSym(timesig, Time_map)) == 0) {
+               entry = add2tbl(timesig, Time_map);
+               /* We'll only allocate the actual table if user gives a
+                * beamstyle or timeunit somewhere. If they never do,
+                * this will avoid wasting memory.
+                */
+               entry->val.ssvtables_p = 0;
+       }
+
+       /* If beamstyle or timeunit are set in this SSV, associate them
+        * with the current time signature. */
+       if (ssv_p->used[BEAMSTLIST] == YES) {
+               if (entry->val.ssvtables_p == 0) {
+                       CALLOC(SSVTABLES, entry->val.ssvtables_p, 1);
+               }
+               /* Note that when staffno and voiceno are zero,
+                * that's actually a score entry, and when voiceno is zero,
+                * but staffno is non-zero, that is actually a staff entry. */
+               entry->val.ssvtables_p->beamstyle_table[ssv_p->staffno][ssv_p->voiceno] = ssv_p;
+       }
+       if (ssv_p->used[TIMEUNIT] == YES) {
+               if (entry->val.ssvtables_p == 0) {
+                       CALLOC(SSVTABLES, entry->val.ssvtables_p, 1);
+               }
+               entry->val.ssvtables_p->timeunit_table[ssv_p->staffno][ssv_p->voiceno] = ssv_p;
+       }
+
+       /* If time signature is set in this SSV, see if we have any
+        * beamstyles or timeunits associated with that time signature.
+        * If so, restore their values. */
+       if (ssv_p->used[TIME] == YES && entry->val.ssvtables_p != 0) {
+               /* Make new SSVs and copy the relevant fields for any
+                * remembered beamstyles and/or timesunits associated 
+                * with this time signature. */
+               struct SSV *beamstyle_ssv_p;    /* SSV having beamstyle info */
+               struct SSV *timeunit_ssv_p;     /* SSV having timeunit info */
+               struct MAINLL *mll_ssv_p;       /* new SSV to add to list */
+               struct SSV *nssv_p;             /* new SSV to add to list */
+               int s;                          /* staff */
+               int v;                          /* voice */
+
+               /* Check all SSV contexts. The [0][0] entry is for Scoreo                        * The rest of row [0] is unused.
+                * The [0] column is for staffs, for s > 0.
+                */
+               for (s = 0; s <= MAXSTAFFS; s++) {
+                       for (v = 0; v <= MAXVOICES; v++) {
+
+                               /* Check if we need to create an SSV for
+                                * this staff/voice */
+                               beamstyle_ssv_p = entry->val.ssvtables_p->beamstyle_table[s][v];
+                               timeunit_ssv_p = entry->val.ssvtables_p->timeunit_table[s][v];
+                               if (beamstyle_ssv_p == 0 &&
+                                               timeunit_ssv_p == 0) {
+                                       /* nothing to do for this one */
+                                       continue;
+                               }
+
+                               /* If both saved SSVs are either zero or
+                                * the same SSV as where the time was just
+                                * set, no need to make another SSV */
+                               if ( (beamstyle_ssv_p == 0 ||
+                                               beamstyle_ssv_p == ssv_p) &&
+                                               (timeunit_ssv_p == 0 ||
+                                               timeunit_ssv_p == ssv_p) ) {
+                                       continue;
+                               }
+
+                               /* need to create an SSV */
+                               mll_ssv_p = newMAINLLstruct(S_SSV, -1);
+                               insertMAINLL(mll_ssv_p, mll_p);
+                               mll_p = mll_ssv_p;
+
+                               /* populate the new SSV */
+                               nssv_p = mll_ssv_p->u.ssv_p;
+                               if (beamstyle_ssv_p != 0) {
+                                       nssv_p->nbeam = beamstyle_ssv_p->nbeam;
+                                       nssv_p->beamstlist = beamstyle_ssv_p->beamstlist;
+                                       nssv_p->beamrests = beamstyle_ssv_p->beamrests;
+                                       nssv_p->beamspaces = beamstyle_ssv_p->beamspaces;
+                                       nssv_p->nsubbeam = beamstyle_ssv_p->nsubbeam;
+                                       nssv_p->subbeamstlist = beamstyle_ssv_p->subbeamstlist;
+                                       nssv_p->used[BEAMSTLIST] = YES;
+                               }
+                               if (timeunit_ssv_p != 0) {
+                                       nssv_p->timeunit = timeunit_ssv_p->timeunit;
+                                       nssv_p->used[TIMEUNIT] = YES;
+                               }
+
+                               /* fill in the SSV header */
+                               if (v != 0) {
+                                       nssv_p->context = C_VOICE;
+                               }
+                               else if (s != 0) {
+                                       /* The [s][0] entry is for staff s
+                                        * when s > 0 */
+                                       nssv_p->context = C_STAFF;
+                               }
+                               else {
+                                       /* The [0][0] entry is actually score */
+                                       nssv_p->context = C_SCORE;
+                               }
+                               nssv_p->staffno = s;
+                               nssv_p->voiceno = v;
+                               asgnssv(nssv_p);
+                       }
+               }
+       }
+}
diff --git a/mup/mup/tie.c b/mup/mup/tie.c
new file mode 100644 (file)
index 0000000..41849e0
--- /dev/null
@@ -0,0 +1,1109 @@
+
+/* Copyright (c) 1995, 1997, 1998, 1999, 2001, 2002 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* This file contains functions for handling ties and slurs.
+ * This includes doing error checking to make sure
+ * there is a note to tie/slur to.
+ * There is also code to add padding to make space for ties/slurs
+ * that are carried into second endings. */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+
+
+/* lengths of line segments of carried in tie marks */
+#define HALFTIEPAD     (3 * STEPSIZE)
+
+/* infomation about a tied or slurred note that gets carried into an ending */
+struct TIECARRY {
+       short   letter;         /* pitch to be tied or slurred to */
+       short   octave;         /* octave of the pitch */
+       short   curveno;        /* slurto index or -1 for tie */
+       short   is_bend;        /* if slurto is actually a bend */
+       struct MAINLL *mll_p;   /* points to first group */
+       struct GRPSYL *gs_p;    /* group of first note */
+       struct TIECARRY *next;  /* linked list */
+};
+
+/* linked list of tie carry info for each staff/voice */
+struct TIECARRY *Tiecarryinfolist_p [MAXSTAFFS + 1] [MAXVOICES];
+
+/* flag to mark if there are any carry ins */
+static short Have_carry_ins = NO;
+
+
+/* static functions */
+static void do_tie P((struct MAINLL *mll_p));
+static void do_group_ties P((struct GRPSYL *gs_p, struct MAINLL *mll_p));
+static void chk_slides P((struct NOTE *note_p, struct GRPSYL *gs_p,
+               struct MAINLL *mll_p));
+static void chk_following4slide P((struct NOTE *note_p, struct GRPSYL *gs_p,
+               struct MAINLL *mll_p));
+static struct MAINLL *do_carry_ties P((struct MAINLL *staff_mll_p,
+               struct MAINLL *bar_mll_p));
+static void savetieinfo P((struct MAINLL *mll_p, struct GRPSYL *gs_p));
+static void do_save_tieinfo P((int staffno, int vno, int letter, int octave,
+               int is_tie, struct MAINLL *mainll_p, struct GRPSYL *gs_p,
+               int is_bend));
+static void carryin_ties P((struct MAINLL *mll_p));
+static void add_carryin P((struct STAFF *staff_p));
+static void free_carryin_info P((void));
+static void free_cinfo P((struct TIECARRY *carryinfo_p));
+static void chk4xpose P((struct MAINLL *mll_p));
+static void chkxpstaff P((struct MAINLL *mll_p, int s));
+static void chkxpgrp P((struct GRPSYL *gs_p, char *inputfile, int lineno));
+static void set_inhibitprint_if_appropriate P((struct GRPSYL *gs_p,
+               struct MAINLL *mll_p));
+\f
+
+
+/* go through main list, checking each STAFF struct for ties and slurs.
+ * For each, do appropriate error checking */
+
+void
+tie()
+
+{
+       struct MAINLL * mll_p;  /* walk through main list */
+
+
+       debug(2, "tie");
+
+       /* first check for any ties across transpositions, and delete them.
+        * Can't do inside the next loop, because by then a less informative
+        * message could be generated for the error */
+       initstructs();
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
+                               mll_p = mll_p->next) {
+               if (mll_p->str == S_SSV) {
+                       chk4xpose(mll_p);
+                       asgnssv(mll_p->u.ssv_p);
+               }
+       }
+
+       /* go through the main list again for other checks */
+       initstructs();
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
+                               mll_p = mll_p->next) {
+       
+               /* process any GRPSYL lists with note info */
+               if (mll_p->str == S_STAFF) {
+                       if ( (svpath(mll_p->u.staff_p->staffno, VISIBLE))
+                                               ->visible == YES) {
+                               do_tie(mll_p);
+                       }
+               }
+               else if (mll_p->str == S_SSV) {
+                       asgnssv(mll_p->u.ssv_p);
+               }
+       }
+}
+\f
+
+/* do the ties and slurs on all groups off a STAFF struct */
+
+static void
+do_tie(mll_p)
+
+struct MAINLL *mll_p;  /* the STAFF struct with list of GRPSYLs */
+
+{
+       struct GRPSYL *gs_p;            /* walk through GRPSYL list */
+       int v;                          /* walk through voices per staff */
+       int is_tab;                     /* YES if tablature staff */
+
+
+       is_tab = is_tab_staff(mll_p->u.staff_p->staffno);
+
+       for (v = 0; v < MAXVOICES; v++) {
+               /* go through entire list of GRPSYLs */
+               for (gs_p = mll_p->u.staff_p->groups_p[v];
+                                       gs_p != (struct GRPSYL *) 0;
+                                       gs_p = gs_p->next) {
+
+                       /* error check */
+                       if (gs_p->grpcont != GC_NOTES) {
+                               if (gs_p->tie == YES) {
+                                       l_warning(mll_p->inputfile,
+                                               mll_p->inputlineno,
+                                               "tie can only apply to notes");
+                                       gs_p->tie = NO;
+                               }
+
+                               /* if rest or space, nothing more to do */
+                               continue;
+                       }
+
+                       do_group_ties(gs_p, mll_p);
+                       if (is_tab == YES) {
+                               set_inhibitprint_if_appropriate(gs_p, mll_p);
+                       }
+               }
+       }
+}
+\f
+
+/* do ties on all notes in a group that have ties. While we're at it, also
+ * make sure any staffs with clefs not printed, don't have accidentals on any
+ * notes  */
+
+static void
+do_group_ties(gs_p, mll_p)
+
+struct GRPSYL *gs_p;           /* do ties from this group */
+struct MAINLL *mll_p;          /* points to gs_p */
+
+{
+       struct GRPSYL *gs2_p;           /* group to tie to */
+       register int n;                 /* walk through note list */
+       struct NOTE *note1_p;           /* info about note */
+       struct NOTE *note2_p;           /* note slurred to */
+       int slur;                       /* index into slurtolist */
+       int d;                          /* index for deleting illegal slurs */
+       short err = NO;                 /* error flag */
+       short inhibitprint;             /* if to set inhibitprint flag on the
+                                        * tied-to group (tab staff only) */
+
+
+       /* if all notes in a group are tied on a tablature staff,
+        * then all the corresponding notes on the tied-to group
+        * should have their inhibitprint flag set. So we need to
+        * find out if that is a possibility */
+       if (is_tab_staff(gs_p->staffno) == YES) {
+               if (gs_p->tie == YES) {
+                       inhibitprint = YES;
+               }
+               else {
+                       /* first assume that all notes will be tied, then
+                        * check them all. If any are found that are not
+                        * tied, then turn the inhibitprint flag back off */
+                       inhibitprint = YES;
+                       for (n = 0; n < gs_p->nnotes; n++) {
+                               if (gs_p->notelist[n].tie == NO) {
+                                       inhibitprint = NO;
+                                       break;
+                               }
+                       }
+               }
+       }
+       else {
+               /* inhibitprint flag is only used on tablature staffs */
+               inhibitprint = NO;
+       }
+
+       /* go through all notes in group, looking for ties */
+       gs2_p = (struct GRPSYL *) 0;
+       for (n = 0; n < gs_p->nnotes; n++) {
+
+               /* For staffs without clef, make sure there are no accidentals.
+                * But tab staffs keep accidentals, even with no clef.
+                * Philosophically, this isn't really a good place to
+                * do this, but since we're going through the list of notes
+                * anyway here, and time-wise in the scheme of the program
+                * this is the right time, rather than make yet another trip
+                * through the list later we do it here. But for MIDI
+                * purposes, we need to keep the accidental, or the wrong
+                * note will play! */
+               if (svpath(gs_p->staffno, STAFFLINES)->printclef != SS_NORMAL
+                               && is_tab_staff(gs_p->staffno) == NO
+                               && Doing_MIDI == NO) {
+                        gs_p->notelist[n].accidental = '\0';
+               }
+
+               note1_p = &(gs_p->notelist[n]);
+               /* if this note's tie flag is set, check the tie */
+               if ( note1_p->tie == YES) {
+
+                       /* if haven't yet found the group to tie to, do that.
+                        * (If this is not the first note to be tied
+                        * in this group, we would have already found
+                        * the other group) */
+                       if (gs2_p == (struct GRPSYL *) 0) {
+                               gs2_p = find_next_group(mll_p, gs_p, "tie");
+                       }
+
+                       if (gs2_p == (struct GRPSYL *) 0) {
+                               /* if nothing to tie to, cancel the tie. We
+                                * will have already printed an error msg. */
+                               note1_p->tie = NO;
+                               gs_p->tie = NO;
+                       }
+                       else {
+                               /* if the inhibitprint flag is set, set it
+                                * in the tied-to group. However,
+                                * if the groups have different numbers of
+                                * notes and the inhibitprint flag is set,
+                                * we have to cancel it, because that only
+                                * applies when the tied-from and tied-to
+                                * groups have identical notes in them */
+                               if (inhibitprint == YES) {
+                                       if (gs_p->nnotes == gs2_p->nnotes) {
+                                               gs2_p->inhibitprint = YES;
+                                       }
+                                       /* turn flag off, so we don't
+                                        * waste time checking it
+                                        * again for each of the remaining
+                                        * notes in the group */
+                                       inhibitprint = NO;
+                               }
+
+                               if (find_matching_note(gs2_p, note1_p->letter,
+                                               note1_p->octave, "tie")
+                                               == (struct NOTE *) 0) {
+                                       note1_p->tie = NO;
+                                       gs_p->tie = NO;
+                               }
+                       }
+               }
+
+
+               /* handle all slurs from current note */
+               for (slur = 0; slur < note1_p->nslurto; slur++) {
+
+                       /* slides to/from nowhere don't get processed here */
+                       if (IS_NOWHERE(note1_p->slurtolist[slur].octave)) {
+                               continue;
+                       }
+
+                       /* if haven't yet found the group to slur to, do that.
+                        * (We may have already found it earlier) */
+                       if (gs2_p == (struct GRPSYL *) 0) {
+                               gs2_p = find_next_group(mll_p, gs_p, "slur");
+                       }
+
+                       if (gs2_p == (struct GRPSYL *) 0) {
+                               /* if nothing to slur to, cancel all slurs */
+                               note1_p->nslurto = 0;
+                               continue;
+                       }
+
+                       /* special case of 'M' when a group 'slur'
+                        * has been specified. Find matching note
+                        * in the second chord */
+                       if (note1_p->slurtolist[slur].letter == 'M') {
+                               if (gs_p->nnotes != gs2_p->nnotes) {
+                                       /* only print message first time */
+                                       if (err == NO) {
+                                               l_warning(gs_p->inputfile,
+                                                       gs_p->inputlineno,
+                                                       "'slur' requires equal number of notes in each chord");
+                                       }
+                                       note2_p = (struct NOTE *) 0;
+
+                                       /* don't do any more on this
+                                        * chord, to avoid multiple
+                                        * error messages */
+                                       err = YES;
+                               }
+                               else {
+                                       note2_p = & (gs2_p->notelist[n]);
+                               }
+                       }
+                       else {
+                               note2_p = find_matching_note(gs2_p,
+                                       note1_p->slurtolist[slur].letter,
+                                       note1_p->slurtolist[slur].octave,
+                                       note1_p->is_bend ? "bend" : "slur");
+                       }
+
+                       if (note2_p != (struct NOTE *) 0) {
+                               /* fill in the letter/octave if they had to
+                                * be derived */
+                               if ((note1_p->slurtolist[slur].letter == 'U')
+                                        || (note1_p->slurtolist[slur].letter == 'M')
+                                        || is_tab_staff(gs_p->staffno) == YES) {
+                                   note1_p->slurtolist[slur].letter =
+                                                       note2_p->letter;
+                                   note1_p->slurtolist[slur].octave =
+                                                       note2_p->octave;
+                               }
+                       }
+                       else {
+                               /* discard this slur--
+                                * nothing to slur to */
+                               for (d = slur + 1; d < note1_p->nslurto; d++) {
+                                       note1_p->slurtolist[d-1] =
+                                               note1_p->slurtolist[d];
+                               }
+                               (note1_p->nslurto)--;
+                       }
+               }
+
+               /* do additional slide checks for tab and tabnote */
+               if (is_tab_staff(gs_p->staffno) == YES
+                               || (gs_p->staffno < MAXSTAFFS
+                               && is_tab_staff(gs_p->staffno + 1) == YES)) {
+                       chk_slides(note1_p, gs_p, mll_p);
+               }
+       }
+}
+
+/* do extra checks for slide. There can be no more than one incoming and one
+ * outgoing slide for any given note */
+
+static void
+chk_slides(note_p, gs_p, mll_p)
+
+struct NOTE *note_p;           /* this note might have slides */
+struct GRPSYL *gs_p;           /* note is in this group */
+struct MAINLL *mll_p;          /* group is tied to this main list struct */
+
+{
+       int s;          /* index through slurtolist */
+       int incoming = 0, outgoing = 0; /* how many slides of each type */
+
+
+       /* go through list counting up incoming and outgoing slides */
+       for (s = 0; s < note_p->nslurto; s++) {
+               switch(note_p->slurtolist[s].octave) {
+
+               case OUT_UPWARD:
+               case OUT_DOWNWARD:
+                       outgoing++;
+                       break;
+
+               case IN_UPWARD:
+               case IN_DOWNWARD:
+                       incoming++;
+                       break;
+
+               default:
+                       outgoing++;
+                       /* make sure following group doesn't have any
+                        * incoming nowhere slides */
+                       chk_following4slide(note_p, gs_p, mll_p);
+                       break;
+               }
+       }
+
+       if (incoming > 1) {
+               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                       "can't have more than one slide into a note");
+       }
+       if (outgoing > 1) {
+               l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                       "can't have more than one slide from a note");
+
+       }
+}
+\f
+
+/* Given a note with a slide to a specific fret,
+ * if there is a following group, see if it has a matching note,
+ * and if so, check that note's slurtolist to see if it
+ * contains any incoming nowhere slides. If so, there is a
+ * problem, because we already have a slide to that note */
+
+static void
+chk_following4slide(note_p, gs_p, mll_p)
+
+struct NOTE *note_p;   /* this note has a slide to a specific fret */
+struct GRPSYL *gs_p;   /* note is in this group */
+struct MAINLL *mll_p;  /* group is attached to this main list struct */
+
+{
+       struct GRPSYL *ngs_p;   /* next group */
+       int n;                  /* index through notes */
+       int ns;                 /* index through slides on next group note */
+
+
+       if ((ngs_p = nextgrpsyl(gs_p, &mll_p)) == (struct GRPSYL *) 0) {
+               /* no next group, so no problem */
+               return;
+       }
+
+       /* check each note in next group */
+       for (n = 0; n < ngs_p->nnotes; n++) {
+               /* is this the matching note?  If the letter matches and
+                * either it's a tab staff or the octave also matches,
+                * then it is the matching note. */
+               if (ngs_p->notelist[n].letter == note_p->letter &&
+                               (is_tab_staff(gs_p->staffno) ||
+                               ngs_p->notelist[n].octave == note_p->octave)) {
+
+                       /* found the matching note. Check its slurtolist */
+                       for (ns = 0; ns < ngs_p->notelist[n].nslurto; ns++) {
+                               switch (ngs_p->notelist[n].slurtolist[ns].octave) {
+                               case IN_UPWARD:
+                               case IN_DOWNWARD:
+                                       l_yyerror(gs_p->inputfile,
+                                               gs_p->inputlineno,
+                                               "can't slide to note that has </n> or <\\n>");
+                                       break;
+                               default:
+                                       break;
+                               }
+                       }
+               }
+       }
+}
+\f
+
+/* find note in following chord having specified pitch/octave.
+ * If the note is found, return pointer to it, otherwise 0
+ */
+
+struct NOTE *
+find_matching_note(gs_p, letter, octave, type)
+
+struct GRPSYL *gs_p;   /* which GRPSYL we're tying to */
+int letter;            /* find note with this pitch, 'a' to 'g' */
+int octave;            /* find note with this octave */
+char *type;            /* "tie", "slur", "slide", or "bend",
+                        * or null if not to print any error messages */
+
+{
+       struct NOTE *note2_p;   /* note to tie to */
+       register int n2;        /* index through notelist of 2nd group */
+
+
+       if (gs_p == (struct GRPSYL *) 0) {
+               return( (struct NOTE *) 0);
+       }
+
+       /* we don't allow tie/slur into a measure repeat. */
+       if (is_mrpt(gs_p) == YES) {
+               l_warning(gs_p->inputfile, gs_p->inputlineno,
+                       "tie/slur/bend not allowed into measure rpt");
+               return (struct NOTE *) 0;
+       }
+
+       /* special case. On slurto, if second group has only a single
+        * note, user doesn't have to specify it. We will have marked the
+        * pitch as 'U'. If second group has only one note in it, use that
+        * one. If not, error */
+       if ( letter == 'U') {
+               if ( gs_p->nnotes != 1) {
+                       if (type != (char *) 0) {
+                               l_warning(gs_p->inputfile, gs_p->inputlineno,
+                                       "note to %s to not specified", type);
+                       }
+                       return(struct NOTE *) 0;
+               }
+               else {
+                       return( &(gs_p->notelist[0]) );
+               }
+       }
+
+       /* try to find matching note in second note group */
+       /* If first note has an accidental and the corresponding one in
+        * the next group doesn't, that's a
+        * match, 'cause we only print the accidental once.
+        */
+       for (n2 = 0; n2 < gs_p->nnotes; n2++) {
+
+               note2_p = &(gs_p->notelist[n2]);
+
+               if (is_tab_staff(gs_p->staffno) == YES) {
+                       /* on tab staff, we just have to match
+                        * the string number */
+                       if (note2_p->letter == letter) {
+                               return(note2_p);
+                       }
+                       else {
+                               continue;
+                       }
+               }
+
+               if ( (note2_p->letter == letter)
+                               && (note2_p->octave == octave) ) {
+
+                       if (type != (char *) 0 && (strcmp(type, "tie") == 0)
+                                       && (note2_p->accidental != '\0')
+                                       && is_tab_staff(gs_p->staffno) == NO) {
+                               l_warning(gs_p->inputfile, gs_p->inputlineno,
+                                       "second note of tie not allowed to have an accidental");
+                               /* fix it so in case we're called again on the
+                                * same note (which is possible), we'll only
+                                * print one error message */
+                               note2_p->accidental = '\0';
+                       }
+
+                       /* found it! */
+                       return(note2_p);
+               }
+       }
+
+       /* oh-oh. User goofed */
+       if (is_tab_staff(gs_p->staffno) == YES) {
+               if (type != (char *) 0) {
+                       l_yyerror(gs_p->inputfile, gs_p->inputlineno,
+                               "can't do %s: %s string not in chord%s",
+                               type, stringname(letter, gs_p->staffno),
+                               gs_p->nnotes == 0 ?
+                               " (in fact no strings at all)" : "");
+               }
+       }
+       else {
+               if (type != (char *) 0) {
+                       if (letter < 'a' || letter > 'g' || octave < MINOCTAVE
+                                               || octave > MAXOCTAVE) {
+                               l_warning(gs_p->inputfile, gs_p->inputlineno,
+                                       "can't do %s: note not in chord",
+                                       type);
+                       }
+                       else {
+                               l_warning(gs_p->inputfile, gs_p->inputlineno,
+                                       "can't do %s: %c%d not in chord%s",
+                                       type, letter, octave,
+                                       gs_p->nnotes == 0 ?
+                                       " (in fact no notes at all)" : "");
+                       }
+               }
+       }
+       return( (struct NOTE *) 0 );
+}
+\f
+
+/* given one GRPSYL, find the next one in the same staff and voice,
+ * which might be in the next measure */
+
+struct GRPSYL *
+find_next_group(mll_p, gs_p, type)
+
+struct MAINLL *mll_p;          /* current place in main list */
+struct GRPSYL *gs_p;           /* group to tie from */
+char *type;                    /* "tie" or "slur" */
+
+{
+       struct MAINLL *ml_p;
+
+       ml_p = mll_p;
+       if ((gs_p = nextgrpsyl(gs_p, &ml_p)) == (struct GRPSYL *) 0) {
+               l_warning(mll_p->inputfile, mll_p->inputlineno,
+                                               "no chord to %s to", type);
+       }
+
+       return(gs_p);
+}
+\f
+
+/* go through main list. If we hit a bar that begins an ending, back up
+ * and go through the previous measure. If the final group of any voice
+ * has any tied or slurred notes, save information about them. Then for
+ * each additional beginning of an ending up until an endending, add
+ * user padding to allow for carried in tie mark. At the endending, free
+ * the information and continue through the rest of the main list */
+
+void
+tie_carry()
+
+{
+       struct MAINLL *mll_p;                   /* walk through main list */
+       struct MAINLL *first_staff_mll_p;       /* points to first STAFF
+                                                * struct of measure */
+
+
+       debug(2, "tie_carry");
+
+       initstructs();
+       first_staff_mll_p = (struct MAINLL *) 0;
+       for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->next) {
+               switch (mll_p->str) {
+
+               case S_STAFF:
+                       /* remember where list of staffs begins and skip
+                        * the rest of the STAFFs */
+                       first_staff_mll_p = mll_p;
+                       for (   ; mll_p->next->str == S_STAFF;
+                                               mll_p = mll_p->next) {
+                               ;
+                       }
+                       break;
+
+               case S_BAR:
+                       if (mll_p->u.bar_p->endingloc == STARTITEM) {
+                               mll_p = do_carry_ties(first_staff_mll_p, mll_p);
+                       }
+                       break;
+
+               case S_CLEFSIG:
+                       /* actually, it should be impossible to hit this case,
+                        * because clefsigs with pseudo-bar haven't been
+                        * created yet at the time this is called, but if things
+                        * are changed some day so things get done in a different
+                        * order, this should then work. */
+                       if (mll_p->u.clefsig_p->bar_p != (struct BAR *) 0 &&
+                                       mll_p->u.clefsig_p->bar_p->endingloc
+                                       == STARTITEM) {
+                               mll_p = do_carry_ties(first_staff_mll_p, mll_p);
+                       }
+                       break;
+
+               case S_SSV:
+                       asgnssv(mll_p->u.ssv_p);
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+\f
+
+/* Save info about any ties and slurs on the last chords before the beginning
+ * of the ending. Then search forward in main list. If there are any more
+ * beginnings of endings, add padding to the appropriate groups.
+ * Return MAINLL at the end of the last ending processed. */
+
+static struct MAINLL *
+do_carry_ties(staff_mll_p, bar_mll_p)
+
+struct MAINLL *staff_mll_p;    /* first staff in measure which ends on
+                                * bar that begins an ending */
+struct MAINLL *bar_mll_p;      /* the bar that begins an ending */
+
+{
+       struct MAINLL *mll_p;   /* walk through list of staffs */
+       int v;                  /* voice number */
+
+
+       /* save all the tie / slur info */
+       for (mll_p = staff_mll_p; mll_p->str == S_STAFF; mll_p = mll_p->next) {
+
+               for (v = 0; v < MAXVOICES; v++) {
+                       savetieinfo(mll_p, mll_p->u.staff_p->groups_p[v]);
+               }
+       }
+
+       /* now search ahead for other endings */
+       for (mll_p = bar_mll_p->next; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->next) {
+               if (mll_p->str != S_BAR) {
+                       continue;
+               }
+
+               switch (mll_p->u.bar_p->endingloc) {
+               case NOITEM:
+               case ENDITEM:
+                       free_carryin_info();
+                       return(mll_p);
+               case STARTITEM:
+                       carryin_ties(mll_p->next);
+                       break;
+               default:
+                       break;
+               }
+       }
+       pfatal("fell off end of list while doing tie carries");
+       /*NOTREACHED*/
+       return( (struct MAINLL *) 0);
+}
+\f
+
+/* given a GRPSYL, save info about any notes in it that have ties or slurs */
+
+static void
+savetieinfo(mll_p, gs_p)
+
+struct MAINLL *mll_p;          /* main list struct that gs_p is connected to */
+struct GRPSYL *gs_p;           /* save info about ties/slurs on last group
+                                * in this list */
+
+{
+       int n;          /* note index */
+       int s;          /* slurto index */
+
+
+       if (gs_p == (struct GRPSYL *) 0) {
+               return;
+       }
+
+       /* find last group in list */
+       for (  ; gs_p->next != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+               ;
+       }
+
+       for (n = 0; n < gs_p->nnotes; n++) {
+
+               /* save tie info */
+               if (gs_p->notelist[n].tie == YES) {
+                       do_save_tieinfo(gs_p->staffno, gs_p->vno,
+                                       gs_p->notelist[n].letter,
+                                       gs_p->notelist[n].octave, -1,
+                                       mll_p, gs_p, NO);
+               }
+
+               /* save slurto info */
+               for (s = 0; s < gs_p->notelist[n].nslurto; s++) {
+                       do_save_tieinfo(gs_p->staffno, gs_p->vno,
+                                       gs_p->notelist[n].slurtolist[s].letter,
+                                       gs_p->notelist[n].slurtolist[s].octave,
+                                       s, mll_p, gs_p,
+                                       gs_p->notelist[n].is_bend);
+               }
+       }
+}
+\f
+
+/* save info about one tie or slur mark that will need to be carried into
+ * subsequent endings. Malloc space for info, fill it in, and put into table */
+
+static void
+do_save_tieinfo(staffno, vno, letter, octave, curveno, mll_p, gs_p, is_bend)
+
+int staffno;
+int vno;
+int letter;    /* a to g */
+int octave;
+int curveno;
+struct MAINLL *mll_p;  /* points to first group */
+struct GRPSYL *gs_p;   /* group of first note */
+int is_bend;           /* YES if is actually a bend rather than slur */
+
+{
+       struct TIECARRY *new_p;
+
+       MALLOC(TIECARRY, new_p, 1);
+       new_p->letter = (short) letter;
+       new_p->octave = (short) octave;
+       new_p->curveno = (short) curveno;
+       new_p->is_bend = is_bend;
+       new_p->mll_p = mll_p;
+       new_p->gs_p = gs_p;
+       new_p->next = Tiecarryinfolist_p [staffno] [vno - 1];
+       Tiecarryinfolist_p [staffno] [vno - 1] = new_p;
+
+       Have_carry_ins = YES;
+}
+\f
+
+/* Once an ending has been found that may have ties/slurs carried in, use
+ * the saved information to add padding. */
+
+static void
+carryin_ties(mll_p)
+
+struct MAINLL *mll_p;  /* look for staffs from here for chords that may have
+                        * things tied or slurred in */
+
+{
+       if (Have_carry_ins == NO) {
+               /* nothing to do */
+               return;
+       }
+
+       /* skip everything up to STAFFS */
+       for (  ; mll_p != (struct MAINLL *) 0; mll_p = mll_p->next) {
+               if (mll_p->str == S_STAFF) {
+                       add_carryin(mll_p->u.staff_p);
+               }
+               else if (mll_p->str == S_BAR) {
+                       break;
+               }
+       }
+}
+\f
+
+/* given a STAFF which is at the beginning of an ending that may have ties/slurs
+ * carried in, go through each voice. If there is anything to carry in, 
+ * add appropriate padding, then generate curve */
+
+static void
+add_carryin(staff_p)
+
+struct STAFF *staff_p;         /* which staff to do ties/slur carry in on */
+
+{
+       int staffno;
+       int v;                          /* voice number */
+       int n;                          /* index into notelist */
+       struct GRPSYL *gs_p;            /* first chord in measure */
+       struct TIECARRY *info_p;        /* info about things carried in */
+       int found;                      /* if matching note found in chord */
+       double padding;                 /* how much padding to add */
+
+
+       staffno = staff_p->staffno;
+       /* do each carried in item on each voice */
+       for (v = 0; v < MAXVOICES; v++) {
+
+               padding = HALFTIEPAD;
+
+               for (info_p = Tiecarryinfolist_p [staffno] [v];
+                                       info_p != (struct TIECARRY *) 0;
+                                       info_p = info_p->next) {
+
+                       gs_p = staff_p->groups_p[v];
+
+                       /* add padding to allow for carried-in mark */
+                       gs_p->padding += padding;
+                       /* only add padding once per chord! */
+                       padding = 0.0;
+
+                       /* mark any notes that will get carried-in mark */
+                       for (found = NO, n = 0; n <  gs_p->nnotes; n++) {
+                               if (gs_p->notelist[n].letter
+                                               == info_p->letter &&
+                                               gs_p->notelist[n].octave
+                                               == info_p->octave) {
+
+                                       /* A carried-in tie on a tablature
+                                        * staff isn't printed, but the fret
+                                        * is put in parentheses. */
+                                       if (is_tab_staff(staff_p->staffno) == YES
+                                                       && info_p->curveno == -1) {
+                                               gs_p->notelist[n].FRET_HAS_PAREN = YES;
+                                       }
+                                       found = YES;
+                                       break;
+                               }
+                       }
+
+                       if (found == NO) {
+                               l_warning(gs_p->inputfile, gs_p->inputlineno,
+                                       "can't carry tie/slur/bend into ending: %c%d not in chord",
+                                       info_p->letter, info_p->octave);
+                       }
+               }
+       }
+}
+\f
+
+/* free all the tie carry in info */
+
+static void
+free_carryin_info()
+
+{
+       int s;
+       int v;
+
+
+       for (s = 1; s <= MAXSTAFFS; s++) {
+               for (v = 0; v < MAXVOICES; v++) {
+                       free_cinfo(Tiecarryinfolist_p [s] [v]);
+                       Tiecarryinfolist_p [s] [v] = (struct TIECARRY *) 0;
+               }
+       }
+
+       Have_carry_ins = NO;
+}
+
+
+/* recursively free list of tie carry information */
+
+static void
+free_cinfo(carryinfo_p)
+
+struct TIECARRY *carryinfo_p;
+
+{
+       if (carryinfo_p == (struct TIECARRY *) 0) {
+               return;
+       }
+
+       free_cinfo(carryinfo_p->next);
+       FREE(carryinfo_p);
+}
+\f
+
+/* check if a transposition occurred, and if so, see if there were any
+ * ties that would cross the bar. If so, print warning and discard the tie */
+
+static void
+chk4xpose(mll_p)
+
+struct MAINLL *mll_p;  /* containing SSV that might contain transpose */
+
+{
+       struct SSV *ssv_p;
+       int s;                  /* staff index */
+       int intnum;             /* transposition interval */
+       int inttype;            /* transposition interval type */
+
+
+       if (mll_p->str != S_SSV) {
+               return;
+       }
+
+       ssv_p = mll_p->u.ssv_p;
+       if (ssv_p->used[TRANSPOSITION] == YES ||
+                                       ssv_p->used[ADDTRANSPOSITION] == YES) {
+               /* this SSV changes transpose value, need to check further */
+               if (ssv_p->context == C_STAFF) {
+                       /* if staff now has a different transpose value than
+                        * before, need to see if any notes tied over the
+                        * previous bar */
+                       s = ssv_p->staffno;
+                       totaltrans(s, &inttype, & intnum);
+                       if (ssv_p->inttype != inttype
+                                       || ssv_p->intnum != intnum) {
+                               chkxpstaff(mll_p, s);
+                       }
+               }
+               else {
+                       /* must be score wide change. This is a little
+                        * trickier. Go through each staff. If its transpose
+                        * value is not set in staff context and it's
+                        * different than the new transpose value, then
+                        * we need to check for ties */
+                       for (s = 1; s <= Score.staffs; s++) {
+                               totaltrans(0, &inttype, & intnum);
+                               if (Staff[s].used[TRANSPOSITION] == NO &&
+                                       Staff[s].used[ADDTRANSPOSITION] == NO &&
+                                       (ssv_p->inttype != inttype
+                                       || ssv_p->intnum != intnum)) {
+                                   chkxpstaff(mll_p, s);
+                               }
+                       }
+               }
+       }
+}
+\f
+
+/* check a specific staff for possible ties across transposition */
+
+static void
+chkxpstaff(mll_p, s)
+
+struct MAINLL *mll_p;  /* look backward in main list from here */
+int s;                 /* which staff */
+
+{
+       int v;
+
+
+       /* back up to find appropriate staff */
+       for (mll_p = mll_p->prev; mll_p != (struct MAINLL *) 0;
+                                               mll_p = mll_p->prev) {
+               if (mll_p->str == S_STAFF) {
+                       if (mll_p->u.staff_p->staffno == s) {
+                               /* found the correct staff. check each voice */
+                               for (v = 0; v < MAXVOICES; v++) {
+                                       chkxpgrp(mll_p->u.staff_p->groups_p[v],
+                                               mll_p->inputfile,
+                                               mll_p->inputlineno);
+                               }
+                               return;
+                       }
+                       else if (mll_p->u.staff_p->staffno < s) {
+                               /* user must have increased the number of
+                                * staffs as well, so the staff in question
+                                * didn't exist in previous measure */
+                               return;
+                       }
+               }
+       }
+}
+\f
+
+/* find the last group in a list of grpsyls. If it has any ties on it,
+ * print warning message for trying to tie across a transposition, and discard
+ * the tie(s). */
+
+static void
+chkxpgrp(gs_p, inputfile, lineno)
+
+struct GRPSYL *gs_p;   /* check this grpsyl list */
+char *inputfile;       /* for error message */
+int lineno;
+
+{
+       register int n;         /* index through notelist */
+
+
+       /* find last group in list */
+       for (   ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
+
+               if (gs_p->next == (struct GRPSYL *) 0) {
+                       /* this is the last group in the measure. See if
+                        * it has any ties on it */
+                       for (n = 0; n < gs_p->nnotes; n++) {
+                               if (gs_p->notelist[n].tie == YES) {
+                                       /* Aha! User tried to do a tie over
+                                        * a transpose */
+                                       l_warning(inputfile, lineno,
+                                               "can't tie into transposition change (use slur)");
+                                       /* cancel any and all ties on this grp,
+                                        * and return, so we don't print more
+                                        * than one error per group */
+                                       for (n = 0; n < gs_p->nnotes; n++) {
+                                               gs_p->notelist[n].tie = NO;
+                                       }
+                                       gs_p->tie = NO;
+                                       return;
+                               }
+                       }
+               }
+       }
+}
+\f
+
+/* On tablature staffs, if two consecutive groups are tied together,
+ * normally the frets are not printed for the second group, so we need
+ * to set the inhibitprint flag on the group. However if there is any
+ * reason why inhibiting printing on a given group isn't a good idea,
+ * we won't set the inhibitprint flag. So this function checks all the
+ * possible reasons for not setting inhibitprint, and if none of them
+ * apply, then it is set.
+ */
+
+static void
+set_inhibitprint_if_appropriate(gs_p, mll_p)
+
+struct GRPSYL *gs_p;
+struct MAINLL *mll_p;
+
+{
+       struct GRPSYL *nextgs_p;        /* the group after gs_p */
+       struct GRPSYL *following_p;     /* the group after next_gs_p */
+       int n;                          /* index through notelist */
+       
+
+
+       if ((nextgs_p = nextgrpsyl(gs_p, &mll_p)) == (struct GRPSYL *) 0) {
+               /* no next group, so nothing to set */
+               return;
+       }
+
+       /* if this group and next group don't have same number of notes,
+        * then there won't be an inhibitprint on the next group */
+       if (gs_p->nnotes == 0 || gs_p->nnotes != nextgs_p->nnotes) {
+               return;
+       }
+
+       /* if next group has a "with" list, no inhibitprint */
+       if (nextgs_p->nwith != 0) {
+               return;
+       }
+
+       for (n = 0; n < gs_p->nnotes; n++) {
+               /* if any notes in this group are not tied, then there won't be
+                * an inhibitprint on the next group */
+               if (gs_p->notelist[n].tie == NO) {
+                       return;
+               }
+
+               /* if next group has any slides to/from nowhere, or slurs
+                * to the next group, it won't get inhibitprint set */
+               if (nextgs_p->notelist[n].nslurto != 0) {
+                       return;
+               }
+       }
+
+       /* next group has a bend of any sort, it doesn't get inhibitprint */
+       for (n = 0; n < nextgs_p->nnotes; n++) {
+               if (HASBEND(nextgs_p->notelist[n]) == YES) {
+                       return;
+               }
+       }
+       
+       /* if group following next group has a non-prebend bend, then the
+        * next group does not get inhibitprint */
+       if ((following_p = nextgrpsyl(nextgs_p, &mll_p)) != (struct GRPSYL *) 0) {
+               for (n = 0; n < following_p->nnotes; n++) {
+                       if (HASBEND(following_p->notelist[n]) == YES &&
+                                       following_p->notelist[n].FRETNO == NOFRET) {
+                               return;
+                       }
+               }
+       }
+
+       /* Whew! If we got here, the group passed all the tests to have its
+        * inhibitprint flag set, so set it */
+       nextgs_p->inhibitprint = YES;
+}
diff --git a/mup/mup/trantab.c b/mup/mup/trantab.c
new file mode 100644 (file)
index 0000000..f04e9bb
--- /dev/null
@@ -0,0 +1,1662 @@
+/* Copyright (c) 1997, 1998, 2000, 2001, 2002, 2004 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ * Name:       trantab.c
+ *
+ * Description:        This file contains functions for translating tablature staffs
+ *             to their corresponding tabnote staffs.
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+/*
+ * Define a temp structure for holding info about the note generated from a
+ * NOTE on a tablature staff.
+ */
+struct TABNOTENOTE {
+       char letter;            /* 'a' to 'g' */
+       char accidental;        /* '\0', 'x', '#', 'n', '&', 'B'(double flat)*/
+       int octave;             /* 0 to 9 */
+       int hs;                 /* half steps above c0 */
+       int strno;              /* the string this note is played on */
+       struct NOTE *note_p;    /* point to the NOTE this is derived from */
+};
+
+static void tabv2tabnotev P((struct MAINLL *mainll_p, int vidx));
+static void fixprevmeas P((struct GRPSYL *ngs_p, struct MAINLL *mll_p));
+static int hasprebend P((struct GRPSYL *gs_p));
+static int cancombine P((struct MAINLL *mll_p, struct GRPSYL *tgs_p,
+               RATIONAL *comp_p));
+static RATIONAL calctime P((struct GRPSYL *gs_p));
+static void translate_group P((struct GRPSYL *tgs_p, struct GRPSYL *pregs_p,
+               struct GRPSYL *ngs_p, struct MAINLL *mll_p, int combine));
+static void calcnote P((struct STRINGINFO *sinfo_p, int fretno, RATIONAL bend,
+               int sharps, struct TABNOTENOTE *note_p, struct GRPSYL *tgs_p));
+static int findfret P((struct GRPSYL *tgs_p, struct MAINLL *mll_p, int strno));
+static void popnotes P((struct GRPSYL *gs_p, struct TABNOTENOTE tnn[],
+               int ntnn, struct GRPSYL *tgs_p, struct MAINLL *mll_p,
+               int is_prebend, int combine, int sharps));
+static int neighbor P((struct TABNOTENOTE *high_p, struct TABNOTENOTE *low_p));
+static int inkeysig P((struct TABNOTENOTE *note_p, int sharps));
+static int upletter P((struct TABNOTENOTE *note_p));
+static int downletter P((struct TABNOTENOTE *note_p));
+static void cleanaccs P((struct GRPSYL *gs_p, struct MAINLL *mll_p));
+\f
+/*
+ * Name:        tab2tabnote()
+ *
+ * Abstract:    Populate tabnote staffs' voices from corresponding tab voices.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through the MLL looking for tab staffs.
+ *             For each it does some work, but the main thing is that it loops
+ *             through each voice and calls tabv2tabnotev() for each GRPSYL
+ *             list.  That function populates the corresponding tabnote voice.
+ */
+
+void
+tab2tabnote()
+
+{
+       struct MAINLL *mainll_p;        /* point along main linked list */
+       struct STAFF *nstaff_p;         /* tabnote STAFF */
+       struct GRPSYL *ngs_p;           /* tabnote GRPSYL */
+       int vidx;
+
+
+       debug(2, "tab2tabnote");
+       initstructs();
+
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               if (mainll_p->str == S_SSV) {
+                       asgnssv(mainll_p->u.ssv_p); /* keep SSVs up to date */
+                       continue;
+               }
+
+               /* if not a tab staff, there's nothing to do */
+               if (mainll_p->str != S_STAFF ||
+                   is_tab_staff(mainll_p->u.staff_p->staffno) == NO) {
+                       continue;
+               }
+
+               /*
+                * The previous staff must be a tabnote staff.  Set pointers to
+                * this tabnote staff and its first voice's first GRPSYL.
+                */
+               nstaff_p = mainll_p->prev->u.staff_p;
+               ngs_p = nstaff_p->groups_p[0];
+
+               /*
+                * If this is a multirest, adjust any octave marks in progress.
+                */
+               if (ngs_p->basictime < -1 &&
+                               Octave_bars[nstaff_p->staffno] > 0) {
+
+                       /* add negative bars plus 1; barline will count as 1 */
+                       Octave_bars[nstaff_p->staffno] += ngs_p->basictime + 1;
+
+                       /* if whole octave stuff is done, re-init */
+                       if (Octave_bars[nstaff_p->staffno] < 0) {
+                               Octave_bars[nstaff_p->staffno] = 0;
+                               Octave_count[nstaff_p->staffno] = 0.0;
+                               Octave_adjust[nstaff_p->staffno] = 0;
+                       }
+               }
+
+               /* loop through all possible voices, populating tabnote */
+               for (vidx = 0; vidx < MAXVOICES; vidx++) {
+                       tabv2tabnotev(mainll_p, vidx);
+               }
+       }
+}
+\f
+/*
+ * Name:        tabv2tabnotev()
+ *
+ * Abstract:    Populate a tabnote voice from its corresponding tab voice.
+ *
+ * Returns:     void
+ *
+ * Description: This function populates a tabnote GRPSYL list based on its
+ *             corresponding tab GRPSYL list, after making sure that the voice
+ *             exists for each.
+ */
+
+static void
+tabv2tabnotev(mainll_p, vidx)
+
+struct MAINLL *mainll_p;       /* main LL struct for this staff */
+int vidx;                      /* voice index, 0 to MAXVOICES-1 */
+
+{
+       struct STAFF *tstaff_p;         /* tablature STAFF */
+       struct STAFF *nstaff_p;         /* tabnote STAFF */
+       struct GRPSYL *tgs_p;           /* tablature GRPSYL */
+       struct GRPSYL *ngs_p;           /* tabnote GRPSYL */
+       struct GRPSYL *nngs_p;          /* next tabnote GRPSYL */
+       struct GRPSYL *gs_p;            /* newly allocated GRPSYL */
+       struct GRPSYL *pregs_p;         /* GRPSYL for prebend's grace group */
+       int combine;                    /* should two groups be combined? */
+       RATIONAL totdur;                /* total duration of combined groups */
+       int n;                          /* loop variable */
+       char *acc_p;                    /* pointer to accidental string */
+
+
+       /*
+        * Set pointers to the tablature staff's STAFF structure and the first
+        * GRPSYL in the voice we're working on.
+        */
+       tstaff_p = mainll_p->u.staff_p;
+       tgs_p = tstaff_p->groups_p[vidx];
+
+       /* if this voice doesn't exist, there is nothing to copy to tabnote */
+       if (tgs_p == 0) {
+               return;
+       }
+
+       /*
+        * The previous staff must be a tabnote staff.  Set pointers to this
+        * tabnote staff and the first GRPSYL of the given voice.
+        */
+       nstaff_p = mainll_p->prev->u.staff_p;
+       ngs_p = nstaff_p->groups_p[vidx];
+
+       /* tabnote staff must have at least as many voices as tab staff */
+       if (ngs_p == 0) {
+               l_ufatal(tgs_p->inputfile, tgs_p->inputlineno,
+                       "tab staff %d has a voice %d, but tabnote staff %d doesn't; change vscheme for tabnote staff",
+                       nstaff_p->staffno + 1, vidx + 1, nstaff_p->staffno);
+       }
+
+       /*
+        * If the tabnote staff/voice doesn't have a measure space, it was
+        * manually entered, and we will leave it alone.  However, it is
+        * possible that this staff/voice in the previous measure was
+        * generated, and that the last GRPSYL there had note(s) that were to
+        * slide to our GRPSYL.  If so, that slurtolist needs to be adjusted.
+        */
+       if (ngs_p->is_meas == NO || ngs_p->grpcont != GC_SPACE) {
+               fixprevmeas(ngs_p, mainll_p->prev);
+               return;
+       }
+
+       FREE(ngs_p);            /* throw away the measure space */
+
+       /*
+        * Loop once for each GRPSYL in this measure on the tablature staff/
+        * voice.  Usually, for each one found, we allocate one for the tabnote
+        * staff/voice.  But in cases involving prebends, we allocate a second
+        * one, since they translate to a grace note (in parentheses) and a
+        * normal note.  And in certain cases of bends of <= 1/4 step, we don't
+        * allocate any, since we combine the two notes into one.
+        */
+       combine = NO;
+       for ( ; tgs_p != 0; tgs_p = tgs_p->next) {
+               /*
+                * If this group was combined into the previous group because
+                * of 1/4 step bends, we don't allocate any group now.
+                */
+               if (combine) {
+                       combine = NO;
+                       continue;
+               }
+
+               /*
+                * Check whether any of the notes in this tab group have
+                * prebends.  If so, allocate a special GRPSYL for the grace
+                * note(s) in parentheses before the main group.  Link it and
+                * set its fields.
+                */
+               if (hasprebend(tgs_p)) {
+                       CALLOC(GRPSYL, pregs_p, 1);
+                       if (tgs_p == tstaff_p->groups_p[vidx]) {
+                               /* first GRPSYL in list; no previous one, */
+                               /*  staff points at us */
+                               pregs_p->prev = 0;
+                               nstaff_p->groups_p[vidx] = pregs_p;
+                       } else {
+                               /* a later one; set both links */
+                               pregs_p->prev = ngs_p;
+                               ngs_p->next = pregs_p;
+                       }
+                       pregs_p->next = 0;      /* last one so far */
+                       ngs_p = pregs_p;
+
+                       /* set fields unless they'd be just hardcoded 0 */
+                       pregs_p->inputlineno = tgs_p->inputlineno;
+                       pregs_p->inputfile = tgs_p->inputfile;
+                       pregs_p->staffno = nstaff_p->staffno;
+                       pregs_p->vno = vidx + 1;
+                       pregs_p->grpsyl = GS_GROUP;
+                       pregs_p->basictime = 4; /* stemless 1/4 note */
+                       pregs_p->is_meas = NO;
+                       pregs_p->tuploc = NOITEM;
+                       pregs_p->fulltime = Zero;
+                       pregs_p->grpcont = GC_NOTES;
+                       pregs_p->grpvalue = GV_ZERO;
+                       pregs_p->grpsize = GS_SMALL;
+                       pregs_p->headshape = HS_UNKNOWN;
+                       pregs_p->clef = NOCLEF;
+                       pregs_p->beamloc = NOITEM;
+                       pregs_p->beamto = CS_SAME;
+                       pregs_p->stemto = CS_SAME;
+                       pregs_p->tie = NO;
+                       pregs_p->roll = NOITEM;
+                       pregs_p->ho_usage = HO_NONE;
+                       /* nnotes and notelist get set later */
+               } else {
+                       pregs_p = 0;            /* no prebend grace */
+               }
+
+               /*
+                * Allocate a GRPSYL.  Initialize it to be the same as the tab
+                * GRPSYL, since most fields are the same.  Later we'll change
+                * the ones that are different.  Link it appropriately to the
+                * staff (if it's the first one) or else the previous GRPSYL.
+                */
+               CALLOC(GRPSYL, gs_p, 1);
+               *gs_p = *tgs_p;
+               if (tgs_p == tstaff_p->groups_p[vidx] && pregs_p == 0) {
+                       /* first one; no previous one, staff points at us */
+                       gs_p->prev = 0;
+                       nstaff_p->groups_p[vidx] = gs_p;
+               } else {
+                       /* later one; set both links */
+                       gs_p->prev = ngs_p;
+                       ngs_p->next = gs_p;
+               }
+               gs_p->next = 0;         /* last one so far */
+               ngs_p = gs_p;           /* use ngs_p var for new one */
+
+               /* set the correct staff number */
+               ngs_p->staffno = nstaff_p->staffno;
+
+               /* can't share same withlist because fonts may be */
+               /*  changed in them differently later */
+               clone_withlist(ngs_p, tgs_p);
+
+               /* notelist will be reset later; nnotes might change */
+
+               combine = cancombine(mainll_p, tgs_p, &totdur);
+               if (combine) {
+                       /* calc basictime and dots of combined note */
+                       ngs_p->basictime = reconstruct_basictime(totdur);
+                       ngs_p->dots = recalc_dots(totdur, ngs_p->basictime);
+
+                       /* combine fulltime (works even for tuplets) */
+                       ngs_p->fulltime = radd(tgs_p->fulltime,
+                                       tgs_p->next->fulltime);
+               }
+
+               if (tgs_p->grpcont == GC_NOTES && ! is_mrpt(ngs_p)) {
+                       translate_group(tgs_p, pregs_p, ngs_p,
+                                       mainll_p, combine);
+               }
+       }
+
+       /*
+        * For measure repeats, mark the staff and get out.  If there is more
+        * than one voice, each will hit this code, but that's okay.
+        */
+       if (is_mrpt(ngs_p)) {
+               nstaff_p->mrptnum = tstaff_p->mrptnum;
+               return;
+       }
+
+       /* blow away unneeded accidentals */
+       cleanaccs(nstaff_p->groups_p[vidx], mainll_p->prev);
+
+       /*
+        * Because we may have combined some groups, we might have lost the
+        * STARTITEM or ENDITEM of some beamed groups.  So find this situation
+        * and fix it.  This can only affect nongrace groups, so ignore grace
+        * groups.
+        */
+       ngs_p = nstaff_p->groups_p[vidx];       /* first group in measure */
+       if (ngs_p->grpvalue == GV_ZERO) /* if grace, */
+               ngs_p = nextnongrace(ngs_p);    /* get first nongrace*/
+
+       for ( ; ngs_p != 0; ngs_p = nngs_p) {
+               /* get the next group, if any, excluding graces */
+               nngs_p = nextnongrace(ngs_p);
+
+               /*
+                * For this and the next group, if it's a quarter or longer,
+                * make sure it won't get beamed.
+                */
+               if (ngs_p->basictime <= 4)
+                       ngs_p->beamloc = NOITEM;
+               if (nngs_p != 0 && nngs_p->basictime <= 4)
+                       nngs_p->beamloc = NOITEM;
+
+               /* based on this and next group, change this group */
+               switch (ngs_p->beamloc) {
+               case STARTITEM:
+                       if (nngs_p == 0 ||
+                           nngs_p->beamloc == STARTITEM ||
+                           nngs_p->beamloc == NOITEM)
+                               ngs_p->beamloc = NOITEM;
+                       break;
+               case INITEM:
+                       if (nngs_p == 0 ||
+                           nngs_p->beamloc == STARTITEM ||
+                           nngs_p->beamloc == NOITEM)
+                               ngs_p->beamloc = ENDITEM;
+                       break;
+               case ENDITEM:
+               case NOITEM:
+                       if (nngs_p != 0) {
+                               if (nngs_p->beamloc == INITEM)
+                                       nngs_p->beamloc = STARTITEM;
+                               else if (nngs_p->beamloc == ENDITEM)
+                                       nngs_p->beamloc = NOITEM;
+                       }
+                       break;
+               }
+       }
+
+       /*
+        * Now we have start and end items on every beamed set, but it is
+        * possible that some of them are rests (if there were rests embedded
+        * in the original set).  So revise to get them out of there.
+        */
+       ngs_p = nstaff_p->groups_p[vidx];       /* first group in measure */
+       if (ngs_p->grpvalue == GV_ZERO) /* if grace, */
+               ngs_p = nextnongrace(ngs_p);    /* get first nongrace*/
+
+       for ( ; ngs_p != 0; ngs_p = nextnongrace(ngs_p)) {
+               int notegroups;         /* number in this set */
+               struct GRPSYL *end_p;   /* point at the enditem */
+
+               if (ngs_p->beamloc != STARTITEM)
+                       continue;
+               /*
+                * We found a startitem; count how many note groups in the set.
+                * Also set end_p to point at the end item in case we need it
+                * later.
+                */
+               notegroups = 0;
+               end_p = 0;      /* avoid useless warnings */
+               for (nngs_p = ngs_p; nngs_p != 0 &&
+                               (nngs_p->prev == 0 ||
+                               nngs_p->prev->beamloc != ENDITEM);
+                               nngs_p = nextnongrace(nngs_p)) {
+                       if (nngs_p->grpcont == GC_NOTES)
+                               notegroups++;
+                       end_p = nngs_p;
+               }
+
+               if (notegroups <= 1) {
+                       /* 0 or 1 note groups; blow away the set */
+                       for (nngs_p = ngs_p; nngs_p != 0 &&
+                                       (nngs_p->prev == 0 ||
+                                       nngs_p->prev->beamloc!=ENDITEM);
+                                       nngs_p = nextnongrace(nngs_p)) {
+                               nngs_p->beamloc = NOITEM;
+                       }
+               } else {
+                       /*
+                        * There are at least two note groups, so we will keep
+                        * the set, but we may need to move the endpoints to
+                        * avoid rests.
+                        */
+                       /* remove any rests at the start */
+                       for (nngs_p = ngs_p; nngs_p->grpcont == GC_REST;
+                                       nngs_p = nextnongrace(nngs_p)) {
+                               nngs_p->beamloc = NOITEM;
+                       }
+                       nngs_p->beamloc = STARTITEM;
+                       /* remove any rests at the end */
+                       for (nngs_p = end_p; nngs_p->grpcont == GC_REST;
+                                       nngs_p = prevnongrace(nngs_p)) {
+                               nngs_p->beamloc = NOITEM;
+                       }
+                       nngs_p->beamloc = ENDITEM;
+               }
+       }
+
+       /* do beaming of tabnote staff based on beamstyle */
+       if (has_cust_beaming(nstaff_p->groups_p[vidx]) == NO) {
+               do_beaming(nstaff_p->groups_p[vidx], GS_NORMAL,
+                                       nstaff_p->staffno, vidx + 1);
+               do_beaming(nstaff_p->groups_p[vidx], GS_SMALL,
+                                       nstaff_p->staffno, vidx + 1);
+       }
+
+       /*
+        * When there are octave marks on the tabnote staff, adjust the notes
+        * the opposite way so that the result is correct.  Then check to make
+        * sure nothing is out of range.
+        */
+       octave_transpose(nstaff_p, mainll_p, vidx, NO);
+
+       for (ngs_p = nstaff_p->groups_p[vidx]; ngs_p != 0; ngs_p = ngs_p->next){
+               for (n = 0; n < ngs_p->nnotes; n++) {
+                       if (ngs_p->notelist[n].octave < MINOCTAVE ||
+                           ngs_p->notelist[n].octave > MAXOCTAVE) {
+
+                               acc_p = ngs_p->notelist[n].accidental == '\0' ?
+                                       "" : Acctostr[strchr(Acclets, ngs_p->
+                                       notelist[n].accidental) - Acclets];
+
+                               l_ufatal(ngs_p->inputfile,
+                                       ngs_p->inputlineno,
+                                       "'octave' string on tabnote staff transposes note %c%s to out of range octave %d",
+                                       ngs_p->notelist[n].letter,
+                                       acc_p,
+                                       ngs_p->notelist[n].octave);
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        fixprevmeas()
+ *
+ * Abstract:    Fixed unresolved slides in the previous tabnote measure.
+ *
+ * Returns:     void
+ *
+ * Description: This function is called for the first GRPSYL of a manually
+ *             entered tabnote measure.  If the previous tabnote measure was
+ *             generated, it might be trying to slide to a note in our GRPSYL.
+ *             If so, its slurtolist would have a string number in place of a
+ *             letter and NOFRET for the octave.  This function resolves this
+ *             to the true letter and octave.
+ */
+
+static void
+fixprevmeas(ngs_p, mll_p)
+
+struct GRPSYL *ngs_p;          /* tabnote GRPSYL */
+struct MAINLL *mll_p;          /* MLL for this GRPSYL */
+
+{
+       struct GRPSYL *prevngs_p;       /* previous GRPSYL */
+       struct SLURTO *s_p;             /* point at a SLURTO structure */
+       int j, k;                       /* for looping through notes */
+
+
+       /* find previous GRPSYL, if any; if not notes, nothing to do */
+       prevngs_p = prevgrpsyl(ngs_p, &mll_p);
+       if (prevngs_p == 0 || prevngs_p->grpcont != GC_NOTES)
+               return;
+
+       /*
+        * Check every note in the preceding group.  Don't break out after
+        * finding one, since multiple ones could slide to our note.  But there
+        * is a max of one slur/bend coming from each note.
+        */
+       s_p = 0;                /* prevent useless 'used before set' warning */
+       for (k = 0; k < prevngs_p->nnotes; k++) {
+               /* check every slur from that note */
+               for (j = 0; j < prevngs_p->notelist[k].nslurto; j++) {
+                       s_p = &prevngs_p->notelist[k].slurtolist[j];
+
+                       /* only deal with unresolved tabslurs */
+                       if (s_p->letter < MAXTABLINES && s_p->octave == NOFRET)
+                               break;
+               }
+               /* if found a tabslur to our GRPSYL */
+               if (j < prevngs_p->notelist[k].nslurto) {
+                       /* if our GRPSYL has no notes, this is no good */
+                       if (ngs_p->grpcont != GC_NOTES) {
+                               l_warning(prevngs_p->inputfile,
+                               prevngs_p->inputlineno,
+                               "no note on tabnote staff to slide to from %c%s%d",
+                               prevngs_p->notelist[k].letter,
+                               prevngs_p->notelist[k].accidental == '\0' ? "" :
+                               Acctostr[ strchr(Acclets, prevngs_p->notelist[k]
+                                               .accidental) - Acclets ],
+                               prevngs_p->notelist[k].octave);
+
+                               prevngs_p->notelist[k].nslurto = 0;
+
+                       /* if our GRPSYL has >= 2 notes, this is no good */
+                       } else if (ngs_p->nnotes >= 2) {
+                               l_warning(prevngs_p->inputfile,
+                               prevngs_p->inputlineno,
+                               "can't slide from %c%s%d because multiple notes in the next group",
+                               prevngs_p->notelist[k].letter,
+                               prevngs_p->notelist[k].accidental == '\0' ? "" :
+                               Acctostr[ strchr(Acclets, prevngs_p->notelist[k]
+                                               .accidental) - Acclets ],
+                               prevngs_p->notelist[k].octave);
+
+                               prevngs_p->notelist[k].nslurto = 0;
+                       /* there is one note, so we can do the slide */
+                       } else {
+                               s_p->letter = ngs_p->notelist[0].letter;
+                               s_p->octave = ngs_p->notelist[0].octave;
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        hasprebend()
+ *
+ * Abstract:    Check whether any of the notes in this group have a prebend.
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function checks whether any of the notes in this group
+ *             have a prebend.  That's the case where a NOTE structure has
+ *             both a fret number and a bend other than "".  A bend of "" is
+ *             the release of a bend.  It will also return NO if this group
+ *             is a rest or space.
+ */
+
+static int
+hasprebend(tgs_p)
+
+struct GRPSYL *tgs_p;
+
+{
+       int n;                  /* for looping through notes */
+
+
+       for (n = 0; n < tgs_p->nnotes; n++) {
+               /* check for a fret with a nonnull bend */
+               if (tgs_p->notelist[n].FRETNO != NOFRET &&
+                   HASREALBEND(tgs_p->notelist[n])) {
+                       return (YES);
+               }
+       }
+
+       return (NO);
+}
+\f
+/*
+ * Name:        cancombine()
+ *
+ * Abstract:    Check two groups can be joined into one on the tabnote staff.
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function checks whether the two given groups are joined
+ *             by 1/4 step or less bends and should be combined into one group
+ *             on the tabnote staff.  There are a number of other conditions
+ *             that must be met for this to be allowed.  If the answer is YES,
+ *             it sets *comb_p to the total duration, ignoring the effect of
+ *             tuplets.
+ */
+
+static int
+cancombine(mll_p, tgs_p, comb_p)
+
+struct MAINLL *mll_p;  /* main linked list structure we are hanging off of */
+struct GRPSYL *tgs_p;  /* tablature GRPSYL for the first of the two groups */
+RATIONAL *comb_p;      /* for returning total time if combinable */
+
+{
+       struct GRPSYL *nexttgs_p;       /* the second GRPSYL */
+       struct GRPSYL *next2tgs_p;      /* the next one after that */
+       int n;                          /* for looping through note lists */
+
+
+       /* must be a note group */
+       if (tgs_p->grpcont != GC_NOTES)
+               return (NO);
+
+       /* must not be grace */
+       if (tgs_p->grpvalue == GV_ZERO)
+               return (NO);
+
+       for (n = 0; n < tgs_p->nnotes; n++) {
+               /* no note can be the destination of a nonnull bend */
+               if (HASREALBEND(tgs_p->notelist[n]))
+                       return (NO);
+       }
+
+       nexttgs_p = tgs_p->next;        /* find the next group */
+
+       /* first group must not be at the end of a measure */
+       if (nexttgs_p == 0)
+               return (NO);
+
+       /* first and second group must have same number of notes */
+       if (tgs_p->nnotes != nexttgs_p->nnotes)
+               return (NO);
+
+       /* each pair of notes must be joined by a bend of <= 1/4 step */
+       for (n = 0; n < nexttgs_p->nnotes; n++) {
+               if ( ! HASBEND(nexttgs_p->notelist[n]) ||
+                  GT(ratbend(&nexttgs_p->notelist[n]), One_fourth))
+                       return (NO);
+       }
+
+       /* find the following (3rd) group, if there is one */
+       next2tgs_p = nextgrpsyl(nexttgs_p, &mll_p);
+
+       /* no notes in the second group are allowed to bend into the third */
+       if (next2tgs_p != 0) {
+               for (n = 0; n < next2tgs_p->nnotes; n++) {
+                       if (HASBEND(next2tgs_p->notelist[n]))
+                               return (NO);
+               }
+       }
+
+       /* first group must not be at the end of a tuplet */
+       if (tgs_p->tuploc == ENDITEM || tgs_p->tuploc == LONEITEM)
+               return (NO);
+
+       /* second group must not be at the start of a tuplet */
+       if (nexttgs_p->tuploc == STARTITEM || nexttgs_p->tuploc == LONEITEM)
+               return (NO);
+
+       /* get total duration of the two groups */
+       *comb_p = radd(calctime(tgs_p), calctime(nexttgs_p));
+
+       /* total must be double whole, or else numerator must be 2**n - 1 */
+       if (NE(*comb_p, Two) && (comb_p->n & (comb_p->n + 1)) != 0)
+               return (NO);
+
+       return (YES);
+}
+\f
+/*
+ * Name:        calctime()
+ *
+ * Abstract:    Calculate time duration, considering basictime and dots.
+ *
+ * Returns:     The rational number answer.
+ *
+ * Description: This function, given a GRPSYL structure, returns the duration
+ *             as a rational number.  It considers basictime and dots, but it
+ *             does not include the effect of tuplets.  It assumes nongrace,
+ *             it assumes GC_NOTES (thus no quadruple wholes), and it assumes
+ *             not multirest.
+ */
+
+static RATIONAL
+calctime(gs_p)
+
+struct GRPSYL *gs_p;
+
+{
+       RATIONAL base;
+
+
+       if (gs_p->basictime == 0) {
+               /* double whole note is 2 */
+               base.n = 2;
+               base.d = 1;
+       } else {
+               /* anything else is 1/basictime */
+               base.n = 1;
+               base.d = gs_p->basictime;
+       }
+
+       /* return  ( base * (2 - (1/2)**dots) )   */
+       return (rmul(base, rsub(Two, rrai(One_half, gs_p->dots))));
+}
+\f
+/*
+ * Name:        translate_group()
+ *
+ * Abstract:    Translate tablature group notes to tabnote group notes.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given a tablature staff group.  It normally
+ *             translates the notes in this one group to the notes in the
+ *             corresponding tabnote staff group.  But in the case where the
+ *             tab staff group has note(s) that are prebends, it also creates
+ *             the notes for the tabnote grace group.  And in the case where
+ *             this tab group is to be combined with the following one, it
+ *             translates the two together into one tabnote group.
+ */
+
+static void
+translate_group(tgs_p, pregs_p, ngs_p, mll_p, combine)
+
+struct GRPSYL *tgs_p;          /* tablature GRPSYL */
+struct GRPSYL *ngs_p;          /* corresponding main tabnote GRPSYL */
+struct GRPSYL *pregs_p;                /* GRPSYL for prebend's grace group */
+struct MAINLL *mll_p;          /* main LL struct we come from */
+int combine;                   /* combining two tab groups into one tabnote?*/
+
+{
+       struct TABNOTENOTE notes[MAXTABLINES];    /* notes in the main group */
+       struct TABNOTENOTE prenotes[MAXTABLINES]; /* notes in prebend group */
+       struct TABNOTENOTE tempnote;    /* temporary storage for sorting */
+       struct STRINGINFO *strinfo;     /* info about the strings */
+       int fret;               /* fret number */
+       int idx, pidx;          /* indices into regular and prebend arrays */
+       int n, k;               /* loop variables */
+       int strno;              /* string number */
+       RATIONAL bend;          /* bend distance as a rational number */
+       int sharps;             /* number of sharps in tabnote staff's keysig*/
+
+
+       /* find the key signature; flats count negative */
+       sharps = svpath(ngs_p->staffno, SHARPS)->sharps;
+
+       /* point to the array of structures describing the strings */
+       strinfo = svpath(tgs_p->staffno, STAFFLINES)->strinfo;
+
+       /*
+        * Loop through the note structures in the tab staff's GRPSYL, filling
+        * the prebend and regular note arrays.
+        */
+       idx = pidx = 0;
+       for (n = 0; n < tgs_p->nnotes; n++) {
+
+               /* get string and fret number */
+               strno = tgs_p->notelist[n].STRINGNO;
+               fret = tgs_p->notelist[n].FRETNO;
+
+               /*
+                * If this note is a prebend note, put the original (unbent)
+                * note in the prenotes array.  Link this to the tab staff's
+                * GRPSYL.  Keep the array sorted so that the highest notes
+                * come first.
+                */
+               if (fret != NOFRET && HASREALBEND(tgs_p->notelist[n])) {
+                       calcnote(&strinfo[strno], fret, Zero, sharps,
+                                       &prenotes[pidx++], tgs_p);
+                       prenotes[pidx-1].strno = strno;
+                       prenotes[pidx-1].note_p = &tgs_p->notelist[n];
+                       for (k = pidx - 1; k > 0; k--) {
+                               if (prenotes[k].hs > prenotes[k-1].hs) {
+                                       tempnote = prenotes[k-1];
+                                       prenotes[k-1] = prenotes[k];
+                                       prenotes[k] = tempnote;
+                               }
+                       }
+               }
+
+               /* find the bend amount; if none we will get Zero */
+               bend = ratbend(&tgs_p->notelist[n]);
+
+               /*
+                * If there is no fret number in this note, it must be the
+                * destination of a bend.  Call findfret to search backwards
+                * through earlier notes on this string, until we find the fret
+                * number, which is where the bend started.
+                */
+               if (fret == NOFRET)
+                       fret = findfret(tgs_p, mll_p, strno);
+               if (fret == NOFRET)
+                       pfatal("cannot find fret number for tablature note");
+
+               /*
+                * Now we have the fret, and maybe a bend too.  Calculate what
+                * note this comes out to, and put it in the notes array.
+                * Link this to the GRPSYL it was derived from.  Keep the
+                * array sorted so that the highest notes come first.
+                */
+               calcnote(&strinfo[strno], fret, bend, sharps, &notes[idx++],
+                               tgs_p);
+               notes[idx-1].note_p = &tgs_p->notelist[n];
+               notes[idx-1].strno = strno;
+               for (k = idx - 1; k > 0; k--) {
+                       if (notes[k].hs > notes[k-1].hs) {
+                               tempnote = notes[k-1];
+                               notes[k-1] = notes[k];
+                               notes[k] = tempnote;
+                       }
+               }
+       }
+
+       /*
+        * If we are generating a prebend group, populate NOTE structures for
+        * it.  Then, in any case, populate NOTE structures for the main group.
+        */
+       if (pregs_p != 0)
+               popnotes(pregs_p, prenotes, pidx, tgs_p, mll_p, YES, NO,sharps);
+
+       popnotes(ngs_p, notes, idx, tgs_p, mll_p, NO, combine, sharps);
+}
+\f
+/*
+ * Name:        calcnote()
+ *
+ * Abstract:    Calculate note info for a tabnote NOTE structure.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given the info about the string in question,
+ *             the fret number on that string, and the amount of bend (which
+ *             might be zero).  From this it calculates what note that results
+ *             in, and how best to represent it, which depends on what the
+ *             key sig is.  Bends are rounded to the nearest half step,
+ *             rounding downward when they fall on an exact quarter step.
+ *             The results are put in the TABNOTENOTE structure provided.
+ */
+
+static void
+calcnote(sinfo_p, fret, bend, sharps, note_p, tgs_p)
+
+struct STRINGINFO *sinfo_p;    /* pointer to info about the string */
+int fret;                      /* fret number on the string */
+RATIONAL bend;                 /* bend distance */
+int sharps;                    /* number of sharps in tabnote staff's keysig*/
+struct TABNOTENOTE *note_p;    /* note structure to be filled */
+struct GRPSYL *tgs_p;          /* pointer to tab group */
+
+{
+       /*
+        * The following table, indexed by a note letter minus 'a', tells how
+        * many half steps that note is above C.
+        */
+       static int hstab[] = { 9, 11, 0, 2, 4, 5, 7 };
+                           /* a   b  c  d  e  f  g */
+       /*
+        * The following table, given the number of sharps in a major key
+        * (flats count negative), is to be indexed by (sharps + 7).  The
+        * result is the number of half steps the key note is above C.
+        */
+       static int sh2keyhs[] = { 11,6, 1, 8, 3,10, 5, 0, 7, 2, 9, 4,11, 6, 1 };
+                              /* c& g& d& a& e& b& f  c  g  d  a  e  b  f# c#*/
+                              /* -7 -6 -5 -4 -3 -2 -1 0  1  2  3  4  5  6  7 */
+       /*
+        * The following table, given the number of sharps in a major key
+        * (flats count negative), is to be indexed by (sharps + 7).  The
+        * result is the number of letters the key note is above C.
+        */
+       static int sh2keylet[] ={ 0, 4, 1, 5, 2, 6, 3, 0, 4, 1, 5, 2, 6, 3, 0 };
+                              /* c& g& d& a& e& b& f  c  g  d  a  e  b  f# c#*/
+                              /* -7 -6 -5 -4 -3 -2 -1 0  1  2  3  4  5  6  7 */
+
+       /*
+        * The following table, given the number of half steps a note is above
+        * the key note, tells how many letters above the key note letter the
+        * given note should be written as.  For example, in the key of C, the
+        * note 6 half steps up (augmented 4th, f#), should be written with
+        * the letter 3 letters above c (c + 3 = f), thus f# and not g&.
+        */
+       static int hs2s[] = { 0, 0, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6 };
+       /* intervals:         P1 A1 M2 m3 M3 P4 A4 P5 A5 M6 m7 M7 */
+       /* key of C example:  c  c# d  e& e  f  f# g  g# a  b& b  */
+
+
+       int hs;                 /* half steps above c0 */
+       RATIONAL bendqs;        /* bend quarter steps */
+       int keyhs;              /* hs above C the key note is */
+       int intervhs;           /* hs above key note the given note is */
+       int intervlet;          /* letters above key note the given note is */
+       int keyletidx;          /* the key letter (c=1, d=1, etc.) */
+       int octacc;             /* half steps due to octave & accidental */
+       int accoffset;          /* resulting note's acc (&=-1, #=1, etc.) */
+
+
+       /*
+        * Convert the bend to quarter steps.  If the result is an odd integer,
+        * dividing by 2 will give the number of half steps we want (we are
+        * rounding downward).  Otherwise, we round to the nearest half step.
+        */
+       bendqs = rmul(bend, Four);
+       if (bendqs.n % 2 == 1 && bendqs.d == 1) {
+               hs = bendqs.n / 2;
+       } else {
+               bendqs = radd(bendqs, One);
+               hs = bendqs.n / bendqs.d / 2;
+       }
+
+       /* add on the half steps due to letter, octave, and fret */
+       hs += hstab[ sinfo_p->letter - 'a' ] + 12 * sinfo_p->octave + fret;
+
+       /* adjust if string has an accidental; only '#' and '&' are allowed */
+       switch (sinfo_p->accidental) {
+       case '#':
+               hs++;           /* sharp */
+               break;
+       case '&':
+               hs--;           /* flat */
+               break;
+       }
+
+       /* hs is now the correct note, in half steps above c0 */
+       note_p->hs = hs;
+
+       /*
+        * Now that we know the note, we still have to decide how to represent
+        * it, like G# versus A&.  If the note falls within the key signature,
+        * we go with that.  Otherwise, we take our best shot at which way to
+        * do it.
+        *
+        * For C major, for example, it seems clear that F# and C# are more
+        * likely to be appropriate than G& and D&, due to borrowed dominant
+        * chords.  G# is probably better than A&, since it's in the dominant
+        * of the relative minor, though it's not good for the flat 6 chord.
+        * But D# is getting a little extreme, and E& is probably better.
+        * Certainly B& is better than A#.
+        *
+        * For A minor, a similar analysis shows that the same note choices
+        * are good, except that D# is probably better than E&.  We could use
+        * the is_minor flag from the key sig to make this difference.  But
+        * since it's only one note, which is questionable anyway, and since
+        * people wouldn't normally bother to set that flag except for some
+        * unknown MIDI purpose, we elect not to differentiate, but rather
+        * simply go with the "major" analysis.  Of course, we have to
+        * transpose this to the appropriate major key.
+        */
+
+       /*
+        * Find how many half steps above a C the key note is, assuming major.
+        * Then find how many half steps higher the given note is, being
+        * careful to add 12 in there because hs could be as small as -1.
+        */
+       keyhs = sh2keyhs[sharps + 7];
+       intervhs = (hs + 12 - keyhs) % 12;
+
+       /* find how many letters above the key letter this note should be */
+       intervlet = hs2s[intervhs];
+
+       /* find the key letter (c = 0, d = 1, etc.) */
+       keyletidx = sh2keylet[sharps + 7];
+
+       /* find the letter that should be used for this note */
+       note_p->letter = "cdefgab"[(keyletidx + intervlet) % 7];
+
+       /*
+        * Subtract out the half steps due to letter (half steps the letter is
+        * above C).  This leaves the half steps due to the octave & accidental.
+        */
+       octacc = hs - hstab[ note_p->letter - 'a' ];
+
+       /*
+        * The nearest multiple of 12 gives the octave.  What's left gives the
+        * accidental from -2 to 2 (double flat to double sharp).  Index a
+        * character array by that plus 2 to get the right character.
+        */
+       note_p->octave = (octacc + 12 + 6) / 12 - 1;
+       accoffset = octacc - 12 * note_p->octave;
+       note_p->accidental = Acclets[accoffset + 2];
+
+       if (note_p->octave < MINOCTAVE || note_p->octave > MAXOCTAVE) {
+               l_ufatal(tgs_p->inputfile, tgs_p->inputlineno,
+               "the indicated note on the %s string is out of range, too %s",
+               format_string_name(sinfo_p->letter, sinfo_p->accidental,
+               sinfo_p->nticks), note_p->octave > MAXOCTAVE ? "high" : "low");
+       }
+}
+\f
+/*
+ * Name:        findfret()
+ *
+ * Abstract:    Find fret number that applies to the given GRPSYL.
+ *
+ * Returns:     The fret number, or NOFRET if none found.
+ *
+ * Description: This function starts at the given GRPSYL and works backwards
+ *             through that voice until it find a GRPSYL containing a fret
+ *             number.  This is needed since when there is a bend (other than
+ *             a prebend), the fret number does not exist in this GRPSYL, but
+ *             in some earlier GRPSYL which is "bent" to this GRPSYL by a
+ *             series of one or more bends.  Every intervening GRPSYL must
+ *             have a "note" for this string.  If the function hits an
+ *             invalid GRPSYL or the beginning of the MLL, it returns NOFRET.
+ *             This should never happen.
+ */
+
+static int
+findfret(tgs_p, mll_p, strno)
+
+struct GRPSYL *tgs_p;          /* tab GRPSYL to start from */
+struct MAINLL *mll_p;          /* MLL struct it hangs off of */
+int strno;                     /* string number */
+
+{
+       int n;                  /* for looping through notelist */
+
+
+       /* loop until we find the fret or something goes wrong */
+       for (;;) {
+               /* the GRPSYL must contain notes */
+               if (tgs_p->grpcont != GC_NOTES)
+                       return (NOFRET);
+
+               /* find the note for the string in question; it must exist */
+               for (n = 0; n < tgs_p->nnotes; n++) {
+                       if (tgs_p->notelist[n].STRINGNO == strno)
+                               break;
+               }
+               if (n == tgs_p->nnotes)
+                       return (NOFRET);
+
+               /* if this note (string) has a valid fret, return it */
+               if (tgs_p->notelist[n].FRETNO != NOFRET)
+                       return (tgs_p->notelist[n].FRETNO);
+
+               /* search backwards for the next GRPSYL, which must exist */
+               tgs_p = prevgrpsyl(tgs_p, &mll_p);
+               if (tgs_p == 0)
+                       return (NOFRET);
+       }
+}
+\f
+/*
+ * Name:        popnotes()
+ *
+ * Abstract:    Adjust the desired notes and populate the NOTE structures.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given the notes desired for one tabnote
+ *             GRPSYL.  If too many notes are too close together to print, it
+ *             throws some away, with warnings.  Then it allocates NOTE
+ *             structures and fills them in.
+ */
+
+static void
+popnotes(ngs_p, tnn, ntnn, tgs_p, mll_p, is_prebend, combine, sharps)
+
+struct GRPSYL *ngs_p;          /* tabnote GRPSYL */
+struct TABNOTENOTE tnn[];      /* array of TABNOTENOTE structures */
+int ntnn;                      /* number of the above structures */
+struct GRPSYL *tgs_p;          /* tablature GRPSYL we came from */
+struct MAINLL *mll_p;          /* main LL structure we came from */
+int is_prebend;                        /* is this a prebend group? */
+int combine;                   /* this group formed by combining tab grps? */
+int sharps;                    /* current key signature */
+
+{
+       struct NOTE *newnote_p; /* handy pointer to an allocated NOTE */
+       struct GRPSYL *nexttgs_p; /* the tab GRPSYL following ours */
+       struct GRPSYL *prevngs_p; /* the tabnote GRPSYL preceding ours */
+       struct SLURTO *s_p;     /* point at a SLURTO structure */
+       struct MAINLL *mainll_p;/* place to store mll_p */
+       int hightight, lowtight;/* are notes next to a conflict neighboring? */
+       int remnote;            /* should a note be removed? */
+       int keysigidx;          /* index to the note that is in the key sig */
+       int nonkeysigidx;       /* index to the note not in the key sig */
+       int n, k, j;            /* loop variables */
+
+
+       /*
+        * Loop through the notes, throwing away duplicates.  They are already
+        * in order, highest note first.
+        */
+       for (n = 1; n < ntnn; n++) {
+               if (tnn[n - 1].hs == tnn[n].hs) {
+                       l_warning(tgs_p->inputfile, tgs_p->inputlineno,
+                        "throwing away duplicate note %c%c%d on tabnote staff",
+                       tnn[n].letter, tnn[n].accidental, tnn[n].octave);
+
+                       for (k = n; k < ntnn; k++)
+                               tnn[k - 1] = tnn[k];
+                       ntnn--;
+                       n--;
+               }
+       }
+
+       /*
+        * Loop through the remaining notes, looking for conflicts, such as f
+        * versus f#.  Because of the way the notes were generated, and because
+        * of the previous loop, at this point any remaining conflicts will
+        * consist of two notes, one fitting the key signature and one not.
+        * Try to rewrite enharmonically the one that is not in the key sig.
+        * The only problem that can arise is if there is a neighoring note in
+        * the way.  Like, with f and f# in the key of 0 sharps, we'd like to
+        * change f# to g&, but we can't if there's already a g.  So if this
+        * happens, try to rewrite the other note (in this case, we'd get e#
+        * and f#).  If there's already an e, give up and throw one note away.
+        * Yes, we could rewrite g as a&& to make room, but this is so rare
+        * that it's not worth the effort.
+        */
+       for (n = 1; n < ntnn; n++) {
+               if (tnn[n - 1].letter == tnn[n].letter &&
+                   tnn[n - 1].octave == tnn[n].octave) {
+                       /*
+                        * We have a conflict.  See whether the notes next to
+                        * the conflicting notes (if any) are on neighboring
+                        * steps.
+                        */
+                       if (n > 1 && neighbor(&tnn[n - 2], &tnn[n - 1]) == YES)
+                               hightight = YES;
+                       else
+                               hightight = NO;
+
+                       if (n < ntnn-1 && neighbor(&tnn[n], &tnn[n + 1]) == YES)
+                               lowtight = YES;
+                       else
+                               lowtight = NO;
+
+                       /* remember which of the notes is in the key sig */
+                       if (inkeysig(&tnn[n], sharps) == YES) {
+                               keysigidx = n;
+                               nonkeysigidx = n - 1;
+                       } else {
+                               keysigidx = n - 1;
+                               nonkeysigidx = n;
+                       }
+
+                       remnote = NO;   /* init to not remove any note */
+
+                       if (hightight == YES && lowtight == YES) {
+                               /* no room to move either note */
+                               remnote = YES;
+                       } else if (hightight == YES) {
+                               /* no room to move high note; move low note */
+                               if (downletter(&tnn[n]) == NO) {
+                                       /* can't move it */
+                                       remnote = YES;
+                               }
+                       } else if (lowtight == YES) {
+                               /* no room to move low note; move high note */
+                               if (upletter(&tnn[n - 1]) == NO) {
+                                       /* can't move it */
+                                       remnote = YES;
+                               }
+                       } else {
+                               /* room on both sides */
+                               if (keysigidx == n) {
+                                       /* try moving nonkeysig note first */
+                                       if (upletter(&tnn[n - 1]) == NO &&
+                                               downletter(&tnn[n]) == NO) {
+                                                       /* can't move either */
+                                                       remnote = YES;
+                                       }
+                               } else {
+                                       /* try moving nonkeysig note first */
+                                       if (downletter(&tnn[n]) == NO &&
+                                               upletter(&tnn[n - 1]) == NO) {
+                                                       /* can't move either */
+                                                       remnote = YES;
+                                       }
+                               }
+                       }
+
+                       /*
+                        * We have to remove one of the two notes in this
+                        * conflict.  Arbitrarily, remove the one that doesn't
+                        * fit the key signature.
+                        */
+                       if (remnote == YES) {
+                               l_warning(tgs_p->inputfile, tgs_p->inputlineno,
+                               "throwing away note %c%c%d on tabnote staff due to conflict with %c%c%d",
+                                               tnn[nonkeysigidx].letter,
+                                               tnn[nonkeysigidx].accidental,
+                                               tnn[nonkeysigidx].octave,
+                                               tnn[keysigidx].letter,
+                                               tnn[keysigidx].accidental,
+                                               tnn[keysigidx].octave);
+
+                               for (k = nonkeysigidx + 1; k < ntnn; k++)
+                                       tnn[k - 1] = tnn[k];
+                               ntnn--;
+                               n--;
+                       }
+               }
+       }
+
+       /* find the tab GRPSYL following our tab GRPSYL, if there is one */
+       mainll_p = mll_p;       /* save mll_p */
+       nexttgs_p = nextgrpsyl(tgs_p, &mll_p);
+
+       /* find the tabnote GRPSYL preceding ours, if there is one */
+       mll_p = mainll_p;       /* restore mll_p in case it was changed */
+       prevngs_p = prevgrpsyl(ngs_p, &mll_p);
+
+       CALLOC(NOTE, ngs_p->notelist, ntnn);
+       ngs_p->nnotes = (short)ntnn;
+
+       /*
+        * Loop through the newly allocated notes, setting all their fields.
+        */
+       for (n = 0; n < ntnn; n++) {
+               newnote_p = &ngs_p->notelist[n];   /* set short cut pointer */
+
+               /* allocate the array of coordinates */
+               MALLOCA(float, ngs_p->notelist[n].c, NUMCTYPE);
+
+               /* copy the calculated letter/accidental/octave */
+               newnote_p->letter = tnn[n].letter;
+               newnote_p->accidental = tnn[n].accidental;
+               newnote_p->octave = tnn[n].octave;
+
+               /* copy note size, except that prebend graces are always small*/
+               newnote_p->notesize = is_prebend == YES ?
+                               GS_SMALL : tnn[n].note_p->notesize;
+
+               newnote_p->headshape = tnn[n].note_p->headshape;
+               newnote_p->tie = tnn[n].note_p->tie;
+               newnote_p->tiestyle = tnn[n].note_p->tiestyle;
+
+               /* flag to draw curved line after notes */
+               if (combine)
+                       newnote_p->smallbend = YES;
+
+               /* copy whether note has paren; but if prebend, always set it*/
+               newnote_p->note_has_paren = tnn[n].note_p->note_has_paren;
+               if (is_prebend)
+                       newnote_p->note_has_paren = YES;
+
+               /*
+                * If this note has slur(s), allocate a slur-to list.  If a
+                * slur is to real frets, set the string number in the letter
+                * for now, and fix it up later when we know the true letter
+                * and octave.  If it's a slur to or from nowhere, copy over
+                * the "octave" (pseudo fret) as is.  The letter on these is
+                * meaningless.  Note:  a maximum of one slur can be to a real
+                * fret and a maximum of two slurs can exist.
+                */
+               if (tnn[n].note_p->nslurto != 0) {
+                       newnote_p->nslurto = tnn[n].note_p->nslurto;
+                       CALLOC(SLURTO, newnote_p->slurtolist,
+                                       newnote_p->nslurto);
+
+                       for (k = 0; k < newnote_p->nslurto; k++) {
+                               s_p = &tnn[n].note_p->slurtolist[k];
+
+                               if (IS_NOWHERE(s_p->octave)) {
+                                       /* slur to or from nowhere */
+                                       /* letter is meaningless */
+                                       newnote_p->slurtolist[k].octave =
+                                                       s_p->octave;
+                               } else {        /* real fret number */
+                                       newnote_p->slurtolist[k].letter =
+                                                       tnn[n].strno;
+                                       newnote_p->slurtolist[k].octave =
+                                                       NOFRET; /* unknown */
+                               }
+
+                               /* always copy slur style */
+                               newnote_p->slurtolist[k].slurstyle =
+                                       s_p->slurstyle;
+                       }
+               }
+
+               /*
+                * If we are a prebend note, allocate a slur-to list.
+                */
+               if (is_prebend) {
+                       CALLOC(SLURTO, newnote_p->slurtolist, 1);
+                       newnote_p->is_bend = YES;
+                       newnote_p->nslurto = 1;
+                       /*
+                        * Although the bent-to note has been calculated, at
+                        * this point in the code we don't know what it is.
+                        * For now, we store the string number in the letter.
+                        * When we are doing the next GRPSYL on this staff, we
+                        * will change this to be the true bent-to letter, and
+                        * set the octave too.
+                        */
+                       newnote_p->slurtolist[0].letter = tnn[n].strno;
+                       newnote_p->slurtolist[0].octave = NOFRET;
+               }
+
+               /*
+                * If we are not a prebend group (those are handled elsewhere)
+                * and our group was not formed by combining two tab groups
+                * and there is a next GRPSYL on the tablature staff (in this
+                * or the next measure), our note might be bent to a note in
+                * that next GRPSYL.  So search it to see if it contains a note
+                * that our current note is bent to.  If so, allocate a slur-to
+                * list.
+                */
+               if ( ! is_prebend && ! combine && nexttgs_p != 0) {
+                       for (k = 0; k < nexttgs_p->nnotes; k++) {
+                               /*
+                                * Find matching string with a bend but either
+                                * no fret or else it has to be a null bend.
+                                * This eliminates finding a prebend.
+                                */
+                               if (nexttgs_p->notelist[k].STRINGNO == tnn[n].
+                                   strno && HASBEND(nexttgs_p->notelist[k]) &&
+                                   (nexttgs_p->notelist[k].FRETNO == NOFRET ||
+                                   HASNULLBEND(nexttgs_p->notelist[k])))
+                                       break;
+                       }
+                       if (k < nexttgs_p->nnotes) {
+                               if (newnote_p->nslurto != 0)
+                                       pfatal("slur and bend on the same note [popnotes]");
+
+                               CALLOC(SLURTO, newnote_p->slurtolist, 1);
+                               newnote_p->is_bend = YES;
+                               newnote_p->nslurto = 1;
+                               /*
+                                * We don't yet know what the bent-to note is
+                                * going to be.  For now, we store the string
+                                * number in the letter.  When we are doing the
+                                * next GRPSYL on this staff, we will change
+                                * this to be the true bent-to letter, and set
+                                * the octave too.
+                                */
+                               newnote_p->slurtolist[0].letter = tnn[n].strno;
+                       }
+               }
+
+               /*
+                * If we are not a prebend note and there is a previous GRPSYL
+                * on the tabnote staff (in this or the previous measure), our
+                * note may be the destination of a bend or a slur.  Try to
+                * find the note in the previous GRPSYL that bends or slurs to
+                * our note, if any.  If found, set its slur-to list correctly,
+                * now that we know what should be put in it.
+                */
+               if ( ! is_prebend && prevngs_p != 0) {
+                       /*
+                        * Check every note in the preceding group.  Don't
+                        * break out after finding one, since multiple ones
+                        * could slide to our note if our note was a duplicate
+                        * (derived from multiple strings).  But there is a
+                        * max of one slur/bend coming from each note.
+                        */
+                       for (k = 0; k < prevngs_p->nnotes; k++) {
+                               /* check every slur from that note */
+                               s_p = 0;        /* avoid 'used before set' */
+                               for (j = 0; j < prevngs_p->notelist[k].nslurto;
+                                               j++) {
+                                       s_p = &prevngs_p->notelist[k].
+                                                       slurtolist[j];
+                                       if (s_p->letter == tnn[n].strno &&
+                                           ! IS_NOWHERE(s_p->octave))
+                                               break;
+                               }
+                               /* if found a slur to our note */
+                               if (j < prevngs_p->notelist[k].nslurto) {
+                                       s_p->letter = ngs_p->notelist[n].letter;
+                                       s_p->octave = ngs_p->notelist[n].octave;
+                               }
+                       }
+               }
+       }
+}
+\f
+/*
+ * Name:        neighbor()
+ *
+ * Abstract:    Find whether the given notes are on neighboring letters.
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function figures out whether the given notes are on
+ *             neighboring letter, taking octaves into account.
+ */
+
+static int
+neighbor(high_p, low_p)
+
+struct TABNOTENOTE *high_p;    /* the higher note */
+struct TABNOTENOTE *low_p;     /* the lower note */
+
+{
+       /* if the letter themselves aren't right, return NO */
+       if (low_p->letter == 'g') {
+               if (high_p->letter != 'a')
+                       return (NO);
+       } else {
+               if (high_p->letter != low_p->letter + 1)
+                       return (NO);
+       }
+
+       /* if the octaves aren't right, return NO */
+       if (low_p->letter == 'b') {
+               if (high_p->octave != low_p->octave + 1)
+                       return (NO);
+       } else {
+               if (high_p->octave != low_p->octave)
+                       return (NO);
+       }
+
+       return (YES);
+}
+\f
+/*
+ * Name:        inkeysig()
+ *
+ * Abstract:    Find whether the given note fits the key signature.
+ *
+ * Returns:     YES or NO
+ *
+ * Description: This function figures out whether the given note fits the key
+ *             signature, and returns the answer.
+ */
+
+static int
+inkeysig(note_p, sharps)
+
+struct TABNOTENOTE *note_p;    /* note contained in a TABNOTENOTE structure */
+int sharps;                    /* current key signature */
+
+{
+       int circnum;            /* position in the circle of 5ths */
+       int accnum;             /* B = 0, & = 1, n = 2, # = 3, x = 4 */
+       int sharpness;          /* how "sharp" is the note */
+
+
+       circnum = strchr(Circle, note_p->letter) - Circle;
+       accnum = strchr(Acclets, note_p->accidental) - Acclets;
+       sharpness = circnum + 7 * (accnum - 2);
+
+       if (sharpness >= sharps && sharpness <= sharps + 6)
+               return (YES);
+       else
+               return (NO);
+}
+\f
+/*
+ * Name:        upletter()
+ *
+ * Abstract:    Alter note enharmonically, incrementing the letter.
+ *
+ * Returns:     void
+ *
+ * Description: This function alters the given note enharmonically.  It raises
+ *             the letter, and adjusts the accidental and octave as needed.
+ */
+
+static int
+upletter(note_p)
+
+struct TABNOTENOTE *note_p;    /* note contained in a TABNOTENOTE structure */
+
+{
+       int accnum;             /* B = 0, & = 1, n = 2, # = 3, x = 4 */
+
+
+       accnum = strchr(Acclets, note_p->accidental) - Acclets;
+
+       /*
+        * If the old letter is e or b, the next higher white note is only a
+        * half step away, so the accidental has to be a half step flatter.
+        * Otherwise, it's a whole step.  If the result would be flatter than
+        * a double flat, we can't do this, so return NO.
+        */
+       if (note_p->letter == 'e' || note_p->letter == 'b') {
+               if (accnum == 0)        /* double flat */
+                       return (NO);
+               accnum--;
+       } else {
+               if (accnum <= 1)        /* flat or double flat */
+                       return (NO);
+               accnum -= 2;
+       }
+
+       /* if the note is b, increment the octave; fail if impossible */
+       if (note_p->letter == 'b') {
+               if (note_p->octave == MAXOCTAVE)
+                       return (NO);
+               note_p->octave++;
+       }
+
+       /* increment the letter; g wraps around to a */
+       if (note_p->letter == 'g')
+               note_p->letter = 'a';
+       else
+               note_p->letter++;
+
+       note_p->accidental = Acclets[accnum];
+
+       return (YES);
+}
+\f
+/*
+ * Name:        downletter()
+ *
+ * Abstract:    Alter note enharmonically, decrementing the letter.
+ *
+ * Returns:     void
+ *
+ * Description: This function alters the given note enharmonically.  It lowers
+ *             the letter, and adjusts the accidental and octave as needed.
+ */
+
+static int
+downletter(note_p)
+
+struct TABNOTENOTE *note_p;    /* note contained in a TABNOTENOTE structure */
+
+{
+       int accnum;             /* B = 0, & = 1, n = 2, # = 3, x = 4 */
+
+
+       accnum = strchr(Acclets, note_p->accidental) - Acclets;
+
+       /*
+        * If the old letter is f or c, the next lower white note is only a
+        * half step away, so the accidental has to be a half step sharper.
+        * Otherwise, it's a whole step.  If the result would be sharper than
+        * a double sharp, we can't do this, so return NO.
+        */
+       if (note_p->letter == 'f' || note_p->letter == 'c') {
+               if (accnum == 4)        /* double sharp */
+                       return (NO);
+               accnum++;
+       } else {
+               if (accnum >= 3)        /* sharp or double sharp */
+                       return (NO);
+               accnum += 2;
+       }
+
+       /* if the note is c, decrement the octave; fail if impossible */
+       if (note_p->letter == 'c') {
+               if (note_p->octave == MINOCTAVE)
+                       return (NO);
+               note_p->octave--;
+       }
+
+       /* decrement the letter; a wraps around to g */
+       if (note_p->letter == 'a')
+               note_p->letter = 'g';
+       else
+               note_p->letter--;
+
+       note_p->accidental = Acclets[accnum];
+
+       return (YES);
+}
+\f
+/*
+ * Name:        cleanaccs()
+ *
+ * Abstract:    Remove unnecessary accidentals from a tabnote staff measure.
+ *
+ * Returns:     void
+ *
+ * Description: This function removes all the unnecessary accidentals from one
+ *             measure of a tabnote staff.  It takes into consideration the
+ *             key signature and the fact that accidentals last for the
+ *             duration of the measure unless changed by another accidental.
+ *             Also, if a note in the first group was tied from the previous
+ *             measure, any accidental is carried over to this note and
+ *             any series of notes it ties into, but if the note occurs again
+ *             in this measure it reverts to the key signature; so the bottom
+ *             line is we can ignore this and pretend that the tied note is in
+ *             the key signature.
+ */
+
+static void
+cleanaccs(gs_p, mll_p)
+
+struct GRPSYL *gs_p;           /* starts at first tabnote GRPSYL */
+struct MAINLL *mll_p;          /* main LL struct that tabnote staff hangs off*/
+
+{
+       /* current accidental for letter and octave */
+       char curacc[7][MAXOCTAVE + 1];  /* assumes MINOCTAVE == 0 */
+
+       int oct;                /* octave number */
+       char let;               /* note letter */
+       int sharps;             /* number of sharps in tabnote staff's keysig*/
+       int cidx;               /* index into circle of fifths */
+       struct GRPSYL *prevgs_p;/* pointer to preceding GRPSYL */
+       struct NOTE *note_p;    /* pointer to a NOTE structure */
+       int n, k;               /* loop variables */
+
+
+
+       /*
+        * Initialize the table to say that for all octaves of all letters,
+        * the accidental is a natural.
+        */
+       for (oct = 0; oct <= MAXOCTAVE; oct++) {
+               for (let = 'a'; let <= 'g'; let++) {
+                       curacc[let - 'a'] [oct] = 'n';
+               }
+       }
+
+       /* find the key signature; flats count negative */
+       sharps = svpath(gs_p->staffno, SHARPS)->sharps;
+
+       /*
+        * Load the key signature's accidentals into the array for every
+        * octave.
+        */
+       for (oct = 0; oct <= 9; oct++) {
+               for (cidx = 0; cidx < sharps; cidx++) {
+                       curacc[ Circle[cidx] - 'a' ] [oct] = '#';
+               }
+               for (cidx = 0; cidx > sharps; cidx--) {
+                       curacc[ Circle[6 + cidx] - 'a' ] [oct] = '&';
+               }
+       }
+
+       /*
+        * Loop through every note group and every note in them, clearing
+        * accidentals when that accidental is already in force, and updating
+        * the table when not.
+        */
+       for ( ; gs_p != 0; gs_p = gs_p->next) {
+               if (gs_p->grpcont != GC_NOTES)
+                       continue;
+
+               /* find previous group; could be in previous measure if any */
+               prevgs_p = prevgrpsyl(gs_p, &mll_p);
+
+               for (n = 0; n < gs_p->nnotes; n++) {
+                       note_p = &gs_p->notelist[n];
+
+                       /*
+                        * If the note is the destination of a tie, blow away
+                        * its accidental.  This wouldn't have to be a special
+                        * check if it weren't for ties across bar lines.
+                        */
+                       if (prevgs_p != 0 && prevgs_p->grpcont == GC_NOTES) {
+                               for (k = 0; k < prevgs_p->nnotes; k++) {
+                                       if (prevgs_p->notelist[k].tie == YES &&
+                                           prevgs_p->notelist[k].letter ==
+                                           note_p->letter && prevgs_p->notelist
+                                           [k].octave == note_p->octave) {
+                                               note_p->accidental = '\0';
+                                               break;
+                                       }
+                               }
+                               /* if we found it was tied, continue to next */
+                               if (k < prevgs_p->nnotes)
+                                       continue;
+                       }
+                       /*
+                        * If this note's accidental agrees with the accidental
+                        * already in force for this letter and octave, wipe it
+                        * out.  If it doesn't, leave it alone, and update the
+                        * table to show the new accidental that is in force.
+                        */
+                       if (note_p->accidental == curacc[ note_p->letter - 'a' ]
+                                        [ note_p->octave ]) {
+                               note_p->accidental = '\0';
+                       } else {
+                               curacc[ note_p->letter - 'a' ] [ note_p->
+                                               octave ] = note_p->accidental;
+                       }
+               }
+       }
+}
diff --git a/mup/mup/trnspose.c b/mup/mup/trnspose.c
new file mode 100644 (file)
index 0000000..6dd5dab
--- /dev/null
@@ -0,0 +1,819 @@
+/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2002, 2004, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+/*
+ * Name:       trnspose.c
+ *
+ * Description:        This file contains functions for transposing to different keys.
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+#define BAD    (99)            /* a bad interval */
+
+/*
+ * For each possible transposition, this table shows the change in the number
+ * of sharps in whatever key we are in.  Invalid intervals are marked as BAD.
+ */
+static short Delshtab[5][8] = {
+       /*      1       2       3       4       5       6       7 */
+
+      { 0,     -7,     -12,    -10,    -8,     -6,     -11,    -9  },  /* d */
+      { 0,     BAD,    -5,     -3,     BAD,    BAD,    -4,     -2  },  /* m */
+      { 0,     0,      BAD,    BAD,    -1,     1,      BAD,    BAD },  /* P */
+      { 0,     BAD,    2,      4,      BAD,    BAD,    3,      5   },  /* M */
+      { 0,     7,      9,      11,     6,      8,      10,     12  },  /* A */
+};
+
+/* index this by an interval type to get a string naming it */
+static char *Inttab[] =
+               { "diminished", "minor", "perfect", "major", "augmented" };
+
+/*
+ * The following hold the transposition information for the score and all the
+ * staffs.  After every bar line it is updated if the transposition changed.
+ * The score's info is stored in inttype[0], intnum[0], and octint[0].
+ */
+static int inttype[MAXSTAFFS+1];       /* interval type of simple interval */
+static int intnum[MAXSTAFFS+1];                /* simple interval (>0, octs removed)*/
+static int octint[MAXSTAFFS+1];                /* number of octaves in interval */
+
+
+static void transnote P((struct GRPSYL *g_p, struct NOTE *n_p, int inttype,
+               int intnum, int octint));
+static void translurto P((struct GRPSYL *g_p, struct NOTE *n_p, int tnum,
+               int toct));
+static void simptrans P((int origtype, int orignum, int *inttype_p,
+               int *intnum_p, int *octint_p));
+static void fixslurto P((int s, struct MAINLL *mainll_p, int nintnum,
+               int noctint));
+\f
+/*
+ * Name:        transgroups()
+ *
+ * Abstract:    Transpose all GRPSYLs by the requested intervals.
+ *
+ * Returns:     void
+ *
+ * Description: This function loops through the main linked list, applying
+ *             SSVs to keep the transpositions of the score and each staff
+ *             up to date.  Whenever it hits a STAFF, it loops through all
+ *             the GRPSYLs in the linked list(s) for the voice(s), changing
+ *             all the affected information.  It also loops through all the
+ *             chords, transposing them.
+ */
+
+void
+transgroups()
+
+{
+       struct MAINLL *mainll_p;        /* point along main LL */
+       struct GRPSYL *g_p;             /* point along LL of groups */
+       struct STUFF *stuff_p;          /* point at stuff, looking for chords*/
+       int tinttype, tintnum;          /* current total transposition */
+       int ninttype, nintnum, noctint; /* new transposition in standard form*/
+       int v;                          /* voice number */
+       int s;                          /* staff number */
+       int n;                          /* loop variable */
+       int gotssv;                     /* seen an SSV since the last STAFF? */
+       int rtran;                      /* rest "transposition" */
+
+
+       debug(16, "transgroups");
+       initstructs();                  /* clean out old SSV info */
+
+       /*
+        * Loop through the rest of the main linked list, applying SSVs to keep
+        * the tranposition info up to date, and processing linked lists of
+        * groups and STUFF.
+        */
+       gotssv = YES;   /* force init of arrays at start even if no SSVs */
+       for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
+
+               switch (mainll_p->str) {
+               case S_SSV:
+                       asgnssv(mainll_p->u.ssv_p);
+                       gotssv = YES;
+                       break;
+
+               case S_STAFF:
+                       if (gotssv == YES) {
+                               /*
+                                * This is the first staff encountered after
+                                * hitting SSV(s).  If the transposition has
+                                * changed on any staff, update any slurto
+                                * lists in the previous measure that go across
+                                * this bar line, and reset the transposition
+                                * tables in preparation to processing this
+                                * staff and the rest of the staffs in this
+                                * measure.
+                                */
+                               for (s = 1; s <= Score.staffs; s++) {
+                                       /*
+                                        * Convert this staff's new transpostion
+                                        * to standard form, storing it in
+                                        * local variables.
+                                        */
+                                       totaltrans(s, &tinttype, &tintnum);
+                                       simptrans(tinttype, tintnum,
+                                            &ninttype, &nintnum, &noctint);
+
+                                       /*
+                                        * If num or oct changed since last
+                                        * measure, we have to fix up slurto
+                                        * lists.  Interval type is irrelevant.
+                                        */
+                                       if (nintnum != intnum[s] ||
+                                           noctint != octint[s])
+                                               fixslurto(s, mainll_p,
+                                                       nintnum, noctint);
+
+                                       /* store whether changed or not */
+                                       inttype[s] = ninttype;
+                                       intnum[s] = nintnum;
+                                       octint[s] = noctint;
+                               }
+
+                               /* do the score; no slurtos to worry about */
+                               totaltrans(0, &tinttype, &tintnum);
+                               simptrans(tinttype, tintnum,
+                                       &inttype[0], &intnum[0], &octint[0]);
+
+                               gotssv = NO;
+                       }
+
+                       /* the staff we're supposed to work on */
+                       s = mainll_p->u.staff_p->staffno;
+
+                       /* loop through stuff list, transposing chords */
+                       for (stuff_p = mainll_p->u.staff_p->stuff_p;
+                                       stuff_p != 0; stuff_p = stuff_p->next) {
+                               if (stuff_p->string != 0 &&
+                                               stuff_p->modifier == TM_CHORD)
+                                       stuff_p->string = tranchstr(stuff_p->
+                                               string, stuff_p->all ? 0 : s);
+                       }
+
+                       /* never transpose tablature staff */
+                       if (is_tab_staff(s))
+                               continue;
+
+                       /* don't transpose notes if a normal clef is not to */
+                       /*  be printed */
+                       if (svpath(s, STAFFLINES)->printclef != SS_NORMAL)
+                               continue;
+
+                       /* loop through all voices that can exist */
+                       for (v = 0; v < MAXVOICES; v++) {
+                               /*
+                                * Loop through the voice's list of GRPSYLs.
+                                * If the voice doesn't exist, the loop will
+                                * execute 0 times.
+                                */
+                               for (g_p = mainll_p->u.staff_p->groups_p[v];
+                                               g_p != 0; g_p = g_p->next) {
+
+                                       if (g_p->grpcont == GC_NOTES) {
+                                               for (n = 0; n < g_p->nnotes;
+                                                                       n++) {
+                                                       transnote(g_p, &g_p->
+                                                               notelist[n],
+                                                               inttype[s],
+                                                               intnum[s],
+                                                               octint[s]);
+                                               }
+                                       } else if (g_p->grpcont == GC_REST &&
+                                         g_p->restdist != NORESTDIST) {
+                                               /*
+                                                * The user hardcoded a rest's
+                                                * position, so "transpose" it.
+                                                * This is complicated by the
+                                                * fact that we normally want
+                                                * to force an even result so
+                                                * that it will look good.
+                                                */
+                                               /* vertical stepsize shift */
+                                               rtran = 7 * octint[s] +
+                                                               intnum[s] - 1;
+
+                                               if (EVEN(g_p->restdist)) {
+                                                       g_p->restdist += rtran;
+                                                       /*
+                                                        * Force even result,
+                                                        * rounded away from
+                                                        * center line.
+                                                        */
+                                                       if (ODD(g_p->restdist)){
+                                                               g_p->restdist =
+                                                               g_p->restdist > 0 ?
+                                                               g_p->restdist + 1 :
+                                                               g_p->restdist - 1;
+                                                       }
+                                               } else {
+                                                       /* no rounding */
+                                                       g_p->restdist += rtran;
+                                                       
+                                                       /* warn if odd result*/
+                                                       if (ODD(g_p->restdist)){
+                                                               l_warning(
+                                                               g_p->inputfile,
+                                                               g_p->inputlineno,
+                                                               "'dist' on rest is an odd number, which may look bad");
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       break;
+               }
+       }
+}
+\f
+/*
+ * Name:        transnote()
+ *
+ * Abstract:    transpose a note
+ *
+ * Returns:    void
+ *
+ * Description: This function alters a NOTE structure according to the given
+ *             transposition.  This involves changing the note itself (letter,
+ *             accidental, and octave) and any notes in its slurred-to list
+ *             (letter and octave).
+ */
+
+static void
+transnote(g_p, n_p, ttype, tnum, toct)
+
+struct GRPSYL *g_p;    /* ptr to note's group, used only in error messages */
+register struct NOTE *n_p; /* pointer to the note structure */
+int ttype;             /* interval type (DIMINISHED, MINOR, . . .) */
+int tnum;              /* simple interval (positive, with octaves removed) */
+int toct;              /* number of octaves in interval */
+
+{
+       int oldaccnum;          /* old accidental number (&&=0, &=1, ...) */
+       int newaccnum;          /* new accidental number (&&=0, &=1, ...) */
+       int oldcircnum;         /* position of old note in circle of 5ths */
+       int newcircnum;         /* position of new note in circle of 5ths */
+       char newlet;            /* new note letter */
+       char newacc;            /* new accidental letter */
+       int newoct;             /* new octave number */
+
+
+       /*
+        * First do the note itself:  letter, accidental, octave.
+        */
+       /* calculate new note letter from old */
+       newlet = (n_p->letter - 'a' + tnum - 1) % 7 + 'a';
+
+       if (n_p->accidental == '\0') {
+               newacc = '\0';  /* no acc before, so no acc now */
+               /* set as if natural, for benefit of error messages later */
+               oldaccnum = strchr(Acclets, 'n') - Acclets;
+       } else {
+               /*
+                * There was an accidental, so we need to get the proper
+                * transposition of it.  Get position of the old note letter
+                * in the circle of 5ths, and the old accidental index.
+                * The index to the new note letter is shifted by delsh.
+                * If this falls outside the circle string, change the index
+                * and accidental until it lies within the string.
+                */
+               oldcircnum = strchr(Circle, n_p->letter) - Circle;
+               oldaccnum = strchr(Acclets, n_p->accidental) - Acclets;
+               newaccnum = oldaccnum;
+               newcircnum = oldcircnum + Delshtab [ ttype ] [ tnum ];
+               while (newcircnum < 0) {
+                       newaccnum--;            /* one more flat */
+                       newcircnum += 7;        /* 7 letters "sharper" */
+               }
+               while (newcircnum >= 7) {
+                       newaccnum++;            /* one more sharp */
+                       newcircnum -= 7;        /* 7 letters "flatter" */
+               }
+
+               /* test for accidental overflow */
+               if (newaccnum < 0 || newaccnum > 4) {
+                       l_ufatal(g_p->inputfile, g_p->inputlineno,
+                               "note %c%s%d is transposed to have triple sharp or flat",
+                               n_p->letter, Acctostr[oldaccnum], n_p->octave);
+               }
+
+               newacc = Acclets[newaccnum];
+       }
+
+       /*
+        * Calculate the new octave.  Add toct (number of octaves to
+        * transpose) to the old octave.  Then, add tnum to the old note
+        * number.  If it exceeds a 7th, wrap into the next octave.
+        */
+       newoct = n_p->octave + toct;
+       if (Letshift[n_p->letter - 'a'] + tnum - 1 >= 7)
+               newoct++;
+
+       /* check for octave overflow, and exit if so */
+       if (newoct < MINOCTAVE || newoct > MAXOCTAVE) {
+               l_ufatal(g_p->inputfile, g_p->inputlineno,
+                               "note %c%s%d octave is transposed out of range",
+                               n_p->letter, Acctostr[oldaccnum], n_p->octave);
+       }
+
+       /* store away the new values */
+       n_p->letter = newlet;
+       n_p->accidental = newacc;
+       n_p->octave = (short)newoct;
+
+
+       /*
+        * Now do any notes in the slurred-to list, notes this note is slurred
+        * to:  letter, octave.  (There is never an accidental here.)
+        */
+       translurto(g_p, n_p, tnum, toct);
+}
+\f
+/*
+ * Name:        translurto()
+ *
+ * Abstract:    transpose a note's slurred-to list
+ *
+ * Returns:    void
+ *
+ * Description: This function is given a pointer to a note and a transposition.
+ *             It transposes the note's slurto list.  Notice that the "type"
+ *             of transposition interval is not needed, since these lists
+ *             never contain accidentals.
+ */
+
+static void
+translurto(g_p, n_p, tnum, toct)
+
+struct GRPSYL *g_p;    /* note's group, used only in error messages */
+struct NOTE *n_p;      /* note whose slurto list is to be transposed */
+int tnum;              /* transposition interval number */
+int toct;              /* transposition interval octave */
+
+{
+       int s;                  /* index into slurto list */
+       char newlet;            /* new note letter */
+       int newoct;             /* new octave number */
+
+
+       /* loop through each note (if any) in the slurred-to list */
+       for (s = 0; s < n_p->nslurto; s++) {
+
+               /* if this is a slur to or from nowhere, don't change it */
+               if (IS_NOWHERE(n_p->slurtolist[s].octave))
+                       continue;
+
+               /* calculate new note letter from old */
+               newlet = (n_p->slurtolist[s].letter - 'a' + tnum - 1) % 7 + 'a';
+
+               newoct = n_p->slurtolist[s].octave + toct;
+               if (Letshift[n_p->slurtolist[s].letter - 'a'] + tnum - 1 >= 7)
+                       newoct++;
+
+               /* check for octave overflow, and exit if so */
+               if (newoct < MINOCTAVE || newoct > MAXOCTAVE) {
+                       l_ufatal(g_p->inputfile, g_p->inputlineno,
+                                       "note in slurred-to list transposed to out of range octave (%c%d)",
+                                       newlet, newoct);
+               }
+
+               /* store away the new values */
+               n_p->slurtolist[s].letter = newlet;
+               n_p->slurtolist[s].octave = (short)newoct;
+       }
+}
+\f
+/*
+ * Name:        tranchnote()
+ *
+ * Abstract:    transpose a note name that's inside a chord symbol
+ *
+ * Returns:    void
+ *
+ * Description: This function is given a letter and accidental that occur
+ *             inside a chord symbol.  It could be the main chord name itself,
+ *             or the name of a note, like the E in "C/E" or "DaddE".  It
+ *             returns a pointer to a static area containing the transposed
+ *             string.
+ */
+
+char *
+tranchnote(letter, acc, s)
+
+int letter;            /* A to G */
+int acc;               /* one of:  'x', '#', '\0', '&', 'B' */
+int s;                 /* staff number, needed to get tranposition interval */
+                       /*  0 means the score as a whole ("all") */
+
+{
+       static char circle[] = "FCGDAEB";       /* circle of 5ths */
+       static char newchord[3];        /* put transposed result here */
+
+       int oldaccnum;          /* old accidental number (&&=0, &=1, ...) */
+       int newaccnum;          /* new accidental number (&&=0, &=1, ...) */
+       int oldcircnum;         /* position of old note in circle of 5ths */
+       int newcircnum;         /* position of new note in circle of 5ths */
+       char newlet;            /* new note letter */
+       char newacc;            /* new accidental letter */
+
+
+       debug(32, "tranchnote letter=%c acc=%c s=%d", letter,
+                       acc==0 ? ' ' : acc, s);
+       /* need to translate naturals so that strchr can use Acclets[] */
+       if (acc == '\0')
+               acc = 'n';
+
+       /* calculate new note letter from old */
+       newlet = (letter - 'A' + intnum[s] - 1) % 7 + 'A';
+
+       /*
+        * Get the proper transposition of the accidental.  Get position of the
+        * old note letter in the circle of 5ths, and the old accidental index.
+        * The index to the new note letter is shifted by delsh.  If this falls
+        * outside the circle string, change the index and accidental until it
+        * lies within the string.
+        */
+       oldcircnum = strchr(circle, letter) - circle;
+       oldaccnum = strchr(Acclets, acc) - Acclets;
+       newaccnum = oldaccnum;
+       newcircnum = oldcircnum + Delshtab [ inttype[s] ] [ intnum[s] ];
+       while (newcircnum < 0) {
+               newaccnum--;            /* one more flat */
+               newcircnum += 7;        /* 7 letters "sharper" */
+       }
+       while (newcircnum >= 7) {
+               newaccnum++;            /* one more sharp */
+               newcircnum -= 7;        /* 7 letters "flatter" */
+       }
+
+       /* test for accidental overflow */
+       if (newaccnum < 0 || newaccnum > 4)
+               ufatal("chord note %c%s is transposed to have triple sharp or flat",
+                       letter, Acctostr[oldaccnum]);
+
+       newacc = Acclets[newaccnum];
+
+       /* store away the new values */
+       newchord[0] = newlet;
+       newchord[1] = (newacc == 'n' ? '\0' : newacc);
+       newchord[2] = '\0';
+
+       return (newchord);
+}
+\f
+/*
+ * Name:        eff_key()
+ *
+ * Abstract:    Return the "effective key" (the key after any transposition).
+ *
+ * Returns:     the number of sharps in the effective key (flats are negative)
+ *
+ * Description: This function, given a staff number, returns the number of
+ *             sharps currently in effect, considering any transpostion that
+ *             may have been requested.  If given 0 for the staff number, it
+ *             does this for the score's key signature.  It assumes the SSVs
+ *             are up to date.
+ */
+
+int
+eff_key(staff)
+
+int staff;                     /* staff number to do it for (0 = score) */
+
+{
+       int sharps;             /* sharps in old key (flats count negative) */
+       int origtype;           /* original transposition interval type */
+       int orignum;            /* original transposition interval number */
+       int inttype;            /* interval type of simple interval */
+       int intnum;             /* simple interval (positive, octs removed) */
+       int octint;             /* number of octaves in interval */
+       int newsharps;          /* sharps in key after transposition */
+
+
+       /*
+        * If no normal clef is to be printed, always treat it like there is
+        * no key signature.
+        */
+       if (staff == 0) {
+               if (Score.printclef != SS_NORMAL)
+                       return (0);
+       } else {
+               if (svpath(staff, STAFFLINES)->printclef != SS_NORMAL)
+                       return (0);
+       }
+
+       /* viewpath to get this staff's current key and transposition */
+       if (staff == 0) {
+               sharps = Score.sharps;
+       } else {
+               sharps = svpath(staff, SHARPS)->sharps;
+       }
+       totaltrans(staff, &origtype, &orignum);
+
+       simptrans(origtype, orignum, &inttype, &intnum, &octint);
+
+       /*
+        * Change number of sharps by the appropriate delta.  We assume the
+        * interval isn't BAD, because the parser wouldn't have allowed it.
+        */
+       newsharps = sharps + Delshtab [ inttype ] [ intnum ];
+
+       /* make sure the resulting key is valid */
+       if (newsharps < -7 || newsharps > 7) {
+               /*
+                * Normally we take the final "else" here.  But for the "1"
+                * interval there is an ambiguity.  If transpose + addtranspose
+                * add up to an aug or dim 1, there are two ways to state the
+                * result.  (Also for per 1, but in that case, we'd never have
+                * an invalid key.)  So we state both ways of looking at it.
+                */
+               if (orignum == 1  && origtype == AUGMENTED ||
+                   orignum == -1 && origtype == DIMINISHED) {
+                       ufatal("staff %d: key of %d %s transposed up by augmented 1 or down diminished 1 results in %d %s",
+                               staff,
+                               abs(sharps),
+                               (sharps >= 0 ? "sharps" : "flats"),
+                               abs(newsharps),
+                               (newsharps >= 0 ? "sharps" : "flats"));
+               } else if (orignum == -1 && origtype == AUGMENTED ||
+                          orignum == 1  && origtype == DIMINISHED) {
+                       ufatal("staff %d: key of %d %s transposed down by augmented 1 or up diminished 1 results in %d %s",
+                               staff,
+                               abs(sharps),
+                               (sharps >= 0 ? "sharps" : "flats"),
+                               abs(newsharps),
+                               (newsharps >= 0 ? "sharps" : "flats"));
+               } else {
+                       ufatal("staff %d: key of %d %s transposed %s by %s %d results in %d %s",
+                               staff,
+                               abs(sharps),
+                               (sharps >= 0 ? "sharps" : "flats"),
+                               (orignum > 0 ? "up" : "down"),
+                               Inttab[origtype],
+                               abs(orignum),
+                               abs(newsharps),
+                               (newsharps >= 0 ? "sharps" : "flats"));
+               }
+       }
+       return (newsharps);
+}
+\f
+/*
+ * Name:        simptrans()
+ *
+ * Abstract:    Simplify a transpostion into standard form.
+ *
+ * Returns:     void
+ *
+ * Description: This function, given a transposition, converts it into
+ *             standard form (a "simple" upwards interval and an octave).
+ */
+
+static void
+simptrans(origtype, orignum, inttype_p, intnum_p, octint_p)
+
+int origtype;          /* original transposition interval type */
+int orignum;           /* original transposition interval number */
+int *inttype_p;                /* interval type (DIMINISHED, MINOR, . . .) */
+int *intnum_p;         /* simple interval (positive, with octaves removed) */
+int *octint_p;         /* number of octaves in interval */
+
+{
+       int direction;          /* UP or DOWN */
+
+
+       *inttype_p = origtype;
+       *intnum_p = orignum;
+
+       /* set direction; if down, make intnum positive */
+       if (*intnum_p > 0) {
+               direction = UP;
+       } else {
+               direction = DOWN;
+               *intnum_p = -*intnum_p;
+       }
+
+       /* break interval into octaves plus a simple interval */
+       *octint_p = (*intnum_p - 1) / 7;
+       *intnum_p -= 7 * *octint_p;
+
+       /* if downwards, adjust so that *intnum_p is upwards */
+       if (direction == DOWN) {
+               if (*intnum_p == 1) {
+                       /* for unison, negate octaves and reverse intvl type */
+                       *octint_p = -*octint_p;
+                       *inttype_p = 4 - *inttype_p;
+               } else {
+                       /* for other intervals, octave becomes one less than */
+                       /* negation, and *intnum_p flips as does its type */
+                       *octint_p = -1 - *octint_p;
+                       *intnum_p = 9 - *intnum_p;
+                       *inttype_p = 4 - *inttype_p;
+               }
+       }
+}
+\f
+/*
+ * Name:        fixslurto()
+ *
+ * Abstract:    Fix transposition of notes in a slurred-to list.
+ *
+ * Returns:     void
+ *
+ * Description: Notes in a slurred-to list are initially transposed the same as
+ *             the regular notes in that measure.  But if they occur in a
+ *             group immediately before a bar line where the transposition
+ *             changes, they should have been transposed according to the new
+ *             transposition.  This function is called when entering the new
+ *             measure.  It searches back and finds any such slurred-to lists
+ *             in the previous measure and fixes their transposition.
+ */
+
+static void
+fixslurto(s, mainll_p, nintnum, noctint)
+
+int s;                         /* staff number */
+struct MAINLL *mainll_p;       /* initially points at current staff */
+int nintnum;                   /* interval number of new transposition */
+int noctint;                   /* octaves in new transposition */
+
+{
+       struct GRPSYL *g_p;     /* point to a group */
+       int deltanum, deltaoct; /* change in transposition */
+       int v;                  /* voice number */
+       int n;                  /* loop index */
+
+
+       /* search back to the last staff of the preceding measure, if any */
+       for (mainll_p = mainll_p->prev; mainll_p != 0 &&
+                       mainll_p->str != S_STAFF; mainll_p = mainll_p->prev)
+               ;
+       if (mainll_p == 0)
+               return; /* no preceding measure; nothing to do */
+
+       /* search back to the matching staff in that measure, if any */
+       while (mainll_p != 0 && mainll_p->str == S_STAFF &&
+                               mainll_p->u.staff_p->staffno != s)
+               mainll_p = mainll_p->prev;
+       if (mainll_p == 0 || mainll_p->str != S_STAFF)
+               return;         /* no matching staff (no. of staffs changed) */
+       /* we found a matching staff in the preceding measure */
+
+       /*
+        * "Subtract" the old transposition from the new one, to find the
+        * "delta" transposition.  This is what we need to apply to the
+        * slurred-to notes to change them from the old to new transposition.
+        */
+       deltanum = nintnum - intnum[s] + 1;
+       deltaoct = noctint - octint[s];
+       if (deltanum < 1) {
+               deltanum += 7;
+               deltaoct--;
+       }
+
+       /*
+        * mainll_p now points to the matching staff in the preceding measure.
+        * Loop through all voices that can exist.
+        */
+       for (v = 0; v < MAXVOICES; v++) {
+               g_p = mainll_p->u.staff_p->groups_p[v];
+               if (g_p == 0)
+                       continue;
+
+               /* find the last grpsyl in this voice */
+               while (g_p->next != 0)
+                       g_p = g_p->next;
+
+               /* if it doesn't contain notes, there is nothing to do */
+               if (g_p->grpcont != GC_NOTES)
+                       continue;
+
+               /* found a group with notes at end of measure; process it */
+               for (n = 0; n < g_p->nnotes; n++) {
+                       translurto(g_p, &g_p->notelist[n], deltanum, deltaoct);
+               }
+       }
+}
+\f
+/*
+ * Name:        totaltrans()
+ *
+ * Abstract:    Find the current total transposition of a staff or the score.
+ *
+ * Returns:     void
+ *
+ * Description: This function is given a staff number, or zero for the score.
+ *             It assumes that the SSVs are up to date.  It gets the two
+ *             tranposition parameters, and adds them to get the current
+ *             total transpostion.  If it's invalid, it does a ufatal.
+ */
+
+void
+totaltrans(s, type_p, num_p)
+
+int s;                         /* staff number, or 0 for score */
+int *type_p;                   /* return type of resulting transposition */
+int *num_p;                    /* return number of resulting transposition */
+
+{
+       /*
+        * inths is to be indexed by interval type and number (1 through 7).
+        * It gives the number of half steps in the interval.
+        */
+       static short inths[5][8] = {
+            /* 1       2       3       4       5       6       7 */
+
+          { 0, -1,     0,      2,      4,      6,      7,      9    }, /* d */
+          { 0, BAD,    1,      3,      BAD,    BAD,    8,      10   }, /* m */
+          { 0, 0,      BAD,    BAD,    5,      7,      BAD,    BAD  }, /* P */
+          { 0, BAD,    2,      4,      BAD,    BAD,    9,      11   }, /* M */
+          { 0, 1,      3,      5,      6,      8,      10,     12   }, /* A */
+       };
+
+       struct SSV *ssv_p;      /* point at the SSV hold a transposition */
+       int type[2];            /* interval types (DIMINISHED, MINOR, . . .) */
+       int num[2];             /* interval numbers (down is negative) */
+       int totalhs;            /* total half steps in resulting interval */
+       char place[15];         /* temp storage for error message use */
+       int offset;             /* like interval no. but counting from 0 */
+       int n;                  /* loop variable */
+
+
+       /* get the type and num of each transpostion interval */
+       ssv_p = svpath(s, TRANSPOSITION);
+       type[0] = ssv_p->inttype;
+       num[0] = ssv_p->intnum;
+       ssv_p = svpath(s, ADDTRANSPOSITION);
+       type[1] = ssv_p->addinttype;
+       num[1] = ssv_p->addintnum;
+
+       /*
+        * To get the interval number of the num of the transpostions, we
+        * basically add the two.  But musicians unfortunately start counting
+        * intervals from 1 instead of 0, so we have to play some games.
+        */
+       offset = (num[0] > 0 ? num[0] - 1 : num[0] + 1) + /* add true offsets*/
+                (num[1] > 0 ? num[1] - 1 : num[1] + 1);
+       if (offset >= 0) {              /* get interval number from offset */
+               *num_p = offset + 1;
+       } else {
+               *num_p = offset - 1;
+       }
+
+       /* accumulate total half steps in both transpositions */
+       totalhs = 0;
+       for (n = 0; n < NUMELEM(num); n++) {
+               if (num[n] > 0) {               /* interval is up */
+                       while (num[n] > 7) {
+                               num[n] -= 7;    /* subtract an octave */
+                               totalhs += 12;  /* add 12 half steps */
+                       }
+                       /* account for this simple interval */
+                       totalhs += inths[type[n]][num[n]];
+               } else {                        /* interval is down */
+                       while (num[n] < -7) {
+                               num[n] += 7;    /* add an octave */
+                               totalhs -= 12;  /* subtract 12 half steps */
+                       }
+                       /* account for this simple interval */
+                       totalhs -= inths[type[n]][abs(num[n])];
+               }
+       }
+
+       /* if interval is down, find the up version of offset and halfsteps */
+       if (offset < 0) {
+               offset = -offset;
+               totalhs = -totalhs;
+       }
+       /* bring it into the range of a simple interval */
+       totalhs -= (offset / 7) * 12;
+       offset %= 7;
+
+       /* make sure this simple interval is valid */
+       if (totalhs < inths[DIMINISHED][offset + 1] ||
+           totalhs > inths[AUGMENTED ][offset + 1]) {
+
+               if (s == 0) {
+                       (void)sprintf(place, "score");
+               } else {
+                       (void)sprintf(place, "staff %d", s);
+               }
+               ufatal("on %s, 'transpose' %s %s %d and 'addtranspose' %s %s %d add up to an invalid interval",
+               place,
+               num[0] > 0 ? "up" : "down", Inttab[type[0]], abs(num[0]),
+               num[1] > 0 ? "up" : "down", Inttab[type[1]], abs(num[1]));
+       }
+
+       /* search table for the type of interval this is; it will be found */
+       for (n = DIMINISHED; n <= AUGMENTED; n++) {
+               if (totalhs == inths[n][offset + 1]) {
+                       break;
+               }
+       }
+
+       *type_p = n;
+}
diff --git a/mup/mup/undrscre.c b/mup/mup/undrscre.c
new file mode 100644 (file)
index 0000000..e45213c
--- /dev/null
@@ -0,0 +1,1542 @@
+/* Copyright (c) 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* This file contains functions that deal with
+ * extending underscores and dashes on lyric syllables. 
+ */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+static double end_dashes P((struct MAINLL *mll_p, struct GRPSYL *syl_p,
+               int verse, int place, int *carryover_p));
+static double end_underscore P((struct MAINLL *mll_p, struct GRPSYL *syl_p,
+               int verse, int place, int *carryover_p));
+static double endx P((struct GRPSYL *last_grp_p, double end));
+static int has_above_lyr P((struct MAINLL *mll_p, RATIONAL begin_time,
+               struct GRPSYL *group_p, int verse));
+static int voice_is_above P((int v1, int v2));
+static struct GRPSYL *find_verse_place P((struct STAFF *staff_p,
+               int verse, int place));
+static RATIONAL default_end P((struct MAINLL *mll_p, struct GRPSYL *syl_p,
+               RATIONAL start_time, double *end_p));
+static int bar_ends_extender P((struct BAR *bar_p, struct MAINLL *mll_p,
+               int staffno, int verse, int place,
+               struct GRPSYL **nextsyl_p_p));
+static void pr_extender P((int ch, double start, double end, double y,
+               int font, int size));
+static void insert_carryover_syllable P((struct MAINLL *mll_p, int staffno,
+               int sylplace, int verseno, char *dash_or_underscore,
+               int font, int size));
+static void add_syllable P((struct STAFF *staff_p, int sylplace, int verseno,
+               char *dash_or_underscore, int font, int size,
+               double begin_x, struct CHORD *chord_p));
+static void stitch_syl_into_chord P((struct CHORD *chord_p,
+               struct GRPSYL *syl_gs_p));
+\f
+
+/* This function is called on lyric syllables in two cases:
+ *     1) During placement phase to determine if an extender needs to
+ *     be carried over to a following staff. In this case, really_print
+ *     will be NO. (The easiest way to see if an extender needs to carry
+ *     over is to pretend to print an extender). The return value will
+ *     be YES if there should be a carryover.
+ *     2) When printing the syllable, to draw an extender after it,
+ *     if appropriate. In this case, really_print will be YES,
+ *     and the return value is meaningless.
+ *
+ * If a syllable ends with a dash, the dash should be placed halfway between
+ * where this syllable ends and the next begins. Or if there is a big space,
+ * multiple dashes should be spread out in that space.  If it ends with an
+ * underscore, then an underline should be drawn from the end of this
+ * syllable to the east edge of the notes in the last chord before
+ * the next syllable for the same staff/verse/place.
+ * But if there is a carryover, this just does the extender up to the
+ * end of the current score; it will get called again on the next score
+ * to continue the extender.
+ * If an underscore is used on a single chord, rather than a mellisma
+ * (which might technically be considered an "incorrect" usage of underscore),
+ * we figure the underscore should be drawn to just before the next syllable,
+ * unless there is a rest earlier. Or if the next syllable begins a measure,
+ * the underscore ends before the bar line, to look better.
+ * If really printing, the dash or underscore is removed
+ * from the end of the string so it won't get printed
+ * with the syllable.
+ */
+
+int
+spread_extender(syl_p, mll_p, verse, sylplace, really_print)
+
+struct GRPSYL *syl_p;  /* current syllable */
+struct MAINLL *mll_p;  /* which MAINLL struct it's hanging off of */
+int verse;             /* verse number */
+int sylplace;          /* PL_ABOVE, etc */
+int really_print;      /* if YES, actually print, otherwise just return
+                        * whether needs to be carried over to next score */
+
+{
+       char *syl;              /* to walk through characters of the syllable */
+       int font;
+       int size;
+       double start;           /* dash area or underscore starts here */
+       double end;             /* dash area or underscore ends here */
+       int ch;                 /* current character in syllable */
+       int last_ch = '\0';     /* final character in syllable */
+       int extndr_font;        /* in case user changes font/size after
+                                * extender, keep track of what font/size the
+                                * extender was */
+       int extndr_size = -1;
+       char *ch_p;             /* pointer to where - or _ is in string */
+       int carryover;          /* YES if will carry over to next staff */
+
+
+       
+       /* See if there is a dash or underscore at the end of the syllable.
+        * If so, save pointer to it. Note that this may not be the last
+        * byte in the string, because there could be font/size changes
+        * after it. */
+       font = syl_p->syl[0];
+       size = syl_p->syl[1];
+       syl = syl_p->syl + 2;
+
+       /* These two assignments avoid "used without being set" warnings */
+       extndr_font = font;
+       ch_p = syl;
+
+       /* Find last character of syllable */
+       while ( (ch = next_str_char( &syl, &font, &size)) != '\0') {
+#ifdef EXTCHAR
+               if ( ( ch == '-' || ch == '_') && ! IS_MUSIC_FONT(font)
+                                       && (font < FONT_XTR) ) {
+#else
+               if ( ( ch == '-' || ch == '_') && ! IS_MUSIC_FONT(font) ) {
+#endif
+                       ch_p = syl - 1;
+                       extndr_font = font;
+                       extndr_size = size;
+                       last_ch = ch;
+               }
+               else {
+                       last_ch = '\0';
+               }
+       }
+
+       /* If there is an extender, handle it */
+       if (last_ch != '\0') {
+               if ( last_ch == '-') {
+                       end = end_dashes(mll_p, syl_p, verse, sylplace,
+                                                       &carryover);
+               }
+               else {
+                       end = end_underscore(mll_p, syl_p, verse, sylplace,
+                                                       &carryover);
+               }
+
+               if (really_print == NO) {
+                       return(carryover);
+               }
+
+               /* Move the rest of the string
+                * over the dash or underscore,
+                * so it won't get printed with the syllable */
+               do {
+                       *ch_p = *(ch_p + 1);
+               } while  ( *++ch_p != '\0');
+               start = syl_p->c[AE];
+
+               /* procsyls() adjusted the east in certain cases for
+                * placement purposes. For printing we need to cancel out
+                * those adjustments. */
+               if (syl_p->next != 0 && last_ch != '-') {
+                       start -= width(extndr_font, extndr_size, ' ');
+               }
+               if (syl_p->next == 0 && last_ch == '-') {
+                       start += width(extndr_font, extndr_size, ' ');
+               }
+
+               /* actually print the extender */
+               pr_extender(last_ch, start, end, syl_p->c[AY],
+                                               extndr_font, extndr_size);
+       }
+       return(NO);
+}
+\f
+
+/* Given a syllable ending with a dash, and some other info,
+ * return where to end the dash(es). If the dashes carry over
+ * to the following score, this will return a point near the east end of
+ * the current score, after setting *carryover_p to YES.
+ */
+
+static double
+end_dashes(mll_p, syl_p, verse, place, carryover_p)
+
+struct MAINLL *mll_p;  /* points to STAFF containing the syl with dash */
+struct GRPSYL *syl_p;  /* this is the syllable with dash */
+int verse;             /* which verse the syl_p is for */
+int place;             /* a PL_* value for where the lyric is */
+int *carryover_p;      /* return value, set to YES if there was a carryover */
+
+{
+       int staffno;
+       struct BAR *lastbar_p;
+
+       staffno = syl_p->staffno;
+       *carryover_p = NO;
+       lastbar_p = 0;  /* will get set to something better before being used */
+       syl_p = syl_p->next;
+
+       do {
+               /* Go forward looking for another non-space syllable */
+               if (syl_p != 0) {
+                       for (    ; syl_p != 0; syl_p = syl_p->next) {
+                               if (syl_p->grpcont != GC_SPACE) {
+                                       /* found it! */
+                                       return(syl_p->c[AW] - Stepsize);
+                               }
+                       }
+               }
+
+               /* No ending syl in current measure. Try the next. */
+               for (mll_p = mll_p->next; mll_p != 0; mll_p = mll_p->next) {
+                       if (mll_p->str == S_BAR) {
+                               if (bar_ends_extender(mll_p->u.bar_p,
+                                               mll_p, staffno, verse,
+                                               place, 0) == YES) {
+                                       return(mll_p->u.bar_p->c[AW] - Stepsize);
+                               }
+                               lastbar_p = mll_p->u.bar_p;
+                       }
+
+                       else if (mll_p->str == S_FEED) {
+                               /* If this is a feed at the very end of the
+                                * main list, or one or more blocks follow it,
+                                * this is not the kind of feed
+                                * we're looking for. */
+                               if (mll_p->next == 0 ||
+                                               mll_p->next->str == S_BLOCKHEAD) {
+                                       continue;
+                               }
+                               /* There is a carryover unless the
+                                * pseudo-bar is something that would end
+                                * the extender. */
+                               mll_p = mll_p->next;
+                               if (mll_p->str != S_CLEFSIG
+                                               || mll_p->u.clefsig_p->bar_p
+                                               == 0) {
+                                       if (mll_p->str == S_FEED) {
+                                               /* Being here means there is
+                                                * a bug somewhere else,
+                                                * because the main list rules
+                                                * are violated. But we can
+                                                * render such a bug harmless
+                                                * by continuing here.
+                                                */
+                                               continue;
+                                       }
+                                       pfatal("end_dashes found unexpected main list contents after feed");
+                               }
+                               if (bar_ends_extender(mll_p->u.clefsig_p->bar_p,
+                                               mll_p, staffno, verse, place, 0)
+                                               == NO) {
+                                       *carryover_p = YES;
+                               }
+                               return(lastbar_p->c[AW] - Stepsize);
+                       }
+
+                       else if (mll_p->str == S_STAFF
+                                               && mll_p->u.staff_p->staffno
+                                               == staffno) {
+                               syl_p = find_verse_place(mll_p->u.staff_p,
+                                                               verse, place);
+                               break;
+                       }
+               }
+       } while (mll_p != 0);
+
+       /* Fell off end of song. Use final bar */
+       return(lastbar_p->c[AW] - Stepsize);
+}
+\f
+
+/* Given a syllable ending with an underscore, and some other info,
+ * return where to end the underscore. If the underscore carries over
+ * to the following score, this will return a point near the east end of
+ * the current score, after setting *carryover_p to YES.
+ */
+
+static double
+end_underscore(mll_p, syl_p, verse, place, carryover_p)
+
+struct MAINLL *mll_p;  /* points to STAFF containing the syl with underscore */
+struct GRPSYL *syl_p;  /* this is the syllable with underscore */
+int verse;             /* which verse the syl_p is for */
+int place;             /* a PL_* value for where the lyric is */
+int *carryover_p;      /* return value, set to YES if there was a carryover */
+
+{
+       struct GRPSYL *current_grp_p[MAXVOICES];/* which group we are
+                                                * currently dealing with on
+                                                * each voice */
+       RATIONAL group_time[MAXVOICES];         /* accumulated time value of
+                                                * groups up to the one we
+                                                * are currently dealing with */
+       short had_rest[MAXVOICES];              /* YES or NO */
+       RATIONAL current_time;                  /* how far we are in meas */
+       RATIONAL end_time;                      /* where next non-space
+                                                * syllable is for this
+                                                * staff/place/verse, if
+                                                * there is one
+                                                * in the current measure,
+                                                * otherwise the end of the
+                                                * current measure. */
+       struct GRPSYL *last_grp_p;              /* if non-zero, this is the
+                                                * current candidate group
+                                                * with which we could
+                                                * potentially align the
+                                                * end of the underscore. */
+       double end;                             /* this is how far we will
+                                                * draw the underscore if we
+                                                * don't find any reason to
+                                                * stop it sooner. */
+       struct GRPSYL *grp_p;                   /* walk through GRPSYLs */
+       struct STAFF *staff_p;                  /* next measure's STAFF */
+       struct GRPSYL *nextsyl_p;               /* syl list for same verse/place
+                                                * in the next measure */
+       RATIONAL grp_end_time;                  /* where a current group ends */
+       
+       int vindex;                             /* voice index */
+       int v;                                  /* voice index */
+       short found_feed;                       /* YES or NO */
+       int staffno;
+
+
+       *carryover_p = NO;      /* assume no carryover for now */
+       staffno = mll_p->u.staff_p->staffno;
+
+       /* Back up from the syllable with underscore to count up time-wise how
+        * far into the measure it is */
+       current_time = Zero;
+       for (grp_p = syl_p->prev; grp_p != 0; grp_p = grp_p->prev) {
+               current_time = radd(current_time, grp_p->fulltime);
+       }
+               
+       /* Set a default end time and place.
+        * Most likely, we will discover later we need to stop the underscore
+        * earlier than this, but if the user is using underscore in a strange
+        * way, like on a single long note rather than a melissma,
+        * we'll use this as the default place to end the underscore. */
+       end_time = default_end(mll_p, syl_p, current_time, &end);
+
+       /* We don't yet have any candidate group with which to align
+        * the ending of the underscore. */
+       last_grp_p = 0;
+
+       /* For each voice, if it exists, find the group that contains
+        * the time of the syllable with the underscore, and make that
+        * the "current group" for that voice. If the voice doesn't exist,
+        * set the current group pointer to zero. */
+       staff_p = mll_p->u.staff_p;
+       for (vindex = 0; vindex < MAXVOICES; vindex++) {
+               group_time[vindex] = Zero;
+               had_rest[vindex] = NO;
+               if (staff_p->groups_p[vindex] != 0) {
+                       for (current_grp_p[vindex] = staff_p->groups_p[vindex];
+                                       current_grp_p[vindex] != 0;
+                                       current_grp_p[vindex]
+                                       = current_grp_p[vindex]->next) {
+                               if (GE(current_time, group_time[vindex]) &&
+                                               LT(current_time,
+                                               radd(group_time[vindex],
+                                               current_grp_p[vindex]->fulltime))) {
+                                       /* This group contains the syl's time */
+
+                                       if (current_grp_p[vindex]->grpcont == GC_REST) {
+                                               had_rest[vindex] = YES;
+                                       }
+                                       break;
+                               }
+                               group_time[vindex] = radd(group_time[vindex],
+                                               current_grp_p[vindex]->fulltime);
+                       }
+                       if (current_grp_p[vindex] == 0) {
+                               pfatal("unable to find group containing syl's time");
+                       }
+               }
+               else {
+                       /* voice doesn't exist in this measure */
+                       current_grp_p[vindex] = 0;
+               }
+       }
+
+       for (   ;  ; ) {
+               /* Most of the time, we use voice 1 to determine where to
+                * end the underscore. However, if voice 1 has spaces,
+                * we'll use voice 3 (the "middle" voice), and 
+                * if that is non-existent or space, we use voice 2.
+                * If everything is space, we keep going and hope for the
+                * best. If all else fails, we would end up using the "end"
+                * value as the default.
+                * 
+                * However, if this is a below or between lyric,
+                * and there exists an above lyric
+                * during the time we are dealing with,
+                * we assume voice 1 goes with the above lyric, and the
+                * below lyric probably goes with voice 2, or possibly voice 3.
+                * If both those voices exist, it's probably not possible
+                * to divine which the user wants the lyric associated with
+                * without reading their mind. But 3 voices on a vocal staff
+                * is quite unusual, especially with rests in different places,
+                * so we use voice 2 if it exists and is non-space.
+                * If that fails, we try 3, then 1, then punt.
+                * If it is a between lyric, there is a slight chance the user
+                * really wanted us to use the staff below, but we always
+                * associate "between" things with the staff above.
+                * They should use "above" on the next staff instead.
+                */
+               vindex = 0;     /* use voice 1 as default */
+               if (place != PL_ABOVE) {
+                       /* The lyric is below or between.
+                        * Test voices 2, 3, and 1 (indexes 1, 2, 0)
+                        * in that order till we find one that isn't a space,
+                        * and see if there is an above lyric
+                        * during its time. If so, that is the voice to use
+                        * during this time to figure out
+                        * where to end underscore. */
+                       if (current_grp_p[1] != 0 &&
+                                       current_grp_p[1]->grpcont != GC_SPACE &&
+                                       has_above_lyr(mll_p, current_time,
+                                       current_grp_p[1], verse) == YES) {
+                               vindex = 1;
+                       }
+                       else if (current_grp_p[2] != 0 &&
+                                       current_grp_p[2]->grpcont != GC_SPACE &&
+                                       has_above_lyr(mll_p, current_time,
+                                       current_grp_p[2], verse) == YES) {
+                               vindex = 2;
+                       }
+                       /* Otherwise we go with the default, voice 1.
+                        * We know voice 1 will always exist. */
+               }
+
+               else {          /* place is above */
+                       /* Note that voice 1 always exists, so
+                        * so we don't need to check for null first
+                        * on that voice. */
+                       if (current_grp_p[0]->grpcont != GC_SPACE) {
+                               vindex = 0;
+                       }
+                       else if (current_grp_p[2] != 0 &&
+                                       current_grp_p[2]->grpcont != GC_SPACE) {
+                               vindex = 2;
+                       }
+                       else if (current_grp_p[1] != 0 &&
+                                       current_grp_p[1]->grpcont != GC_SPACE) {
+                               vindex = 1;
+                       }
+               }
+
+               /* At this point, we know which voice is most relevant for
+                * checking if it is time to end the underscore.
+                * See if the current group in that voice contains the
+                * time value of the ending syllable. */
+               if ( GE(end_time, group_time[vindex]) && LT(end_time,
+                                       radd(group_time[vindex],
+                                       current_grp_p[vindex]->fulltime)) ) {
+                       /* We need to end the underscore now. */
+                       return(endx(last_grp_p, end));
+               }
+
+               /* If the relevant group is a rest, need to stop here */
+               if (current_grp_p[vindex]->grpcont == GC_REST) {
+                       return(endx(last_grp_p, current_grp_p[vindex]->c[AW]));
+               }
+               else if (current_grp_p[vindex]->grpcont == GC_NOTES) {
+                       /* Save as last known group so far at which we
+                        * could potentially end the underscore. */
+                       last_grp_p = current_grp_p[vindex];
+               }
+
+               /* We're done with this group; move to next */
+               current_time = radd(current_time,
+                               current_grp_p[vindex]->fulltime);
+
+               /* Catch up all the voices to the current time */
+               for (v = 0; v < MAXVOICES; v++) {
+                       if (current_grp_p[v] != 0) {
+                               grp_end_time = radd(group_time[v],
+                                       current_grp_p[v]->fulltime);
+
+                               while ( LE(grp_end_time, current_time) ){
+                                       /* Special case. Suppose,
+                                        * as an example, soprano and
+                                        * alto share a staff and the
+                                        * soprano has a long note
+                                        * while the alto has a
+                                        * melissma. The underscore
+                                        * should then go to the
+                                        * last note of the melissma,
+                                        * even though soprano is
+                                        * the reference voice.
+                                        * However, if the alto line
+                                        * had had rests, it's likely
+                                        * it's just accompaniment,
+                                        * not a vocal line, or at
+                                        * least they should have
+                                        * used separate above/below
+                                        * lyrics. 
+                                        * So if this group is below
+                                        * the reference group and
+                                        * hasn't had any rests and
+                                        * is east of our candidate
+                                        * last group, make it the
+                                        * new candidate last group. */
+                                       if (voice_is_above(vindex, v)
+                                         && place != PL_ABOVE
+                                         && had_rest[v] == NO
+                                         && last_grp_p != 0
+                                         && current_grp_p[v]->grpcont
+                                         == GC_NOTES
+                                         && current_grp_p[v]->c[AX]
+                                         > last_grp_p->c[AX]) {
+                                               last_grp_p = current_grp_p[v];
+                                       }
+
+                                       /* move on to next group */
+                                       current_grp_p[v] =
+                                               current_grp_p[v]->next;
+                                       if (current_grp_p[v] == 0) {
+                                               break;
+                                       }
+
+                                       group_time[v] = grp_end_time;
+                                       grp_end_time = radd(
+                                               group_time[v],
+                                               current_grp_p[v]->fulltime);
+                                       if (current_grp_p[v]->grpcont
+                                                               == GC_REST) {
+                                               had_rest[v] = YES;
+                                       }
+                               }
+                       }
+               }
+
+               /* Are we now at the end of the current measure? */
+               if (current_grp_p[vindex] == 0) {
+                       /* If there is a feed after this bar,
+                        * we need to see if a carryover is needed.
+                        * If so, we will end this underscore just before
+                        * the bar, and carry it over to the next score.
+                        */
+                       found_feed = NO;
+                       for (mll_p = mll_p->next; mll_p != 0; mll_p = mll_p->next) {
+                               if (mll_p->str == S_BAR) {
+                                       if (bar_ends_extender(mll_p->u.bar_p, mll_p,
+                                                       syl_p->staffno, verse,
+                                                       place, &nextsyl_p)
+                                                       == YES) {
+                                               /* It's not clear
+                                                * where we should stop if
+                                                * we can't deduce a following
+                                                * syllable. However,
+                                                * if we go to the bar line,
+                                                * the user can always use
+                                                * a <> syllable to force
+                                                * an earlier ending if needed,
+                                                * whereas if we go
+                                                * with the last group,
+                                                * there's probably no
+                                                * reasonable workaround
+                                                * if that's not what they want,
+                                                * so use the bar line. */
+                                               if (nextsyl_p == 0) {
+                                                       return(end);
+                                               }
+                                               else if (nextsyl_p->grpcont
+                                                               == GC_SPACE) {
+                                                       /* "carries over" */
+                                                       return(end);
+                                               }
+                                               else {
+                                                       return(endx(last_grp_p, end));
+                                               }
+                                       }
+                               }
+                               else if (mll_p->str == S_FEED) {
+                                       found_feed = YES;
+                               }
+                               else if (mll_p->str == S_STAFF &&
+                                               mll_p->u.staff_p->staffno ==
+                                               staffno) {
+                                       break;
+                               }
+                               else if (mll_p->str == S_SSV) {
+                                       /* if this staff becomes invisible,
+                                        * end the underscore at the last
+                                        * group before that. */
+                                       struct SSV *ssv_p;
+                                       ssv_p = mll_p->u.ssv_p;
+                                       if (ssv_p->context == C_STAFF
+                                               && ssv_p->staffno == staffno
+                                               && ssv_p->used[VISIBLE] == YES
+                                               && ssv_p->visible == NO) {
+                                           return(endx(last_grp_p, end));
+                                       }
+                               }
+                       }
+                       if (mll_p == 0) {
+                               /* fell off end of song */
+                               return(endx(last_grp_p, end));
+                       }
+                       staff_p = mll_p->u.staff_p;
+
+                       /* See if there is a syllable at the same verse/place */
+                       if ((nextsyl_p = find_verse_place(staff_p,
+                                       verse, place)) != 0 &&
+                                       nextsyl_p->grpcont != GC_SPACE) {
+                               /* There is a syllable at the
+                                * beginning of the next meas,
+                                * so we end the underscore,
+                                * unless it was just a carryover syllable
+                                * that we added earlier. */
+                               if (nextsyl_p->syl[2] != '_'
+                                               || nextsyl_p->syl[3] != '\0') {
+                                       return(endx(last_grp_p, end));
+                               }
+                       }
+                       if (found_feed == YES) {
+                               if (staff_p->groups_p[vindex] != 0 &&
+                                               staff_p->groups_p[vindex]->grpcont == GC_REST) {
+                                       /* next meas begins with a rest,
+                                        * so no need to carry over */
+                                       return(endx(last_grp_p, end));
+                               }
+                               /* We need to end the underscore on the
+                                * current score, and arrange to carry it
+                                * over on the next score. */
+                               *carryover_p = YES;
+                               return(end);
+                       }
+
+       
+                       /* Move to next measure by initing each
+                        * current_grp_p[vindex] to the first group
+                        * in the next measure. */
+                       for (vindex = 0; vindex < MAXVOICES; vindex++) {
+                               current_grp_p[vindex] = staff_p->groups_p[vindex];
+                               group_time[vindex] = Zero;
+                               if (current_grp_p[vindex] != 0 &&
+                                               current_grp_p[vindex]->grpcont
+                                               == GC_REST) {
+                                       had_rest[vindex] = YES;
+                               }
+                       }
+                       end_time = default_end(mll_p,
+                               find_verse_place(staff_p, verse, place),
+                               Zero, &end);
+                       current_time = Zero;
+               }
+       }
+}
+\f
+
+/* If we found a last group where we could end a underscore,
+ * return where the east edge of its notes are,
+ * otherwise return the "end" value as the default.
+ */
+
+static double
+endx(last_grp_p, end)
+
+struct GRPSYL *last_grp_p;     /* if != 0, use east edge of notes of this */
+double end;                    /* if all else fails, use this */
+
+{
+       int n;          /* note index */
+       double edge;    /* return value */
+
+
+       if (last_grp_p == 0) {
+               return(end);
+       }
+
+       if (last_grp_p->grpcont != GC_NOTES) {
+               /* This should actually never happen with the current code,
+                * but just in case, we use the east of the group */
+               return(last_grp_p->c[AE]);
+       }
+
+       /* find east edge of notes, not counting any dots or flags */
+       edge = -1000000.0;      /* init to impossible value */
+       for (n = 0; n < last_grp_p->nnotes; n++) {
+               if (last_grp_p->notelist[n].c[AE] > edge) {
+                       edge = last_grp_p->notelist[n].c[AE];
+               }
+       }
+       /* If the edge we calculated is east of the default end, use
+        * the default end, because that is suppose to be the farthest
+        * possible east we can be. This could happen if the user used
+        * <^....> on a lyric to force part of the lyric to encroach
+        * into the previous groups' space.  In that case we need to end
+        * the underscore where the encroaching lyric begins, not where
+        * the last note group ends.
+        */
+       if (edge > end) {
+               return(end);
+       }
+       return(edge);
+}
+\f
+
+/*
+ * Return YES if there is an above lyrics during the specified time.
+ * We have to use some heuristics.
+ *
+ *     If there is any non-space above lyric for the given verse
+ *     at any point between the begin time
+ *     and the begin time plus the fulltime of the group_p,
+ *     then there is an above lyric.   
+ *
+ *     If there is a rest on voice 1, that implies a rest in an above lyric
+ *     line.
+ *
+ *     If there is lyric space for the duration in question, either
+ *     explicit space, or just no above lyrics at all for the given verse
+ *     in this measure, then we don't know for sure where there are no
+ *     above lyrics, or there is an earlier above lyric for this verse
+ *     that extends into the duration.
+ *     If we find some earlier non-space above lyric
+ *     and it ends with an extender (dash or underscore),
+ *     we say there is an above lyric.
+ *     If there is no such lyric, or the first non-space above lyric
+ *     lyric we come to in backing up does not end with an extender,
+ *     we say there isn't an above lyric.
+ */
+
+static int
+has_above_lyr(mll_p, begin_time, group_p, verse)
+
+struct MAINLL *mll_p;          /* points to syl's STAFF */
+RATIONAL begin_time;
+struct GRPSYL *group_p;                /* see if there a lyric above this group */
+int verse;
+
+{
+       struct STAFF *staff_p;
+       struct GRPSYL *grp_p;
+       RATIONAL cumm_time;             /* current cummulative time */
+       RATIONAL new_cumm_time;         /* cumm_time + group's fulltime */
+       RATIONAL end_time;              /* begin_time + syl's fulltime */
+       int n;                          /* syllist index */
+       int prev_extends;               /* YES/NO if prev syl has extender */
+
+
+       if (mll_p->str != S_STAFF) {
+               pfatal("has_above_lyr passed wrong type of struct");
+       }
+
+       staff_p = mll_p->u.staff_p;
+       end_time = radd(begin_time, group_p->fulltime);
+
+       /* Go through syllists for the staff */
+       prev_extends = NO;
+       for (n = 0; n < staff_p->nsyllists; n++) {
+               if (staff_p->sylplace[n] == PL_ABOVE &&
+                                       staff_p->syls_p[n]->vno == verse) {
+                       cumm_time = Zero;
+                       for (grp_p = staff_p->syls_p[n]; grp_p != 0; grp_p = grp_p->next) {
+                               new_cumm_time = radd(cumm_time, grp_p->fulltime);
+
+                               if ( LT(new_cumm_time, begin_time) &&
+                                               grp_p->grpcont != GC_SPACE) {
+                                       prev_extends = has_extender(grp_p->syl);
+                               }
+
+                               /* See if this syllable overlaps the time
+                                * of the group we are checking against. */
+                               else if ( (GE(begin_time, cumm_time) &&
+                                               LT(begin_time, new_cumm_time)) ||
+                                               (GE(end_time, cumm_time) &&
+                                               LT(end_time, new_cumm_time)) ) {
+
+                                       /* This is a relevant group. If it isn't
+                                        * a space, then we know there is
+                                        * indeed an above lyric. */
+                                       if (grp_p->grpcont != GC_SPACE) {
+                                               return(YES);
+                                       }
+                                       if (prev_extends == YES) {
+                                               /* A syllable
+                                                * earlier in the measure
+                                                * is extending into the
+                                                * duration, so that counts.
+                                                */
+                                               return(YES);
+                                       }
+                               }
+                               else if (GT(new_cumm_time, end_time)) {
+                                       /* we're past the relevant syl(s) */
+                                       break;
+                               }
+                               cumm_time = new_cumm_time;
+                       }
+                       /* We've dealt with the only relevant syl list
+                        * in this measure. */
+                       break;
+               }
+       }
+
+       /* If there is a rest on voice 1, there is an implicit above
+        * lyric (albeit a pause in the above lyrics). Or at least it hardly
+        * makes sense to use voice 1 for below/between lyrics if voice 1
+        * is a rest but there is another voice below it that isn't.
+        */
+       cumm_time = Zero;
+       for (grp_p = mll_p->u.staff_p->groups_p[0]; grp_p != 0; grp_p = grp_p->next) {
+               new_cumm_time = radd(cumm_time, grp_p->fulltime);
+               if ( (GE(begin_time, cumm_time) &&
+                                       LT(begin_time, new_cumm_time)) ||
+                                       (GE(end_time, cumm_time) &&
+                                       LT(end_time, new_cumm_time)) ) {
+                       if (grp_p->grpcont == GC_REST) {
+                               return(YES);
+                       }
+               }
+               cumm_time = new_cumm_time;
+               if (GT(cumm_time, end_time)) {
+                       /* past the relevant groups */
+                       break;
+               }
+       }
+
+       /* If we got here, we weren't able to tell for
+        * sure if there is an above lyric, because there
+        * was either implicit or explicit space.
+        * Most likely there is no above lyric,
+        * but there is a slight possibility there is
+        * a lyric holding over into this time period
+        * via a melisma or tied notes from a previous measure.
+        * So we back up looking for such a lyric. If we find an above lyric
+        * that ends with an extender (underscore or dash),
+        * we declare that there is an above lyric.
+        * If we find one without an extender or back up
+        * all the way to the beginning of the song without
+        * finding any above lyric, there is no above lyric here.
+        * But we give up after 20 measures, figuring it's
+        * really unlikely for any melisma or tie to last
+        * that long, especially since any scorefeeds
+        * would cause a syllable to get added. The exact
+        * value of 20 is arbitrary; it just seems like plenty.
+        *
+        * prevgrpsyl doesn't work on syls, just groups,
+        * but by giving it staff_p->groups_p[0] (we
+        * know voice 1 will always exist), it will give
+        * us the mll_p for the staff we need.
+        */
+       for (n = 0; n < 20; n++) {
+               struct GRPSYL *last_non_space_p;
+
+               if (prevgrpsyl(mll_p->u.staff_p->groups_p[0],
+                                       &mll_p) == 0) {
+                       /* Got to beginning of song */
+                       return(NO);
+               }
+
+               grp_p = find_verse_place(mll_p->u.staff_p, verse, PL_ABOVE);
+
+               if (grp_p == 0) {
+                       /* No relevant lyrics in this meas */
+                       continue;
+               }
+
+               last_non_space_p = 0;
+               for (  ; grp_p != 0; grp_p = grp_p->next) {
+                       if (grp_p->grpcont != GC_SPACE) {
+                               last_non_space_p = grp_p;
+                       }
+               }
+               if (last_non_space_p != 0) {
+                       /* Found a preceeding syllable */
+                       return(has_extender(last_non_space_p->syl));
+               }
+       }
+       /* We've backed up far enough that the chances of there actually being
+        * an above lyrics are very, very slim. */
+       return(NO);
+}
+\f
+
+/* Returns YES if voice with index v1 is "above" voice v2; else NO */
+
+static int
+voice_is_above(v1, v2)
+
+int v1;
+int v2;
+
+{
+       /* Voice number is one more than its index, so convert index to
+        * number so it's easier to think about */
+       v1++;
+       v2++;
+
+       /* Voice 1 is above voice 2 and 3 */
+       if (v1 == 1) {
+               return(YES);
+       }
+
+       /* Voice 3 is the "middle" voice and thus "above" voice 2 */
+       if (v1 == 3 && v2 == 2) {
+               return(YES);
+       }
+
+       return(NO);
+}
+\f
+
+/* Given a STAFF, return the first GRPSYL in the syllable list for the given
+ * verse and place, if one exists. Otherwise return 0.
+ */
+
+static struct GRPSYL *
+find_verse_place(staff_p, verse, place)
+
+struct STAFF *staff_p;
+int verse;
+int place;
+
+{
+       int n;
+
+       for (n = 0; n < staff_p->nsyllists; n++) {
+               if (staff_p->sylplace[n] == place &&
+                               staff_p->syls_p[n]->vno == verse) {
+                       return(staff_p->syls_p[n]);
+               }
+       }
+       return(0);
+}
+\f
+
+/* Given a syl and related info, return the default time and place at which to
+ * end an underscore from that syl, for this measure. If there is a
+ * non-space syl later in the measure, this will be right before that syl,
+ * otherwise right before the bar line.
+ */
+
+static RATIONAL
+default_end(mll_p, syl_p, start_time, end_p)
+
+struct MAINLL *mll_p;          /* the STAFF pointing to the syl */
+struct GRPSYL *syl_p;          /* start looking from the syl */
+RATIONAL start_time;           /* syl is already this far into measure */
+double *end_p;                 /* X value at which to end underscore is
+                                * returned via this pointer */
+
+{
+       struct GRPSYL *grp_p;
+       RATIONAL end_time;      /* return value */
+
+       if (syl_p == 0) {
+               /* No syllable for current verse/place in current measure.
+                * Time signature may not be up to date, so add up the
+                * time of voice 1, which we know exists.
+                */
+               end_time = start_time;
+               for (grp_p = mll_p->u.staff_p->groups_p[0]; grp_p != 0;
+                                                       grp_p = grp_p->next) {
+                       end_time = radd(end_time, grp_p->fulltime);
+               }
+       }
+       else {
+               /* Go forward in the syl list, finding where the next non-space
+                * syllable is, if there is one in the current measure,
+                * otherwise find the end of the measure.
+                * Save the time and location of this.
+                */
+               end_time = radd(start_time, syl_p->fulltime);
+               for (grp_p = syl_p->next; grp_p != 0; grp_p = grp_p->next) {
+                       if (grp_p->grpcont == GC_SPACE) {
+                               /* Underscore continues through "space" syls */
+                               end_time = radd(end_time, grp_p->fulltime);
+                               continue;
+                       }
+                       else {
+                               /* We have found the syllable
+                                * at which the underscore
+                                * from the previous syllable ends */
+                               break;
+                       }
+               }
+       }
+
+       /* If a next syl was found, set end to near its west.
+        * Most likely, we will discover later we need to stop the underscore
+        * earlier than this, but if the user is using underscore in a strange
+        * way, like on a single long note rather than a melissma,
+        * we'll use this as the default place to end the underscore.*/
+       if (grp_p != 0) {
+               *end_p = grp_p->c[AW] - Stepsize;
+       }
+       else {
+               /* The ending syllable (if any) is not in the current measure.
+                * So for now we set the end to near the west of the bar line.
+                * Note that end_time will have added up to
+                * the full measure duration in this case.
+                */
+               for (  ; mll_p != 0; mll_p = mll_p->next) {
+                       if (mll_p->str == S_BAR) {
+                               *end_p = mll_p->u.bar_p->c[AW] - Stepsize;
+                               break;
+                       }
+               }
+               if (mll_p == 0) {
+                       pfatal("underscore: failed to find next bar");
+               }
+       }
+       return(end_time);
+}
+\f
+
+/* Given a bar, see if it is a bar that might force stopping an extender,
+ * and return YES, if so. If nextsyl_p_p is non-null, it also attempts
+ * to fill that in with a pointer to the next "logical" syllable.
+ * (Usually the next syllable, but at the end of a repeat it would
+ * be the first syllable in the repeated section).
+ * If it can't figure out the correct syllable, it fills in null.
+ */
+
+static int
+bar_ends_extender(bar_p, mll_p, staffno, verse, place, nextsyl_p_p)
+
+struct BAR *bar_p;
+struct MAINLL *mll_p;  /* points to a BAR  or CLEFSIG*/
+int staffno;
+int verse;
+int place;
+struct GRPSYL **nextsyl_p_p;   /* If this is non-zero, and we can deduce
+                                * the next "logical" syl, the pointed to value
+                                * will be updated to point to that next syl,
+                                * else will be zero. */
+               
+{
+       int bartype;
+
+       bartype = bar_p->bartype;
+       if (bartype == RESTART) {
+               /* We shouldn't continue an extender over a restart.
+                * The "next" logical measure is probably the
+                * target of a D.S. or a D.C.
+                * But we don't attempt to parse
+                * STUFF strings to know such things.
+                * So we say the extender ends here,
+                * but we don't know what the "next" measure is.
+                */
+               if (nextsyl_p_p != 0) {
+                       *nextsyl_p_p = 0;
+               }
+               return(YES);
+       }
+
+       if (bartype == REPEATEND || bartype == REPEATBOTH) {
+               if (nextsyl_p_p == 0) {
+                       return(YES);
+               }
+
+               /* This ends the extender. The next logical measure
+                * is at the beginning of the repeat. */
+               for (mll_p = mll_p->prev; mll_p != 0; mll_p = mll_p->prev) {
+                       if (mll_p->str == S_BAR &&
+                                       (mll_p->u.bar_p->bartype
+                                       == REPEATSTART ||
+                                       mll_p->u.bar_p->bartype
+                                       == REPEATBOTH)) {
+                               mll_p = mll_p->next;
+                               break;
+                       }
+               }
+               if (mll_p == 0) {
+                       /* repeatstart is implicit at beginning of song */
+                       mll_p = Mainllhc_p;
+               }
+               for (  ; mll_p != 0; mll_p = mll_p->next) {
+                       if (mll_p->str == S_BAR) {
+                               /* staff doesn't exist in this measure */
+                               *nextsyl_p_p = 0;
+                               return(YES);
+                       }
+                       if (mll_p->str == S_STAFF && mll_p->u.staff_p->staffno
+                                               == staffno) {
+                               *nextsyl_p_p = find_verse_place(
+                                               mll_p->u.staff_p, verse, place);
+                               return(YES);
+                       }
+               }
+       }
+
+       if (mll_p->u.bar_p->endingloc == STARTITEM) {
+               /* If this is the start of a second or subsequent ending,
+                * this ends the extender. This is the case if the previous
+                * bar was a STARTITEM on INITEM. But apparently there
+                * isn't a repeat ending here, or we would have hit the
+                * bartype check for that. So it is too hard to try to deduce
+                * the next logical syllable. */
+               for (mll_p = mll_p->prev; mll_p != 0; mll_p = mll_p->prev) {
+                       if (mll_p->str == S_BAR) {
+                               if (mll_p->u.bar_p->endingloc == STARTITEM ||
+                                               mll_p->u.bar_p->endingloc
+                                               == INITEM) {
+                                       if (nextsyl_p_p != 0) {
+                                               *nextsyl_p_p = 0;
+                                       }
+                                       return(YES);
+                               }
+                               break;
+                       }
+               }
+       }
+
+       return(NO);
+}
+\f
+
+/* Actually print an extender (dash or underscore) */
+
+static void
+pr_extender(ch, start, end, y, font, size)
+
+int ch;                /* dash or underscore */
+double start;  /* where to start printing */
+double end;    /* where to end printing */
+double y;      /* y coordinate */
+int font;      /* font to use for dash */
+int size;      /* size to use for dash */
+
+{
+       if (ch == '-') {
+               double dashwidth;
+               char dashstring[4];
+
+               dashwidth = width(font, size, '-');
+
+               /* generate the internal string format of a dash */
+               /* can't use dash_string function here since that also
+                * deals with ~ which is okay for stuff but not lyrics */
+               dashstring[0] = (char) font;
+               dashstring[1] = (char) size;
+               dashstring[2] = '-';
+               dashstring[3] = '\0';
+
+               if ( (end - start) < (15.0 * dashwidth) ) {
+                       /* not much space, so find midpoint of
+                        * available distance and put dash there */
+                       pr_string(start + ((end - start) / 2.0)
+                                       - (dashwidth / 2.0),
+                                       y, dashstring, J_LEFT,
+                                       (char *) 0, -1);
+               }
+               else {
+                       int numdashes;          /* how many dashes to print */
+                       double spacebetween;    /* between dashes */
+
+                       /* Lots of space, so will need to print multiple dashes.
+                        * Figure out how to spread out */
+                       numdashes = (int) ((end - start) / (8.0 * dashwidth));
+                       spacebetween = ((end - start) - (dashwidth * numdashes))
+                                       / numdashes;
+                       
+                       for (  ; numdashes > 0; numdashes--) {
+                               pr_string(start +
+                                       (numdashes - 0.5) * spacebetween
+                                       + ((numdashes - 1.0) * dashwidth),
+                                       y, dashstring, J_LEFT,
+                                       (char *) 0, -1);
+                       }
+               }
+       }
+       else {
+               /* if long enough to bother drawing underscore, draw it */
+               if (end - start > Stepsize) {
+                       /* Note: line width probably really ought to
+                        * be scaled based on the lyric size, but unless
+                        * somebody uses really huge or really tiny lyrics,
+                        * a normal line width looks good enough,
+                        * so we just go with that.
+                        */
+                       do_linetype(L_NORMAL);
+                       draw_line(start, y, end, y);
+               }
+       }
+}
+\f
+
+/* Return YES if last character of syllable is an underscore or dash,
+ * NO if it isn't.
+ */
+
+int
+has_extender(syl)
+
+char *syl;     /* the syllable to check */
+
+{
+       switch (last_char(syl)) {
+
+       case '_':
+       case '-':
+               return(YES);
+
+       default:
+               return(NO);
+       }
+}
+\f
+
+/* Return last character in a string.
+ * If last character is a music character,
+ * or the string is null, return null.
+ */
+
+int
+last_char(str)
+
+char *str;     /* return last character in this string */
+
+{
+       int font, size;
+       int ch;                 /* current character in string */
+       int last_font = FONT_UNKNOWN;   /* font of last character */
+       int last_ch = '\0';
+
+
+       if (str == (char *) 0) {
+               return('\0');
+       }
+
+       font = str[0];
+       size = str[1];
+
+       /* keep track of each character. When we hit
+        * end of string, return the last character we saw */
+       for ( str += 2; (ch = next_str_char(&str, &font, &size)) != 0;  ) {
+               last_font = font;
+               last_ch = ch;
+       }
+       /* music characters don't count */
+       if (IS_MUSIC_FONT(last_font)) {
+               return('\0');
+       }
+       return (last_ch & 0xff);
+}
+\f
+
+/* See if an underscore or dash will need to be carried to the following score.
+ * If so, add an appropriate "syllable" at the beginning of that score */
+
+void
+cont_extender(mll_p, sylplace, verseno)
+
+struct MAINLL *mll_p;  /* the syllable is hanging off of this STAFF */
+int sylplace;          /* PL_ABOVE, etc */
+int verseno;           /* verse number */
+
+{
+       struct GRPSYL *syl_p;   /* walk through GRPSYL list */
+       struct GRPSYL *last_non_space_p;
+       int last_ch;            /* last character of syllable */
+       int font;               /* of syllable */
+       int size;               /* of syllable */
+
+
+       if (mll_p->str != S_STAFF) {
+               pfatal("cont_extender called with wrong argument");
+       }
+
+       /* Find the actual syl grpsyl that is the last on the score */
+       syl_p = find_verse_place(mll_p->u.staff_p, verseno, sylplace);
+
+       if (syl_p == 0) {
+               pfatal("cont_extender called without any syllable");
+       }
+
+       /* Find the final non-space syllable in the list  */
+       last_non_space_p = 0;
+       for (  ; syl_p != 0; syl_p = syl_p->next) {
+               if (syl_p->grpcont != GC_SPACE) {
+                       last_non_space_p = syl_p;
+               }
+       }
+
+       if (last_non_space_p == 0) {
+               pfatal("cont_extender couldn't find non-space syllable");
+       }
+
+       last_ch = last_char(last_non_space_p->syl);
+       if (last_ch != '-' && last_ch != '_') {
+               pfatal("cont_extender called on syl without extender");
+       }
+
+       /* See if will carry over */
+       if (spread_extender(last_non_space_p, mll_p, verseno, sylplace, NO)
+                                                               == YES) {
+
+               /* determine proper font/size of
+                * carried over dash/underscore
+                * based on font/size at end of syllable */
+               end_fontsize(last_non_space_p->syl, &font, &size);
+
+               /* insert the syllable on next score */
+               insert_carryover_syllable(mll_p,
+                                       last_non_space_p->staffno, sylplace,
+                                       verseno,
+                                       (last_ch == '-' ? "-" : "_"),
+                                       font, size);
+       }
+}
+\f
+
+/* A dash or underscore needs to be carried over to the following score.
+ * Search forward for the appropriate STAFF. If there is already a lyric
+ * there for the sylplace and verseno, if its first syllable is a space,
+ * change it to a dash or underscore as appropriate. 
+ * If there is no lyric in that measure for the sylplace and verseno,
+ * insert a measure long syllable of the appropriate type.
+ * If there is no STAFF of the proper number after a FEED, assume we are
+ * at the end of the piece or of visibility of the staff, and do nothing.
+ * If there is already a syllable, leave it as is.
+ */
+
+
+static void
+insert_carryover_syllable(mll_p, staffno, sylplace, verseno, dash_or_underscore,
+               font, size)
+
+struct MAINLL *mll_p;  /* points to staff info */
+int staffno;           /* staff number */
+int sylplace;          /* PL_ABOVE, etc */
+int verseno;           /* verse number */
+char *dash_or_underscore;      /* "-" or "_" */
+int font;              /* font and size to use for dash or underscore */
+int size;
+
+{
+       struct STAFF *staff_p;  /* add syllable to this staff */
+       struct CHORD *chord_p;  /* chord syllables goes with */
+       int v;                  /* verse index */
+       float begin_x;          /* where to start carryover syllable */
+
+
+       /* search forward for FEED */
+       for (   ; mll_p != (struct MAINLL *) 0; mll_p = mll_p->next) {
+               if (IS_CLEFSIG_FEED(mll_p)) {
+                       break;
+               }
+       }
+
+       if (mll_p == (struct MAINLL *) 0) {
+               return;
+       }
+
+       /* The AE coordinates of syllable groups
+        * have already been set, but we need to have
+        * this one set for the underscore/dash syllable being added. So deduce
+        * where it should be using the pseudo-bar */
+       if ((mll_p = mll_p->next) == (struct MAINLL *) 0) {
+               return;
+       }
+       if (mll_p->str == S_CLEFSIG) {
+               begin_x = mll_p->u.clefsig_p->bar_p->c[AE] + STDPAD;
+       }
+       else {
+               /* setting begin_x is just to shut up compilers that erroneously
+                * think it could be used without being set. */
+               begin_x = 0.0;
+               pfatal("no clefsig after feed");
+       }
+
+       /* silence compilers that think chord_p might not be set */
+       chord_p = (struct CHORD *) 0;
+
+       /* search forward for STAFF of interest, and save CHORD info */
+       for ( mll_p = mll_p->next; mll_p != (struct MAINLL *) 0;
+                                                       mll_p = mll_p->next) {
+
+               if (mll_p->str == S_CHHEAD) {
+                       chord_p = mll_p->u.chhead_p->ch_p;
+               }
+               else if (mll_p->str == S_STAFF) {
+                       if (mll_p->u.staff_p->staffno == staffno) {
+                               break;
+                       }
+               }
+       }
+
+       /* see if has syllable of specified place and verse */
+       if (mll_p != (struct MAINLL *) 0) {
+
+               staff_p = mll_p->u.staff_p;
+               for (v = 0; v < staff_p->nsyllists; v++) {
+
+                       if (staff_p->sylplace[v] == sylplace &&
+                                       staff_p->syls_p[v]->vno == verseno) {
+
+                               /* are lyrics in this measure. See if first
+                                * syllable is a space. If so, replace with
+                                * a dash. Otherwise we are done */
+                               if (staff_p->syls_p[v]->syl == (char *) 0) {
+                                       staff_p->syls_p[v]->syl =
+                                               copy_string(dash_or_underscore,
+                                                               font, size);
+                                       /* no longer a "space" syllable */
+                                       staff_p->syls_p[v]->grpcont = GC_NOTES;
+                               }
+                               return;
+                       }
+               }
+
+               /* no lyrics in first measure on next score for this
+                * verse/place. Need to insert one */
+               add_syllable(staff_p, sylplace, verseno,
+                                       dash_or_underscore, font, size,
+                                       begin_x, chord_p);
+       }
+}
+\f
+
+/* Add a dash or underscore syllable to list of lyrics. Need to alloc new
+ * space for the sylplace and syls_p arrays, copy the existing data into
+ * them, adding the new syllable at the proper place (sorted by verseno),
+ * then free the old arrays */
+
+static void
+add_syllable(staff_p, sylplace, verseno, dash_or_underscore, font, size,
+               begin_x, chord_p)
+
+struct STAFF *staff_p;         /* add syllable to this staff */
+int sylplace;                  /* PL_ABOVE, etc */
+int verseno;
+char *dash_or_underscore;      /* "-" or "_" */
+int font;
+int size;
+double begin_x;                        /* where syllable is to start */
+struct CHORD *chord_p;         /* what chord to attach to */
+
+{
+       short *new_sylplace;            /* new, expanded sylplace array */
+       struct GRPSYL **new_syls_p;     /* new, expanded syls_p array */
+       int v;                          /* verse index */
+       int insert_index;               /* where to put in new arrays */
+       int inserted;                   /* 0 if haven't found where to insert
+                                        * yet, 1 if we have. This is then the
+                                        * difference between the index of the
+                                        * original arrays and where the copy
+                                        * goes in the new arrays. Since it's
+                                        * used in array subscript calculation
+                                        * we can't use YES and NO here */
+
+       
+       /* alloc arrays that are one larger than the current arrays */
+       MALLOCA(short, new_sylplace, staff_p->nsyllists + 1);
+       MALLOCA(struct GRPSYL *, new_syls_p, staff_p->nsyllists + 1);
+
+       /* now copy and insert */
+       insert_index = staff_p->nsyllists;
+       for (inserted = v = 0; v < staff_p->nsyllists; v++) {
+               if (insert_index > v && staff_p->syls_p[v]->vno > verseno) {
+                       /* insert here */
+                       insert_index = v;
+                       inserted = 1;
+               }
+
+               new_sylplace[v + inserted] = staff_p->sylplace[v];
+               new_syls_p[v + inserted] = staff_p->syls_p[v];
+       }
+
+       /* alloc and fill in the new GRPSYL */
+       new_sylplace[insert_index] = (short) sylplace;
+       new_syls_p[insert_index] = newGRPSYL(GS_SYLLABLE);
+       new_syls_p[insert_index]->syl = copy_string(dash_or_underscore,
+                                                       font, size);
+       new_syls_p[insert_index]->inputlineno = -1;
+       new_syls_p[insert_index]->basictime = -1;
+       new_syls_p[insert_index]->is_meas = YES;
+       new_syls_p[insert_index]->fulltime = Score.time;
+       new_syls_p[insert_index]->staffno = staff_p->staffno;
+       new_syls_p[insert_index]->vno = (short) verseno;
+       /* X coords of normal syllables already set, so have to set for
+        * this special syllable here */
+       new_syls_p[insert_index]->c[AE] = begin_x
+                               + strwidth(new_syls_p[insert_index]->syl);
+       new_syls_p[insert_index]->c[AW] = begin_x;
+       new_syls_p[insert_index]->c[AX] = begin_x;
+
+       /* now have one one list of syllables */
+       (staff_p->nsyllists)++;
+
+       /* free old arrays if non-null */
+       if (staff_p->sylplace != (short *) 0) {
+               FREE(staff_p->sylplace);
+       }
+       if (staff_p->syls_p != (struct GRPSYL **) 0) {
+               FREE(staff_p->syls_p);
+       }
+
+       /* now link up the new arrays */
+       staff_p->sylplace = new_sylplace;
+       staff_p->syls_p = new_syls_p;
+
+       /* add to appropriate chord */
+       stitch_syl_into_chord(chord_p, new_syls_p[insert_index]);
+}
+\f
+
+/* Given a syllable and chord to attach it to, attach it */
+/* Strictly speaking, this function probably isn't necessary, since I think
+ * all use of the CHORD struct has already been done before this function is
+ * called, but it's probably good to do anyway on general principles, in case
+ * some day the CHORDs are looked at later */
+
+static void
+stitch_syl_into_chord(chord_p, syl_gs_p)
+
+struct CHORD *chord_p;         /* add to this chord */
+struct GRPSYL *syl_gs_p;       /* add this syllable */
+
+{
+       struct GRPSYL *gs_p;    /* walk through chord */
+
+
+       /* go down chord list */
+       for (gs_p = chord_p->gs_p; gs_p->gs_p != (struct GRPSYL *) 0;
+                                                       gs_p = gs_p->gs_p) {
+
+               /* if next grpsyl in chord has staffno < staffno of syl to add,
+                * keep going */
+               if (gs_p->gs_p->staffno < syl_gs_p->staffno) {
+                       continue;
+               }
+
+               /* if next grpsyl in chord had staffno > staffno of syl to add,
+                * put it here */
+               if (gs_p->gs_p->staffno > syl_gs_p->staffno) {
+                       /* found where to insert */
+                       break;
+               }
+
+               /* If here, must be same staffno.
+                * Keep going until find syllable with larger vno. */
+               if (gs_p->gs_p->grpsyl == GS_GROUP) {
+                       continue;
+               }
+
+               if (gs_p->gs_p->vno > syl_gs_p->vno) {
+                       /* found where to insert */
+                       break;
+               }
+       }
+
+       /* insert syllable */
+       syl_gs_p->gs_p = gs_p->gs_p;
+       gs_p->gs_p = syl_gs_p;
+}
diff --git a/mup/mup/utils.c b/mup/mup/utils.c
new file mode 100644 (file)
index 0000000..3b70edc
--- /dev/null
@@ -0,0 +1,2024 @@
+
+/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* miscellaneous utility functions for music publication program, mostly
+ * for the print phase */
+
+#include "defines.h"
+#include "structs.h"
+#include "globals.h"
+
+static void grp_octave_adjust P((struct GRPSYL *gs_p, int adj, struct MAINLL *mll_p));
+static void set_height_blockhead P((struct BLOCKHEAD *blockhead_p, int context,
+               struct MAINLL *mll_p));
+static double coord_staffscale P((float *coord_array));
+
+\f
+
+/* set _cur location variable to specified value */
+
+void
+set_cur(x, y)
+
+float x, y;    /* x, east, and west get set to x value. y, north and south,
+                * get set to y value */
+
+{
+       float *cur_p;   /* coord array for _cur in current context */
+
+
+       /* look up _cur symbol and fill in the values */
+       cur_p = symval("_cur", (float **) 0);
+       cur_p[AX] = cur_p[AE] = cur_p[AW] = x;
+       cur_p[AY] = cur_p[AN] = cur_p[AS] = y;
+}
+\f
+
+/* set the values for location variable _win */
+
+void
+set_win(n, s, e, w)
+
+float n, s, e, w;      /* north, south, east, and west */
+
+{
+       float *window;  /* coordinate info for _win */
+
+
+       /* look up symbol and fill in values */
+       window = symval("_win", (float **) 0);
+       window[AN] = n;
+       window[AS] = s;
+       window[AE] = e;
+       window[AW] = w;
+       /* set x and y to midpoints of rectangle */
+       window[AY] = s + (n - s)/2.0;
+       window[AX] = w + (e - w)/2.0;
+}
+\f
+
+/* Return width of a bar line. Allow a couple pixels on either side
+ * of the actual line(s) [and dots]. Does not include user padding.
+ * Since an invisbar has no lines or dots, it has zero width.
+ */
+
+double
+width_barline(bar_p)
+
+struct BAR *bar_p;     /* return width of this bar line */
+
+{
+       if (bar_p == (struct BAR *) 0) {
+               return(0.0);
+       }
+
+       switch(bar_p->bartype) {
+
+       case SINGLEBAR:
+               return(7 * STDPAD);
+
+       case DOUBLEBAR:
+               return(9 * STDPAD);
+
+       case ENDBAR:
+               return(12 * STDPAD);
+
+       case REPEATSTART:
+       case REPEATEND:
+               return(16 * STDPAD);
+
+       case REPEATBOTH:
+               return(19 * STDPAD);
+
+       case RESTART:
+               return(2.0 * HALF_RESTART_WIDTH);
+
+       case INVISBAR:
+               return(0.0);
+
+       default:
+               pfatal("bad bar type");
+               /*NOTREACHED*/
+               break;
+       }
+
+       /*NOTREACHED*/
+       return(0.0);
+}
+\f
+
+/* Normally, we want some padding on both sides of a bar line,
+ * but at the end of a staff, we don't want right padding.
+ * This applies either if we are at the right
+ * margin or if the next bar is a restart.
+ * This function returns how much to adjust an end-of-score bar line
+ * eastward to make it at the right edge of the score.
+ */
+
+double
+eos_bar_adjust(bar_p)
+
+struct BAR *bar_p;     /* the bar to adjust */
+
+{
+       double halfbarwidth;
+
+       halfbarwidth = width_barline(bar_p) / 2.0;
+       switch (bar_p->bartype) {
+       case DOUBLEBAR:
+               return(halfbarwidth - STDPAD - (W_NORMAL / PPI / 2.0));
+       case SINGLEBAR:
+               return(halfbarwidth - (W_NORMAL / PPI / 2.0));
+       case REPEATEND:
+               return(halfbarwidth - (4.0 * STDPAD) - (W_WIDE / PPI /  2.0));
+       case ENDBAR:
+               return(halfbarwidth - (2.0 * STDPAD) - (W_WIDE / PPI / 2.0));
+       default:
+               break;
+       }
+       return(0.0);
+}
+\f
+
+/* width of clef, keysig, timesig */
+
+double
+width_clefsig(clefsig_p)
+
+struct CLEFSIG *clefsig_p;     /* return width of this clefsig */
+
+{
+       /* we just call the routine to print a clefsig, but with
+        * flag to tell it to not really print */
+       return(pr_clefsig((struct MAINLL *) 0, clefsig_p, NO));
+}
+\f
+
+/* translate clef name to clef output character */
+
+int
+clefchar(clef)
+
+int clef;      /* TREBLE, etc */
+
+{
+       switch(clef) {
+
+       case TREBLE:
+       case TREBLE_8:
+       case FRENCHVIOLIN:
+       case TREBLE_8A:
+               return(C_GCLEF);
+
+       case BASS:
+               return(C_FCLEF);
+
+       default:
+               /* everything else uses the C clef */
+               return(C_CCLEF);
+       }
+}
+\f
+
+/* Returns width of the given clef in inches in the default size.
+ * If is_small is YES, give width of the 3/4 sized one used in mid-score,
+ * rather than the full-sized used at beginning of line.
+ * Caller must adjust by staffscale if they need that.
+ * No padding is included beyond the padding of the clef music character
+ * itself, so caller needs to add any they deem appropriate for aesthetics.
+ */
+
+double
+clefwidth(clef, is_small)
+
+int clef;      /* TREBLE, BASS, ALTO, FRENCHVIOLIN, etc */
+int is_small;  /* If YES, assume mid-score clef, not full sized one */
+
+{
+       return(width(FONT_MUSIC, (is_small ? (3 * DFLT_SIZE) / 4 : DFLT_SIZE),
+                                               clefchar(clef)));
+}
+\f
+
+/* Returns where the given clef's baseline should be
+ * relative to the middle line of the staff, in stepsizes.
+ * (Above the middle line is positive, below is negative).
+ * If north_p and/or south_p are non-null, the relative north/south values
+ * of the clef are returned via the pointers. These will be relative
+ * to the middle line of the staff and  will be in inches
+ * in the default staffscale, using default size
+ * (unless is_small == YES, in which case it will be 3/4 size).
+ * Note that this should not be called with TABCLEF or NOCLEF.
+ */
+
+int
+clefvert(clef, is_small, north_p, south_p)
+
+int clef;      /* TREBLE, BASS, ALTO, FRENCHVIOLIN, etc */
+int is_small;  /* If YES, assume mid-score clef, not full sized one.
+                * Note that if both of the following arguments are null,
+                * this is_small argument's value is actually irrelevent. */
+float *north_p;        /* if non-null, relative north will be returned here */
+float *south_p;        /* if non-null, relative south will be returned here */
+
+{
+       int steps;      /* relative to middle line, to be returned */
+
+       switch(clef) {
+
+       case TREBLE:
+       case TREBLE_8:
+       case TREBLE_8A:
+               steps = -2;
+               break;
+
+       case FRENCHVIOLIN:
+       case SOPRANO:
+               steps = -4;
+               break;
+
+       case MEZZOSOPRANO:
+               steps = -2;
+               break;
+
+       case ALTO:
+               steps = 0;
+               break;
+
+       case TENOR:
+               steps = 2;
+               break;
+
+       case BARITONE:
+               steps = 4;
+               break;
+
+       case BASS:
+               steps = 2;
+               break;
+
+       case TABCLEF:
+       default:
+               pfatal("clefvert called with invalid clef %d", clef);
+               /*NOTREACHED*/
+               steps = 0;              /* shut up bogus compiler warning */
+               break;
+       }
+
+       /* If caller wants relative north/south values, calculate them */
+       if (north_p != 0 || south_p != 0) {
+               char muschar;   /* music character to print for the clef */
+               int clefsize;
+               char tr8str[4]; /* "8" of treble8 or 8treble */
+               float value;    /* of north or south */
+
+               muschar = clefchar(clef);
+               clefsize = (is_small ? (3 * DFLT_SIZE) / 4 : DFLT_SIZE);
+               tr8str[0] = FONT_TI;
+               tr8str[1] = 9;
+               tr8str[2] = '8';
+               tr8str[3] = '\0';
+               
+               if (north_p != 0) {
+                       value = (float) ascent(FONT_MUSIC, clefsize, muschar);
+                       if (clef == TREBLE_8A) {
+                               value += (float) strheight(tr8str);
+                       }
+                       *north_p = value + (float)(steps * STEPSIZE);
+               }
+
+               if (south_p != 0) {
+                       value = (float) descent(FONT_MUSIC, clefsize, muschar);
+                       if (clef == TREBLE_8) {
+                               value += (float) strheight(tr8str);
+                       }
+                       *south_p = -value + (float)(steps * STEPSIZE);
+               }
+       }
+
+       return(steps);
+}
+\f
+
+/* Given a BLOCKHEAD, fill in its height. BLOCKHEADs are a bit strange,
+ * in that they are in a separate coordinate space of unknown size.
+ * So we start out assuming it is infinitely thin. Then we check
+ * each string in the list and keep track of the lowest one, by
+ * pretending to go where it would be printed and adding the descent
+ * of the string. At the end, the height must be the page height minus the
+ * lowest, since upwards is positive */
+
+static void
+set_height_blockhead(blockhead_p, context, mll_p)
+
+struct BLOCKHEAD *blockhead_p; /* which block to get height of */
+int context;                   /* C_HEADER, etc */
+struct MAINLL *mll_p;          /* for getting margin overrides */
+
+{
+       float distance;         /* of headfoot from bottom of page */
+       float lowest;
+       float x_offset;         /* because of justification */
+       float yval;             /* y coordinate value */
+       struct PRINTDATA *pr_p; /* walk through list of things to print */
+       float block_width;      /* page width minus margins */
+       float s_descent;        /* strdescent() of the current string */
+       float extra;            /* how much farther the string descended
+                                * than would be expected of a normal,
+                                * single line. */
+       struct MAINLL *rightmargin_mll_p;       /* mll_p to use for
+                                * finding the right margin */
+
+
+       /* Set _win in this context to zero height at top margin */
+       Context = context;
+       rightmargin_mll_p = (mll_p ? mll_p->next : 0);
+       set_win_coord(blockhead_p->c);
+       set_win(PGHEIGHT - EFF_TOPMARGIN, PGHEIGHT - EFF_TOPMARGIN,
+               PGWIDTH - eff_rightmargin(rightmargin_mll_p),
+               eff_leftmargin(mll_p));
+       block_width = PGWIDTH - eff_rightmargin(rightmargin_mll_p) -
+                                                       eff_leftmargin(mll_p);
+
+       if (blockhead_p->printdata_p != (struct PRINTDATA *) 0) {
+               /* set current to left corner */
+               set_cur(eff_leftmargin((struct MAINLL *)0),
+                                               PGHEIGHT - EFF_TOPMARGIN);
+
+               distance = _Cur[AY];
+
+               /* Process each item in the list */
+               for (pr_p = blockhead_p->printdata_p;
+                               pr_p != (struct PRINTDATA *) 0;
+                               pr_p = pr_p->next) {
+
+                       /* If this is a paragraph,
+                        * split it into as many lines as needed. */
+                       if (pr_p->justifytype == J_JUSTPARA ||
+                                       pr_p->justifytype == J_RAGPARA) {
+                               pr_p->string = split_string(pr_p->string,
+                                                               block_width);
+                       }
+                       pr_p->width = strwidth(pr_p->string);
+                       /* stretch justified paragraphs to full width */
+                       if (pr_p->justifytype == J_JUSTPARA &&
+                                               pr_p->width < block_width) {
+                               pr_p->width = block_width;
+                       }
+
+                       /* adjust for justification */
+                       switch (pr_p->justifytype) {
+
+                       case J_RIGHT:
+                               x_offset = pr_p->width;
+                               break;
+
+                       case J_CENTER:
+                               x_offset = pr_p->width / 2.0;
+                               break;
+
+                       default:
+                               x_offset = 0.0;
+                               break;
+                       }
+
+                       /* set current to specified location */
+                       yval = inpc_y (&(pr_p->location), (char *) 0, -1);
+                       set_cur( inpc_x( &(pr_p->location), (char *) 0, -1 )
+                                                       - x_offset, yval);
+
+                       /* if user said to go off of south or y of _win,
+                        * change to equivalent offset off of north of _win.
+                        * because the  south and y could change */
+                       if (pr_p->location.vtype == AS ||
+                                       pr_p->location.vtype == AY) {
+                               if (pr_p->location.vert_p == blockhead_p->c) {
+                                       pr_p->location.vtype = AN;
+                                       pr_p->location.vsteps = (yval
+                                               - (PGHEIGHT - EFF_TOPMARGIN)
+                                               ) / STEPSIZE;
+                               }
+                       }
+
+                       /* determine lowest descent of current string */
+                       if (pr_p->isPostScript == YES) {
+                               s_descent = 0.0;
+                       }
+                       else {
+                               s_descent = strdescent(pr_p->string);
+                       }
+                       lowest = _Cur[AY] - s_descent;
+
+                       /* if lowest of anything found so far, note that */
+                       if ( lowest < distance) {
+                               distance = lowest;
+                               set_win(PGHEIGHT - EFF_TOPMARGIN, distance,
+                                       PGWIDTH - eff_rightmargin((struct MAINLL *)0),
+                                       eff_leftmargin((struct MAINLL *)0));
+                       }
+
+                       /* Set to end of string just "printed."
+                        * If the string when down farther than a single line
+                        * add in that extra.
+                        */
+                       if (pr_p->isPostScript == YES) {
+                               extra = 0.0;
+                       }
+                       else {
+                               extra = s_descent - fontdescent(pr_p->string[0],
+                                                       pr_p->string[1]);
+                               if (extra < 0.0) {
+                                       extra = 0.0;
+                               }
+                       }
+                       set_cur( _Cur[AX] + pr_p->width, _Cur[AY] - extra);
+               }
+
+               /* set height to lowest distance encountered */
+               blockhead_p->height = (PGHEIGHT - distance - EFF_TOPMARGIN);
+
+       }
+       else {
+               /* empty header/footer */
+               blockhead_p->height = 0.0;
+       }
+
+       /* if was a footer, now we can set the actual _win coordinates,
+        * by offsetting from bottom of page instead of top */
+       if ( (context == C_FOOTER) || (context == C_FOOT2) ) {
+               set_win(EFF_BOTMARGIN + blockhead_p->height, EFF_BOTMARGIN,
+                       PGWIDTH - eff_rightmargin((struct MAINLL *)0),
+                       eff_leftmargin((struct MAINLL *)0));
+       }
+       set_win_coord(0);
+}
+\f
+
+/* Calculate the height of all blocks, including headers and footers,
+ * and fill in the height field of the struct. */
+
+void
+calc_block_heights()
+
+{
+       struct MAINLL *mll_p;
+       double topheight = -1.0;        /* if > 0.0, is height of "top" */
+       double botheight = -1.0;        /* if > 0.0, is height of "bottom" */
+
+       debug(2, "calc_block_heights");
+
+       set_height_blockhead(&Header, C_HEADER, 0);
+       set_height_blockhead(&Footer, C_FOOTER, 0);
+       set_height_blockhead(&Header2, C_HEAD2, 0);
+       set_height_blockhead(&Footer2, C_FOOT2, 0);
+
+       /* set main _win to space within margins and header/footer
+        * for first page. */
+       Context = C_MUSIC;
+
+       /* set the size of _page */
+       _Page[AW] = _Page[AS] = 0.0;
+       _Page[AE] = PGWIDTH;
+       _Page[AN] = PGHEIGHT;
+       _Page[AX] = PGWIDTH / 2.0;
+       _Page[AY] = PGHEIGHT / 2.0;
+
+       /* now calculate top/bot and any other blocks in the main list */
+       initstructs();
+       for (mll_p = Mainllhc_p; mll_p != 0; mll_p = mll_p->next) {
+               if (mll_p->str == S_SSV) {
+                       /* keep margins up to date */
+                       asgnssv(mll_p->u.ssv_p);
+               }
+               else if (mll_p->str == S_FEED) {
+                       if (mll_p->u.feed_p->top_p != 0) {
+                               set_height_blockhead(mll_p->u.feed_p->top_p,
+                                               C_TOP, 0);
+                               if (topheight < 0.0) {
+                                       /* save for setting music _win */
+                                       topheight = mll_p->u.feed_p->top_p->height;
+                               }
+                       }
+                       if (mll_p->u.feed_p->top2_p != 0) {
+                               set_height_blockhead(mll_p->u.feed_p->top2_p,
+                                               C_TOP2, 0);
+                       }
+                       if (mll_p->u.feed_p->bot_p != 0) {
+                               set_height_blockhead(mll_p->u.feed_p->bot_p,
+                                               C_BOT, 0);
+                               if (botheight < 0.0) {
+                                       /* save for setting music _win */
+                                       botheight = mll_p->u.feed_p->bot_p->height;
+                               }
+                       }
+                       if (mll_p->u.feed_p->bot2_p != 0) {
+                               set_height_blockhead(mll_p->u.feed_p->bot2_p,
+                                               C_BOT2, 0);
+                       }
+               }
+               else if (mll_p->str == S_BLOCKHEAD) {
+                       set_height_blockhead(mll_p->u.blockhead_p,
+                                               C_BLOCK, mll_p);
+               }
+       }
+
+       set_win(PGHEIGHT - EFF_TOPMARGIN - Header.height
+                       - (topheight > 0.0 ? topheight : 0.0),
+                       EFF_BOTMARGIN + Footer.height
+                       + (botheight > 0.0 ? botheight : 0.0),
+                       PGWIDTH - eff_rightmargin((struct MAINLL *)0),
+                       eff_leftmargin((struct MAINLL *)0));
+}
+\f
+
+/* return number of beams or flags to use for a given basic time */
+
+int
+numbeams(btime)
+
+int btime;     /* basic time of note to be checked */
+
+{
+       int n;
+
+       /* no beams for long notes */
+       if (btime <= 4) {
+               return(0);
+       }
+
+       /* number of beams is equal to the number of bits 4 has to be
+        * shifted left in order to equal the given basic time */
+       for (n = 1; (4 << n) <= MAXBASICTIME; n++) {
+               if (btime == (4 << n)) {
+                       return(n);
+               }
+       }
+       return(0);
+}
+\f
+
+/* given an accidental (#, &, x, B, n) return its music character
+ * C_SHARP, etc of the proper size. If not a valid accidental,
+ * return 0 */
+
+int acc2char(acc)
+
+int acc;
+
+
+{
+       switch (acc) {
+
+       case '&':
+               return(C_FLAT);
+       case '#':
+               return(C_SHARP);
+       case 'n':
+               return(C_NAT);
+       case 'x':
+               return(C_DBLSHARP);
+       case 'B':
+               return(C_DBLFLAT);
+       default:
+               /* no accidental */
+               return(0);
+       }
+}
+\f
+
+/* get the absolute x and y values for an INPCOORD */
+/* get the proper one of the coordinates of the specified location, and
+ * add in any offsets */
+
+double
+inpc_x(inpcoord_p, fname, lineno)
+
+struct INPCOORD *inpcoord_p;   /* return the x value of this inpcoord */
+char *fname;                   /* filename, for error message */
+int lineno;                    /* for error message */
+
+{
+       double retval;
+
+
+       /* if hor_p is null, then this is an absolute coord, rather
+        * than relative to some variable */
+       if (inpcoord_p->hor_p == (float *) 0) {
+               if (inpcoord_p->counts != 0.0) {
+                       /* parser should have blocked this case */
+                       pfatal("can't specify time offset if no variable specified");
+               }
+               retval = inpcoord_p->hsteps * STEPSIZE;
+       }
+
+       /* X location is the x, e, or w value of the specified location
+        * variable, plus any offset plus any time offset */
+       else {
+               retval = inpcoord_p->hor_p [ inpcoord_p->htype ]
+               + inpcoord_p->hsteps * STEPSIZE
+               * coord_staffscale(inpcoord_p->hor_p)
+               + ( inpcoord_p->counts * inpcoord_p->hor_p [INCHPERWHOLE] /
+               (double) Score.timeden );
+       }
+
+       if (retval < 0.0 || retval > PGWIDTH) {
+               if (lineno > 0 && fname != (char *) 0) {
+                       l_warning(fname, lineno,
+                               "x value of %f is off the page", retval);
+               }
+       }
+       return(retval);
+}
+\f
+
+/* given an inpcoord, return its y coordinate */
+
+double
+inpc_y(inpcoord_p, fname, lineno)
+
+struct INPCOORD *inpcoord_p;   /* return y value of this inpcoord */
+char *fname;                   /* filename, for error message */
+int lineno;                    /* for error message */
+
+{
+       double retval;
+
+
+       /* if vert_p is null, then this is absolute rather than relative */
+       if ( inpcoord_p->vert_p == (float *) 0) {
+               retval = inpcoord_p->vsteps * STEPSIZE;
+       }
+
+       /* Y value is y, n, or s value of specified location variable
+        * plus any vertical offset plus any vsteps offset */
+       else {
+               retval = inpcoord_p->vert_p [ inpcoord_p->vtype ]
+                               + (inpcoord_p->vsteps * STEPSIZE
+                               * coord_staffscale(inpcoord_p->vert_p));
+       }
+
+       if (retval < 0.0 || retval > PGHEIGHT) {
+               if (lineno > 0 && fname != (char *) 0) {
+                       l_warning(fname, lineno,
+                               "y value of %f is off the page", retval);
+               }
+       }
+       return(retval);
+}
+\f
+
+/* Given an INPCOORD, return the appropriate staffscale value. Look
+ * up which staff, if any, the INPCOORD is associated with, and then get
+ * the staffscale out of the SSVs.
+ */
+
+static double
+coord_staffscale(coord_array)
+
+float *coord_array;
+
+{
+       struct COORD_INFO *coord_info_p;
+
+
+       /* figure out what staffscale value to use, based on
+        * which staff the coordinate is associated with */
+       if ((coord_info_p = find_coord(coord_array))
+                                       != (struct COORD_INFO *) 0 &&
+                                       coord_info_p->staffno != 0) {
+               return(svpath(coord_info_p->staffno, STAFFSCALE)->staffscale);
+       }
+       else {
+               return(1.0);
+       }
+}
+\f
+
+/* return the y coordinate of the end of a note stem */
+/* (the end farthest from the note head) */
+
+double
+find_y_stem(gs_p)
+
+struct GRPSYL *gs_p;   /* which group to get the stem of */
+
+{
+       /* error checks */
+       if (gs_p == (struct GRPSYL *) 0) {
+               pfatal("null group passed to find_y_stem");
+       }
+
+       if (gs_p->nnotes == 0) {
+               pfatal("group with no notes passed to find_y_stem (from line %d, grpcont %d)",
+                               gs_p->inputlineno, gs_p->grpcont);
+       }
+
+       /* if stem is up, start at bottom note, if down at top */
+       if (gs_p->stemdir == UP) {
+               return(gs_p->notelist[ gs_p->nnotes - 1].c[AY] + gs_p->stemlen);
+       }
+       else {
+               return(gs_p->notelist[0].c[AY] - gs_p->stemlen);
+       }
+}
+\f
+
+/* return x coordinate of a note stem */
+
+double
+find_x_stem(gs_p)
+
+struct GRPSYL *gs_p;   /* return x of stem of this group */
+
+{
+       double stem_adjust;     /* to overlap the note head */
+
+       if ( gs_p == (struct GRPSYL *) 0) {
+               pfatal("bad group passed to find_x_stem");
+       }
+
+       /* if called with something longer than a half note, then there
+        * is no real stem. We must be being called for printing slashes,
+        * so in that case, the x of the "stem" is the x of the group */
+       if (gs_p->basictime < 2) {
+               return(gs_p->c[AX]);
+       }
+
+       /* move stem by half of stem width so edge lines up with edge of note */
+       stem_adjust = W_NORMAL / PPI / 2.0;
+       if (gs_p->stemdir == UP) {
+               stem_adjust = -stem_adjust;
+       }
+       return(gs_p->c[AX] + (gs_p->stemx + stem_adjust) * Staffscale);
+}
+\f
+
+/* return the width of a key signature in inches */
+
+double
+width_keysig(sharps, naturals)
+
+int sharps;    /* how many sharps to print, or if negative, how many flats. */
+int naturals;  /* how many naturals to print for canceling previous key */
+
+{
+       double total_width = 0.0;
+       int size;
+
+       /* In keysig, things are drawn closer together than
+        * in other places, so to get the total width, we first
+        * multiply the width of the sharp, flat, or natural character
+        * by the number of times it is to be printed, then subtract off
+        * two points for each character printed, except for naturals,
+        * which are only jammed together by one point. */
+       
+       size = adj_size(DFLT_SIZE, Staffscale, (char *) 0, -1);
+       if (sharps >= 1) {
+               total_width = (width(FONT_MUSIC, size, C_SHARP) - 2.0 * Stdpad)
+                                       * sharps;
+       }
+       else if (sharps <= -1) {
+               /* negative sharps are flats */
+               total_width = (width(FONT_MUSIC, size, C_FLAT) - 2.0 * Stdpad)
+                                       * -sharps;
+       }
+       if (naturals != 0) {
+               total_width += (width(FONT_MUSIC, size, C_NAT) - Stdpad)
+                               * abs(naturals) + 3.0 * Stdpad;
+       }
+       return(total_width);
+}
+\f
+/*
+ * Name:        nextgrpsyl()
+ *
+ * Abstract:    Find next GRPSYL in this voice (same measure or not).
+ *
+ * Returns:     Pointer to the GRPSYL, or 0 if none.
+ *
+ * Description: This function, given a GRPSYL and the MLL structure it hangs
+ *             off of, returns the next GRPSYL in this voice, even if it's in
+ *             the next measure.  If it is in the next measure, *mll_p_p gets
+ *             updated.  But if that next measure is a second or later ending,
+ *             it's not considered to be a "next" measure, so return 0.
+ */
+
+struct GRPSYL *
+nextgrpsyl(gs_p, mll_p_p)
+
+struct GRPSYL *gs_p;    /* the given GRPSYL */
+struct MAINLL **mll_p_p; /* main linked list structure it is hanging off of */
+
+{
+       struct MAINLL *mll_p;   /* point at a MLL item */
+       int endingloc;          /* of the following barline */
+
+
+       /* if not at end of measure, just return the next GRPSYL */
+       if (gs_p->next != 0) {
+               return (gs_p->next);
+       }
+
+       mll_p = *mll_p_p;       /* save original MLL item */
+
+       /*
+        * We hit the end of the measure.  We need to find the first group in
+        * the next measure.  Find the coming bar line, then the corresponding
+        * staff in the next measure.  We do this in case the number of staffs
+        * changes back and forth; we don't want to find the staff in some
+        * later measure.
+        */
+       for (*mll_p_p = (*mll_p_p)->next; *mll_p_p != (struct MAINLL *) 0 &&
+                       (*mll_p_p)->str != S_BAR; *mll_p_p = (*mll_p_p)->next) {
+               ;
+       }
+
+       /* if we hit the end of the MLL, there is no next GRPSYL */
+       if (*mll_p_p == (struct MAINLL *) 0) {
+               return (struct GRPSYL *) 0;
+       }
+
+       /* we found a bar; get its endingloc */
+       endingloc = (*mll_p_p)->u.bar_p->endingloc;
+
+       /*
+        * Search for this staff in next measure.  If we find a pseudobar while
+        * doing this, save its endingloc in preference to the real bar's.
+        */
+       for (*mll_p_p = (*mll_p_p)->next; *mll_p_p != (struct MAINLL *) 0 &&
+                       (*mll_p_p)->str != S_BAR &&
+                       ((*mll_p_p)->str != S_STAFF ||
+                       (*mll_p_p)->u.staff_p->staffno != gs_p->staffno);
+                       *mll_p_p = (*mll_p_p)->next) {
+
+               if ((*mll_p_p)->str == S_CLEFSIG && 
+                   (*mll_p_p)->u.clefsig_p->bar_p != (struct BAR *) 0) {
+                       endingloc = (*mll_p_p)->u.clefsig_p->bar_p->endingloc;
+               }
+       }
+
+       /* if we hit the end or another bar before finding our staff, return */
+       if (*mll_p_p == (struct MAINLL *) 0 || (*mll_p_p)->str == S_BAR) {
+               return (struct GRPSYL *) 0;
+       }
+
+       /*
+        * We found the appropriate staff in the next measure.  But if we have
+        * crossed into a second or later ending, this bar doesn't really
+        * "follow" the previous bar, and we must return null.  So if endingloc
+        * shows this is the case, we must search backwards to find out if we
+        * were already in an ending.
+        */
+       if (endingloc == STARTITEM) {
+               while (mll_p != 0 && mll_p->str != S_BAR && (mll_p->str !=
+                               S_CLEFSIG || mll_p->u.clefsig_p->bar_p == 0))
+                       mll_p = mll_p->prev;
+
+               /* set endingloc of the previous measure */
+               if (mll_p == 0) {
+                       endingloc = NOITEM;
+               } else if (mll_p->str == S_BAR) {
+                       endingloc = mll_p->u.bar_p->endingloc;
+               } else {
+                       endingloc = mll_p->u.clefsig_p->bar_p->endingloc;
+               }
+
+               /* if we were already in an ending, there's no next GRPSYL */
+               if (endingloc == STARTITEM || endingloc == INITEM) {
+                       return (struct GRPSYL *) 0;
+               }
+       }
+
+       /* return the first GRPSYL of the appropriate voice */
+       return ((*mll_p_p)->u.staff_p->groups_p[ gs_p->vno - 1 ]);
+}
+\f
+/*
+ * Name:        prevgrpsyl()
+ *
+ * Abstract:    Find previous GRPSYL in this voice (same measure or not).
+ *
+ * Returns:     Pointer to the GRPSYL, or 0 if none.
+ *
+ * Description: This function, given a GRPSYL and the MLL structure it hangs
+ *             off of, returns the previous GRPSYL in this voice, even if it's
+ *             in an earlier measure.  If we are at the start of an ending,
+ *             it skips over any previous ending and goes to the measure
+ *             preceding the first ending.  If the resulting GRPSYL is in a
+ *             previous measure, *mll_p_p gets updated.
+ */
+
+struct GRPSYL *
+prevgrpsyl(gs_p, mll_p_p)
+
+struct GRPSYL *gs_p;    /* the given GRPSYL */
+struct MAINLL **mll_p_p; /* main linked list structure it is hanging off of */
+
+{
+       struct GRPSYL *gs2_p;   /* for looping through prev measure's list */
+       struct BAR *bar_p;      /* point at a bar line */
+       struct MAINLL *mll_p;   /* point at a MLL item */
+       int pseudo;             /* was the last thing we saw a pseudobar? */
+       int barcount;           /* how many bar lines we looped backward thru*/
+       int safmoae;            /* "started at first measure of an ending" */
+
+
+       /* if not at start of measure, just return the previous GRPSYL */
+       if (gs_p->prev != (struct GRPSYL *) 0) {
+               return (gs_p->prev);
+       }
+
+       /*
+        * We hit the start of the measure.  Loop backwards through the MLL
+        * looking for the bar line at the start of the "previous" measure.
+        * If our measure is not the first measure of an ending, this is
+        * simply the bar at the start of the previous measure.  Otherwise,
+        * this is the bar before the measure before the first ending.  Also
+        * handle the cases where we fall off the start of the MLL.
+        */
+       bar_p = 0;
+       mll_p = *mll_p_p;
+       pseudo = NO;
+       barcount = 0;
+       safmoae = NO;
+       do {
+               /* find preceding bar or pseudobar, if either exists */
+               for (mll_p = mll_p->prev; mll_p != (struct MAINLL *) 0 &&
+                               mll_p->str != S_BAR &&
+                               (mll_p->str != S_CLEFSIG ||
+                               mll_p->u.clefsig_p->bar_p == 0);
+                               mll_p = mll_p->prev) {
+                       ;
+               }
+
+               /*
+                * If we hit the start of the MLL without crossing any bars, or
+                * just a pseudobar, there is no preceding GRPSYL, so return 0.
+                * (Depending on who is calling this function, the pseudobar at
+                * the start of the song may or may not exist.)  Otherwise, it
+                * must be that we started in the second measure, or an ending
+                * that we skipped over started there.  Point at the start of
+                * the MLL, and get out of the loop.  Note that we can't still
+                * be in the process of skipping over endings:  no ending can
+                * start at the first measure of the song, because there is no
+                * bar line there.
+                */
+               if (mll_p == 0) {
+                       if (barcount == 0 || (barcount == 1 && pseudo == YES)) {
+                               return (struct GRPSYL *) 0;
+                       }
+                       mll_p = Mainllhc_p;
+                       break;
+               }
+
+               barcount++;
+
+               /*
+                * Point bar_p at the relevant bar/pseudobar for checking the
+                * endingloc.  If this is a pseudobar, it's relevant.  If this
+                * is a bar, it's relevant only if it's the first thing we've
+                * seen, or the thing we saw last was not a pseudobar.  That
+                * is, the endingloc of the bar at the end of a score is to be
+                * ignored, because the true endingloc has been moved to the
+                * next score's pseudobar.  We need to worry about this because
+                * of the case where a second ending starts at the start of the
+                * new score (STARTITEM) and the previous score ends with
+                * ENDITEM, which should be ignored.
+                */
+               if (mll_p->str == S_BAR) {
+                       if (bar_p == 0 || pseudo == NO) {
+                               bar_p = mll_p->u.bar_p;
+                       }
+                       if (pseudo == YES) {
+                               barcount--;     /* forget this bar */
+                               pseudo = NO;
+                       }
+               } else {
+                       bar_p = mll_p->u.clefsig_p->bar_p;
+                       pseudo = YES;
+               }
+
+               /*
+                * If this is the first measure we're backing into, and this
+                * first bar we hit shows that our GRPSYL was in the first
+                * measure of an ending, remember that fact.
+                */
+               if (barcount == 1 && bar_p->endingloc == STARTITEM) {
+                       safmoae = YES;
+               }
+
+       /*
+        * Get out, when, in the normal case, we've hit the second meaningful
+        * bar; or in the safmoae case, we've skipped back to the back before
+        * the first bar of the first ending.
+        */
+       } while (! ( (safmoae == NO && barcount == 2) || (safmoae == YES &&
+               (bar_p->endingloc == NOITEM || bar_p->endingloc == ENDITEM))));
+
+       /*
+        * Search forward to the next bar, which is the bar before which we
+        * want to find a GRPSYL.  We don't care about pseudobars here.
+        */
+       for (mll_p = mll_p->next; mll_p->str != S_BAR; mll_p = mll_p->next) {
+               ;
+       }
+
+       /*
+        * Now mll_p is the bar before which we want to find the GRPSYL.
+        * Find the corresponding staff in the previous measure.  We do
+        * this in case the number of staffs changes back and forth; we
+        * don't want to find the staff in some earlier measure.
+        */
+
+       /* search for this staff in previous measure */
+       for (*mll_p_p = mll_p->prev; *mll_p_p != (struct MAINLL *) 0 &&
+                       (*mll_p_p)->str != S_BAR &&
+                       ((*mll_p_p)->str != S_STAFF ||
+                       (*mll_p_p)->u.staff_p->staffno != gs_p->staffno);
+                       *mll_p_p = (*mll_p_p)->prev) {
+               ;
+       }
+
+       /* if we hit the start or another bar before finding our staff, return*/
+       if (*mll_p_p == (struct MAINLL *) 0 || (*mll_p_p)->str == S_BAR) {
+               return (struct GRPSYL *) 0;
+       }
+
+       /* return the last GRPSYL of the appropriate voice */
+       gs2_p = (*mll_p_p)->u.staff_p->groups_p[ gs_p->vno - 1 ];
+       if (gs2_p == (struct GRPSYL *) 0) {
+               return(gs2_p);
+       }
+       while (gs2_p->next != (struct GRPSYL *) 0) {
+               gs2_p = gs2_p->next;
+       }
+
+       return (gs2_p);
+}
+\f
+
+/* if user asked for octave marks, we need to transpose any affected notes
+ * by the appropriate number of octaves. This should be called for a measure
+ * at a time. It will handle all the octave marks
+ * within the measure for the current voice, both those carrying over into
+ * this measure and ones starting there. If an octave mark spills beyond
+ * the end of the measure, the amount to transpose and how long to do so
+ * is saved away for use in the next measure. Checks for things becoming
+ * out of range because of the transposition are not done here; caller
+ * must do that if they care. */
+
+void
+octave_transpose(staff_p, mll_p, vno, normdir)
+
+struct STAFF *staff_p;
+struct MAINLL *mll_p;  /* staff_p connects here, used for bends */
+int vno;               /* voice number */
+int normdir;           /* YES if should move note pitches up for above and
+                        * down for below. NO if the inverse should be done */
+
+{
+       struct GRPSYL *gs_p;    /* walk through list of GRPSYLs */
+       struct GRPSYL *gs_roll_p;       /* group generated for a roll */
+       struct STUFF *stuff_p;  /* to look for octave marks */
+       RATIONAL total_time;    /* accumulated time in measure */
+       float float_total_time; /* for comparing with count */
+       int carry_adjust;       /* adjust to carry into next measure */
+       int carry_bars;         /* how many bars to carry over */
+       float carry_counts;     /* how many counts in final bar */
+       int staffno;            /* which staff we are working with */
+
+
+       staffno = staff_p->staffno;
+       carry_adjust = carry_bars = 0;
+       carry_counts = 0.0;
+
+       /* if currently have octave mark */
+       if (Octave_adjust[staffno] != 0) {
+
+               /* if bar count > 0, transpose all notes in measure */
+               if (--(Octave_bars[staffno]) > 0) {
+
+                       for (gs_p = staff_p->groups_p[vno];
+                                       gs_p != (struct GRPSYL *) 0;
+                                       gs_p = gs_p->next) {
+
+                               grp_octave_adjust(gs_p, Octave_adjust[staffno], mll_p);
+                       }
+               }
+
+               /* otherwise just transpose until specified time */
+               else {
+                       total_time = Zero;
+                       for (gs_p = staff_p->groups_p[vno];
+                                               gs_p != (struct GRPSYL *) 0;
+                                               gs_p = gs_p->next) {
+
+                               float_total_time = RAT2FLOAT(total_time)
+                                               * Score.timeden + 1.0;
+
+                               if (float_total_time <= Octave_count[staffno]) {
+                                       grp_octave_adjust(gs_p,
+                                               Octave_adjust[staffno], mll_p);
+                               }
+                               else {
+                                       break;
+                               }
+                               total_time = radd(total_time, gs_p->fulltime);
+                       }
+
+                       Octave_adjust[staffno] = 0;
+               }
+       }
+
+       /* go through stuff list. If any octave marks, transpose appropriate
+        * notes in this measure. If extends to next measure, remember for
+        * next time. If user put in more than one octave
+        * mark going over the bar, catch that. If there are overlaps within
+        * a measure, it seems like too much trouble to catch this, so just
+        * transpose as often as they say and let them figure out why it
+        * sounds funny. */
+       for (stuff_p = staff_p->stuff_p; stuff_p != (struct STUFF *) 0;
+                                               stuff_p = stuff_p->next) {
+
+               if (stuff_p->stuff_type == ST_OCTAVE) {
+
+                       if (Octave_adjust[staffno] != 0) {
+                               l_warning(stuff_p->inputfile,
+                                               stuff_p->inputlineno,
+                                               "overlapping octave marks");
+                       }
+
+                       /* figure out how many octaves to move */
+                       Octave_adjust[staffno] = parse_octave(stuff_p->string,
+                                       stuff_p->place, stuff_p->inputfile,
+                                       stuff_p->inputlineno);
+
+                       /* if this call is for inverse transpostion, adjust
+                        * to go in opposite direction */
+                       if (normdir == NO) {
+                               Octave_adjust[staffno] *= -1;
+                       }
+
+                       /* figure out to which count the octave mark applies
+                        * within this measure. */
+                       Octave_count[staffno] = (stuff_p->end.bars > 0 ? 1.0 +
+                                       RAT2FLOAT(Score.time) * Score.timeden
+                                       : stuff_p->end.count);
+                       
+                       total_time = Zero;
+                       for (gs_p = staff_p->groups_p[vno];
+                                               gs_p != (struct GRPSYL *) 0;
+                                               gs_p = gs_p->next) {
+
+                               float_total_time = RAT2FLOAT(total_time) *
+                                               Score.timeden + 1.0;
+                               if (float_total_time >= stuff_p->start.count) {
+
+                                       if (float_total_time <=
+                                                       Octave_count[staffno]) {
+                                               /* is within the mark, so move */
+                                               grp_octave_adjust(gs_p,
+                                                       Octave_adjust[staffno],
+                                                       mll_p);
+                                       }
+
+                                       /* special case. If we have a rolled
+                                        * chord, and user specified
+                                        * an octave mark without a til clause,
+                                        * all the chords that got
+                                        * generated internally to cause the
+                                        * "roll" effect need to be transposed,
+                                        * even though they have been moved
+                                        * in time */
+                                       if (float_total_time == stuff_p->start.count
+                                               && stuff_p->end.bars == 0
+                                               && stuff_p->end.count == 0.0
+                                               && gs_p->inputlineno < 0) {
+
+                                           /* adjust all the groups generated
+                                            * to create the roll effect */
+                                           for (gs_roll_p = gs_p->next;
+                                                       gs_roll_p != (struct GRPSYL *) 0;
+                                                       gs_roll_p = gs_roll_p->next) {
+
+                                                   grp_octave_adjust(gs_roll_p,
+                                                       Octave_adjust[staffno],
+                                                       mll_p);
+                                                   /* stop when we hit the
+                                                    * end of the roll */
+                                                   if (gs_roll_p->inputlineno > 0) {
+                                                       break;
+                                                   }
+                                           }
+                                       }
+                               }
+
+                               total_time = radd(total_time, gs_p->fulltime);
+                       }
+
+                       /* if octave mark carried over into subsequent
+                        * measure(s), make a note of that for future use */
+                       if (stuff_p->end.bars > 0) {
+                               if (carry_adjust != 0) {
+                                       l_warning(stuff_p->inputfile,
+                                               stuff_p->inputlineno,
+                                               "overlapping octave marks");
+                               }
+                               carry_bars = stuff_p->end.bars;
+                               carry_counts = stuff_p->end.count;
+                               carry_adjust = Octave_adjust[staffno];
+                       }
+
+                       Octave_adjust[staffno] = 0;
+               }
+       }
+
+       /* above octave marks that were put in on the same input line will
+        * be in backwards order (because above stuff needs to be that
+        * way to pile on correctly). However, if the last octave in the
+        * stuff input line carried over a bar line, we would see it
+        * first and lose the carryover information when handling the earlier
+        * octave marks (which are later in the stuff list). That's why the
+        * carryover information had to be saved. Now we can assign it */
+       if (carry_bars > 0) {
+               Octave_adjust[staffno] = carry_adjust;
+               Octave_bars[staffno] = carry_bars;
+               Octave_count[staffno] = carry_counts;
+       }
+}
+\f
+
+/* transpose all the notes in a group by the specified octave adjustment */
+
+static void
+grp_octave_adjust(gs_p, adj, mll_p)
+
+struct GRPSYL *gs_p;           /* adjust this group */
+int adj;                       /* add this (potentially negative) value to
+                                * each notelist octave */
+struct MAINLL *mll_p;          /* STAFF of gs_p for finding prev grp for bends */
+
+{
+       register int n;
+       struct GRPSYL *prevgs_p;        /* previous group, for bends */
+
+       for (n = 0; n < gs_p->nnotes; n++) {
+               gs_p->notelist[n].octave += adj;
+       }
+       /* Transpose any bends going to this group */
+       prevgs_p = prevgrpsyl(gs_p, &mll_p);
+       if (prevgs_p == 0) {
+               /* If there is no previous group, nothing to transpose. */
+               return;
+       }
+       for (n = 0; n < prevgs_p->nnotes; n++) {
+               if (prevgs_p->notelist[n].is_bend == YES) {
+                       /* Note that when is_bend is YES, nslurto will always
+                        * be 1, but we loop through as many as there are
+                        * (all 1 of them!), to not be dependent
+                        * on that piece of inside information.
+                        */
+                       int s;
+                       for (s = 0; s < prevgs_p->notelist[n].nslurto; s++) {
+                               prevgs_p->notelist[n].slurtolist[s].octave += adj;
+                       }
+               }
+       }
+}
+\f
+
+/* Given a group and note value, return the effective accidental
+ * on that note, (-2 to +2) taking key signature
+ * and previous accidentals into account.
+ * There are certain pathological cases that this doesn't
+ * handle right, notably if the user changes the key signature at a bar
+ * line, and the note in question is tied to from before that bar line,
+ * and the key signature change is such that it changes what the accidental
+ * should be. But it should handle anything less convoluted than that.
+ */
+
+int
+eff_acc(gs_p, note_p, mll_p)
+
+struct GRPSYL *gs_p;   /* get effective accidental for note in this group */
+struct NOTE *note_p;   /* get for this note */
+struct MAINLL *mll_p;  /* main list item that points to gs_p */
+
+{
+       struct MAINLL *orig_mll_p;
+       struct GRPSYL *pgs_p;           /* previous group */
+       int n;
+       int tie_break;                  /* YES if there has been a break
+                                        * in the chain of notes
+                                        * tied together */
+       int eff_accidental;             /* effective accidental so far */
+
+
+       /* if this group has an explicit accidental, that's also the
+        * effective accidental */
+       if (note_p->accidental != '\0') {
+               /* note: the - 2 is to adjust for natural being element 2
+                * of the Circle array */
+               return( (int) (strchr(Acclets, note_p->accidental) - Acclets) - 2);
+       }
+
+       /* remember which measure we are starting in, so we know when we cross
+        * a bar line */
+       orig_mll_p = mll_p;
+
+       /* init to assume we might have ties */
+       tie_break = NO;
+
+       /* if all else fails, we will use the accidental from the key sig */
+       eff_accidental = acc_from_keysig(note_p->letter, gs_p->staffno,
+                                               mll_p);
+
+       /* back up until we figure out the effective accidental */
+       for (pgs_p = prevgrpsyl(gs_p, &mll_p); pgs_p != (struct GRPSYL *) 0;
+                               pgs_p = prevgrpsyl(pgs_p, &mll_p)) {
+
+
+               /* see if this group contains the note in question */
+               for (n = 0; n < pgs_p->nnotes; n++) {
+                       if (pgs_p->notelist[n].letter == note_p->letter &&
+                                               pgs_p->notelist[n].octave
+                                               == note_p->octave) {
+                               /* it does have the note: it's notelist[n] */
+                               break;
+                       }
+               }
+
+               /* see if this is end of ties to the note, working backwards */
+               if (n == pgs_p->nnotes) {
+                       /* no note at all, so clearly no tied note */
+                       tie_break = YES;
+               }
+               else if (pgs_p->notelist[n].tie == NO) {
+                       /* end of chain of tied notes */
+                       tie_break = YES;
+               }
+
+               if (orig_mll_p == mll_p) {
+                       /* we're still in same measure. If we have a matching
+                        * note, see if it has an accidental */
+                       if (n < pgs_p->nnotes) {
+                               if (pgs_p->notelist[n].accidental != '\0') {
+                                       return( (int) (strchr(Acclets,
+                                               pgs_p->notelist[n].accidental)
+                                               - Acclets) - 2);
+                               }
+                       }
+
+                       /* have to keep backing up */
+               }
+               else {
+                       /* Now in previous measure. If no matching note,
+                        * we use the effective accidental found so far */
+                       if (n == pgs_p->nnotes) {
+                               return(eff_accidental);
+                       }
+
+                       /* if the note isn't tied, then use the most recent
+                        * effective accidental we found */
+                       if (pgs_p->notelist[n].tie == NO || tie_break == YES) {
+                               return(eff_accidental);
+                       }
+
+                       /* if there is an accidental on this note,
+                        * then it's the one we're looking for. */
+                       if (pgs_p->notelist[n].accidental != '\0') {
+                               return( (int) (strchr(Acclets,
+                                       pgs_p->notelist[n].accidental) -
+                                       Acclets - 2));
+                       }
+
+                       /* need to continue working backwards toward
+                        * the beginning of this new measure */
+                       orig_mll_p = mll_p;
+                       eff_accidental = acc_from_keysig(note_p->letter,
+                                       gs_p->staffno, mll_p);
+               }
+       }
+
+       /* backed up all the way to the beginning of the song, use last we
+        * found */
+       return(eff_accidental);
+}
+\f
+
+/* given a letter and staff number, return 1 if the pitch with that letter
+ * gets a sharps according to the key signature,  or -1 if it gets a flat,
+ * or 0 if it gets neither. */
+
+int
+acc_from_keysig(letter, staffno, mll_p)
+
+int letter;            /* which pitch */
+int staffno;           /* which staff to get the key signature from */
+struct MAINLL *mll_p;  /* pitch is from the staff hanging off of here */
+
+{
+       int index;      /* where the letter is in circle of fifths */
+       int sharps;     /* sharps in key sig for the given staff */
+       struct SSV *ssv_p;      /* to get key signature */
+
+
+       /* find letter in circle of fifths */
+       index = strchr(Circle, letter) - Circle + 1;
+
+       /* get key signature. Unfortunately, the SSVs may not be
+        * accurate at the time we are called, so we have to search
+        * backwards in the main list for the most recent relevant
+        * key signature change. */
+       for (sharps = 0; mll_p != (struct MAINLL *) 0; mll_p = mll_p->prev) {
+               if (mll_p->str == S_SSV) {
+                       ssv_p = mll_p->u.ssv_p;
+
+                       /* does this SSV have a key signature change in it? */
+                       if (ssv_p->used[SHARPS] == YES) {
+                               if (ssv_p->context == C_STAFF &&
+                                               ssv_p->staffno == staffno) {
+                                       /* aha! found the most recent
+                                        * key signature
+                                        * for the relevant staff */
+                                       sharps = ssv_p->sharps;
+                                       break;
+                               }
+                               else if (ssv_p->context == C_SCORE) {
+                                       /* this will be the score-wide default
+                                        * if we don't find a staff-specific
+                                        * value, so save this as our default */
+                                       sharps = ssv_p->sharps;
+                               }
+                       }
+               }
+       }
+
+       if (sharps > 0) {
+               /* key signature is one with sharps */
+               if (index <= sharps) {
+                       /* this letter gets a sharp */
+                       return(1);
+               }
+       }
+       else if (sharps < 0) {
+               /* key signature is one with flats */
+               if ( (8 - index) <= -sharps) {
+                       /* this letter gets a flat */
+                       return(-1);
+               }
+       }
+
+       /* must be a natural */
+       return(0);
+}
+
+/* Set Staffscale, Stepsize, Stdpad, and other similar values based on the
+ * specified staff number. If staff of 0 is given, set Staffscale to the
+ * score value
+ */
+
+void
+set_staffscale(s)
+
+int s;                 /* which staff */
+
+{
+       Staffscale = (s == 0 ? Score.staffscale
+                                       : svpath(s, STAFFSCALE)->staffscale);
+       Stepsize = STEPSIZE * Staffscale;
+       Stdpad = STDPAD * Staffscale;
+       Flagsep = FLAGSEP * Staffscale;
+       Smflagsep = SMFLAGSEP * Staffscale;
+       Tupheight = TUPHEIGHT * Staffscale;
+}
+\f
+
+/* Determine the space between lines of a grid. A staff of 0 means use
+ * the score size. A staff of -1 means ATEND. Return distance in inches. */
+
+double
+gridspace(staff)
+
+int staff;
+
+{
+       double space;
+
+       if (staff == -1) {
+               space = ATEND_GS * STEPSIZE * Score.gridscale;
+       }
+       else {
+               space = WHEREUSED_GS * STEPSIZE
+                               * svpath(staff, STAFFSCALE)->staffscale
+                               * svpath(staff, GRIDSCALE)->gridscale;
+       }
+       return(space);
+}
+\f
+
+/* Given a grid, return (via pointer) the items needed for the PostScript
+ * plus the top fret.
+ */
+
+void
+gridinfo(grid_p, staff, frets_p, fretnum_p, numvert_p, topfret_p)
+
+struct GRID *grid_p;
+int staff;     /* 0 == score, -1 = ATEND, otherwise the staff number */
+int *frets_p;  /* how many frets high the grid should be */
+int *fretnum_p;        /* the N of "N fr" */
+int *numvert_p;        /* how many frets from the top to print the "N fr" */
+int *topfret_p; /* the fret number of the top line of the grid */
+
+{
+       int minfret, maxfret;   /* smallest and largest frets used */
+       int rightmost_fret;     /* the 'N' of 'N fr" if any */
+       int right_stringnum;    /* string number having rightmost_fret */
+       int mincurvefret;       /* smallest fret number inside curve */
+       int has_o;              /* if there are 'o' items */
+       int gridfret;
+       int s;
+
+
+       /* Go through strings finding min/max/rightmost */
+       minfret = MAXFRET + 1;
+       maxfret = MINFRET - 1;
+       mincurvefret = MAXFRET + 1;
+       has_o = NO;
+       rightmost_fret = right_stringnum = 0;  /* avoids bogus warnings */
+       for (s = 0; s < grid_p->numstr; s++) {
+               /* x o and - things don't count */
+               if (grid_p->positions[s] > 0) {
+                       if (grid_p->positions[s] < minfret) {
+                               minfret = grid_p->positions[s];
+                       }
+                       if (grid_p->positions[s] > maxfret) {
+                               maxfret = grid_p->positions[s];
+                       }
+                       rightmost_fret = grid_p->positions[s];
+                       right_stringnum = s;
+
+                       /* find smallest fret inside curve */
+                       if (grid_p->curvel != 0 && s >= grid_p->curvel - 1 &&
+                                       s <= grid_p->curver - 1 &&
+                                       grid_p->positions[s] < mincurvefret) {
+                               mincurvefret = grid_p->positions[s];
+                       }
+               }
+               else if (grid_p->positions[s] == 0) {
+                       has_o = YES;
+               }
+       }
+
+       /* set the values to defaults, then calculate actuals if needed */
+       *frets_p = 5;
+       *fretnum_p = 0;
+       *numvert_p = 0;
+       if (minfret <= MAXFRET) {
+               /* at least one fret was used */
+
+               /* figure out how many frets tall to make the grid */
+               *frets_p = maxfret + 1;
+
+               /* see if gridfret is set */
+               gridfret = svpath(staff == -1 ? 0 : staff, GRIDFRET)->gridfret;
+               if (gridfret != NOGRIDFRET) {
+                       /* gridfret is set; see if all frets larger than that.
+                        * But we only use "N fr" if there are no 'o' items. */
+                       if (has_o == NO && minfret >= gridfret) {
+                               /* We will need "N fr"
+                                * Usually we use the rightmost string
+                                * that has a fret on it,
+                                * but there is one special case:
+                                * if the curve comes at least that far right,
+                                * and the minimum fret inside the curve is
+                                * smaller than the rightmost_fret, then we
+                                * put the "N fr" by the curve minimum.
+                                */
+                               if (grid_p->curver - 1 >= right_stringnum
+                                               && mincurvefret < rightmost_fret) {
+                                       rightmost_fret = mincurvefret;
+                               }
+                               *fretnum_p = rightmost_fret;
+                               *numvert_p = rightmost_fret - minfret + 1;
+                               *frets_p = maxfret - minfret + 2;
+                       }
+               }
+
+               if (*frets_p < 5) {
+                       /* always at least 4 frets plus top line */
+                       *frets_p = 5;
+               }
+       }
+       *topfret_p = (*fretnum_p == 0 ? 0 : *fretnum_p - *numvert_p);
+}
+\f
+
+/* Determine the dimensions of a grid, relative to a point in the middle
+ * of the top line of the grid, and return them via pointers.
+ * If pointers are 0, don't bother; caller doesn't care about these things.
+ * Things in this function must be kept in sync with the PostScript prolog
+ * definition of grids.
+ */
+
+void
+gridsize(grid_p, staff, north_p, south_p, east_p, west_p)
+
+struct GRID *grid_p;   /* find the size of this grid */
+int staff;             /* use this staff for scaling. 0 means score,
+                        * -1 means ATEND */
+float *north_p;                /* return values... */
+float *south_p;
+float *east_p;
+float *west_p;
+
+{
+       double space;   /* distance between adjacent line of the grid */
+       int frets;
+       int fretnum;
+       int numvert;
+       int topfret;
+       int s;          /* string index */
+
+       if (grid_p == 0) {
+               pfatal("gridsize() was passed a null pointer");
+       }
+
+       /* determine distance between grid lines and other needed info */
+       space = gridspace(staff);
+       gridinfo(grid_p, staff, &frets, &fretnum, &numvert, &topfret);
+
+       /* Start with minimum. East and west are equal, at half the
+        * total grid width, based on number of strings. The number of
+        * spaces is the number of strings minus one, but dots, X's,
+        * and O's will hang over the sides, so use the number of strings.
+        * Then adjust east for "N fr" if needed. */
+       if (west_p != 0) {
+               *west_p = -((space * grid_p->numstr) / 2.0);
+       }
+       if (east_p != 0) {
+               *east_p = (space * grid_p->numstr) / 2.0;
+               if (fretnum > 0) {
+                       /* We will need "N fr".
+                        * Get enough space to hold
+                        * font, size, 2 digits, space, "fr", null */
+                       char tmp[8];
+
+                       /* this is printed in Palatino Roman */
+                       tmp[0] = (char) FONT_PR;
+
+                       /* Between staffscale and gridscale,
+                        * we could get a size that we can't represent
+                        * in internal format, so get string width
+                        * in default size and adjust afterwards. */
+                       tmp[1] = (char) DFLT_SIZE;
+
+                       /* since we know there are no funny characters
+                        * in this string, we can cheat and not bother
+                        * to call the string normalizer. */
+                       sprintf(tmp + 2, "%d fr", fretnum);
+
+                       *east_p += strwidth(tmp) *
+                                               (space * PPI * 1.9)/ DFLT_SIZE;
+               }
+       }
+
+       if (north_p != 0) {
+               /* Always put almost one space of padding on top, which allows
+                * room for x's and o's and curves. Even if this particular grid
+                * doesn't have those, many do, so it's nice to line
+                * all of them up as much as possible */
+               *north_p = 0.85 * space;
+               /* If there is a curve above the top fret,
+                * with x's or o's above it, leave some more space */
+               if (grid_p->positions[grid_p->curvel - 1] == topfret + 1 
+                                       || grid_p->positions[grid_p->curver - 1]
+                                       == topfret + 1) {
+                       for (s = grid_p->curvel; s <= grid_p->curver; s++) {
+                               if (grid_p->positions[s-1] == 0 ||
+                                               grid_p->positions[s-1]
+                                               == -1) {
+                                       *north_p += 0.7 * space;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       /* Grid is always at least 4 boxes high, more if needed,
+        * plus 1/2 space of padding at bottom */
+       if (south_p != 0) {
+               *south_p = -(frets - 0.5) * space;
+       }
+}
+\f
+
+/* This function returns the minimum distance needed between the current 
+ * staff and previous one, given their clefs and allowing for a measure
+ * number. The clefs might be NOCLEF, like if this is for the top
+ * staff of a page or a staff where printclef is false.
+ */
+double
+clefspace(prevclef, prevscale, curclef, curscale, measnum)
+
+int prevclef;          /* clef on staff above */
+double prevscale;      /* staffscale for the staff above */
+int curclef;           /* clef on staff below */
+double curscale;       /* staffscale for the staff below */
+int measnum;           /* YES if a measure number needs to be printed */
+
+{
+       double cur_extend;      /* space needed for current clef */
+       double prev_extend;     /* space needed for clef above */
+       double space_needed;    /* total for both clefs and measure number */
+
+
+       /* Figure out how much the clef on current staff sticks up,
+        * Do in approximate STEPSIZEs here, and adjust later for scale. */
+       switch (curclef) {
+       case TREBLE_8A:
+               cur_extend = 6.0;
+               break;
+       case TREBLE:
+       case TREBLE_8:
+               cur_extend = 4.0;
+               break;
+       case BARITONE:
+               cur_extend = 4.2;
+               break;
+       case TENOR:
+               cur_extend = 2.2;
+               break;
+       case FRENCHVIOLIN:
+               cur_extend = 2.0;
+               break;
+       default:
+               cur_extend = 0.0;
+               break;
+       }
+
+       /* Similar for the clef above, only how much it sticks down
+        * rather than up */
+       switch (prevclef) {
+       case TREBLE:
+       case TREBLE_8A:
+               prev_extend = 3.2;
+               break;
+       case MEZZOSOPRANO:
+               prev_extend = 2.2;
+               break;
+       case SOPRANO:
+               prev_extend = 4.2;
+               break;
+       case FRENCHVIOLIN:
+       case TREBLE_8:
+               prev_extend = 5.2;
+               break;
+       default:
+               prev_extend = 0.0;
+               break;
+       }
+
+       /* Add top and bottom together, adjusting for scale factors,
+        * and adding a little padding */
+       space_needed = prev_extend * STEPSIZE * prevscale +
+                       cur_extend * STEPSIZE * curscale +
+                       STDPAD * curscale;
+
+       /* Add on the space for the measure number, if necessary.
+        * Note that we can use fontascent since all digits are that high. */
+       if (measnum == YES) {
+               space_needed += fontascent(Score.measnumfamily + Score.measnumfont,
+                               Score.measnumsize) + STDPAD;
+       }
+       return(space_needed);
+}
+\f
+/*
+ * Name:        eff_rightmargin()
+ *
+ * Abstract:    Return the effective right margin for this score.
+ *
+ * Returns:     the margin in inches
+ *
+ * Description: There are two reason that code can't just use Score.rightmargin
+ *             but must call this function.  First, the way the "scale" param
+ *             works, we pretend the paper is smaller by that amount and then
+ *             in PostScript magnify it back to the real size; but margins are
+ *             not to be scaled, so we have to fake out the code by dividing
+ *             out the scale here.  Second, the user can override the param
+ *             on a "newscore" or "newpage".  To ignore a user override, pass
+ *             0 for mainll_p, else pass some MLL on that score.
+ */
+
+double
+eff_rightmargin(mainll_p)
+
+struct MAINLL *mainll_p; /* MLL struct on some score, or 0 for normal margin */
+
+{
+       /* if not already at a FEED, find FEED at right end of this score */
+       while (mainll_p != 0 && mainll_p->str != S_FEED)
+               mainll_p = mainll_p->next;
+
+       /* if there is none, or there is no override, use the parameter */
+       if (mainll_p == 0 || mainll_p->u.feed_p->rightmargin < 0.0)
+               return (Score.rightmargin / Score.scale_factor);
+
+       /* use this override value */
+       return (mainll_p->u.feed_p->rightmargin / Score.scale_factor);
+}
+\f
+/*
+ * Name:        eff_leftmargin()
+ *
+ * Abstract:    Return the effective left margin for this score.
+ *
+ * Returns:     the margin in inches
+ *
+ * Description: There are two reason that code can't just use Score.leftmargin
+ *             but must call this function.  First, the way the "scale" param
+ *             works, we pretend the paper is smaller by that amount and then
+ *             in PostScript magnify it back to the real size; but margins are
+ *             not to be scaled, so we have to fake out the code by dividing
+ *             out the scale here.  Second, the user can override the param
+ *             on a "newscore" or "newpage".  To ignore a user override, pass
+ *             0 for mainll_p, else pass some MLL on that score.
+ */
+
+double
+eff_leftmargin(mainll_p)
+
+struct MAINLL *mainll_p; /* MLL struct on some score, or 0 for normal margin */
+
+{
+       /* if not already at a FEED, find FEED at left end of this score */
+       while (mainll_p != 0 && mainll_p->str != S_FEED)
+               mainll_p = mainll_p->prev;
+
+       /* if there is none, or there is no override, use the parameter */
+       if (mainll_p == 0 || mainll_p->u.feed_p->leftmargin < 0.0)
+               return (Score.leftmargin / Score.scale_factor);
+
+       /* use this override value */
+       return (mainll_p->u.feed_p->leftmargin / Score.scale_factor);
+}
+\f
+/*
+ * Name:        findprimes()
+ *
+ * Abstract:    Find all the prime numbers up to the given number ("max").
+ *
+ * Returns:     array indexed 0 to max, each element YES or NO (is index prime?)
+ *
+ * Description: This function mallocs and returns an array of shorts, indexed
+ *             from 0 to max.  Each element is YES or NO, telling whether its
+ *             index is a prime number.  The first time it is called, or if
+ *             max is greater than the previous time, it calculates all this,
+ *             but on other calls it just returns the answer from before.
+ */
+
+short *
+findprimes(max)
+
+int max;               /* max integer we need to consider */
+
+{
+       static short *isprime = 0;      /* array to be malloc'ed */
+       static int oldmax = 0;          /* the max passed in previously */
+       int stop;                       /* where to stop looking */
+       int prime;                      /* a prime number */
+       int n;                          /* loop index */
+
+
+       /* if we've already been here ... */
+       if (isprime != 0) {
+               /* if we've already done the same or more, just return answer*/
+               if (max <= oldmax) {
+                       return (isprime);
+               }
+               /* max increased; free the old array */
+               FREE(isprime);
+       }
+       oldmax = max;           /* remember if for next time */
+
+       MALLOCA(short, isprime, max + 1);
+
+       /* 0 and 1 are not primes */
+       isprime[0] = isprime[1] = NO;
+
+       /*
+        * We're going to use the Sieve of Eristosthenes.  We start out by
+        * assuming everything 2 and greater is prime.
+        */
+       for (n = 2; n <= max; n++) {
+               isprime[n] = YES;
+       }
+
+       /* the following loop can stop when it gets to this point */
+       stop = sqrt((double)max) + 1;
+
+       prime = 2;
+       while (prime <= stop) {
+               /* knock out all multiples of this prime number */
+               for (n = 2 * prime; n <= max; n += prime) {
+                       isprime[n] = NO;
+               }
+               /* find the next prime */
+               for (n = prime + 1; n <= stop && isprime[n] == NO; n++)
+                       ;
+               prime = n;
+       }
+
+       return (isprime);
+}
+\f
+/*
+ * Name:        factor()
+ *
+ * Abstract:    Factor the given number.
+ *
+ * Returns:     array indexed 0 to num, giving the prime factors
+ *
+ * Description: This function mallocs and returns an array of shorts, indexed
+ *             from 0 to max.  Each element indexed by a prime number tells
+ *             how many times that prime factor occurs in num.  All other
+ *             elements are 0.  The first time it is called, or if num is
+ *             different from the previous time, it calculates all this,
+ *             but on other calls it just returns the answer from before.
+ */
+
+short *
+factor(num)
+
+int num;               /* the integer to be factored */
+
+{
+       static short *factors = 0;      /* array to be malloc'ed */
+       static int oldnum = 0;          /* the number passed in previously */
+       short *isprime;                 /* list of which numbers are prime */
+       int orignum;                    /* remember original num */
+       int n;                          /* loop index */
+
+
+       /* if we've just done the same number, just return the answer */
+       if (factors != 0) {
+               /* if we've already done the same or more, just return answer*/
+               if (num == oldnum) {
+                       return (factors);
+               }
+               /* num changed; free the old array */
+               FREE(factors);
+       }
+       oldnum = num;           /* remember it for next time */
+
+       CALLOCA(short, factors, num + 1);
+
+       /* find which numbers up to num are primes */
+       isprime = findprimes(num);
+
+       /*
+        * For every prime number until "num" is used up, divide it into num
+        * as many times as possible, keeping track of how many times.
+        */
+       orignum = num;
+       for (n = 2; n <= orignum && num > 1; n++) {
+               if (isprime[n] == YES) {
+                       while (num % n == 0) {
+                               num /= n;
+                               factors[n]++;
+                       }
+               }
+       }
+
+       return (factors);
+}
+\f
+
+/* Return the width of the widest note head in the given GRPSYL. */
+
+double
+widest_head(gs_p)
+
+struct GRPSYL *gs_p;
+
+{
+       double widest;          /* widest note head in the group */
+       double thiswidth;       /* width of current note */
+       int n;                  /* note index */
+
+       widest = 0.0;
+       for (n = 0; n < gs_p->nnotes; n++) {
+               thiswidth = width(gs_p->notelist[n].headfont,
+                       (gs_p->notelist[n].notesize == GS_NORMAL ?
+                       DFLT_SIZE : SMALLSIZE),
+                       gs_p->notelist[n].headchar);
+               if (thiswidth > widest) {
+                       widest = thiswidth;
+               }
+       }
+       return(widest);
+}
diff --git a/mup/mup/ytab.c b/mup/mup/ytab.c
new file mode 100644 (file)
index 0000000..e3536b0
--- /dev/null
@@ -0,0 +1,8414 @@
+/* A Bison parser, made from gram.y, by GNU bison 1.75.  */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* Written by Richard Stallman by simplifying the original so called
+   ``semantic'' parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON        1
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     T_SCORE = 258,
+     T_STAFF = 259,
+     T_VOICE = 260,
+     T_GRIDS = 261,
+     T_BLOCKHEAD = 262,
+     T_NUMBER = 263,
+     T_EQUAL = 264,
+     T_SEMICOLON = 265,
+     T_NEWLINE = 266,
+     T_COLON = 267,
+     T_COMMA = 268,
+     T_LBRACKET = 269,
+     T_RBRACKET = 270,
+     T_LBRACE = 271,
+     T_RBRACE = 272,
+     T_VARIABLE = 273,
+     T_DASH = 274,
+     T_PLUS = 275,
+     T_PLACE = 276,
+     T_ALL = 277,
+     T_WITH = 278,
+     T_CUE = 279,
+     T_GRACE = 280,
+     T_XNOTE = 281,
+     T_DIAM = 282,
+     T_DOT = 283,
+     T_MULTIWHOLE = 284,
+     T_LET_M = 285,
+     T_LET_R = 286,
+     T_LET_S = 287,
+     T_LET_U = 288,
+     T_PITCH = 289,
+     T_SHARP = 290,
+     T_AMPERSAND = 291,
+     T_LET_N = 292,
+     T_LET_X = 293,
+     T_DBLFLAT = 294,
+     T_LETTER = 295,
+     T_LYRICS = 296,
+     T_PAD = 297,
+     T_LPAREN = 298,
+     T_RPAREN = 299,
+     T_LVAR = 300,
+     T_MUSIC = 301,
+     T_HEADSHAPES = 302,
+     T_HS = 303,
+     T_SWINGUNIT = 304,
+     T_POSTSCRIPT = 305,
+     T_SCOREFEED = 306,
+     T_BARTYPE = 307,
+     T_HAT = 308,
+     T_TILDE = 309,
+     T_QUESTION = 310,
+     T_LINETYPE = 311,
+     T_LINE = 312,
+     T_TO = 313,
+     T_STAR = 314,
+     T_BULGE = 315,
+     T_CURVE = 316,
+     T_TIE = 317,
+     T_PRINTTYPE = 318,
+     T_NL = 319,
+     T_STAFFLINES = 320,
+     T_FFAMILY = 321,
+     T_PARAGRAPH = 322,
+     T_PARATYPE = 323,
+     T_NUMVAR = 324,
+     T_FNUMVAR = 325,
+     T_2FNUMVAR = 326,
+     T_RATNUMLISTVAR = 327,
+     T_RANGELISTVAR = 328,
+     T_TIMEUNIT = 329,
+     T_FONTVAR = 330,
+     T_STRVAR = 331,
+     T_CLEFVAR = 332,
+     T_VVAR = 333,
+     T_BARSTLISTVAR = 334,
+     T_SCORESEP = 335,
+     T_FONT = 336,
+     T_SLASH = 337,
+     T_KEY = 338,
+     T_TIME = 339,
+     T_CUT = 340,
+     T_COMMON = 341,
+     T_CLEF = 342,
+     T_MULTIREST = 343,
+     T_YESNOVAR = 344,
+     T_BM = 345,
+     T_ESBM = 346,
+     T_EBM = 347,
+     T_INVISBAR = 348,
+     T_OCTAVE = 349,
+     T_ROLL = 350,
+     T_VISVAR = 351,
+     T_WHEREUSED = 352,
+     T_UNSET = 353,
+     T_VCOMBINE = 354,
+     T_VCOMBVAL = 355,
+     T_SCOREPAD = 356,
+     T_WORD = 357,
+     T_UP = 358,
+     T_DOWN = 359,
+     T_ENDING = 360,
+     T_ENDENDING = 361,
+     T_FAMILY = 362,
+     T_ENDSTYLE = 363,
+     T_ENDTYPE = 364,
+     T_SLASHMARK = 365,
+     T_ALT = 366,
+     T_TITLE = 367,
+     T_REHEARSAL = 368,
+     T_NUM = 369,
+     T_LET = 370,
+     T_MNUM = 371,
+     T_TRANSPOSE = 372,
+     T_XPOS_INT = 373,
+     T_PEDAL = 374,
+     T_PHRASE = 375,
+     T_MUSSYM = 376,
+     T_L_ANGLE = 377,
+     T_MODIFIER = 378,
+     T_R_ANGLE = 379,
+     T_TIL = 380,
+     T_MIDI = 381,
+     T_PEDSTYLE = 382,
+     T_PEDSTAR = 383,
+     T_HIDECHANGES = 384,
+     T_SLUR = 385,
+     T_UNITS = 386,
+     T_CENTIMETERS = 387,
+     T_UNITTYPE = 388,
+     T_TAB = 389,
+     T_TICKS = 390,
+     T_NOWHERE_SLIDE = 391,
+     T_LEN = 392,
+     T_EXCLAM = 393,
+     T_OTHERTEXT = 394,
+     T_ORDER = 395,
+     T_GRIDPLACE = 396,
+     T_GRPLVALUE = 397,
+     T_DRUM = 398,
+     T_RPT = 399,
+     T_STRING = 400,
+     T_HO = 401,
+     T_REH_STYLE = 402,
+     T_REHTYPE = 403,
+     T_L_DBLANGLE = 404,
+     T_R_DBLANGLE = 405,
+     T_SLOPE = 406,
+     T_PSVAR = 407,
+     T_PAGESIZE = 408,
+     T_ORIENTATION = 409
+   };
+#endif
+#define T_SCORE 258
+#define T_STAFF 259
+#define T_VOICE 260
+#define T_GRIDS 261
+#define T_BLOCKHEAD 262
+#define T_NUMBER 263
+#define T_EQUAL 264
+#define T_SEMICOLON 265
+#define T_NEWLINE 266
+#define T_COLON 267
+#define T_COMMA 268
+#define T_LBRACKET 269
+#define T_RBRACKET 270
+#define T_LBRACE 271
+#define T_RBRACE 272
+#define T_VARIABLE 273
+#define T_DASH 274
+#define T_PLUS 275
+#define T_PLACE 276
+#define T_ALL 277
+#define T_WITH 278
+#define T_CUE 279
+#define T_GRACE 280
+#define T_XNOTE 281
+#define T_DIAM 282
+#define T_DOT 283
+#define T_MULTIWHOLE 284
+#define T_LET_M 285
+#define T_LET_R 286
+#define T_LET_S 287
+#define T_LET_U 288
+#define T_PITCH 289
+#define T_SHARP 290
+#define T_AMPERSAND 291
+#define T_LET_N 292
+#define T_LET_X 293
+#define T_DBLFLAT 294
+#define T_LETTER 295
+#define T_LYRICS 296
+#define T_PAD 297
+#define T_LPAREN 298
+#define T_RPAREN 299
+#define T_LVAR 300
+#define T_MUSIC 301
+#define T_HEADSHAPES 302
+#define T_HS 303
+#define T_SWINGUNIT 304
+#define T_POSTSCRIPT 305
+#define T_SCOREFEED 306
+#define T_BARTYPE 307
+#define T_HAT 308
+#define T_TILDE 309
+#define T_QUESTION 310
+#define T_LINETYPE 311
+#define T_LINE 312
+#define T_TO 313
+#define T_STAR 314
+#define T_BULGE 315
+#define T_CURVE 316
+#define T_TIE 317
+#define T_PRINTTYPE 318
+#define T_NL 319
+#define T_STAFFLINES 320
+#define T_FFAMILY 321
+#define T_PARAGRAPH 322
+#define T_PARATYPE 323
+#define T_NUMVAR 324
+#define T_FNUMVAR 325
+#define T_2FNUMVAR 326
+#define T_RATNUMLISTVAR 327
+#define T_RANGELISTVAR 328
+#define T_TIMEUNIT 329
+#define T_FONTVAR 330
+#define T_STRVAR 331
+#define T_CLEFVAR 332
+#define T_VVAR 333
+#define T_BARSTLISTVAR 334
+#define T_SCORESEP 335
+#define T_FONT 336
+#define T_SLASH 337
+#define T_KEY 338
+#define T_TIME 339
+#define T_CUT 340
+#define T_COMMON 341
+#define T_CLEF 342
+#define T_MULTIREST 343
+#define T_YESNOVAR 344
+#define T_BM 345
+#define T_ESBM 346
+#define T_EBM 347
+#define T_INVISBAR 348
+#define T_OCTAVE 349
+#define T_ROLL 350
+#define T_VISVAR 351
+#define T_WHEREUSED 352
+#define T_UNSET 353
+#define T_VCOMBINE 354
+#define T_VCOMBVAL 355
+#define T_SCOREPAD 356
+#define T_WORD 357
+#define T_UP 358
+#define T_DOWN 359
+#define T_ENDING 360
+#define T_ENDENDING 361
+#define T_FAMILY 362
+#define T_ENDSTYLE 363
+#define T_ENDTYPE 364
+#define T_SLASHMARK 365
+#define T_ALT 366
+#define T_TITLE 367
+#define T_REHEARSAL 368
+#define T_NUM 369
+#define T_LET 370
+#define T_MNUM 371
+#define T_TRANSPOSE 372
+#define T_XPOS_INT 373
+#define T_PEDAL 374
+#define T_PHRASE 375
+#define T_MUSSYM 376
+#define T_L_ANGLE 377
+#define T_MODIFIER 378
+#define T_R_ANGLE 379
+#define T_TIL 380
+#define T_MIDI 381
+#define T_PEDSTYLE 382
+#define T_PEDSTAR 383
+#define T_HIDECHANGES 384
+#define T_SLUR 385
+#define T_UNITS 386
+#define T_CENTIMETERS 387
+#define T_UNITTYPE 388
+#define T_TAB 389
+#define T_TICKS 390
+#define T_NOWHERE_SLIDE 391
+#define T_LEN 392
+#define T_EXCLAM 393
+#define T_OTHERTEXT 394
+#define T_ORDER 395
+#define T_GRIDPLACE 396
+#define T_GRPLVALUE 397
+#define T_DRUM 398
+#define T_RPT 399
+#define T_STRING 400
+#define T_HO 401
+#define T_REH_STYLE 402
+#define T_REHTYPE 403
+#define T_L_DBLANGLE 404
+#define T_R_DBLANGLE 405
+#define T_SLOPE 406
+#define T_PSVAR 407
+#define T_PAGESIZE 408
+#define T_ORIENTATION 409
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 2 "gram.y"
+
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ * 2005, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* parser for music publication program. Uses lex to get tokens. */
+
+
+#include "rational.h"
+#include "globals.h"
+#include "defines.h"
+#include "structs.h"
+
+#define YYDEBUG 1
+
+
+/* how many items to allocate at a time for
+ * "with" list, and location lists, etc */
+#define ITEMS  (4)
+
+
+static struct MAINLL *Currstruct_p;    /* main list struct being filled in */
+static struct BLOCKHEAD *Currblock_p;  /* current block, if non-zero */
+
+static struct INPCOORD *Curr_loc_info_p; /* location info being collected */
+
+
+static short Gotheader, Gotfooter;     /* boolean: to make sure each is defined only once */
+static short Gothead2, Gotfoot2;
+static short Getting_tup_dur;          /* YES if currently collection tuplet
+                                        * duration rather than GRPSYL dur */
+
+static struct GRPSYL *Curr_grpsyl_p;   /* current GRPSYL struct being filled in */
+static struct GRPSYL *Last_grpsyl_p;   /* previous GRPSYL struct filled in (contains
+                                        * defaults for the current one */
+static struct TIMELIST *Extra_time_p;  /* If user enters times to be added
+                                        * together, like 2.+16 this points to
+                                        * a linked list of the extra times */
+static struct TIMELIST *Curr_timelist_p;/* current additive time, used to know
+                                        * where to link items to the list */
+static struct TIMELIST *Last_alloced_timelist_p; /* Most recently allocated
+                                        * list. Keeping track of this lets us
+                                        * avoid trying to free the list
+                                        * when Extra_time_p is pointing
+                                        * to a list from an SSV. */
+static struct GRPSYL *Prev_grpsyl_p;   /* Like Last_grpsyl_p except in the
+                                        * case of additive times,
+                                        * in which case it points to the
+                                        * first group. This is needed in case
+                                        * the following group is to get its
+                                        * time value by defaulting to that
+                                        * of its previous group. */
+static int Extra_basictime;            /* for saving basictime, when doing
+                                        * additive times */
+static int Doing_timeunit = NO;                /* YES if gathering timeunit param */
+static struct GRPSYL *Lyrics_p;                /* pointer to current list of lyrics */
+static char **Curr_marklist;           /* current "with" list */
+static struct PRINTDATA **Next_print_link_p_p; /* points to where to attach next
+                                                * print command that we get */
+static int Item_count;                 /* items in current list */
+static int Max_items;                  /* current amount of space in lists
+                                        * "with" list, curve locations, etc) */
+
+static int Plus_minus;                 /* if 1 add, if -1 subtract offset */
+static int Defining_multiple = NO;     /* if defining multiple voices at once */
+static int Chord_at_a_time = NO;       /* YES for chord-at-a-time,
+                                        * NO for voice-at-a-time */
+static short Endingloc;                        /* if current bar starts or ends an
+                                        * ending, etc (STARTITEM, ENDITEM, etc) */
+static short Got_ending;               /* YES if got ending on this bar */
+
+static int Til_bars;                   /* number of bars in "til" clause */
+static int Dist;                       /* dist for a specific STUFF */
+static int Dist_usage;                 /* meaning of Dist field */
+static short User_meas_time;           /* YES if user specified a time for
+                                        * an 'm' item. Only valid on mr */
+static int Order_place;                        /* PL_* for markorder in SSV */
+static int Order_prio;                 /* value in markorder in SSV */
+static int Gracebackup;                        /* how many grace notes to back up
+                                        * before starting a "stuff" */
+static float Til_offset;               /* beat count in "til" clause */
+static int Slurstyle;                  /* L_DOTTED, L_DASHED, or L_NORMAL */
+
+static char *String1, *String2;                /* to temporarily keep track
+                                        * of labels and other temporary
+                                        * strings */
+static char Tmpbuff[20];               /* temporary buffer for converting
+                                        * float numbers */
+static char Stringbuff[100];           /* temporary string storage */
+static int Titlefont, Titlesize;       /* font/size for title command */
+static double Extra;                   /* extra vertical space for prints */
+static short Good_till_canceled = NO;  /* if [] things should be continued
+                                        * until turned off */
+static short Curr_paratype = J_JUSTPARA; /* current paragraph type */
+static struct TIMEDSSV *Curr_tssv_p;   /* current mid-measure param change */
+static char Timerep[MAXTSLEN];         /* Internal representation of time
+                                        * signature being collected */
+static int Tsig_offset;                        /* Current place in Timerep while
+                                        * collecting a time signature */
+static char *Alt_timesig_list;         /* If user specified alternating
+                                        * time signatures, this points to
+                                        * the beginning of the list, for
+                                        * when we need to wrap around */
+static char *Next_alt_timesig;         /* If user specified alternating
+                                        * time signatures, this points to
+                                        * the one for the next measure */
+static short Tsig_visibility;          /* If EACHMEAS, alternating
+                                        * time signatures will be done
+                                        * by explicitly printing
+                                        * the appropriate time signature at
+                                        * the beginning of every measure,
+                                        * rather than printing them all just
+                                        * once at the beginning of the run
+                                        * of measures that alternate. */
+
+/* Row index values must match the PS_* value definitions in defines.h.
+ * Column [0] is height in portrait mode, and column [1] is height. */
+double pagesztbl[7][2] = {
+       { 8.5, 11.0 },          /* PS_LETTER */
+       { 8.5, 14.0 },          /* PS_LEGAL */
+       { 8.5, 13.0 },          /* PS_FLSA */
+       { 5.5, 8.5 },           /* PS_HALFLETTER */
+       { 8.26, 11.69 },        /* PS_A4 */
+       { 5.84, 8.26 },         /* PS_A5 */
+       { 4.12, 5.84 }          /* PS_A6 */
+};
+
+
+
+/* static functions */
+static char *stripquotes P((char *string));    /* rmv double quotes
+                                                * from string */
+static void chkdup_headfoot P((int flag, char *which));
+static void end_prev_context P((void));
+static void var_valid P((void));        /* check if okay to set location var */
+static void proc_printcmd P((int justifytype, struct INPCOORD *inpc_p,
+               char *str, int font, int size, int got_nl,
+               int isPostScript, double extra));
+static double extra_needed P((int font, int size, char *string));
+static void keyword_notes P((char *str));
+static void free_extra_time P((void));
+static void tsig_item P((int item));
+
+
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+#ifndef YYSTYPE
+#line 152 "gram.y"
+typedef union {
+int    intval;         /* for tokens/nonterminals that return int values */
+char   *stringval;     /* for tokens/nonterminals that return strings */
+float  floatval;       /* for nonterminals that return floats */
+RATIONAL ratval;       /* for nonterminals that return rational numbers */
+struct INPCOORD *inpcoord_p;   /* for nonterminals that return coord info */
+} yystype;
+/* Line 193 of /usr/share/bison/yacc.c.  */
+#line 536 "y.tab.c"
+# define YYSTYPE yystype
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+#ifndef YYLTYPE
+typedef struct yyltype
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+} yyltype;
+# define YYLTYPE yyltype
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 213 of /usr/share/bison/yacc.c.  */
+#line 557 "y.tab.c"
+
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# if YYSTACK_USE_ALLOCA
+#  define YYSTACK_ALLOC alloca
+# else
+#  ifndef YYSTACK_USE_ALLOCA
+#   if defined (alloca) || defined (_ALLOCA_H)
+#    define YYSTACK_ALLOC alloca
+#   else
+#    ifdef __GNUC__
+#     define YYSTACK_ALLOC __builtin_alloca
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning. */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+#  if defined (__STDC__) || defined (__cplusplus)
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T size_t
+#  endif
+#  define YYSTACK_ALLOC malloc
+#  define YYSTACK_FREE free
+# endif
+#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+
+
+#if (! defined (yyoverflow) \
+     && (! defined (__cplusplus) \
+        || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short yyss;
+  YYSTYPE yyvs;
+  };
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE))                                \
+      + YYSTACK_GAP_MAX)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)             \
+      do                                       \
+       {                                       \
+         register YYSIZE_T yyi;                \
+         for (yyi = 0; yyi < (Count); yyi++)   \
+           (To)[yyi] = (From)[yyi];    \
+       }                                       \
+      while (0)
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)                                       \
+    do                                                                 \
+      {                                                                        \
+       YYSIZE_T yynewbytes;                                            \
+       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
+       Stack = &yyptr->Stack;                                          \
+       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX;   \
+       yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                        \
+    while (0)
+
+#endif
+
+#if defined (__STDC__) || defined (__cplusplus)
+   typedef signed char yysigned_char;
+#else
+   typedef short yysigned_char;
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL  167
+#define YYLAST   1149
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS  155
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS  273
+/* YYNRULES -- Number of rules. */
+#define YYNRULES  618
+/* YYNRULES -- Number of states. */
+#define YYNSTATES  914
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   409
+
+#define YYTRANSLATE(X) \
+  ((unsigned)(X) <= YYMAXUTOK ? yytranslate[X] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const unsigned char yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
+      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
+     105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
+     115,   116,   117,   118,   119,   120,   121,   122,   123,   124,
+     125,   126,   127,   128,   129,   130,   131,   132,   133,   134,
+     135,   136,   137,   138,   139,   140,   141,   142,   143,   144,
+     145,   146,   147,   148,   149,   150,   151,   152,   153,   154
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const unsigned short yyprhs[] =
+{
+       0,     0,     3,     5,     8,    10,    12,    14,    16,    19,
+      22,    24,    28,    30,    33,    35,    37,    39,    41,    44,
+      47,    51,    56,    58,    59,    61,    63,    65,    69,    71,
+      73,    75,    77,    80,    82,    84,    89,    92,    96,   102,
+     107,   108,   113,   118,   123,   129,   134,   139,   143,   147,
+     151,   155,   159,   163,   167,   171,   175,   178,   179,   184,
+     188,   193,   198,   202,   206,   210,   216,   220,   224,   226,
+     228,   230,   231,   233,   235,   236,   237,   239,   241,   243,
+     247,   251,   252,   257,   262,   264,   265,   267,   268,   271,
+     274,   276,   278,   279,   280,   282,   286,   290,   291,   294,
+     295,   300,   301,   304,   306,   307,   308,   310,   314,   317,
+     319,   321,   325,   329,   331,   333,   335,   337,   339,   341,
+     343,   345,   347,   350,   352,   353,   357,   359,   360,   365,
+     367,   369,   373,   377,   379,   381,   385,   387,   388,   390,
+     391,   393,   397,   401,   404,   407,   409,   414,   416,   419,
+     424,   425,   427,   428,   430,   432,   434,   436,   437,   440,
+     443,   444,   448,   450,   453,   454,   456,   457,   460,   461,
+     463,   465,   467,   469,   471,   472,   474,   476,   479,   481,
+     483,   490,   493,   494,   496,   497,   499,   500,   504,   506,
+     509,   513,   521,   522,   524,   526,   528,   530,   532,   534,
+     536,   538,   540,   542,   544,   546,   548,   550,   552,   554,
+     556,   558,   560,   562,   564,   566,   568,   570,   572,   574,
+     576,   578,   580,   582,   586,   591,   595,   597,   598,   600,
+     602,   604,   607,   611,   613,   615,   617,   621,   623,   627,
+     629,   631,   634,   636,   638,   642,   645,   646,   649,   652,
+     657,   658,   661,   663,   666,   668,   674,   675,   677,   679,
+     682,   687,   689,   691,   693,   695,   699,   703,   707,   710,
+     712,   717,   724,   725,   729,   730,   735,   736,   737,   739,
+     741,   745,   749,   751,   753,   755,   757,   761,   764,   767,
+     770,   773,   775,   777,   780,   781,   783,   784,   786,   788,
+     792,   794,   798,   801,   804,   807,   808,   809,   811,   813,
+     817,   819,   821,   823,   825,   827,   829,   831,   833,   835,
+     837,   839,   841,   843,   846,   848,   850,   851,   853,   854,
+     858,   860,   862,   863,   866,   871,   872,   873,   875,   876,
+     879,   881,   885,   886,   888,   890,   892,   895,   898,   899,
+     901,   904,   907,   911,   914,   917,   919,   920,   923,   926,
+     927,   931,   933,   934,   938,   940,   942,   944,   947,   949,
+     951,   953,   955,   957,   959,   961,   965,   968,   974,   980,
+     984,   990,   998,  1003,  1008,  1015,  1020,  1026,  1031,  1032,
+    1034,  1036,  1037,  1039,  1040,  1042,  1044,  1046,  1048,  1050,
+    1052,  1054,  1056,  1058,  1060,  1063,  1065,  1068,  1073,  1075,
+    1076,  1078,  1080,  1082,  1085,  1088,  1091,  1093,  1095,  1097,
+    1099,  1101,  1103,  1105,  1107,  1109,  1118,  1119,  1121,  1123,
+    1125,  1127,  1129,  1130,  1132,  1133,  1136,  1141,  1145,  1147,
+    1148,  1150,  1152,  1154,  1158,  1161,  1162,  1165,  1168,  1169,
+    1170,  1176,  1178,  1180,  1182,  1186,  1189,  1190,  1193,  1194,
+    1197,  1198,  1200,  1202,  1205,  1208,  1212,  1214,  1220,  1221,
+    1223,  1225,  1228,  1231,  1237,  1240,  1242,  1244,  1245,  1249,
+    1251,  1252,  1255,  1259,  1260,  1262,  1263,  1265,  1267,  1269,
+    1273,  1274,  1278,  1279,  1282,  1284,  1287,  1289,  1291,  1295,
+    1299,  1303,  1311,  1314,  1316,  1317,  1319,  1321,  1323,  1325,
+    1332,  1333,  1336,  1338,  1342,  1344,  1346,  1348,  1350,  1351,
+    1354,  1357,  1359,  1361,  1363,  1366,  1369,  1371,  1375,  1377,
+    1379,  1381,  1382,  1385,  1388,  1390,  1392,  1396,  1399,  1400,
+    1402,  1404,  1406,  1414,  1415,  1416,  1418,  1419,  1424,  1432,
+    1433,  1436,  1439,  1441,  1445,  1447,  1451,  1454,  1456,  1460,
+    1467,  1474,  1477,  1479,  1481,  1483,  1485,  1488,  1490,  1492,
+    1494,  1496,  1498,  1499,  1503,  1504,  1506,  1507,  1510,  1513,
+    1517,  1518,  1520,  1522,  1525,  1531,  1534,  1535,  1540,  1541,
+    1546,  1547,  1549,  1551,  1552,  1555,  1558,  1559,  1562,  1563,
+    1566,  1572,  1573,  1575,  1577,  1580,  1582,  1585,  1586,  1589,
+    1593,  1596,  1600,  1604,  1608,  1610,  1612,  1613,  1615
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const short yyrhs[] =
+{
+     156,     0,    -1,   157,    -1,   156,   157,    -1,   158,    -1,
+     170,    -1,   229,    -1,   235,    -1,   239,    11,    -1,   359,
+      11,    -1,   165,    -1,   353,   358,    11,    -1,    11,    -1,
+       1,    11,    -1,   159,    -1,   162,    -1,   164,    -1,   166,
+      -1,   163,   161,    -1,     3,   160,    -1,     4,   167,   160,
+      -1,     5,   167,   168,   160,    -1,   161,    -1,    -1,     7,
+      -1,    46,    -1,     6,    -1,   238,   238,    11,    -1,    47,
+      -1,   169,    -1,   169,    -1,     8,    -1,   172,   171,    -1,
+      10,    -1,    11,    -1,    69,     9,   296,   169,    -1,    69,
+       9,    -1,    70,     9,   382,    -1,    71,     9,   382,    13,
+     382,    -1,   152,     9,   220,   221,    -1,    -1,    99,     9,
+     173,   222,    -1,    42,     9,   296,   382,    -1,    78,     9,
+     169,   176,    -1,    72,     9,   177,   178,   184,    -1,    73,
+       9,   185,   186,    -1,    79,     9,   192,   193,    -1,   195,
+       9,   196,    -1,    83,     9,   209,    -1,    84,     9,   199,
+      -1,    65,     9,   210,    -1,    75,     9,    81,    -1,   107,
+       9,    66,    -1,    77,     9,    87,    -1,    89,     9,   215,
+      -1,    96,     9,   175,    -1,    98,   237,    -1,    -1,    74,
+       9,   174,   182,    -1,    49,     9,   183,    -1,    80,     9,
+     216,   217,    -1,   101,     9,   218,   219,    -1,   108,     9,
+     224,    -1,   147,     9,   148,    -1,   127,     9,   227,    -1,
+     117,     9,   225,   228,   169,    -1,   131,     9,   133,    -1,
+      76,     9,   238,    -1,    97,    -1,    40,    -1,    37,    -1,
+      -1,    34,    -1,    40,    -1,    -1,    -1,   179,    -1,   182,
+      -1,   180,    -1,   179,    13,   182,    -1,   179,    13,   180,
+      -1,    -1,    43,   181,   179,    44,    -1,   288,   293,   289,
+     292,    -1,    30,    -1,    -1,   182,    -1,    -1,    31,    32,
+      -1,    32,    31,    -1,    32,    -1,    31,    -1,    -1,    -1,
+     187,    -1,   186,    13,   187,    -1,   169,   188,   189,    -1,
+      -1,    19,   169,    -1,    -1,    43,   191,   190,    44,    -1,
+      -1,    13,   191,    -1,   238,    -1,    -1,    -1,   194,    -1,
+     193,    13,   194,    -1,   169,   188,    -1,   140,    -1,   197,
+      -1,   196,    13,   197,    -1,   196,    36,   197,    -1,   198,
+      -1,   121,    -1,    94,    -1,   139,    -1,   123,    -1,    41,
+      -1,   105,    -1,   113,    -1,   119,    -1,   200,   207,    -1,
+     202,    -1,    -1,   200,   201,   202,    -1,   204,    -1,    -1,
+     202,    20,   203,   204,    -1,    85,    -1,    86,    -1,   205,
+      82,   169,    -1,   205,    20,    29,    -1,    29,    -1,   206,
+      -1,   205,    20,   206,    -1,   169,    -1,    -1,   215,    -1,
+      -1,    37,    -1,   169,   313,   226,    -1,   310,   311,   226,
+      -1,   169,   208,    -1,   169,   143,    -1,   134,    -1,   134,
+      43,   211,    44,    -1,   212,    -1,   211,   212,    -1,   310,
+     213,   214,   312,    -1,    -1,   313,    -1,    -1,   135,    -1,
+      40,    -1,    37,    -1,   169,    -1,    -1,    13,   169,    -1,
+     296,   169,    -1,    -1,    13,   296,   169,    -1,   153,    -1,
+     310,   169,    -1,    -1,   154,    -1,    -1,   254,   223,    -1,
+      -1,   100,    -1,   109,    -1,     7,    -1,   103,    -1,   104,
+      -1,    -1,   118,    -1,    57,    -1,   111,   128,    -1,   128,
+      -1,   118,    -1,   112,   230,   233,   234,   358,    11,    -1,
+     232,   231,    -1,    -1,    81,    -1,    -1,    66,    -1,    -1,
+      43,   169,    44,    -1,   238,    -1,   238,   238,    -1,   238,
+     238,   238,    -1,   236,    67,   230,   233,   238,   358,    11,
+      -1,    -1,    68,    -1,    69,    -1,    89,    -1,    80,    -1,
+      65,    -1,    74,    -1,    49,    -1,    42,    -1,    79,    -1,
+      70,    -1,    71,    -1,   131,    -1,   108,    -1,   147,    -1,
+     127,    -1,    78,    -1,    99,    -1,   101,    -1,    73,    -1,
+     140,    -1,    83,    -1,    84,    -1,   117,    -1,    72,    -1,
+      96,    -1,    76,    -1,    75,    -1,   107,    -1,    77,    -1,
+     145,    -1,   238,    20,   145,    -1,   240,   241,   250,   256,
+      -1,    88,   169,   358,    -1,   330,    -1,    -1,   247,    -1,
+     242,    -1,   243,    -1,   242,   243,    -1,   244,   246,   245,
+      -1,    14,    -1,    15,    -1,   247,    -1,   246,    10,   247,
+      -1,   249,    -1,   247,   248,   249,    -1,    36,    -1,   251,
+      -1,   251,   254,    -1,    12,    -1,   252,    -1,   251,    13,
+     252,    -1,   167,   253,    -1,    -1,    19,   167,    -1,   168,
+     255,    -1,   168,    19,   168,   255,    -1,    -1,    13,   254,
+      -1,   257,    -1,   256,   257,    -1,   324,    -1,   258,   264,
+     297,   274,    10,    -1,    -1,   259,    -1,   260,    -1,   259,
+     260,    -1,   149,   261,   262,   150,    -1,     3,    -1,     4,
+      -1,     5,    -1,   263,    -1,   262,    10,   263,    -1,    77,
+       9,    87,    -1,    69,     9,   169,    -1,   265,   286,    -1,
+     268,    -1,    14,    19,    15,   268,    -1,    14,   268,   269,
+      15,   266,   267,    -1,    -1,    28,    28,    28,    -1,    -1,
+     267,    14,   269,    15,    -1,    -1,    -1,   270,    -1,   271,
+      -1,   269,    10,   271,    -1,    23,   277,   279,    -1,   322,
+      -1,   283,    -1,   294,    -1,   284,    -1,    69,   296,   169,
+      -1,   146,   272,    -1,    48,   238,    -1,   137,   382,    -1,
+     110,   169,    -1,    20,    -1,    19,    -1,   273,   382,    -1,
+      -1,   374,    -1,    -1,   275,    -1,   276,    -1,   275,    13,
+     276,    -1,   285,    -1,   151,   296,   382,    -1,   111,   169,
+      -1,   130,   278,    -1,    62,   278,    -1,    -1,    -1,   284,
+      -1,   280,    -1,   279,    13,   280,    -1,   281,    -1,   282,
+      -1,   238,    -1,    28,    -1,    19,    -1,   124,    -1,    53,
+      -1,    24,    -1,    25,    -1,    27,    -1,    26,    -1,   103,
+      -1,   104,    -1,    90,   287,    -1,    91,    -1,    92,    -1,
+      -1,   182,    -1,    -1,    23,     4,    21,    -1,    29,    -1,
+     169,    -1,    -1,   289,   290,    -1,   374,   291,   288,   293,
+      -1,    -1,    -1,    30,    -1,    -1,   293,    28,    -1,   295,
+      -1,    42,   296,   382,    -1,    -1,    19,    -1,   303,    -1,
+     298,    -1,   299,   302,    -1,   300,   301,    -1,    -1,    55,
+      -1,    54,   278,    -1,     9,   323,    -1,    53,   310,   312,
+      -1,    53,    82,    -1,    48,   238,    -1,   317,    -1,    -1,
+     302,   301,    -1,   306,   304,    -1,    -1,   305,   306,    21,
+      -1,    23,    -1,    -1,   306,   307,   302,    -1,   308,    -1,
+      31,    -1,    32,    -1,    33,    32,    -1,   144,    -1,    52,
+      -1,    25,    -1,   109,    -1,    68,    -1,    73,    -1,    87,
+      -1,    43,   308,    44,    -1,   310,   309,    -1,   310,    43,
+     313,    44,   312,    -1,   310,    43,   314,    44,   309,    -1,
+     310,    43,   310,    -1,   310,   313,   214,   312,   309,    -1,
+     310,   313,   214,    43,   314,    44,   309,    -1,   310,   313,
+      43,   310,    -1,   310,   135,   312,   309,    -1,   310,   135,
+      43,   314,    44,   309,    -1,   310,   314,   311,   309,    -1,
+     310,   314,    43,   313,    44,    -1,   310,   314,    43,   310,
+      -1,    -1,   238,    -1,    34,    -1,    -1,   313,    -1,    -1,
+     314,    -1,    35,    -1,    36,    -1,    37,    -1,    38,    -1,
+      39,    -1,   169,    -1,   315,    -1,   316,    -1,    19,    -1,
+     315,    19,    -1,    20,    -1,   316,    20,    -1,   318,   319,
+     124,   278,    -1,   122,    -1,    -1,   136,    -1,   320,    -1,
+     321,    -1,   320,   321,    -1,   310,   312,    -1,     9,   323,
+      -1,    40,    -1,    34,    -1,    30,    -1,    31,    -1,    32,
+      -1,    33,    -1,    37,    -1,    38,    -1,    45,    -1,   326,
+     256,   327,   328,   169,   325,   329,    10,    -1,    -1,    37,
+      -1,   114,    -1,    40,    -1,    16,    -1,    17,    -1,    -1,
+      21,    -1,    -1,    13,   182,    -1,    41,   331,    12,   344,
+      -1,   332,   334,   337,    -1,   333,    -1,    -1,    21,    -1,
+     335,    -1,    22,    -1,   334,    13,   335,    -1,   169,   336,
+      -1,    -1,    19,   169,    -1,    36,   169,    -1,    -1,    -1,
+     337,    10,    21,   338,   334,    -1,   340,    -1,    34,    -1,
+     341,    -1,   340,    13,   341,    -1,   169,   342,    -1,    -1,
+      19,   169,    -1,    -1,   345,   351,    -1,    -1,   346,    -1,
+     347,    -1,   346,   347,    -1,   348,    10,    -1,   343,   286,
+     350,    -1,   349,    -1,   326,   346,   327,   169,   329,    -1,
+      -1,    32,    -1,   352,    -1,   351,   352,    -1,   238,    10,
+      -1,    14,   339,    15,   238,    10,    -1,   360,   362,    -1,
+     386,    -1,   390,    -1,    -1,    51,   354,   355,    -1,   424,
+      -1,    -1,   355,   356,    -1,    70,   357,   382,    -1,    -1,
+       9,    -1,    -1,    10,    -1,   397,    -1,   418,    -1,   388,
+     361,    52,    -1,    -1,    43,    52,    44,    -1,    -1,   362,
+     363,    -1,   295,    -1,     9,   323,    -1,   364,    -1,   129,
+      -1,   116,     9,   169,    -1,   115,     9,   238,    -1,   114,
+       9,   169,    -1,   113,   365,   232,   231,   403,   366,   405,
+      -1,   105,   238,    -1,   106,    -1,    -1,   238,    -1,   116,
+      -1,   114,    -1,   115,    -1,    43,   368,   369,    13,   376,
+      44,    -1,    -1,   370,   372,    -1,   375,    -1,   385,    28,
+     371,    -1,   373,    -1,    40,    -1,    38,    -1,    34,    -1,
+      -1,   372,   373,    -1,   374,   375,    -1,    20,    -1,    19,
+      -1,   382,    -1,    84,   382,    -1,   377,   379,    -1,   381,
+      -1,   385,    28,   378,    -1,    37,    -1,    32,    -1,    40,
+      -1,    -1,   379,   380,    -1,   374,   381,    -1,   382,    -1,
+     169,    -1,   169,    28,   383,    -1,    28,   384,    -1,    -1,
+     384,    -1,     8,    -1,   323,    -1,   388,    57,   387,   367,
+      58,   367,   389,    -1,    -1,    -1,    56,    -1,    -1,    23,
+     230,   233,   238,    -1,   388,    61,   391,   396,    58,   396,
+     392,    -1,    -1,    58,   393,    -1,    60,   394,    -1,   396,
+      -1,   393,    58,   396,    -1,   395,    -1,   394,    13,   395,
+      -1,   296,   382,    -1,   367,    -1,   398,    12,   408,    -1,
+     401,   403,   404,   333,   334,   405,    -1,   388,   120,   403,
+     333,   334,   405,    -1,   399,   400,    -1,   126,    -1,   247,
+      -1,    22,    -1,   402,    -1,   232,    81,    -1,   122,    -1,
+     124,    -1,   119,    -1,   121,    -1,    94,    -1,    -1,    43,
+     169,    44,    -1,    -1,   123,    -1,    -1,    69,   406,    -1,
+     169,   407,    -1,    19,   169,   407,    -1,    -1,   138,    -1,
+     409,    -1,   408,   409,    -1,   410,   412,   413,   414,    10,
+      -1,   382,   411,    -1,    -1,    43,    19,   169,    44,    -1,
+      -1,    14,   374,   382,    15,    -1,    -1,    59,    -1,   238,
+      -1,    -1,   125,   415,    -1,   382,   416,    -1,    -1,    30,
+     417,    -1,    -1,    20,   382,    -1,    95,   419,   420,    12,
+     423,    -1,    -1,   103,    -1,   104,    -1,   421,   422,    -1,
+     167,    -1,   167,   168,    -1,    -1,    58,   167,    -1,    58,
+     167,   168,    -1,   382,    10,    -1,   423,   382,    10,    -1,
+     426,   427,   238,    -1,   425,   427,   238,    -1,    50,    -1,
+      63,    -1,    -1,    64,    -1,   367,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const unsigned short yyrline[] =
+{
+       0,   245,   245,   247,   251,   253,   256,   259,   262,   275,
+     278,   281,   284,   290,   302,   308,   314,   318,   322,   338,
+     343,   351,   361,   367,   374,   533,   538,   545,   560,   569,
+     572,   578,   583,   586,   588,   592,   610,   625,   631,   637,
+     647,   646,   650,   657,   663,   673,   679,   685,   693,   696,
+     702,   707,   713,   719,   734,   740,   743,   773,   772,   785,
+     795,   800,   805,   815,   826,   836,   867,   873,   879,   889,
+     903,   912,   918,   931,   944,   950,   953,   957,   963,   966,
+     972,   977,   976,   982,  1037,  1054,  1060,  1064,  1070,  1076,
+    1082,  1088,  1094,  1101,  1104,  1107,  1111,  1119,  1125,  1137,
+    1143,  1150,  1156,  1163,  1166,  1172,  1175,  1178,  1182,  1190,
+    1209,  1217,  1225,  1233,  1244,  1250,  1256,  1262,  1281,  1287,
+    1293,  1299,  1305,  1327,  1331,  1330,  1336,  1342,  1341,  1347,
+    1353,  1359,  1382,  1394,  1402,  1405,  1409,  1426,  1432,  1438,
+    1443,  1452,  1462,  1501,  1507,  1513,  1523,  1530,  1536,  1543,
+    1551,  1556,  1564,  1570,  1582,  1591,  1597,  1609,  1627,  1638,
+    1651,  1669,  1681,  1684,  1709,  1715,  1722,  1728,  1736,  1742,
+    1749,  1755,  1765,  1770,  1776,  1781,  1798,  1803,  1809,  1815,
+    1818,  1822,  1841,  1846,  1852,  1857,  1862,  1867,  1873,  1881,
+    1901,  1920,  2010,  2018,  2025,  2028,  2031,  2034,  2037,  2040,
+    2043,  2046,  2049,  2052,  2055,  2058,  2061,  2064,  2067,  2070,
+    2073,  2076,  2079,  2082,  2085,  2088,  2091,  2094,  2097,  2100,
+    2103,  2106,  2110,  2120,  2134,  2152,  2187,  2193,  2198,  2203,
+    2210,  2212,  2216,  2219,  2224,  2229,  2234,  2241,  2247,  2251,
+    2258,  2265,  2274,  2282,  2284,  2291,  2299,  2305,  2315,  2328,
+    2350,  2353,  2359,  2361,  2365,  2368,  2412,  2415,  2419,  2422,
+    2426,  2435,  2441,  2447,  2454,  2457,  2461,  2471,  2488,  2491,
+    2506,  2512,  2517,  2522,  2528,  2532,  2540,  2547,  2554,  2558,
+    2560,  2564,  2570,  2573,  2576,  2579,  2595,  2611,  2622,  2649,
+    2660,  2683,  2689,  2695,  2709,  2715,  2721,  2723,  2727,  2730,
+    2734,  2737,  2750,  2771,  2786,  2799,  2809,  2814,  2821,  2823,
+    2827,  2841,  2849,  2853,  2860,  2867,  2874,  2881,  2891,  2904,
+    2914,  2925,  2931,  2937,  2965,  2971,  3001,  3010,  3021,  3026,
+    3043,  3069,  3108,  3114,  3118,  3132,  3154,  3159,  3172,  3177,
+    3184,  3204,  3209,  3215,  3222,  3234,  3239,  3243,  3247,  3266,
+    3282,  3300,  3332,  3350,  3363,  3382,  3386,  3388,  3392,  3398,
+    3404,  3429,  3435,  3443,  3450,  3452,  3459,  3471,  3483,  3498,
+    3518,  3525,  3537,  3548,  3560,  3572,  3578,  3588,  3597,  3606,
+    3622,  3628,  3637,  3653,  3659,  3665,  3674,  3680,  3694,  3699,
+    3717,  3723,  3729,  3734,  3740,  3745,  3751,  3757,  3764,  3771,
+    3777,  3783,  3795,  3806,  3811,  3818,  3823,  3830,  3837,  3844,
+    3853,  3860,  3864,  3867,  3871,  3883,  3893,  3898,  3906,  3913,
+    3920,  3927,  3934,  3941,  3948,  3954,  3960,  3966,  3973,  3980,
+    3992,  3998,  4003,  4008,  4017,  4024,  4030,  4034,  4039,  4043,
+    4050,  4056,  4058,  4068,  4072,  4079,  4086,  4096,  4103,  4107,
+    4106,  4110,  4115,  4126,  4131,  4136,  4144,  4150,  4156,  4166,
+    4177,  4183,  4187,  4189,  4193,  4196,  4217,  4222,  4228,  4234,
+    4241,  4243,  4247,  4258,  4264,  4356,  4359,  4364,  4362,  4436,
+    4440,  4443,  4447,  4474,  4476,  4480,  4482,  4486,  4489,  4493,
+    4545,  4551,  4561,  4563,  4567,  4575,  4586,  4618,  4629,  4636,
+    4642,  4647,  4657,  4665,  4677,  4687,  4694,  4703,  4712,  4721,
+    4726,  4736,  4742,  4744,  4756,  4761,  4769,  4775,  4785,  4787,
+    4790,  4793,  4798,  4804,  4809,  4824,  4827,  4829,  4842,  4847,
+    4853,  4863,  4865,  4869,  4873,  4880,  4885,  4891,  4897,  4903,
+    4907,  4912,  4915,  4936,  4943,  4948,  4952,  4958,  4964,  4975,
+    4988,  4991,  4995,  4997,  5001,  5004,  5008,  5025,  5062,  5069,
+    5076,  5090,  5099,  5106,  5109,  5116,  5125,  5149,  5161,  5167,
+    5173,  5179,  5186,  5192,  5198,  5203,  5209,  5215,  5228,  5234,
+    5247,  5252,  5258,  5261,  5265,  5272,  5280,  5285,  5291,  5296,
+    5302,  5307,  5319,  5325,  5329,  5334,  5352,  5357,  5363,  5368,
+    5374,  5377,  5382,  5389,  5396,  5400,  5407,  5414,  5416,  5423,
+    5430,  5436,  5442,  5452,  5463,  5469,  5472,  5479,  5486
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE
+/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "T_SCORE", "T_STAFF", "T_VOICE", "T_GRIDS", 
+  "T_BLOCKHEAD", "T_NUMBER", "T_EQUAL", "T_SEMICOLON", "T_NEWLINE", 
+  "T_COLON", "T_COMMA", "T_LBRACKET", "T_RBRACKET", "T_LBRACE", 
+  "T_RBRACE", "T_VARIABLE", "T_DASH", "T_PLUS", "T_PLACE", "T_ALL", 
+  "T_WITH", "T_CUE", "T_GRACE", "T_XNOTE", "T_DIAM", "T_DOT", 
+  "T_MULTIWHOLE", "T_LET_M", "T_LET_R", "T_LET_S", "T_LET_U", "T_PITCH", 
+  "T_SHARP", "T_AMPERSAND", "T_LET_N", "T_LET_X", "T_DBLFLAT", "T_LETTER", 
+  "T_LYRICS", "T_PAD", "T_LPAREN", "T_RPAREN", "T_LVAR", "T_MUSIC", 
+  "T_HEADSHAPES", "T_HS", "T_SWINGUNIT", "T_POSTSCRIPT", "T_SCOREFEED", 
+  "T_BARTYPE", "T_HAT", "T_TILDE", "T_QUESTION", "T_LINETYPE", "T_LINE", 
+  "T_TO", "T_STAR", "T_BULGE", "T_CURVE", "T_TIE", "T_PRINTTYPE", "T_NL", 
+  "T_STAFFLINES", "T_FFAMILY", "T_PARAGRAPH", "T_PARATYPE", "T_NUMVAR", 
+  "T_FNUMVAR", "T_2FNUMVAR", "T_RATNUMLISTVAR", "T_RANGELISTVAR", 
+  "T_TIMEUNIT", "T_FONTVAR", "T_STRVAR", "T_CLEFVAR", "T_VVAR", 
+  "T_BARSTLISTVAR", "T_SCORESEP", "T_FONT", "T_SLASH", "T_KEY", "T_TIME", 
+  "T_CUT", "T_COMMON", "T_CLEF", "T_MULTIREST", "T_YESNOVAR", "T_BM", 
+  "T_ESBM", "T_EBM", "T_INVISBAR", "T_OCTAVE", "T_ROLL", "T_VISVAR", 
+  "T_WHEREUSED", "T_UNSET", "T_VCOMBINE", "T_VCOMBVAL", "T_SCOREPAD", 
+  "T_WORD", "T_UP", "T_DOWN", "T_ENDING", "T_ENDENDING", "T_FAMILY", 
+  "T_ENDSTYLE", "T_ENDTYPE", "T_SLASHMARK", "T_ALT", "T_TITLE", 
+  "T_REHEARSAL", "T_NUM", "T_LET", "T_MNUM", "T_TRANSPOSE", "T_XPOS_INT", 
+  "T_PEDAL", "T_PHRASE", "T_MUSSYM", "T_L_ANGLE", "T_MODIFIER", 
+  "T_R_ANGLE", "T_TIL", "T_MIDI", "T_PEDSTYLE", "T_PEDSTAR", 
+  "T_HIDECHANGES", "T_SLUR", "T_UNITS", "T_CENTIMETERS", "T_UNITTYPE", 
+  "T_TAB", "T_TICKS", "T_NOWHERE_SLIDE", "T_LEN", "T_EXCLAM", 
+  "T_OTHERTEXT", "T_ORDER", "T_GRIDPLACE", "T_GRPLVALUE", "T_DRUM", 
+  "T_RPT", "T_STRING", "T_HO", "T_REH_STYLE", "T_REHTYPE", "T_L_DBLANGLE", 
+  "T_R_DBLANGLE", "T_SLOPE", "T_PSVAR", "T_PAGESIZE", "T_ORIENTATION", 
+  "$accept", "song", "item", "context", "ssv_context", "alloc_ssv", 
+  "new_context", "blockhead_context", "music_context", "grid_context", 
+  "stringpair", "headshape_context", "staffnum", "voicenum", "num", 
+  "assignment", "terminator", "assign", "@1", "@2", "visval", 
+  "vschemetype", "allocbeamlist", "ratnumlist", "nonempty_ratnumlist", 
+  "subbeam", "@3", "time_item", "swing_time", "opt_rs", "alloc_rangelist", 
+  "rangelist", "rangeitem", "rangetail", "grplabel", "optlabel2", 
+  "glabel", "alloc_barstlist", "barstlist", "barst_item", "mark_order", 
+  "orderlist", "orderitem", "marktype", "timesig", "tsiglist", "@4", 
+  "meas_tsig", "@5", "fraction", "numerator", "numerator_value", 
+  "opt_ts_visibility", "opt_n", "keyspec", "stafflinedef", 
+  "tab_string_list", "tab_item", "opt_str_acc", "opt_ticks", "flagval", 
+  "minscsep", "maxscsep", "minscpad", "maxscpad", "pagesize", 
+  "orientation", "vcombine_value", "opt_vcombine_qualifier", "end_type", 
+  "updown", "majmin", "pedstyle", "transpose_interval", "title", "tfont", 
+  "title_font", "font_family", "title_size", "titleA", "paragraph", 
+  "opt_paratype", "paramname", "string", "noteinfo", "init_staff", 
+  "sv_spec", "sv_map_list", "sv_map_entry", "map_start", "map_finish", 
+  "sv_map_item_list", "voice_id", "sv_and", "sv_item", "notecolon", 
+  "grp_stafflist", "grp_staff_item", "grp_staff_range", "voice_spec", 
+  "voice_tail", "groupinfo", "groupdata", "mid_meas_param", 
+  "mid_meas_list", "mid_meas_item", "mm_context", "mm_params", 
+  "mm_param_item", "grp_attributes", "styleinfo", "gtc", 
+  "extra_styleinfo", "alloc_grpsyl", "marklist", "marklistA", "markitem", 
+  "hor_offset", "opt_plus_or_minus", "other_attr", "attr_list", 
+  "attr_item", "alloc_marklist", "opt_dir", "marks", "mark", "mark_item", 
+  "shorthand_mark", "notetype", "dir", "beammark", "time_val", 
+  "crossbeam", "basic_time_val", "opt_more_time", "more_time_item", 
+  "alloc_timelist", "opt_m", "dots", "padding", "padspec", "opt_minus", 
+  "group", "special_group", "extra_attr", "spec_grp_alloc", "extra_item", 
+  "note_opts", "notelist", "opt_other_staff", "css_with", "some_notes", 
+  "notedata", "notedata1", "opt_bend", "pitch", "opt_accidental", 
+  "opt_octave", "acc_symbol", "octave", "minuslist", "pluslist", 
+  "slur_item", "start_slur", "slurlist", "fullslurlist", "slurnote", 
+  "grp_locsave", "loc_variable", "ntuplet", "printtup", "start_tuplet", 
+  "rbrace", "opt_side", "opt_time", "lyricinfo", "lyric_id", 
+  "lyr_opt_place", "opt_place", "staff_list", "staff_item", "staff_range", 
+  "more_lyric_ids", "@6", "verse_spec", "verselist", "verse_item", 
+  "verse_range", "alloc_lyr_grpsyl", "lyricdata", "lyr_tlist", 
+  "lyrics_timelist", "lyr_time_item", "lyr_tm", "lyrtuplet", "opt_space", 
+  "lyr_verse", "verse_string", "os_directive", "@7", "opt_temp_margin", 
+  "temp_margin", "opt_equals", "opt_semi", "directive", "barinfo", 
+  "precbartype", "bar_items", "bar_opt", "ending_info", "chk_dup_reh", 
+  "rehearsal_mark", "location", "alloc_loc", "xcoord", "xterm", 
+  "east_or_west", "xoffsetlist", "xoffset", "plus_or_minus", "xoffsetval", 
+  "ycoord", "yterm", "north_or_south", "yoffsetlist", "yoffset", 
+  "yoffsetval", "floatnum", "opt_decimal_part", "numstr", "variable", 
+  "line", "line_alloc", "linetype", "opt_line_str", "curve", 
+  "curve_alloc", "curve_tail", "loc_list", "bulgelist", "bulge_value", 
+  "curve_loc", "stuff_info", "stuff_header", "midi", "midi_staff", 
+  "stuff_id", "stuff_type", "opt_size", "opt_modifier", "opt_dist", 
+  "stuff_dist", "opt_exclam", "stufflist", "stuff_item", "beat_offset", 
+  "gracebackup", "steps_offset", "opt_string", "til_clause", "til_val", 
+  "til_suffix", "til_offset", "roll_cmd", "opt_roll_dir", "roll_extent", 
+  "roll_start", "roll_end", "roll_offsetlist", "printcmd", "postscript", 
+  "printtype", "opt_loc", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const unsigned short yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
+     305,   306,   307,   308,   309,   310,   311,   312,   313,   314,
+     315,   316,   317,   318,   319,   320,   321,   322,   323,   324,
+     325,   326,   327,   328,   329,   330,   331,   332,   333,   334,
+     335,   336,   337,   338,   339,   340,   341,   342,   343,   344,
+     345,   346,   347,   348,   349,   350,   351,   352,   353,   354,
+     355,   356,   357,   358,   359,   360,   361,   362,   363,   364,
+     365,   366,   367,   368,   369,   370,   371,   372,   373,   374,
+     375,   376,   377,   378,   379,   380,   381,   382,   383,   384,
+     385,   386,   387,   388,   389,   390,   391,   392,   393,   394,
+     395,   396,   397,   398,   399,   400,   401,   402,   403,   404,
+     405,   406,   407,   408,   409
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const unsigned short yyr1[] =
+{
+       0,   155,   156,   156,   157,   157,   157,   157,   157,   157,
+     157,   157,   157,   157,   158,   158,   158,   158,   158,   159,
+     159,   159,   160,   161,   162,   163,   164,   165,   166,   167,
+     168,   169,   170,   171,   171,   172,   172,   172,   172,   172,
+     173,   172,   172,   172,   172,   172,   172,   172,   172,   172,
+     172,   172,   172,   172,   172,   172,   172,   174,   172,   172,
+     172,   172,   172,   172,   172,   172,   172,   172,   175,   175,
+     175,   176,   176,   176,   177,   178,   178,   179,   179,   179,
+     179,   181,   180,   182,   182,   183,   183,   184,   184,   184,
+     184,   184,   185,   186,   186,   186,   187,   188,   188,   189,
+     189,   190,   190,   191,   192,   193,   193,   193,   194,   195,
+     196,   196,   196,   197,   198,   198,   198,   198,   198,   198,
+     198,   198,   199,   200,   201,   200,   202,   203,   202,   204,
+     204,   204,   204,   204,   205,   205,   206,   207,   207,   208,
+     208,   209,   209,   210,   210,   210,   210,   211,   211,   212,
+     213,   213,   214,   214,   215,   215,   216,   217,   217,   218,
+     219,   219,   220,   220,   221,   221,   222,   222,   223,   223,
+     224,   224,   225,   225,   226,   226,   227,   227,   227,   228,
+     229,   230,   231,   231,   232,   232,   233,   233,   234,   234,
+     234,   235,   236,   236,   237,   237,   237,   237,   237,   237,
+     237,   237,   237,   237,   237,   237,   237,   237,   237,   237,
+     237,   237,   237,   237,   237,   237,   237,   237,   237,   237,
+     237,   237,   238,   238,   239,   239,   239,   240,   241,   241,
+     242,   242,   243,   244,   245,   246,   246,   247,   247,   248,
+     249,   249,   250,   251,   251,   252,   253,   253,   254,   254,
+     255,   255,   256,   256,   257,   257,   258,   258,   259,   259,
+     260,   261,   261,   261,   262,   262,   263,   263,   264,   265,
+     265,   265,   266,   266,   267,   267,   268,   269,   269,   270,
+     270,   271,   271,   271,   271,   271,   271,   271,   271,   271,
+     271,   272,   272,   272,   273,   273,   274,   274,   275,   275,
+     276,   276,   276,   276,   276,   277,   278,   278,   279,   279,
+     280,   281,   281,   282,   282,   282,   282,   283,   283,   283,
+     283,   284,   284,   285,   285,   285,   286,   286,   287,   287,
+     288,   288,   289,   289,   290,   291,   292,   292,   293,   293,
+     294,   295,   296,   296,   297,   297,   298,   299,   300,   301,
+     301,   301,   301,   301,   301,   301,   302,   302,   303,   304,
+     304,   305,   306,   306,   307,   307,   307,   307,   307,   307,
+     307,   307,   307,   307,   307,   307,   308,   308,   308,   308,
+     308,   308,   308,   308,   308,   308,   308,   308,   309,   309,
+     310,   311,   311,   312,   312,   313,   313,   313,   313,   313,
+     314,   314,   314,   315,   315,   316,   316,   317,   318,   319,
+     319,   319,   320,   320,   321,   322,   323,   323,   323,   323,
+     323,   323,   323,   323,   323,   324,   325,   325,   325,   325,
+     326,   327,   328,   328,   329,   329,   330,   331,   332,   333,
+     333,   334,   334,   334,   335,   336,   336,   336,   337,   338,
+     337,   339,   339,   340,   340,   341,   342,   342,   343,   344,
+     345,   345,   346,   346,   347,   348,   348,   349,   350,   350,
+     351,   351,   352,   352,   353,   353,   353,   354,   353,   353,
+     355,   355,   356,   357,   357,   358,   358,   359,   359,   360,
+     361,   361,   362,   362,   363,   363,   363,   363,   363,   363,
+     363,   363,   364,   364,   365,   366,   366,   366,   366,   367,
+     368,   369,   370,   370,   370,   371,   371,   371,   372,   372,
+     373,   374,   374,   375,   375,   376,   377,   377,   378,   378,
+     378,   379,   379,   380,   381,   382,   382,   382,   383,   383,
+     384,   385,   386,   387,   388,   388,   389,   389,   390,   391,
+     392,   392,   393,   393,   394,   394,   395,   396,   397,   398,
+     398,   398,   399,   400,   400,   401,   402,   402,   402,   402,
+     402,   402,   403,   403,   404,   404,   405,   405,   406,   406,
+     407,   407,   408,   408,   409,   410,   411,   411,   412,   412,
+     413,   413,   413,   414,   414,   415,   416,   416,   417,   417,
+     418,   419,   419,   419,   420,   421,   421,   422,   422,   422,
+     423,   423,   424,   424,   425,   426,   427,   427,   427
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const unsigned char yyr2[] =
+{
+       0,     2,     1,     2,     1,     1,     1,     1,     2,     2,
+       1,     3,     1,     2,     1,     1,     1,     1,     2,     2,
+       3,     4,     1,     0,     1,     1,     1,     3,     1,     1,
+       1,     1,     2,     1,     1,     4,     2,     3,     5,     4,
+       0,     4,     4,     4,     5,     4,     4,     3,     3,     3,
+       3,     3,     3,     3,     3,     3,     2,     0,     4,     3,
+       4,     4,     3,     3,     3,     5,     3,     3,     1,     1,
+       1,     0,     1,     1,     0,     0,     1,     1,     1,     3,
+       3,     0,     4,     4,     1,     0,     1,     0,     2,     2,
+       1,     1,     0,     0,     1,     3,     3,     0,     2,     0,
+       4,     0,     2,     1,     0,     0,     1,     3,     2,     1,
+       1,     3,     3,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     2,     1,     0,     3,     1,     0,     4,     1,
+       1,     3,     3,     1,     1,     3,     1,     0,     1,     0,
+       1,     3,     3,     2,     2,     1,     4,     1,     2,     4,
+       0,     1,     0,     1,     1,     1,     1,     0,     2,     2,
+       0,     3,     1,     2,     0,     1,     0,     2,     0,     1,
+       1,     1,     1,     1,     0,     1,     1,     2,     1,     1,
+       6,     2,     0,     1,     0,     1,     0,     3,     1,     2,
+       3,     7,     0,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     3,     4,     3,     1,     0,     1,     1,
+       1,     2,     3,     1,     1,     1,     3,     1,     3,     1,
+       1,     2,     1,     1,     3,     2,     0,     2,     2,     4,
+       0,     2,     1,     2,     1,     5,     0,     1,     1,     2,
+       4,     1,     1,     1,     1,     3,     3,     3,     2,     1,
+       4,     6,     0,     3,     0,     4,     0,     0,     1,     1,
+       3,     3,     1,     1,     1,     1,     3,     2,     2,     2,
+       2,     1,     1,     2,     0,     1,     0,     1,     1,     3,
+       1,     3,     2,     2,     2,     0,     0,     1,     1,     3,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     2,     1,     1,     0,     1,     0,     3,
+       1,     1,     0,     2,     4,     0,     0,     1,     0,     2,
+       1,     3,     0,     1,     1,     1,     2,     2,     0,     1,
+       2,     2,     3,     2,     2,     1,     0,     2,     2,     0,
+       3,     1,     0,     3,     1,     1,     1,     2,     1,     1,
+       1,     1,     1,     1,     1,     3,     2,     5,     5,     3,
+       5,     7,     4,     4,     6,     4,     5,     4,     0,     1,
+       1,     0,     1,     0,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     2,     1,     2,     4,     1,     0,
+       1,     1,     1,     2,     2,     2,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     8,     0,     1,     1,     1,
+       1,     1,     0,     1,     0,     2,     4,     3,     1,     0,
+       1,     1,     1,     3,     2,     0,     2,     2,     0,     0,
+       5,     1,     1,     1,     3,     2,     0,     2,     0,     2,
+       0,     1,     1,     2,     2,     3,     1,     5,     0,     1,
+       1,     2,     2,     5,     2,     1,     1,     0,     3,     1,
+       0,     2,     3,     0,     1,     0,     1,     1,     1,     3,
+       0,     3,     0,     2,     1,     2,     1,     1,     3,     3,
+       3,     7,     2,     1,     0,     1,     1,     1,     1,     6,
+       0,     2,     1,     3,     1,     1,     1,     1,     0,     2,
+       2,     1,     1,     1,     2,     2,     1,     3,     1,     1,
+       1,     0,     2,     2,     1,     1,     3,     2,     0,     1,
+       1,     1,     7,     0,     0,     1,     0,     4,     7,     0,
+       2,     2,     1,     3,     1,     3,     2,     1,     3,     6,
+       6,     2,     1,     1,     1,     1,     2,     1,     1,     1,
+       1,     1,     0,     3,     0,     1,     0,     2,     2,     3,
+       0,     1,     1,     2,     5,     2,     0,     4,     0,     4,
+       0,     1,     1,     0,     2,     2,     0,     2,     0,     2,
+       5,     0,     1,     1,     2,     1,     2,     0,     2,     3,
+       2,     3,     3,     3,     1,     1,     0,     1,     1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const unsigned short yydefact[] =
+{
+       0,     0,    23,     0,     0,    26,    24,    12,   439,     0,
+      25,    28,     0,   614,   477,   545,   615,     0,   185,   193,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   571,   601,     0,     0,
+       0,     0,     0,     0,   184,     0,   569,   570,   567,   568,
+     562,     0,     0,   109,   222,     0,     0,     0,     2,     4,
+      14,    15,    23,    16,    10,    17,     5,     0,     0,     6,
+       0,     7,     0,     0,     0,     0,   226,   485,     0,   492,
+     475,   490,   476,   487,     0,     0,   572,   565,   488,   479,
+     616,   616,    13,    19,    22,    31,    23,    29,     0,   440,
+       0,     0,   438,   342,    85,   480,     0,    36,     0,     0,
+      74,    92,    57,     0,     0,     0,     0,   104,     0,     0,
+       0,   485,     0,   602,   603,     0,     0,   200,   199,   197,
+     194,   202,   203,   216,   211,   198,   219,   218,   221,   208,
+     201,   196,   213,   214,   195,   217,   209,   210,   220,   205,
+     215,   207,   204,   212,   206,    56,    40,   342,     0,     0,
+     186,   182,     0,     0,     0,     0,     0,     1,     3,    18,
+      33,    34,    32,     0,   566,   184,     0,     0,     8,   233,
+     246,     0,   229,   230,     0,   228,   237,   240,   243,   486,
+       0,     9,   474,     0,   543,   549,   572,     0,     0,   564,
+     563,   561,     0,   574,   510,   617,   618,     0,     0,    20,
+      23,    30,   458,   442,   445,   448,   441,   343,     0,   330,
+      84,   331,    86,    59,   338,   478,   145,   139,    50,     0,
+       0,   535,    37,     0,    75,    93,     0,    51,    67,    53,
+      71,   105,   156,   157,   390,     0,    48,   391,   133,   129,
+     130,   136,    49,   124,   123,   126,     0,   134,   225,   155,
+     154,    54,   605,     0,   607,    70,    69,    68,    55,   166,
+     160,     0,    52,   171,   170,    62,     0,     0,   183,   181,
+     172,   173,     0,   176,     0,   178,    64,    66,    63,   162,
+     164,     0,   118,   115,   119,   120,   121,   114,   117,   116,
+      47,   110,   113,   186,   223,    27,     0,   245,   242,   256,
+     231,     0,   235,   239,     0,     0,   250,   241,    11,     0,
+     342,     0,   503,   504,     0,     0,     0,   497,   494,   493,
+     496,     0,     0,     0,   439,   489,   586,   558,   582,   588,
+       0,   575,   439,     0,   613,   612,    21,   430,   458,   326,
+     436,     0,   458,   462,     0,   466,     0,     0,   444,     0,
+     437,    42,   332,   483,   481,     0,   140,   144,   143,    35,
+     540,   537,   538,     0,    81,    87,    76,    78,    77,    97,
+      45,    94,    58,    72,    73,    43,    97,    46,   106,     0,
+      60,   395,   396,   397,   398,   399,   174,   174,   392,     0,
+     122,   138,   127,     0,     0,   606,     0,     0,   604,    41,
+     168,   342,    61,   159,     0,   485,   188,   179,     0,   177,
+     165,    39,   163,     0,     0,     0,   247,     0,   256,   252,
+     276,   257,   258,   254,   256,     0,   234,   232,   238,   244,
+       0,     0,   248,   418,   419,   420,   421,   417,   422,   423,
+     416,   424,   495,     0,   502,   184,     0,     0,     0,   491,
+       0,   557,     0,     0,     0,   585,   583,     0,   590,   573,
+       0,   522,   521,     0,   541,     0,   518,   514,     0,   512,
+     523,     0,   458,   327,   468,     0,     0,   459,   470,   463,
+     464,   446,   447,   443,     0,   339,   336,   484,     0,     0,
+     147,   150,   536,   539,    38,     0,    91,    90,    44,     0,
+       0,    99,     0,   108,     0,   158,   175,   141,   142,   125,
+       0,   132,   135,   131,     0,   600,   608,   169,   167,     0,
+     187,     0,   189,    65,   111,   112,   485,   261,   262,   263,
+       0,   253,   276,   362,   326,   269,   259,   256,   236,   251,
+     250,   341,   182,   500,   499,   498,     0,     0,   576,     0,
+       0,   591,   592,   593,   576,   524,     0,   511,   520,     0,
+     431,     0,   469,   465,   452,   456,     0,   451,   453,   472,
+     471,   449,   337,   333,    83,   335,   482,   146,   148,   152,
+     151,     0,    88,    89,    80,    79,    98,     0,    96,    95,
+     107,   128,   610,     0,   609,   161,   180,   190,     0,     0,
+       0,     0,   264,     0,   277,   296,   345,   356,     0,   344,
+     359,   268,   432,   249,   572,   546,     0,     0,   560,     0,
+       0,     0,     0,   559,     0,   531,   526,   534,     0,   519,
+     517,   516,   515,   513,   434,     0,   455,     0,     0,     0,
+       0,   153,   393,    82,   101,   103,   611,   191,     0,     0,
+       0,   260,   276,     0,   305,   317,   318,   320,   319,     0,
+     342,   321,   322,     0,     0,   294,     0,   278,   279,   283,
+     285,   284,   340,   282,   306,   328,   324,   325,     0,   306,
+     342,     0,   297,   298,   300,   346,     0,     0,     0,   306,
+     349,   408,   347,   355,   409,   361,   370,   365,   366,     0,
+       0,   369,   372,   373,   374,   371,   368,   358,   362,   356,
+     364,   388,   433,     0,     0,   184,   542,     0,   342,   548,
+       0,   580,   577,   587,   589,   596,   594,   584,   509,   525,
+       0,     0,   467,   457,     0,   454,   450,   338,   403,   405,
+     400,   149,   394,   401,   402,     0,     0,   267,   266,   265,
+     270,   415,     0,   288,     0,   290,   289,   292,   291,   287,
+       0,   295,     0,   272,   304,   307,     0,   323,   302,   303,
+       0,   255,     0,   357,   351,   354,   353,   393,   350,   410,
+     393,     0,   411,   412,   367,     0,     0,   363,     0,   393,
+     389,   376,   152,   391,   426,   507,   508,   506,   505,   576,
+     186,   550,   552,     0,   551,   554,   580,   581,   578,   598,
+     595,     0,   532,   529,   528,   530,   527,   435,   473,   334,
+     404,   406,   102,   100,   314,   313,   316,   315,   312,   281,
+     308,   310,   311,   286,   293,   280,     0,   274,     0,   301,
+     299,   352,   414,   306,   413,   375,   360,   379,     0,     0,
+       0,   388,     0,   393,     0,   388,   427,   429,   428,   434,
+     501,     0,     0,   556,   342,   579,     0,   597,   533,     0,
+       0,   271,   329,   407,   393,   388,     0,   383,   382,     0,
+     388,   387,     0,   385,     0,   547,   553,   555,   599,   309,
+     273,   277,   377,   378,   388,     0,   380,   386,   425,     0,
+     384,   388,   275,   381
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const short yydefgoto[] =
+{
+      -1,    57,    58,    59,    60,    93,    94,    61,    62,    63,
+      64,    65,   180,   316,   231,    66,   172,    67,   269,   236,
+     268,   385,   234,   375,   376,   377,   505,   378,   223,   508,
+     235,   380,   381,   511,   598,   756,   654,   241,   387,   388,
+      68,   300,   301,   302,   252,   253,   399,   254,   520,   255,
+     256,   257,   400,   368,   246,   228,   499,   500,   589,   652,
+     261,   243,   390,   270,   412,   290,   421,   409,   528,   275,
+     282,   517,   286,   418,    69,   160,   279,   161,   277,   415,
+      71,    72,   155,   800,    74,    75,   181,   182,   183,   184,
+     437,   311,   185,   314,   186,   309,   187,   188,   307,   317,
+     442,   428,   429,   430,   431,   432,   540,   611,   612,   543,
+     544,   847,   881,   545,   676,   677,   678,   769,   770,   691,
+     692,   693,   762,   774,   839,   840,   841,   842,   679,   775,
+     694,   484,   777,   224,   496,   583,   650,   584,   362,   681,
+     682,   813,   615,   616,   617,   618,   783,   695,   619,   717,
+     718,   620,   719,   720,   801,   721,   397,   751,   398,   752,
+     753,   754,   703,   704,   791,   792,   793,   683,   474,   433,
+     869,   348,   571,   723,   742,    76,   100,   101,   102,   215,
+     216,   358,   360,   649,   576,   577,   578,   646,   349,   350,
+     351,   352,   353,   354,   355,   573,   487,   488,    77,   105,
+     225,   364,   498,   190,    78,    79,   197,   192,   329,   330,
+     455,   809,   461,   343,   475,   476,   643,   567,   477,   478,
+     479,   634,   635,   826,   739,   822,   636,   336,   502,   371,
+     481,    80,   332,    81,   726,    82,   333,   729,   811,   814,
+     815,   462,    83,    84,    85,   201,    86,    87,   203,   342,
+     628,   732,   818,   337,   338,   339,   465,   468,   563,   632,
+     736,   820,   877,    88,   125,   263,   264,   408,   525,    89,
+      90,    91,   207
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -693
+static const short yypact[] =
+{
+     997,    49,  -693,   101,   101,  -693,  -693,  -693,    43,   116,
+    -693,  -693,   143,  -693,  -693,  -693,  -693,   158,  -693,  -693,
+     199,   215,   254,   284,   296,   315,   372,   401,   410,   419,
+     421,   422,   424,   426,   101,   427,  -693,   244,   431,   732,
+     432,   433,   435,   436,   236,   438,  -693,  -693,  -693,  -693,
+    -693,   439,   440,  -693,  -693,   441,   443,   847,  -693,  -693,
+    -693,  -693,  -693,  -693,  -693,  -693,  -693,   378,   445,  -693,
+     123,  -693,   324,    26,   384,   309,  -693,   446,   447,  -693,
+    -693,    69,  -693,  -693,   451,   245,   414,  -693,  -693,  -693,
+      32,    32,  -693,  -693,  -693,  -693,  -693,  -693,   101,  -693,
+     454,   278,  -693,   449,   210,  -693,    41,   190,   182,   182,
+    -693,  -693,  -693,   381,   314,   383,   101,  -693,   101,    70,
+      51,   446,   225,  -693,  -693,   101,    57,  -693,  -693,  -693,
+    -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,
+    -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,
+    -693,  -693,  -693,  -693,  -693,  -693,  -693,   449,   405,    44,
+     430,   393,   295,    94,   344,   333,    29,  -693,  -693,  -693,
+    -693,  -693,  -693,   371,  -693,   236,   335,    68,  -693,  -693,
+     464,   489,   490,  -693,   101,   467,  -693,   353,  -693,  -693,
+     494,  -693,   114,   456,  -693,  -693,   414,   462,   182,  -693,
+     467,  -693,   101,   390,  -693,  -693,  -693,   314,   314,  -693,
+    -693,  -693,    28,  -693,   124,   502,  -693,  -693,   182,  -693,
+    -693,  -693,  -693,  -693,  -693,   448,   473,    15,  -693,   101,
+     511,   493,  -693,   507,   207,   101,   210,  -693,   504,  -693,
+     293,   101,  -693,   512,  -693,   492,  -693,   492,  -693,  -693,
+    -693,  -693,  -693,   332,   515,  -693,    50,  -693,  -693,  -693,
+    -693,  -693,   101,   520,   479,  -693,  -693,  -693,  -693,   101,
+     525,   101,  -693,  -693,  -693,  -693,   101,   314,  -693,  -693,
+    -693,  -693,   425,  -693,   411,  -693,  -693,  -693,  -693,  -693,
+     395,   101,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,
+      56,  -693,  -693,   430,  -693,  -693,   101,  -693,  -693,    21,
+    -693,   358,   467,  -693,   101,   101,   338,  -693,  -693,   575,
+     449,   314,  -693,  -693,   544,   549,   551,  -693,  -693,  -693,
+    -693,   519,   521,   521,    43,  -693,   522,   182,  -693,   552,
+     526,  -693,    43,   514,   504,   504,  -693,  -693,   553,   210,
+    -693,    24,    31,  -693,   561,  -693,   101,   101,  -693,   101,
+     562,  -693,   545,   565,  -693,   550,  -693,  -693,  -693,  -693,
+    -693,  -693,   511,   182,  -693,   377,   572,  -693,  -693,   567,
+     581,  -693,  -693,  -693,  -693,  -693,   567,   587,  -693,   101,
+    -693,  -693,  -693,  -693,  -693,  -693,   484,   484,  -693,    51,
+    -693,  -693,  -693,    85,   101,  -693,   182,   101,  -693,  -693,
+     503,   449,  -693,  -693,   566,   446,    26,  -693,   101,  -693,
+    -693,  -693,  -693,   371,   371,   314,  -693,   374,    25,  -693,
+     597,   465,  -693,  -693,    21,   101,  -693,  -693,  -693,  -693,
+     101,   101,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,
+    -693,  -693,  -693,   182,   504,   236,   101,   314,   101,  -693,
+     558,  -693,   560,   278,   598,  -693,  -693,   386,    -5,  -693,
+     278,  -693,  -693,   182,  -693,   606,  -693,  -693,   103,  -693,
+    -693,   594,   397,  -693,   591,    73,   234,    24,  -693,  -693,
+    -693,  -693,  -693,  -693,   604,  -693,   289,  -693,   182,   253,
+    -693,   492,  -693,  -693,  -693,   207,   595,   599,  -693,   207,
+     101,   583,   101,  -693,   101,  -693,  -693,  -693,  -693,   515,
+      51,  -693,  -693,  -693,   618,   182,   101,  -693,  -693,   101,
+    -693,   620,    26,  -693,  -693,  -693,   286,  -693,  -693,  -693,
+      33,  -693,   610,    80,   210,  -693,  -693,    17,   467,  -693,
+     619,  -693,   393,  -693,   504,  -693,   521,   521,    52,   101,
+     182,  -693,   504,   508,    52,  -693,   559,   386,  -693,   336,
+    -693,   101,  -693,  -693,  -693,   615,   621,   622,  -693,  -693,
+    -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,   505,
+    -693,    61,  -693,  -693,  -693,  -693,  -693,   314,  -693,  -693,
+    -693,  -693,  -693,   627,  -693,  -693,  -693,   504,   628,   629,
+     632,    22,  -693,   633,   138,   273,  -693,  -693,    91,  -693,
+     307,  -693,   623,  -693,   414,   630,   276,   198,  -693,   608,
+     635,   182,   644,  -693,   612,  -693,  -693,  -693,   631,  -693,
+    -693,  -693,  -693,  -693,   645,   101,  -693,   314,   101,   278,
+     100,  -693,   227,  -693,   647,   504,  -693,  -693,   101,   570,
+      33,  -693,  -693,   575,  -693,  -693,  -693,  -693,  -693,   314,
+     449,  -693,  -693,   101,   182,   398,   375,  -693,  -693,  -693,
+    -693,  -693,  -693,  -693,   318,   638,  -693,  -693,   101,   318,
+     449,   652,   650,  -693,  -693,    91,   575,   314,    37,   318,
+    -693,  -693,  -693,  -693,    19,  -693,  -693,  -693,  -693,   634,
+     550,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,
+    -693,    48,  -693,   101,   162,   236,  -693,   521,   449,  -693,
+     101,   527,  -693,  -693,  -693,   637,  -693,  -693,  -693,   386,
+     312,   210,  -693,  -693,   308,  -693,   502,  -693,  -693,  -693,
+    -693,  -693,  -693,   649,   651,   314,   625,  -693,  -693,  -693,
+    -693,  -693,    71,   504,   101,  -693,  -693,   193,   195,  -693,
+     182,  -693,   138,   636,  -693,  -693,   668,  -693,  -693,  -693,
+     182,  -693,   273,  -693,  -693,   504,  -693,   227,  -693,  -693,
+     227,   554,   550,  -693,  -693,   639,   258,    91,   542,   237,
+     504,  -693,    14,   450,    36,  -693,  -693,  -693,   504,   605,
+     430,   617,  -693,   182,   664,  -693,   527,  -693,  -693,   660,
+    -693,   182,  -693,  -693,  -693,  -693,  -693,  -693,  -693,   545,
+    -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,   504,   671,
+    -693,  -693,  -693,  -693,  -693,  -693,   653,  -693,   665,  -693,
+    -693,  -693,  -693,   318,  -693,  -693,  -693,  -693,   643,   646,
+     227,   314,   550,   252,   461,   314,  -693,  -693,  -693,   645,
+    -693,   314,   521,  -693,   449,  -693,   182,  -693,  -693,    71,
+     663,   674,  -693,  -693,   227,   314,   648,  -693,  -693,   227,
+     314,  -693,   654,  -693,   683,   504,  -693,  -693,  -693,  -693,
+    -693,   138,  -693,  -693,   314,   655,  -693,  -693,  -693,   382,
+    -693,   314,  -693,  -693
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const short yypgoto[] =
+{
+    -693,  -693,   640,  -693,  -693,   -53,   641,  -693,  -693,  -693,
+    -693,  -693,    16,   -83,    -3,  -693,  -693,  -693,  -693,  -693,
+    -693,  -693,  -693,  -693,   189,   186,  -693,   -98,  -693,  -693,
+    -693,  -693,   184,   316,  -693,  -693,   -55,  -693,  -693,   191,
+    -693,  -693,     3,  -693,  -693,  -693,  -693,   305,  -693,   187,
+    -693,   303,  -693,  -693,  -693,  -693,  -693,   209,  -693,   -93,
+     457,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,
+    -693,   317,  -693,  -693,  -693,  -168,   159,     9,  -298,  -693,
+    -693,  -693,  -693,     4,  -693,  -693,  -693,  -693,   530,  -693,
+    -693,  -693,   -64,  -693,   399,  -693,  -693,   400,  -693,  -244,
+     166,   283,  -370,  -693,  -693,   288,  -693,  -693,    63,  -693,
+    -693,  -693,  -693,  -503,  -180,  -693,   -48,  -693,  -693,  -693,
+    -693,   -57,  -693,  -659,  -693,  -153,  -693,  -693,  -693,  -587,
+    -693,   185,  -693,    81,  -693,  -693,  -693,  -693,   -15,  -693,
+     541,   -95,  -693,  -693,  -693,  -693,   117,    18,  -693,  -693,
+    -693,    23,  -693,    30,  -591,  -116,   -69,  -599,  -243,  -692,
+    -693,  -693,  -693,  -693,  -693,  -693,   -56,  -693,  -303,  -693,
+    -693,  -286,   192,  -693,  -127,  -693,  -693,  -693,   -13,  -435,
+     385,  -693,  -693,  -693,  -693,  -693,    95,  -693,  -693,  -693,
+    -693,   402,  -304,  -693,  -693,  -693,  -693,   260,  -693,  -693,
+    -693,  -693,  -693,  -111,  -693,  -693,  -693,  -693,  -693,  -693,
+    -693,  -693,   -77,  -693,  -693,  -693,  -693,  -693,   178,  -441,
+     271,  -693,  -693,  -693,  -693,  -693,   -70,   -91,  -693,   380,
+     188,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,
+    -121,  -535,  -693,  -693,  -693,  -693,  -693,  -693,  -185,  -693,
+    -540,  -693,   -61,  -693,   420,  -693,  -693,  -693,  -693,  -693,
+    -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,  -693,
+    -693,  -693,   667
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, parse error.  */
+#define YYTABLE_NINF -545
+static const short yytable[] =
+{
+      97,    97,   396,   247,    73,   425,   222,   303,   218,    70,
+     258,   334,   229,   206,   206,   210,   452,   232,   233,    96,
+      98,   200,   626,   434,   633,   410,   560,   680,   558,   803,
+     779,   121,   660,   347,   570,   564,  -224,   347,   485,   614,
+     788,   347,  -460,   209,   347,  -461,   176,   347,   489,    95,
+     291,   273,   366,   244,   561,   585,    95,   862,   541,    95,
+      92,    73,   271,   244,    99,   359,    70,   748,   749,   423,
+     403,   244,    97,   866,   509,   204,   867,   177,    95,   305,
+     248,    95,    97,   391,   392,   393,   394,   395,   176,  -348,
+     834,   798,   424,    95,   265,   211,   205,   266,   214,   835,
+     696,   221,   609,   227,   244,   653,   859,   574,    95,    95,
+     610,    95,   193,   240,   521,   242,   245,   251,   238,   786,
+     312,   627,    97,   319,   836,   103,   194,   361,  -348,   219,
+     195,   230,   404,  -348,  -348,  -348,   249,   250,   382,   697,
+      54,   262,   434,   356,   698,   699,   700,   663,   434,   651,
+     868,   283,   104,   274,   267,   789,   320,   346,   367,   760,
+     357,   664,   665,   666,   667,   668,   427,   106,   886,    54,
+     427,    54,   661,  -460,   427,   226,  -461,   541,   489,   405,
+     320,    97,   289,   799,   211,   680,   669,   473,   851,   196,
+      95,   852,   812,    54,   883,   837,   549,   905,  -342,   340,
+     861,  -522,  -348,  -521,   174,   284,    95,   670,   107,   217,
+     230,   344,   345,   701,   746,    95,    54,   730,    95,   321,
+     322,  -522,   285,  -521,   108,   453,   369,   323,   324,   325,
+     326,   221,   379,   221,   771,    95,   219,   220,   386,   219,
+     220,   671,   672,   327,   579,    95,   748,   749,   673,   501,
+     374,   483,   480,    95,   176,   460,   748,   749,   590,   211,
+      95,   434,   259,   109,   890,   260,   211,   199,   413,   870,
+     887,   748,   749,   414,   893,   674,   805,   806,   807,   856,
+     860,   416,   504,   706,   675,   902,    95,   244,   422,   707,
+     708,   709,   244,   110,   903,   889,   189,   587,   821,   906,
+     213,   710,    18,    97,   531,   111,   176,    54,   471,   472,
+     711,    97,    97,   910,   680,   524,   529,    95,   828,   582,
+     913,   463,   426,   179,   112,   454,   712,   383,   176,   470,
+     705,   713,   706,   384,   727,   684,   728,   896,   707,   708,
+     709,   244,  -137,  -137,   823,   714,   221,   123,   124,   824,
+     710,   440,   825,   491,   492,   486,   214,   441,   550,   711,
+     761,    95,   551,   685,   686,   687,   315,   715,   435,   259,
+     640,   548,   260,   436,   641,   712,   642,   537,   538,   539,
+     713,   113,   565,   501,   688,   772,   515,   480,   170,   171,
+     773,   175,   772,   784,   714,   178,   251,   912,   280,   281,
+     251,   523,   716,   689,    97,   471,   472,   586,   506,   507,
+     114,   595,   292,   347,   570,   533,   715,   767,   768,   115,
+     532,   671,   672,   526,   690,   608,   534,   535,   116,   536,
+     117,   118,    97,   119,   603,   120,   122,   211,   211,   724,
+     126,   156,   157,   604,   158,   159,   483,   162,   163,   164,
+     165,   716,   166,   553,   173,   555,   189,   202,   191,    54,
+     214,   554,   237,   198,   552,   293,   212,   214,   217,   630,
+     239,   272,   562,   276,   278,   637,   294,   287,   802,   625,
+     304,   288,   575,   306,   295,   391,   392,   393,   394,   395,
+     296,   486,   297,   864,   298,   244,   391,   392,   393,   394,
+     395,   308,   221,   313,   179,   318,   221,   596,   331,   379,
+     299,   386,   871,   341,   335,   359,   365,   251,   363,   370,
+     373,   372,    95,   211,   176,   389,   605,   391,   392,   393,
+     394,   395,   406,   471,   472,   402,   607,   407,   411,   419,
+     735,   221,   230,   417,   443,   444,   445,   446,   447,   420,
+      95,   448,   449,   456,   450,   858,   629,   810,   457,   451,
+     458,   748,   749,   459,   204,   464,   467,    95,   644,   347,
+     469,   490,   494,   495,   497,   764,   244,   391,   392,   393,
+     394,   395,   787,   766,   244,   509,   510,   230,   790,   443,
+     444,   445,   446,   447,   512,   780,   448,   449,   473,   450,
+     514,   655,   516,   527,   451,   443,   444,   445,   446,   447,
+     530,   542,   448,   449,   427,   450,   556,   559,   557,   566,
+     451,   892,   569,   572,   731,   581,   597,   592,   602,   613,
+     593,   606,   440,   631,   645,   648,   647,   656,   658,   657,
+     651,   659,   743,   827,   722,   575,   214,   221,   662,   750,
+     734,   744,   733,   725,   737,   757,   738,   758,   741,   740,
+     755,   776,   781,   782,   846,   817,   794,   819,   830,   833,
+     765,   831,   848,   763,   627,   872,   790,   874,   853,   844,
+     876,   880,   857,   855,   879,   778,   882,   884,   901,   849,
+     885,   900,   904,   908,   591,   594,   599,   168,   907,   911,
+     832,   785,   513,   169,   519,   600,   522,   601,   588,   863,
+     401,   624,   310,   438,   518,   439,   623,   547,   750,   546,
+     804,   909,   873,   759,   845,   850,   899,   816,   808,   621,
+     637,   747,   829,   328,   865,   702,   854,   797,   221,   622,
+     795,   796,   894,   745,   493,   639,   888,   580,   891,   568,
+     482,   878,   503,   897,   638,   875,     0,   466,   208,   655,
+       0,   843,     0,     0,     0,     0,   838,     0,     0,     0,
+       0,     0,     0,     0,   127,     0,     0,     0,     0,     0,
+       0,   128,     0,     0,   750,   898,     0,   750,     0,     0,
+       0,     0,     0,     0,     0,   750,   750,   129,     0,     0,
+       0,   130,   131,   132,   133,   134,   135,   136,   137,   138,
+     139,   140,   141,     0,     0,   142,   143,     0,     0,     0,
+       0,   144,     0,     0,     0,     0,     0,     0,   145,     0,
+       0,   146,     0,   147,     0,     0,     0,     0,     0,   148,
+     149,     0,     0,     0,     0,     0,     0,   167,     1,   150,
+       2,     3,     4,     5,     6,  -227,     0,   750,     7,   151,
+     750,  -227,     0,   152,     0,     0,     0,     0,     0,     0,
+       0,     0,   153,     0,     0,   895,     0,     0,     0,   154,
+       0,   750,     0,   838,     0,     0,   750,     0,     8,     9,
+    -544,     0,     0,    10,    11,     0,    12,    13,    14,  -544,
+       0,     0,     0,    15,  -544,     0,     0,     0,  -544,     0,
+      16,     0,    17,    18,  -192,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,  -184,     0,
+      32,    33,     0,     0,     0,    34,    35,     0,     0,     0,
+       0,    36,    37,    38,     0,    39,    40,     0,    41,     0,
+       0,     0,     0,     0,    42,    43,     0,     0,     0,    44,
+       0,     0,     0,     0,    45,     0,    46,  -544,    47,    48,
+       0,    49,     0,    50,    51,     0,     0,     0,    52,     0,
+       0,     0,     0,     0,     0,     0,     0,    53,     0,     0,
+       0,     0,    54,     0,    55,     0,     0,     0,     1,    56,
+       2,     3,     4,     5,     6,  -227,     0,     0,     7,     0,
+       0,  -227,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     8,     9,
+    -544,     0,     0,    10,    11,     0,    12,    13,    14,  -544,
+       0,     0,     0,    15,  -544,     0,     0,     0,  -544,     0,
+      16,     0,    17,    18,  -192,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,  -184,     0,
+      32,    33,     0,     0,     0,    34,    35,     0,     0,     0,
+       0,    36,    37,    38,     0,    39,    40,     0,    41,     0,
+       0,     0,     0,     0,    42,    43,     0,     0,     0,    44,
+       0,     0,     0,     0,    45,     0,    46,  -544,    47,    48,
+       0,    49,     0,    50,    51,     0,     0,     0,    52,     0,
+       0,     0,     0,     0,     0,     0,     0,    53,     0,     0,
+       0,     0,    54,     0,    55,     0,     0,     0,     0,    56
+};
+
+static const short yycheck[] =
+{
+       3,     4,   245,   119,     0,   303,   104,   175,   103,     0,
+     121,   196,   107,    90,    91,    98,   319,   108,   109,     3,
+       4,    85,   557,   309,   564,   269,   467,   614,   463,   721,
+     689,    34,    10,    16,    17,   470,    11,    16,    14,   542,
+     699,    16,    14,    96,    16,    14,    20,    16,   352,     8,
+     166,     7,    37,    34,    59,   496,     8,    43,   428,     8,
+      11,    57,   157,    34,    21,    13,    57,    19,    20,    13,
+      20,    34,    75,    37,    13,    43,    40,    73,     8,    11,
+      29,     8,    85,    35,    36,    37,    38,    39,    20,     9,
+      19,    43,    36,     8,    37,    98,    64,    40,   101,    28,
+       9,   104,    69,   106,    34,    44,   798,    34,     8,     8,
+      77,     8,    43,   116,    29,   118,   119,   120,   114,    82,
+     184,    69,   125,     9,    53,     9,    57,   218,    48,    29,
+      61,    28,    82,    53,    54,    55,    85,    86,   236,    48,
+     145,   125,   428,    19,    53,    54,    55,     9,   434,   135,
+     114,    57,     9,   109,    97,   136,    42,   210,   143,   662,
+      36,    23,    24,    25,    26,    27,   149,     9,   860,   145,
+     149,   145,   150,   145,   149,   134,   145,   547,   482,   262,
+      42,   184,   153,   135,   187,   772,    48,    84,   787,   120,
+       8,   790,   727,   145,   853,   124,   440,   889,     8,   202,
+     799,     8,   122,     8,    81,   111,     8,    69,     9,    19,
+      28,   207,   208,   122,   649,     8,   145,    19,     8,   105,
+     106,    28,   128,    28,     9,   320,   229,   113,   114,   115,
+     116,   234,   235,   236,   675,     8,    29,    30,   241,    29,
+      30,   103,   104,   129,    10,     8,    19,    20,   110,   365,
+      43,   349,   343,     8,    20,   332,    19,    20,   501,   262,
+       8,   547,    37,     9,   863,    40,   269,    22,   271,   809,
+     861,    19,    20,   276,   865,   137,   114,   115,   116,    21,
+      43,   277,   373,    25,   146,   884,     8,    34,   291,    31,
+      32,    33,    34,     9,   885,    43,    10,    44,   739,   890,
+      22,    43,    66,   306,   415,     9,    20,   145,    19,    20,
+      52,   314,   315,   904,   901,   406,   411,     8,    10,    30,
+     911,   334,   306,    14,     9,   321,    68,    34,    20,   342,
+      23,    73,    25,    40,    58,    62,    60,   872,    31,    32,
+      33,    34,    10,    11,    32,    87,   349,   103,   104,    37,
+      43,    13,    40,   356,   357,   351,   359,    19,   441,    52,
+     663,     8,   453,    90,    91,    92,    13,   109,    10,    37,
+      34,   435,    40,    15,    38,    68,    40,     3,     4,     5,
+      73,     9,   473,   499,   111,    10,   389,   478,    10,    11,
+      15,    67,    10,   696,    87,    11,   399,    15,   103,   104,
+     403,   404,   144,   130,   407,    19,    20,   498,    31,    32,
+       9,   509,    41,    16,    17,   418,   109,    19,    20,     9,
+     416,   103,   104,   407,   151,   536,   423,   424,     9,   425,
+       9,     9,   435,     9,   525,     9,     9,   440,   441,   624,
+       9,     9,     9,   526,     9,     9,   544,     9,     9,     9,
+       9,   144,     9,   456,     9,   458,    10,    43,    11,   145,
+     463,   457,    81,    12,   455,    94,    12,   470,    19,   560,
+      87,    66,   468,    43,    81,   566,   105,   133,   721,   556,
+     145,   148,   485,    19,   113,    35,    36,    37,    38,    39,
+     119,   487,   121,    43,   123,    34,    35,    36,    37,    38,
+      39,    12,   505,    36,    14,    11,   509,   510,    52,   512,
+     139,   514,   810,   123,    52,    13,    43,   520,    70,     8,
+      13,    28,     8,   526,    20,    13,   529,    35,    36,    37,
+      38,    39,    12,    19,    20,    20,   532,    58,    13,   128,
+     631,   544,    28,   118,    30,    31,    32,    33,    34,   154,
+       8,    37,    38,     9,    40,   798,   559,   725,     9,    45,
+       9,    19,    20,    44,    43,    43,    14,     8,   571,    16,
+      44,    10,    10,    28,     9,   670,    34,    35,    36,    37,
+      38,    39,   698,   674,    34,    13,    19,    28,   704,    30,
+      31,    32,    33,    34,    13,   690,    37,    38,    84,    40,
+      13,   597,   118,   100,    45,    30,    31,    32,    33,    34,
+      44,    14,    37,    38,   149,    40,    58,    19,    58,    13,
+      45,   864,    28,    32,   627,    21,    43,    32,    10,    19,
+      31,    11,    13,   125,    19,    13,    15,    10,     9,    11,
+     135,     9,   645,   741,    21,   648,   649,   650,    15,   652,
+      15,   647,    44,    23,    10,   658,    44,    87,    13,    28,
+      13,    23,    10,    13,    28,   138,    32,    30,    19,    44,
+     673,    20,     4,   669,    69,    58,   792,    13,   124,   770,
+      20,    28,   798,    44,    13,   688,    21,    44,    14,   780,
+      44,    28,    44,    10,   505,   509,   512,    57,    44,    44,
+     755,   697,   386,    62,   399,   514,   403,   520,   499,   802,
+     253,   552,   182,   314,   397,   315,   550,   434,   721,   431,
+     723,   901,   813,   660,   772,   782,   879,   730,   724,   544,
+     821,   650,   747,   192,   803,   618,   792,   719,   741,   547,
+     710,   718,   869,   648,   359,   567,   862,   487,   864,   478,
+     348,   821,   372,   874,   566,   816,    -1,   337,    91,   755,
+      -1,   764,    -1,    -1,    -1,    -1,   762,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    42,    -1,    -1,    -1,    -1,    -1,
+      -1,    49,    -1,    -1,   787,   876,    -1,   790,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   798,   799,    65,    -1,    -1,
+      -1,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    80,    -1,    -1,    83,    84,    -1,    -1,    -1,
+      -1,    89,    -1,    -1,    -1,    -1,    -1,    -1,    96,    -1,
+      -1,    99,    -1,   101,    -1,    -1,    -1,    -1,    -1,   107,
+     108,    -1,    -1,    -1,    -1,    -1,    -1,     0,     1,   117,
+       3,     4,     5,     6,     7,     8,    -1,   860,    11,   127,
+     863,    14,    -1,   131,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   140,    -1,    -1,   871,    -1,    -1,    -1,   147,
+      -1,   884,    -1,   879,    -1,    -1,   889,    -1,    41,    42,
+      43,    -1,    -1,    46,    47,    -1,    49,    50,    51,    52,
+      -1,    -1,    -1,    56,    57,    -1,    -1,    -1,    61,    -1,
+      63,    -1,    65,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    75,    76,    77,    78,    79,    80,    81,    -1,
+      83,    84,    -1,    -1,    -1,    88,    89,    -1,    -1,    -1,
+      -1,    94,    95,    96,    -1,    98,    99,    -1,   101,    -1,
+      -1,    -1,    -1,    -1,   107,   108,    -1,    -1,    -1,   112,
+      -1,    -1,    -1,    -1,   117,    -1,   119,   120,   121,   122,
+      -1,   124,    -1,   126,   127,    -1,    -1,    -1,   131,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   140,    -1,    -1,
+      -1,    -1,   145,    -1,   147,    -1,    -1,    -1,     1,   152,
+       3,     4,     5,     6,     7,     8,    -1,    -1,    11,    -1,
+      -1,    14,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    41,    42,
+      43,    -1,    -1,    46,    47,    -1,    49,    50,    51,    52,
+      -1,    -1,    -1,    56,    57,    -1,    -1,    -1,    61,    -1,
+      63,    -1,    65,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    75,    76,    77,    78,    79,    80,    81,    -1,
+      83,    84,    -1,    -1,    -1,    88,    89,    -1,    -1,    -1,
+      -1,    94,    95,    96,    -1,    98,    99,    -1,   101,    -1,
+      -1,    -1,    -1,    -1,   107,   108,    -1,    -1,    -1,   112,
+      -1,    -1,    -1,    -1,   117,    -1,   119,   120,   121,   122,
+      -1,   124,    -1,   126,   127,    -1,    -1,    -1,   131,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   140,    -1,    -1,
+      -1,    -1,   145,    -1,   147,    -1,    -1,    -1,    -1,   152
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const unsigned short yystos[] =
+{
+       0,     1,     3,     4,     5,     6,     7,    11,    41,    42,
+      46,    47,    49,    50,    51,    56,    63,    65,    66,    68,
+      69,    70,    71,    72,    73,    74,    75,    76,    77,    78,
+      79,    80,    83,    84,    88,    89,    94,    95,    96,    98,
+      99,   101,   107,   108,   112,   117,   119,   121,   122,   124,
+     126,   127,   131,   140,   145,   147,   152,   156,   157,   158,
+     159,   162,   163,   164,   165,   166,   170,   172,   195,   229,
+     232,   235,   236,   238,   239,   240,   330,   353,   359,   360,
+     386,   388,   390,   397,   398,   399,   401,   402,   418,   424,
+     425,   426,    11,   160,   161,     8,   167,   169,   167,    21,
+     331,   332,   333,     9,     9,   354,     9,     9,     9,     9,
+       9,     9,     9,     9,     9,     9,     9,     9,     9,     9,
+       9,   169,     9,   103,   104,   419,     9,    42,    49,    65,
+      69,    70,    71,    72,    73,    74,    75,    76,    77,    78,
+      79,    80,    83,    84,    89,    96,    99,   101,   107,   108,
+     117,   127,   131,   140,   147,   237,     9,     9,     9,     9,
+     230,   232,     9,     9,     9,     9,     9,     0,   157,   161,
+      10,    11,   171,     9,    81,    67,    20,   238,    11,    14,
+     167,   241,   242,   243,   244,   247,   249,   251,   252,    10,
+     358,    11,   362,    43,    57,    61,   120,   361,    12,    22,
+     247,   400,    43,   403,    43,    64,   367,   427,   427,   160,
+     168,   169,    12,    22,   169,   334,   335,    19,   296,    29,
+      30,   169,   182,   183,   288,   355,   134,   169,   210,   296,
+      28,   169,   382,   382,   177,   185,   174,    81,   238,    87,
+     169,   192,   169,   216,    34,   169,   209,   310,    29,    85,
+      86,   169,   199,   200,   202,   204,   205,   206,   358,    37,
+      40,   215,   167,   420,   421,    37,    40,    97,   175,   173,
+     218,   296,    66,     7,   109,   224,    43,   233,    81,   231,
+     103,   104,   225,    57,   111,   128,   227,   133,   148,   153,
+     220,   310,    41,    94,   105,   113,   119,   121,   123,   139,
+     196,   197,   198,   230,   145,    11,    19,   253,    12,   250,
+     243,   246,   247,    36,   248,    13,   168,   254,    11,     9,
+      42,   105,   106,   113,   114,   115,   116,   129,   295,   363,
+     364,    52,   387,   391,   403,    52,   382,   408,   409,   410,
+     169,   123,   404,   368,   238,   238,   160,    16,   326,   343,
+     344,   345,   346,   347,   348,   349,    19,    36,   336,    13,
+     337,   382,   293,    70,   356,    43,    37,   143,   208,   169,
+       8,   384,    28,    13,    43,   178,   179,   180,   182,   169,
+     186,   187,   182,    34,    40,   176,   169,   193,   194,    13,
+     217,    35,    36,    37,    38,    39,   313,   311,   313,   201,
+     207,   215,    20,    20,    82,   168,    12,    58,   422,   222,
+     254,    13,   219,   169,   169,   234,   238,   118,   228,   128,
+     154,   221,   169,    13,    36,   233,   167,   149,   256,   257,
+     258,   259,   260,   324,   326,    10,    15,   245,   249,   252,
+      13,    19,   255,    30,    31,    32,    33,    34,    37,    38,
+      40,    45,   323,   296,   238,   365,     9,     9,     9,    44,
+     367,   367,   396,   333,    43,   411,   409,    14,   412,    44,
+     333,    19,    20,    84,   323,   369,   370,   373,   374,   375,
+     382,   385,   346,   182,   286,    14,   238,   351,   352,   347,
+      10,   169,   169,   335,    10,    28,   289,     9,   357,   211,
+     212,   310,   383,   384,   382,   181,    31,    32,   184,    13,
+      19,   188,    13,   188,    13,   169,   118,   226,   226,   202,
+     203,    29,   206,   169,   382,   423,   167,   100,   223,   296,
+      44,   358,   238,   169,   197,   197,   238,     3,     4,     5,
+     261,   257,    14,   264,   265,   268,   260,   256,   247,   254,
+     168,   382,   232,   169,   238,   169,    58,    58,   334,    19,
+     374,    59,   238,   413,   334,   382,    13,   372,   375,    28,
+      17,   327,    32,   350,    34,   169,   339,   340,   341,    10,
+     352,    21,    30,   290,   292,   374,   382,    44,   212,   213,
+     313,   179,    32,    31,   180,   182,   169,    43,   189,   187,
+     194,   204,    10,   382,   168,   169,    11,   238,   358,    69,
+      77,   262,   263,    19,   268,   297,   298,   299,   300,   303,
+     306,   286,   327,   255,   231,   367,   396,    69,   405,   169,
+     382,   125,   414,   405,   376,   377,   381,   382,   385,   373,
+      34,    38,    40,   371,   169,    19,   342,    15,    13,   338,
+     291,   135,   214,    44,   191,   238,    10,    11,     9,     9,
+      10,   150,    15,     9,    23,    24,    25,    26,    27,    48,
+      69,   103,   104,   110,   137,   146,   269,   270,   271,   283,
+     284,   294,   295,   322,    62,    90,    91,    92,   111,   130,
+     151,   274,   275,   276,   285,   302,     9,    48,    53,    54,
+      55,   122,   301,   317,   318,    23,    25,    31,    32,    33,
+      43,    52,    68,    73,    87,   109,   144,   304,   305,   307,
+     308,   310,    21,   328,   403,    23,   389,    58,    60,   392,
+      19,   169,   406,    44,    15,   382,   415,    10,    44,   379,
+      28,    13,   329,   169,   238,   341,   334,   288,    19,    20,
+     169,   312,   314,   315,   316,    13,   190,   169,    87,   263,
+     268,   323,   277,   238,   296,   169,   382,    19,    20,   272,
+     273,   374,    10,    15,   278,   284,    23,   287,   169,   278,
+     296,    10,    13,   301,   323,   238,    82,   310,   278,   136,
+     310,   319,   320,   321,    32,   308,   306,   302,    43,   135,
+     238,   309,   313,   314,   169,   114,   115,   116,   238,   366,
+     230,   393,   396,   296,   394,   395,   169,   138,   407,    30,
+     416,   374,   380,    32,    37,    40,   378,   182,    10,   293,
+      19,    20,   191,    44,    19,    28,    53,   124,   238,   279,
+     280,   281,   282,   169,   382,   271,    28,   266,     4,   382,
+     276,   312,   312,   124,   321,    44,    21,   310,   313,   314,
+      43,   312,    43,   214,    43,   311,    37,    40,   114,   325,
+     405,   233,    58,   382,    13,   407,    20,   417,   381,    13,
+      28,   267,    21,   278,    44,    44,   314,   309,   310,    43,
+     312,   310,   313,   309,   329,   238,   396,   395,   382,   280,
+      28,    14,   312,   309,    44,   314,   309,    44,    10,   269,
+     309,    44,    15,   309
+};
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok                (yyerrstatus = 0)
+#define yyclearin      (yychar = YYEMPTY)
+#define YYEMPTY                -2
+#define YYEOF          0
+
+#define YYACCEPT       goto yyacceptlab
+#define YYABORT                goto yyabortlab
+#define YYERROR                goto yyerrlab1
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL         goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                 \
+do                                                             \
+  if (yychar == YYEMPTY && yylen == 1)                         \
+    {                                                          \
+      yychar = (Token);                                                \
+      yylval = (Value);                                                \
+      yychar1 = YYTRANSLATE (yychar);                          \
+      YYPOPSTACK;                                              \
+      goto yybackup;                                           \
+    }                                                          \
+  else                                                         \
+    {                                                          \
+      yyerror ("syntax error: cannot back up");                        \
+      YYERROR;                                                 \
+    }                                                          \
+while (0)
+
+#define YYTERROR       1
+#define YYERRCODE      256
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+   are run).  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)           \
+  Current.first_line   = Rhs[1].first_line;      \
+  Current.first_column = Rhs[1].first_column;    \
+  Current.last_line    = Rhs[N].last_line;       \
+  Current.last_column  = Rhs[N].last_column;
+#endif
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#define YYLEX  yylex ()
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                       \
+do {                                           \
+  if (yydebug)                                 \
+    YYFPRINTF Args;                            \
+} while (0)
+# define YYDSYMPRINT(Args)                     \
+do {                                           \
+  if (yydebug)                                 \
+    yysymprint Args;                           \
+} while (0)
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YYDSYMPRINT(Args)
+#endif /* !YYDEBUG */
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef        YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#if YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+\f
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined (__GLIBC__) && defined (_STRING_H)
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+#   if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+#   else
+yystrlen (yystr)
+     const char *yystr;
+#   endif
+{
+  register const char *yys = yystr;
+
+  while (*yys++ != '\0')
+    continue;
+
+  return yys - yystr - 1;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+#   if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+#   else
+yystpcpy (yydest, yysrc)
+     char *yydest;
+     const char *yysrc;
+#   endif
+{
+  register char *yyd = yydest;
+  register const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+#endif /* !YYERROR_VERBOSE */
+
+\f
+
+#if YYDEBUG
+/*-----------------------------.
+| Print this symbol on YYOUT.  |
+`-----------------------------*/
+
+static void
+#if defined (__STDC__) || defined (__cplusplus)
+yysymprint (FILE* yyout, int yytype, YYSTYPE yyvalue)
+#else
+yysymprint (yyout, yytype, yyvalue)
+    FILE* yyout;
+    int yytype;
+    YYSTYPE yyvalue;
+#endif
+{
+  /* Pacify ``unused variable'' warnings.  */
+  (void) yyvalue;
+
+  if (yytype < YYNTOKENS)
+    {
+      YYFPRINTF (yyout, "token %s (", yytname[yytype]);
+# ifdef YYPRINT
+      YYPRINT (yyout, yytoknum[yytype], yyvalue);
+# endif
+    }
+  else
+    YYFPRINTF (yyout, "nterm %s (", yytname[yytype]);
+
+  switch (yytype)
+    {
+      default:
+        break;
+    }
+  YYFPRINTF (yyout, ")");
+}
+#endif /* YYDEBUG. */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+static void
+#if defined (__STDC__) || defined (__cplusplus)
+yydestruct (int yytype, YYSTYPE yyvalue)
+#else
+yydestruct (yytype, yyvalue)
+    int yytype;
+    YYSTYPE yyvalue;
+#endif
+{
+  /* Pacify ``unused variable'' warnings.  */
+  (void) yyvalue;
+
+  switch (yytype)
+    {
+      default:
+        break;
+    }
+}
+
+\f
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+   into yyparse.  The argument should have type void *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   to the proper pointer type.  */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+#  define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL
+# else
+#  define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+# endif
+#else /* !YYPARSE_PARAM */
+# define YYPARSE_PARAM_ARG
+# define YYPARSE_PARAM_DECL
+#endif /* !YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+# ifdef YYPARSE_PARAM
+int yyparse (void *);
+# else
+int yyparse (void);
+# endif
+#endif
+
+
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of parse errors so far.  */
+int yynerrs;
+
+
+int
+yyparse (YYPARSE_PARAM_ARG)
+     YYPARSE_PARAM_DECL
+{
+  
+  register int yystate;
+  register int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yychar1 = 0;
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  short        yyssa[YYINITDEPTH];
+  short *yyss = yyssa;
+  register short *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  register YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK   (yyvsp--, yyssp--)
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
+  /* When reducing, the number of symbols on the RHS of the reduced
+     rule.  */
+  int yylen;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;            /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed. so pushing a state here evens the stacks.
+     */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyssp >= yyss + yystacksize - 1)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+       /* Give user a chance to reallocate the stack. Use copies of
+          these so that the &'s don't force the real ones into
+          memory.  */
+       YYSTYPE *yyvs1 = yyvs;
+       short *yyss1 = yyss;
+
+
+       /* Each stack pointer address is followed by the size of the
+          data in use in that stack, in bytes.  This used to be a
+          conditional around just the two extra args, but that might
+          be undefined if yyoverflow is a macro.  */
+       yyoverflow ("parser stack overflow",
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+
+                   &yystacksize);
+
+       yyss = yyss1;
+       yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyoverflowlab;
+# else
+      /* Extend the stack our own way.  */
+      if (yystacksize >= YYMAXDEPTH)
+       goto yyoverflowlab;
+      yystacksize *= 2;
+      if (yystacksize > YYMAXDEPTH)
+       yystacksize = YYMAXDEPTH;
+
+      {
+       short *yyss1 = yyss;
+       union yyalloc *yyptr =
+         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+       if (! yyptr)
+         goto yyoverflowlab;
+       YYSTACK_RELOCATE (yyss);
+       YYSTACK_RELOCATE (yyvs);
+
+#  undef YYSTACK_RELOCATE
+       if (yyss1 != yyssa)
+         YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                 (unsigned long int) yystacksize));
+
+      if (yyssp >= yyss + yystacksize - 1)
+       YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with.  */
+
+  if (yychar <= 0)             /* This means end of input.  */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;          /* Don't call YYLEX any more.  */
+
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE (yychar);
+
+      /* We have to keep this `#if YYDEBUG', since we use variables
+        which are defined only if `YYDEBUG' is set.  */
+      YYDPRINTF ((stderr, "Next token is "));
+      YYDSYMPRINT ((stderr, yychar1, yylval));
+      YYDPRINTF ((stderr, "\n"));
+    }
+
+  /* If the proper action on seeing token YYCHAR1 is to reduce or to
+     detect an error, take that action.  */
+  yyn += yychar1;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yychar1)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+       goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+  YYDPRINTF ((stderr, "Shifting token %d (%s), ",
+             yychar, yytname[yychar1]));
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+
+#if YYDEBUG
+  /* We have to keep this `#if YYDEBUG', since we use variables which
+     are defined only if `YYDEBUG' is set.  */
+  if (yydebug)
+    {
+      int yyi;
+
+      YYFPRINTF (stderr, "Reducing via rule %d (line %d), ",
+                yyn - 1, yyrline[yyn]);
+
+      /* Print the symbols being reduced, and their result.  */
+      for (yyi = yyprhs[yyn]; yyrhs[yyi] >= 0; yyi++)
+       YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);
+      YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+    }
+#endif
+  switch (yyn)
+    {
+        case 8:
+#line 264 "gram.y"
+    {
+               (void) contextcheck(C_MUSIC, "music information");
+               tssv_line();
+               /* reset flags for next voice */
+               Defining_multiple = NO;
+               Curr_grpsyl_p = (struct GRPSYL *) 0;
+               Good_till_canceled = NO;
+               free_extra_time();
+               Prev_grpsyl_p = 0;
+       }
+    break;
+
+  case 12:
+#line 286 "gram.y"
+    {
+               /* for blank lines -- nothing to do */
+       }
+    break;
+
+  case 13:
+#line 292 "gram.y"
+    {
+               /* to keep going after stumbling on an input error */
+               Getting_tup_dur = NO;
+               Good_till_canceled = NO;
+               Defining_multiple = NO;
+               Curr_grpsyl_p = (struct GRPSYL *) 0;
+               Last_grpsyl_p = (struct GRPSYL *) 0;
+               Prev_grpsyl_p = (struct GRPSYL *) 0;
+       }
+    break;
+
+  case 14:
+#line 303 "gram.y"
+    {
+               /* fill in context field of the SSV struct */
+               Currstruct_p->u.ssv_p->context = (short) Context;
+       }
+    break;
+
+  case 15:
+#line 310 "gram.y"
+    {
+               Curr_family = Score.fontfamily;
+       }
+    break;
+
+  case 16:
+#line 316 "gram.y"
+    {}
+    break;
+
+  case 17:
+#line 320 "gram.y"
+    {}
+    break;
+
+  case 18:
+#line 324 "gram.y"
+    {
+               /* have lots of separate structs in music context, so
+                * mark that we have no current struct */
+               Currstruct_p = (struct MAINLL *) 0;
+
+               /* make sure at least 1 staff is visible. Not good to
+                * check when user sets visible, because it would be
+                * nice to first set everything invisible and later
+                * turn one on. So if we wait till now to check,
+                * user doesn't have to switch back and forth from
+                * score to staff to get 1 voice visible. */
+               check_at_least1visible();
+       }
+    break;
+
+  case 19:
+#line 339 "gram.y"
+    {
+               Context = C_SCORE;
+       }
+    break;
+
+  case 20:
+#line 345 "gram.y"
+    {
+               (void) rangecheck(yyvsp[-1].intval, MINSTAFFS, Score.staffs, "staff number");
+               Context = C_STAFF;
+               Currstruct_p->u.ssv_p->staffno = yyvsp[-1].intval;
+       }
+    break;
+
+  case 21:
+#line 353 "gram.y"
+    {
+               (void) rangecheck(yyvsp[-2].intval, MINSTAFFS, Score.staffs, "staff number");
+               (void) rangecheck(yyvsp[-1].intval, MINVOICES, MAXVOICES, "voice number");
+               Context = C_VOICE;
+               Currstruct_p->u.ssv_p->staffno = yyvsp[-2].intval;
+               Currstruct_p->u.ssv_p->voiceno = yyvsp[-1].intval;
+       }
+    break;
+
+  case 22:
+#line 362 "gram.y"
+    {
+               /* allocate an SSV struct */
+               Currstruct_p = newMAINLLstruct(S_SSV, yylineno);
+       }
+    break;
+
+  case 23:
+#line 368 "gram.y"
+    {
+               /* entering new context, if we have a current struct,
+                * we were in a different context, so add its info to the list */
+               end_prev_context();
+       }
+    break;
+
+  case 24:
+#line 375 "gram.y"
+    {
+               struct FEED *feed_p;            /* where to attach blocks */
+               int calloced;                   /* YES if dynamically alloced */
+
+               end_prev_context();
+               Currstruct_p = (struct MAINLL *) 0;
+               Context = yyvsp[0].intval;
+               calloced = NO;
+
+               switch (yyvsp[0].intval) {
+               case C_HEADER:
+                       /* We only allow one of these */
+                       chkdup_headfoot(Gotheader++, "header");
+                       Currblock_p = &Header;
+                       break;
+               case C_HEAD2:
+                       chkdup_headfoot(Gothead2++, "header2");
+                       Currblock_p = &Header2;
+                       break;
+               case C_FOOTER:
+                       chkdup_headfoot(Gotfooter++, "footer");
+                       Currblock_p = &Footer;
+                       break;
+               case C_FOOT2:
+                       chkdup_headfoot(Gotfoot2++, "foot2");
+                       Currblock_p = &Footer2;
+                       break;
+                       break;
+               case C_TOP:
+               case C_TOP2:
+               case C_BOT:
+               case C_BOT2:
+               case C_BLOCK:
+                       CALLOC(BLOCKHEAD, Currblock_p, 1);
+                       calloced = YES;
+                       break;
+               default:
+                       pfatal("Unknown block-type context");
+                       /*NOTREACHED*/
+                       break;
+               }
+               set_win_coord(Currblock_p->c);
+               /* Remember where to start attaching "print" commands */
+               Next_print_link_p_p = &(Currblock_p->printdata_p);
+
+               /* The dynamically allocated blocks
+                * (not the static head/foot blocks)
+                * need extra processing to populate
+                * the main list properly with FEEDs.
+                */
+               if (calloced == YES) {
+                       if (Mainlltc_p == 0 || Mainlltc_p->str != S_FEED) {
+                               /* User had not specified a feed
+                                * right before this block, so we need
+                                * to add one for them implicitly.
+                                * Create a new FEED and add it
+                                * to the end of the main list.
+                                */
+                               insertMAINLL(newMAINLLstruct(S_FEED, yylineno),
+                                                       Mainlltc_p);
+                       }
+                       feed_p = Mainlltc_p->u.feed_p;
+
+                       /* Normally, top/top2/bot/bot2 result in a pagefeed.
+                        * But we have a special case for backward
+                        * compatiblity and for flexibility.
+                        * User can get a separate
+                        * "title" page if they really want to,
+                        * by using an explicit newpage at the beginning.
+                        * But in the normal case, they'd want to declare
+                        * top/bot that will go on the first page without
+                        * that causing a newpage. So if there hasn't been
+                        * any music or block yet, we won't set newpage=YES
+                        * for top/top2/bot/bot2, but otherwise we will.
+                        */
+                       if (Context & (C_TOP|C_TOP2|C_BOT|C_BOT2)) {
+                               struct MAINLL *m_p;
+                               for (m_p = Mainlltc_p->prev; m_p != 0;
+                                                       m_p = m_p->prev) {
+                                       if (m_p->str == S_BAR ||
+                                                       m_p->str == S_BLOCKHEAD) {
+                                               /* There was music or block,
+                                                * so this is not
+                                                * at very beginning,
+                                                * so no special case:
+                                                * there will be new page.
+                                                */
+                                               feed_p->pagefeed = YES;
+                                               break;
+                                       }
+                               }
+                       }
+
+                       /* Now check for redefined blocks and
+                        * attach the BLOCKHEAD onto the FEED or the
+                        * main list, as appropriate.
+                        */
+                       switch (Context) {
+                       case C_TOP:
+                               if (feed_p->top_p != 0) {
+                                       warning("top redefined before being used");
+                               }
+                               feed_p->top_p = Currblock_p;
+                               break;
+                       case C_TOP2:
+                               if (feed_p->top2_p != 0) {
+                                       warning("top2 redefined before being used");
+                               }
+                               feed_p->top2_p = Currblock_p;
+                               break;
+                       case C_BOT:
+                               if (feed_p->bot_p != 0) {
+                                       warning("bot redefined before being used");
+                               }
+                               feed_p->bot_p = Currblock_p;
+                               break;
+                       case C_BOT2:
+                               if (feed_p->bot2_p != 0) {
+                                       warning("bot2 redefined before being used");
+                               }
+                               feed_p->bot2_p = Currblock_p;
+                               break;
+                       case C_BLOCK:
+                               insertMAINLL(newMAINLLstruct(S_BLOCKHEAD, yylineno),
+                                               Mainlltc_p);
+                               Mainlltc_p->u.blockhead_p = Currblock_p;
+                               /* These blocks count like "music" for purposes
+                                * of things that can only be set
+                                * before any "music"
+                                */
+                               Got_some_data = YES;
+                               break;
+                       case C_HEADER:
+                       case C_HEAD2:
+                       case C_FOOTER:
+                       case C_FOOT2:
+                               /* These are static, not in main list,
+                                * so nothing needs to be done with them.
+                                */
+                               break;
+                       default:
+                               pfatal("unexpected context (0x%x) for block", Context);
+                               /*NOTREACHED*/
+                               break;
+                       }
+
+                       /* We need a feed after a block.
+                        * Use -1 as lineno to mark it as internally generated.
+                        * That way if user puts their own explicit feed
+                        * next in the input, we can know we can
+                        * discard this internally generated one.
+                        */
+                       if (Context & C_BLOCK) {
+                               insertMAINLL(newMAINLLstruct(S_FEED, -1), Mainlltc_p);
+                       }
+               }
+       }
+    break;
+
+  case 25:
+#line 534 "gram.y"
+    {
+               Context = C_MUSIC;
+       }
+    break;
+
+  case 26:
+#line 539 "gram.y"
+    {
+               end_prev_context();
+               Currstruct_p = (struct MAINLL *) 0;
+               Context = C_GRIDS;
+       }
+    break;
+
+  case 27:
+#line 547 "gram.y"
+    {
+               if (Context == C_GRIDS) {
+                       add_grid(yyvsp[-2].stringval, yyvsp[-1].stringval);
+               }
+               else if (Context == C_HEADSHAPES) {
+                       /* skip past the font/size bytes */
+                       add_shape(yyvsp[-2].stringval + 2, yyvsp[-1].stringval + 2);
+               }
+               else {
+                       yyerror("unexpected strings");
+               }
+       }
+    break;
+
+  case 28:
+#line 562 "gram.y"
+    {
+               end_prev_context();
+               Currstruct_p = (struct MAINLL *) 0;
+               Context = C_HEADSHAPES;
+       }
+    break;
+
+  case 30:
+#line 573 "gram.y"
+    {
+               yyval.intval = yyvsp[0].intval;
+               /* later on we check for being within current range */
+       }
+    break;
+
+  case 31:
+#line 579 "gram.y"
+    {
+               yyval.intval = atoi(yytext);
+       }
+    break;
+
+  case 35:
+#line 593 "gram.y"
+    {
+               /* Only a few things are allowed to have a negative number.
+                * Other code assumes that that restriction is enforced here,
+                * so we only honor the minus if it is legal. */
+               if (yyvsp[-1].intval == -1) {
+                       if (yyvsp[-3].intval != STAFFPAD && yyvsp[-3].intval != SYLPOSITION) {
+                               yyerror("negative value not allowed");
+                       }
+                       else {
+                               assign_int(yyvsp[-3].intval, -(yyvsp[0].intval), Currstruct_p);
+                       }
+               }
+               else {
+                       assign_int(yyvsp[-3].intval, yyvsp[0].intval, Currstruct_p);
+               }
+       }
+    break;
+
+  case 36:
+#line 612 "gram.y"
+    {
+               /* only restcombine and gridfret can be set to empty */
+               if (yyvsp[-1].intval == RESTCOMBINE) {
+                       assign_int(yyvsp[-1].intval, NORESTCOMBINE, Currstruct_p);
+               }
+               else if (yyvsp[-1].intval == GRIDFRET) {
+                       assign_int(yyvsp[-1].intval, NOGRIDFRET, Currstruct_p);
+               }
+               else {
+                       yyerror("parameter value required");
+               }
+       }
+    break;
+
+  case 37:
+#line 627 "gram.y"
+    {
+               assign_float(yyvsp[-2].intval, yyvsp[0].floatval, Currstruct_p);
+       }
+    break;
+
+  case 38:
+#line 633 "gram.y"
+    {
+               assign_2floats(yyvsp[-4].intval, yyvsp[-2].floatval, yyvsp[0].floatval, Currstruct_p);
+       }
+    break;
+
+  case 39:
+#line 639 "gram.y"
+    {
+               double multiplier;
+               multiplier = (Score.units == INCHES ? 1.0 : CMPERINCH);
+               assign_float(PAGEWIDTH, pagesztbl[yyvsp[-1].intval][yyvsp[0].intval] * multiplier, Currstruct_p);
+               assign_float(PAGEHEIGHT, pagesztbl[yyvsp[-1].intval][yyvsp[0].intval ^ 1] * multiplier, Currstruct_p);
+       }
+    break;
+
+  case 40:
+#line 647 "gram.y"
+    { begin_range(PL_UNKNOWN);  }
+    break;
+
+  case 41:
+#line 648 "gram.y"
+    { }
+    break;
+
+  case 42:
+#line 652 "gram.y"
+    {
+               /* specified in stepsizes, stored in inches */
+               assign_float(PAD, yyvsp[-1].intval * yyvsp[0].floatval * STEPSIZE, Currstruct_p);
+       }
+    break;
+
+  case 43:
+#line 659 "gram.y"
+    {
+               assign_vscheme (yyvsp[-1].intval, yyvsp[0].intval, Currstruct_p);
+       }
+    break;
+
+  case 44:
+#line 665 "gram.y"
+    {
+               set_beamlist(Currstruct_p);
+               if (Currstruct_p != 0 && Currstruct_p->u.ssv_p != 0) {
+                       Currstruct_p->u.ssv_p->beamrests = (yyvsp[0].intval & 0x1);
+                       Currstruct_p->u.ssv_p->beamspaces = ((yyvsp[0].intval >> 1) & 0x1);
+               }
+       }
+    break;
+
+  case 45:
+#line 675 "gram.y"
+    {
+               set_staffset(yyvsp[-3].intval, Currstruct_p);
+       }
+    break;
+
+  case 46:
+#line 681 "gram.y"
+    {
+               set_barstlist(Currstruct_p);
+       }
+    break;
+
+  case 47:
+#line 687 "gram.y"
+    {
+               if (Currstruct_p != 0) {
+                       chk_order(Currstruct_p->u.ssv_p, Order_place);
+               }
+       }
+    break;
+
+  case 49:
+#line 698 "gram.y"
+    {
+               /* all the work for this is done in timesig */
+       }
+    break;
+
+  case 50:
+#line 704 "gram.y"
+    {
+       }
+    break;
+
+  case 51:
+#line 709 "gram.y"
+    {
+               set_font(yyvsp[-2].intval, yyvsp[0].intval, Currstruct_p);
+       }
+    break;
+
+  case 52:
+#line 715 "gram.y"
+    {
+               set_font(yyvsp[-2].intval, yyvsp[0].intval, Currstruct_p);
+       }
+    break;
+
+  case 53:
+#line 721 "gram.y"
+    {
+               if (contextcheck(C_SCORE|C_STAFF,"clef parameter") == YES) {
+                       used_check(Currstruct_p, CLEF, "clef");
+                       if (Context == C_STAFF &&
+                                       is_tab_staff(Currstruct_p->u.ssv_p->staffno)) {
+                               yyerror("can't set clef on tab staff");
+                       }
+                       Currstruct_p->u.ssv_p->clef = yyvsp[0].intval;
+                       Currstruct_p->u.ssv_p->used[CLEF] = YES;
+                       asgnssv(Currstruct_p->u.ssv_p);
+               }
+       }
+    break;
+
+  case 54:
+#line 736 "gram.y"
+    {
+               assign_int(yyvsp[-2].intval, yyvsp[0].intval, Currstruct_p);
+       }
+    break;
+
+  case 56:
+#line 745 "gram.y"
+    {
+               if (contextcheck(C_STAFF|C_VOICE, "unset") == YES) {
+                       if (yyvsp[0].intval < 0 || yyvsp[0].intval >= NUMFLDS) {
+                               pfatal("invalid parameter index %d", yyvsp[0].intval);
+                       }
+                       if (Currstruct_p->u.ssv_p->used[yyvsp[0].intval] == YES) {
+                               warning("unsetting parameter overrides previous setting");
+                       }
+                       /* Note that if user tries to unset something that
+                        * can't be set in the current context, we silently
+                        * ignore that. We figure that since it's already unset,
+                        * it doesn't hurt anything to unset it again,
+                        * and it's easier to not bother to check.
+                        */
+
+                       Currstruct_p->u.ssv_p->used[yyvsp[0].intval] = UNSET;
+
+                       /* special case: scoresep controls two fields */
+                       if (yyvsp[0].intval == MINSCSEP) {
+                               Currstruct_p->u.ssv_p->used[MAXSCSEP] = UNSET;
+                       }
+
+                       /* Assign, just in case there are new interactions */
+                       asgnssv(Currstruct_p->u.ssv_p);
+               }
+       }
+    break;
+
+  case 57:
+#line 773 "gram.y"
+    { Doing_timeunit = YES; }
+    break;
+
+  case 58:
+#line 774 "gram.y"
+    {
+               if ( contextcheck(C_SSV, "timeunit parameter") == YES ) {
+                       used_check(Currstruct_p, TIMEUNIT, "timeunit");
+                       Currstruct_p->u.ssv_p->timeunit = yyvsp[0].ratval;
+                       Currstruct_p->u.ssv_p->timelist_p = Extra_time_p;
+                       Extra_time_p = 0;
+                       Doing_timeunit = NO;
+                       Currstruct_p->u.ssv_p->used[TIMEUNIT] = YES;
+               }
+       }
+    break;
+
+  case 59:
+#line 787 "gram.y"
+    {
+               if ( contextcheck(C_SSV, "swingunit parameter") == YES ) {
+                       used_check(Currstruct_p, SWINGUNIT, "swingunit");
+                       Currstruct_p->u.ssv_p->swingunit = yyvsp[0].ratval;
+                       Currstruct_p->u.ssv_p->used[SWINGUNIT] = YES;
+               }
+       }
+    break;
+
+  case 60:
+#line 797 "gram.y"
+    {
+       }
+    break;
+
+  case 61:
+#line 802 "gram.y"
+    {
+       }
+    break;
+
+  case 62:
+#line 807 "gram.y"
+    {
+               if ( contextcheck(C_SCORE, "endingstyle parameter") == YES ) {
+                       used_check(Currstruct_p, ENDINGSTYLE, "endingstyle");
+                       Currstruct_p->u.ssv_p->endingstyle = yyvsp[0].intval;
+                       Currstruct_p->u.ssv_p->used[ENDINGSTYLE] = YES;
+               }
+       }
+    break;
+
+  case 63:
+#line 817 "gram.y"
+    {
+               if (contextcheck(C_SCORE | C_STAFF, "rehstyle parameter") == YES ) {
+                       used_check(Currstruct_p, REHSTYLE, "rehstyle");
+                       Currstruct_p->u.ssv_p->rehstyle = yyvsp[0].intval;
+                       Currstruct_p->u.ssv_p->used[REHSTYLE] = YES;
+               }
+               
+       }
+    break;
+
+  case 64:
+#line 828 "gram.y"
+    {
+               if ( contextcheck(C_SCORE | C_STAFF, "pedstyle parameter") == YES ) {
+                       used_check(Currstruct_p, PEDSTYLE, "pedstyle");
+                       Currstruct_p->u.ssv_p->pedstyle = yyvsp[0].intval;
+                       Currstruct_p->u.ssv_p->used[PEDSTYLE] = YES;
+               }
+       }
+    break;
+
+  case 65:
+#line 838 "gram.y"
+    {
+               char *trans_name;
+               trans_name = (yyvsp[-4].intval == TRANSPOSITION ?
+                       "transpose" : "addtranspose");
+               if (contextcheck(C_SCORE|C_STAFF, trans_name) == YES) {
+                       used_check(Currstruct_p, yyvsp[-4].intval, trans_name);
+                       chk_interval(yyvsp[-1].intval, yyvsp[0].intval);
+                       if (yyvsp[-4].intval == TRANSPOSITION) {
+                               Currstruct_p->u.ssv_p->inttype = yyvsp[-1].intval;
+                               Currstruct_p->u.ssv_p->intnum = yyvsp[-2].intval * yyvsp[0].intval;
+                       }
+                       else {
+                               Currstruct_p->u.ssv_p->addinttype = yyvsp[-1].intval;
+                               Currstruct_p->u.ssv_p->addintnum = yyvsp[-2].intval * yyvsp[0].intval;
+                       }
+                       Currstruct_p->u.ssv_p->used[yyvsp[-4].intval] = YES;
+                       if (Context == C_STAFF &&
+                                       is_tab_staff(Currstruct_p->u.ssv_p->staffno)
+                                       == YES) {
+                               l_yyerror(Curr_filename, yylineno,
+                                       "%s not allowed on tablature staff",
+                                       trans_name);
+                       }
+                       else {
+                               asgnssv(Currstruct_p->u.ssv_p);
+                       }
+               }
+       }
+    break;
+
+  case 66:
+#line 869 "gram.y"
+    {
+               assign_unit(yyvsp[0].intval, Currstruct_p);
+       }
+    break;
+
+  case 67:
+#line 875 "gram.y"
+    {
+               assign_string(yyvsp[-2].intval, yyvsp[0].stringval, Currstruct_p);
+       }
+    break;
+
+  case 68:
+#line 881 "gram.y"
+    {
+               /* whereused is not allowed on voice, just score and staff */
+               if (contextcheck(C_SCORE|C_STAFF, "visible=whereused") == YES) {
+                       assign_int(VISIBLE, YES, Currstruct_p);
+                       Currstruct_p->u.ssv_p->hidesilent = YES;
+               }
+       }
+    break;
+
+  case 69:
+#line 891 "gram.y"
+    {
+               /* only valid letter is y */
+               if (*yytext != 'y') {
+                       yyerror("visible value must be y, n, or whereused");
+               }
+               else if (contextcheck(C_SSV, "visible parameter")
+                                                               == YES) {
+                       assign_int(VISIBLE, YES, Currstruct_p);
+                       Currstruct_p->u.ssv_p->hidesilent = NO;
+               }
+       }
+    break;
+
+  case 70:
+#line 905 "gram.y"
+    {
+               if (contextcheck(C_SSV, "visible parameter") == YES) {
+                       assign_int(VISIBLE, NO, Currstruct_p);
+                       Currstruct_p->u.ssv_p->hidesilent = NO;
+               }
+       }
+    break;
+
+  case 71:
+#line 913 "gram.y"
+    {
+               /* none specified */
+               yyval.intval = V_1;
+       }
+    break;
+
+  case 72:
+#line 920 "gram.y"
+    {
+               /* only valid value here is 'f'  */
+               if (*yytext == 'f') {
+                       yyval.intval = V_2FREESTEM;
+               }
+               else {
+                       yyerror("invalid voice qualifier: must be f or o");
+                       yyval.intval = V_1;
+               }
+       }
+    break;
+
+  case 73:
+#line 933 "gram.y"
+    {
+               /* only valid value here is 'o' */
+               if (*yytext == 'o') {
+                       yyval.intval = V_2OPSTEM;
+               }
+               else {
+                       yyerror("invalid voice qualifier: must be f or o");
+                       yyval.intval = (int) V_1;
+               }
+       }
+    break;
+
+  case 74:
+#line 945 "gram.y"
+    {
+               /* NULL token for allocating a new beamlist */
+               new_beamlist();
+       }
+    break;
+
+  case 77:
+#line 959 "gram.y"
+    {
+               add_beamlist(yyvsp[0].ratval);
+       }
+    break;
+
+  case 79:
+#line 968 "gram.y"
+    {
+               add_beamlist(yyvsp[0].ratval);
+       }
+    break;
+
+  case 81:
+#line 977 "gram.y"
+    { begin_subbeam(); }
+    break;
+
+  case 82:
+#line 978 "gram.y"
+    {
+               end_subbeam();
+       }
+    break;
+
+  case 83:
+#line 983 "gram.y"
+    {
+               yyval.ratval = calcfulltime(yyvsp[-3].ratval, yyvsp[-2].intval);
+
+               /* if filling in a GRPSYL struct, need to fill in dots.
+                * Could also be here due to beamstyle
+                * or timeunit or location time offset,
+                * in which case the Curr_grpsyl_p will be NULL,
+                * or while getting tuplet duration. */
+               if (Curr_grpsyl_p != (struct GRPSYL *) 0
+                                               && Getting_tup_dur == NO) {
+                       Curr_grpsyl_p->dots = yyvsp[-2].intval;
+               }
+               else {
+                       struct TIMELIST *timelist_p;    /* walk thru list */
+                       struct TIMELIST *next_p;/* save next to delete curr */
+                       RATIONAL totaltime;     /* sum of extra times */
+
+                       /* Start with first time value (which was calculated
+                        * above and is now in $$), then add on the added
+                        * times, if any. */
+                       totaltime = yyval.ratval;
+                       for (timelist_p = Extra_time_p; timelist_p != 0;
+                                               timelist_p = next_p) {
+                               next_p = timelist_p->next;
+                               totaltime = radd(totaltime, timelist_p->fulltime);
+                               if (Doing_timeunit == NO) {
+                                       /* For things like swingunit
+                                        * or tuplet time, we just need the
+                                        * resulting time, not the individual
+                                        * time units and arithmetic. */
+                                       FREE(timelist_p);
+                               }
+                       }
+                       if (Extra_time_p != 0 && LE(totaltime, Zero)) {
+                               yyerror("Time values must add up to more than zero");
+                       }
+                       /* Current timelist is finished; can't append any
+                        * more items to it. */
+                       Curr_timelist_p = 0;
+                       if (Doing_timeunit == YES) {
+                               /* For timeunit, we return the initial
+                                * timeunit, but also preserve
+                                * Extra_time_p for putting in SSV.
+                                */
+                               yyval.ratval = calcfulltime(yyvsp[-3].ratval, yyvsp[-2].intval);
+                       }
+                       else {
+                               /* the list has been freed above */
+                               Extra_time_p = 0;
+                               yyval.ratval = totaltime;
+                       }
+               }
+       }
+    break;
+
+  case 84:
+#line 1039 "gram.y"
+    {
+               yyval.ratval.n = (svpath(1, TIME))->time.n;
+               yyval.ratval.d = (svpath(1, TIME))->time.d;
+               if (Curr_grpsyl_p != (struct GRPSYL *) 0
+                                       && Getting_tup_dur == NO) {
+                       /* use whole note symbol as default */
+                       Curr_grpsyl_p->basictime = 1;
+                       Curr_grpsyl_p->is_meas = YES;
+                       User_meas_time = NO;
+               }
+               else {
+                       yyerror("'m' is not valid here");
+               }
+       }
+    break;
+
+  case 85:
+#line 1056 "gram.y"
+    {
+               yyval.ratval = Zero;
+       }
+    break;
+
+  case 87:
+#line 1066 "gram.y"
+    {
+               yyval.intval = NO;
+       }
+    break;
+
+  case 88:
+#line 1072 "gram.y"
+    {
+               yyval.intval = (YES | (YES << 1));
+       }
+    break;
+
+  case 89:
+#line 1078 "gram.y"
+    {
+               yyval.intval = ((YES << 1) | YES);
+       }
+    break;
+
+  case 90:
+#line 1084 "gram.y"
+    {
+               yyval.intval = (YES << 1);
+       }
+    break;
+
+  case 91:
+#line 1090 "gram.y"
+    {
+               yyval.intval = YES;
+       }
+    break;
+
+  case 92:
+#line 1095 "gram.y"
+    {
+               /* null token for the purpose of allocating a new rangelist
+                * to be filled in with user data */
+               new_staffset();
+       }
+    break;
+
+  case 96:
+#line 1112 "gram.y"
+    {
+               /* save information about this range in the list */
+               /* if only a single number, not a range, rangetail will be
+                * 0, so use num as both beginning and end of range */
+               add_staffset( yyvsp[-2].intval, (yyvsp[-1].intval > 0 ? yyvsp[-1].intval : yyvsp[-2].intval), String1, String2);
+       }
+    break;
+
+  case 97:
+#line 1120 "gram.y"
+    {
+               /* no end of range, so return 0 as flag that there was only 1 number */
+               yyval.intval = 0;
+       }
+    break;
+
+  case 98:
+#line 1127 "gram.y"
+    {
+               /* make sure isn't 0, because that it illegal and would be used
+                * later as though there were no range. Other error checking
+                * on this number will be done later. */
+               if (yyvsp[0].intval == 0) {
+                       yyerror("second number of range may not be zero");
+               }
+               yyval.intval = yyvsp[0].intval;
+       }
+    break;
+
+  case 99:
+#line 1138 "gram.y"
+    {
+               /* no labels */
+               String1 = String2 = (char *) 0;
+       }
+    break;
+
+  case 100:
+#line 1145 "gram.y"
+    {
+               /* save label */
+               String1 = yyvsp[-2].stringval;
+       }
+    break;
+
+  case 101:
+#line 1151 "gram.y"
+    {
+               /* no second label */
+               String2 = (char *) 0;
+       }
+    break;
+
+  case 102:
+#line 1158 "gram.y"
+    {
+               /* save label2 for later use */
+               String2 = yyvsp[0].stringval;
+       }
+    break;
+
+  case 104:
+#line 1167 "gram.y"
+    {
+               /* NULL token for allocating space for a bar style list */
+               new_barstlist();
+       }
+    break;
+
+  case 108:
+#line 1184 "gram.y"
+    {
+               /* if only 1 number, not range, rangetail will be 0, so use
+                * same number for beginning and end */
+               add_barst(yyvsp[-1].intval, (yyvsp[0].intval == 0 ? yyvsp[-1].intval : yyvsp[0].intval) );
+       }
+    break;
+
+  case 109:
+#line 1191 "gram.y"
+    {
+               Order_place = yyvsp[0].intval;
+               Order_prio = 1;
+               if (Currstruct_p != 0) {
+                       switch (yyvsp[0].intval) {
+                       case PL_ABOVE:
+                               Currstruct_p->u.ssv_p->used[ABOVEORDER] = YES;
+                               break;
+                       case PL_BELOW:
+                               Currstruct_p->u.ssv_p->used[BELOWORDER] = YES;
+                               break;
+                       case PL_BETWEEN:
+                               Currstruct_p->u.ssv_p->used[BETWEENORDER] = YES;
+                               break;
+                       }
+               }
+       }
+    break;
+
+  case 110:
+#line 1211 "gram.y"
+    {
+               if (Currstruct_p != 0) {
+                       Currstruct_p->u.ssv_p->markorder[Order_place][yyvsp[0].intval] = Order_prio;
+               }
+       }
+    break;
+
+  case 111:
+#line 1219 "gram.y"
+    {
+               if (Currstruct_p != 0) {
+                       Currstruct_p->u.ssv_p->markorder[Order_place][yyvsp[0].intval] = ++Order_prio;
+               }
+       }
+    break;
+
+  case 112:
+#line 1227 "gram.y"
+    {
+               if (Currstruct_p != 0) {
+                       Currstruct_p->u.ssv_p->markorder[Order_place][yyvsp[0].intval] = Order_prio;
+               }
+       }
+    break;
+
+  case 113:
+#line 1234 "gram.y"
+    {
+               if (Currstruct_p != 0) {
+                       if (Currstruct_p->u.ssv_p->markorder[Order_place][yyvsp[0].intval] != 0) {
+                               l_yyerror(Curr_filename, yylineno,
+                                       "order item %s specified more than once", yyvsp[0].intval);
+                       }
+               }
+               yyval.intval = yyvsp[0].intval;
+       }
+    break;
+
+  case 114:
+#line 1246 "gram.y"
+    {
+               yyval.intval = MK_MUSSYM;
+       }
+    break;
+
+  case 115:
+#line 1252 "gram.y"
+    {
+               yyval.intval = MK_OCTAVE;
+       }
+    break;
+
+  case 116:
+#line 1258 "gram.y"
+    {
+               yyval.intval = MK_OTHERTEXT;
+       }
+    break;
+
+  case 117:
+#line 1264 "gram.y"
+    {
+               switch (yyvsp[0].intval) {
+               case TM_CHORD:
+                       yyval.intval = MK_CHORD;
+                       break;
+               case TM_DYN:
+                       yyval.intval = MK_DYN;
+                       break;
+               default:
+                       yyerror("invalid text modifier in order list");
+                       /* set to something valid, since $$ will be used
+                        * as an array subscript. */
+                       yyval.intval = MK_CHORD;
+                       break;
+               }
+       }
+    break;
+
+  case 118:
+#line 1283 "gram.y"
+    {
+               yyval.intval = MK_LYRICS;
+       }
+    break;
+
+  case 119:
+#line 1289 "gram.y"
+    {
+               yyval.intval = MK_ENDING;
+       }
+    break;
+
+  case 120:
+#line 1295 "gram.y"
+    {
+               yyval.intval = MK_REHEARSAL;
+       }
+    break;
+
+  case 121:
+#line 1301 "gram.y"
+    {
+               yyval.intval = MK_PEDAL;
+       }
+    break;
+
+  case 122:
+#line 1307 "gram.y"
+    {
+               tsig_item(TSR_END);
+               if (Currstruct_p != 0 && Currstruct_p->u.ssv_p != 0) {
+                       MALLOCA(char, Currstruct_p->u.ssv_p->timerep, Tsig_offset);
+                       strcpy(Currstruct_p->u.ssv_p->timerep, Timerep);
+                       assign_timesig(Currstruct_p, yyvsp[0].intval, &Next_alt_timesig);
+                       Tsig_visibility = yyvsp[0].intval;
+                       /* If there are alternating time signatures,
+                        * need to save pointer to this list */
+                       if (Next_alt_timesig != 0) {
+                               Alt_timesig_list = Timerep;
+                       }
+                       else {
+                               Alt_timesig_list = 0;
+                       }
+               }
+               /* Reset for next time signature usage, if any */
+               Tsig_offset = 0;
+       }
+    break;
+
+  case 124:
+#line 1331 "gram.y"
+    { tsig_item(TSR_ALTERNATING); }
+    break;
+
+  case 125:
+#line 1332 "gram.y"
+    {
+               /* this is for alternating time signature */
+       }
+    break;
+
+  case 126:
+#line 1338 "gram.y"
+    {
+       }
+    break;
+
+  case 127:
+#line 1342 "gram.y"
+    { tsig_item(TSR_ADD); }
+    break;
+
+  case 128:
+#line 1343 "gram.y"
+    {
+               /* This would be for things like 2/4 + 3/8 */
+       }
+    break;
+
+  case 129:
+#line 1349 "gram.y"
+    {
+               tsig_item(TSR_CUT);
+       }
+    break;
+
+  case 130:
+#line 1355 "gram.y"
+    {
+               tsig_item(TSR_COMMON);
+       }
+    break;
+
+  case 131:
+#line 1361 "gram.y"
+    {
+               tsig_item(TSR_SLASH);
+               if (yyvsp[0].intval < MINDENOMINATOR) {
+                       l_yyerror(Curr_filename, yylineno,
+                               "time signature denominator cannot be less than %d",
+                               MINDENOMINATOR);
+                       yyvsp[0].intval = MINDENOMINATOR;
+               }
+               else if (yyvsp[0].intval > MAXDENOMINATOR) {
+                       l_yyerror(Curr_filename, yylineno,
+                               "time signature denominator cannot be greater than %d",
+                               MAXDENOMINATOR);
+                       yyvsp[0].intval = MAXDENOMINATOR;
+               }
+               else if (power_of2check(yyvsp[0].intval, "time signature denominator") == NO) {
+                       yyvsp[0].intval = 1 << drmo(yyvsp[0].intval);
+               }
+
+               tsig_item(yyvsp[0].intval);
+       }
+    break;
+
+  case 132:
+#line 1384 "gram.y"
+    {
+               /* this is something like 3+1/4 where the 1/4 get interpreted
+                * by lexer as quadwhole, but it's really 1 for numerator
+                * and 4 for denominator. 
+                */
+               tsig_item(1);
+               tsig_item(TSR_SLASH);
+               tsig_item(yyvsp[0].intval);
+       }
+    break;
+
+  case 133:
+#line 1396 "gram.y"
+    {
+               tsig_item(1);
+               tsig_item(TSR_SLASH);
+               tsig_item(yyvsp[0].intval);
+       }
+    break;
+
+  case 136:
+#line 1410 "gram.y"
+    {
+               if (yyvsp[0].intval < MINNUMERATOR) {
+                       l_yyerror(Curr_filename, yylineno,
+                               "time signature numerator cannot be less than %d",
+                               MINNUMERATOR);
+                       yyvsp[0].intval = MINNUMERATOR;
+               }
+               else if (yyvsp[0].intval > MAXNUMERATOR) {
+                       l_yyerror(Curr_filename, yylineno,
+                               "time signature numerator cannot be greater than %d",
+                               MAXNUMERATOR);
+                       yyvsp[0].intval = MAXNUMERATOR;
+               }
+               tsig_item(yyvsp[0].intval);
+       }
+    break;
+
+  case 137:
+#line 1428 "gram.y"
+    {
+               yyval.intval = PTS_ONCE;
+       }
+    break;
+
+  case 138:
+#line 1434 "gram.y"
+    {
+               yyval.intval = (yyvsp[0].intval == YES ? PTS_ALWAYS : PTS_NEVER);
+       }
+    break;
+
+  case 139:
+#line 1439 "gram.y"
+    {
+               yyval.intval = NO;
+       }
+    break;
+
+  case 140:
+#line 1445 "gram.y"
+    {
+               /* 'n' is used in various places to mean do NOT
+                * print something that would normally be printed,
+                * so YES means we do want to inhibit the normal printing. */
+               yyval.intval = YES;
+       }
+    break;
+
+  case 141:
+#line 1453 "gram.y"
+    {
+               if ( (yyvsp[-1].intval != '#') && (yyvsp[-1].intval != '&') ) {
+                       yyerror("key signature must include # or &");
+               }
+               else {
+                       assign_key(yyvsp[-2].intval, yyvsp[-1].intval, yyvsp[0].intval, Currstruct_p);
+               }
+       }
+    break;
+
+  case 142:
+#line 1464 "gram.y"
+    {
+               int sharps;
+
+               /* Get number of sharps for the pitch letter */
+               sharps = strchr(Circle, yyvsp[-2].intval) - Circle - 1;
+
+               /* adjust for sharp/flat */
+               if (yyvsp[-1].intval == '#') {
+                       sharps += 7;
+               }
+               else if (yyvsp[-1].intval == '&') {
+                       sharps -= 7;
+               }
+               else if (yyvsp[-1].intval != 0) {
+                       yyerror("key letter can only be followed by # or &");
+                       /* set to some ridiculous value, so will fail below */
+                       sharps = 999;
+               }
+
+               /* Adjust if needed for minor */
+               if (yyvsp[0].intval == YES) {
+                       sharps -= 3;
+               }
+
+               /* disallow illegal keys, like f& */
+               if (abs(sharps) > 7) {
+                       /* print error unless already printed one above */
+                       if (sharps < 100) {
+                               yyerror("invalid key--too many sharps or flats");
+                       }
+               }
+               else {
+                       assign_key(abs(sharps), (sharps >= 0 ? '#' : '&'),
+                                                       yyvsp[0].intval, Currstruct_p);
+               }
+       }
+    break;
+
+  case 143:
+#line 1503 "gram.y"
+    {
+               asgn_stafflines(yyvsp[-1].intval, yyvsp[0].intval == YES ? SS_NOTHING : SS_NORMAL, Currstruct_p);
+       }
+    break;
+
+  case 144:
+#line 1509 "gram.y"
+    {
+               asgn_stafflines(yyvsp[-1].intval, SS_DRUM, Currstruct_p);
+       }
+    break;
+
+  case 145:
+#line 1515 "gram.y"
+    {
+               /* use default tablature */
+               if (Currstruct_p != 0) {
+                       Currstruct_p->u.ssv_p->strinfo = Guitar;
+                       asgn_stafflines(DEFTABLINES, NO, Currstruct_p);
+               }
+       }
+    break;
+
+  case 146:
+#line 1525 "gram.y"
+    {
+               /* user-specified tablature */
+               asgn_stafflines(yyvsp[-1].intval, NO, Currstruct_p);
+       }
+    break;
+
+  case 147:
+#line 1532 "gram.y"
+    {
+               yyval.intval = 1;
+       }
+    break;
+
+  case 148:
+#line 1538 "gram.y"
+    {
+               /* count up the number of strings */
+               yyval.intval = yyvsp[-1].intval + 1;
+       }
+    break;
+
+  case 149:
+#line 1544 "gram.y"
+    {
+               /* save info about this tablature string */
+               if (Currstruct_p != 0) {
+                       add_tab_string_info(yyvsp[-3].intval, yyvsp[-2].intval, yyvsp[-1].intval, yyvsp[0].intval, Currstruct_p->u.ssv_p);
+               }
+       }
+    break;
+
+  case 150:
+#line 1552 "gram.y"
+    {
+               yyval.intval = 0;
+       }
+    break;
+
+  case 151:
+#line 1558 "gram.y"
+    {
+               if (yyvsp[0].intval != '&' && yyvsp[0].intval != '#') {
+                       yyerror("accidental on string can only be & or #");
+               }
+       }
+    break;
+
+  case 152:
+#line 1565 "gram.y"
+    {
+               /* no ticks */
+               yyval.intval = 0;
+       }
+    break;
+
+  case 153:
+#line 1572 "gram.y"
+    {
+               /* limit number of ticks. Has to match the number of bits
+                * used by TMP_NTICKS in grpsyl.c */
+               if (yyvsp[0].intval > MAXTICKS) {
+                       l_yyerror(Curr_filename, yylineno,
+                               "too many ' marks (%d max)", MAXTICKS);
+                       yyvsp[0].intval = MAXTICKS;
+               }
+       }
+    break;
+
+  case 154:
+#line 1583 "gram.y"
+    {
+               /* only valid letter is y */
+               if (*yytext != 'y') {
+                       yyerror("flag value must be y or n");
+               }
+               yyval.intval = YES;
+       }
+    break;
+
+  case 155:
+#line 1593 "gram.y"
+    {
+               yyval.intval = NO;
+       }
+    break;
+
+  case 156:
+#line 1598 "gram.y"
+    {
+               if (Currstruct_p == 0) {
+                       yyerror("wrong context for setting scoresep");
+               }
+               else {
+                       /* Assign the value of minimum vertical space
+                        * between scores. */
+                       assign_int(MINSCSEP, yyvsp[0].intval, Currstruct_p);
+               }
+       }
+    break;
+
+  case 157:
+#line 1610 "gram.y"
+    {
+               if (Currstruct_p != 0) {
+                       /* if user set minimum greater than default maximum,
+                        * adjust maximum to equal the minimum
+                        * they specified. */
+                       if (Currstruct_p->u.ssv_p->minscsep
+                                       > Currstruct_p->u.ssv_p->maxscsep) {
+                               Currstruct_p->u.ssv_p->maxscsep
+                                       = Currstruct_p->u.ssv_p->minscsep;
+                       }
+                       else {
+                               /* fill in default */
+                               assign_int(MAXSCSEP, DEFMAXSCSEP, Currstruct_p);
+                       }
+               }
+       }
+    break;
+
+  case 158:
+#line 1629 "gram.y"
+    {
+               if (Currstruct_p != 0) {
+                       if (Currstruct_p->u.ssv_p->minscsep > yyvsp[0].intval) {
+                               yyerror("scoresep maximum smaller than minimum");
+                       }
+                       assign_int(MAXSCSEP, yyvsp[0].intval, Currstruct_p);
+               }
+       }
+    break;
+
+  case 159:
+#line 1639 "gram.y"
+    {
+               if (Currstruct_p == 0) {
+                       yyerror("wrong context for setting scorepad");
+               }
+               else {
+                       /* Assign the value of minimum vertical space
+                        * between scores. */
+                       assign_int(MINSCPAD, yyvsp[-1].intval * yyvsp[0].intval, Currstruct_p);
+               }
+       }
+    break;
+
+  case 160:
+#line 1652 "gram.y"
+    {
+               if (Currstruct_p != 0) {
+                       /* If user set minimum greater than default maximum,
+                        * adjust maximum to equal the minimum
+                        * they specified. */
+                       if (Currstruct_p->u.ssv_p->minscpad
+                                       > Currstruct_p->u.ssv_p->maxscpad) {
+                               Currstruct_p->u.ssv_p->maxscpad
+                                       = Currstruct_p->u.ssv_p->minscpad;
+                       }
+                       else {
+                               /* fill in default */
+                               assign_int(MAXSCPAD, DEFMAXSCPAD, Currstruct_p);
+                       }
+               }
+       }
+    break;
+
+  case 161:
+#line 1671 "gram.y"
+    {
+               if (Currstruct_p != 0) {
+                       if (Currstruct_p->u.ssv_p->minscpad > yyvsp[-1].intval * yyvsp[0].intval) {
+                               yyerror("scorepad maximum smaller than minimum");
+                       }
+                       assign_int(MAXSCPAD, yyvsp[-1].intval * yyvsp[0].intval, Currstruct_p);
+               }
+       }
+    break;
+
+  case 163:
+#line 1686 "gram.y"
+    {
+               if (yyvsp[-1].intval == (int) 'a' && yyvsp[0].intval >= 4 && yyvsp[0].intval <= 6) {
+                       switch (yyvsp[0].intval) {
+                       case 4:
+                               yyval.intval = PS_A4;
+                               break;
+                       case 5:
+                               yyval.intval = PS_A5;
+                               break;
+                       case 6:
+                               yyval.intval = PS_A6;
+                               break;
+                       default:
+                               pfatal("impossible pagesize");
+                               break;
+                       }
+               }
+               else {
+                       yyerror("unsupported pagesize");
+               }
+       }
+    break;
+
+  case 164:
+#line 1711 "gram.y"
+    {
+               yyval.intval = 0;
+       }
+    break;
+
+  case 165:
+#line 1717 "gram.y"
+    {
+               yyval.intval = (yyvsp[0].intval == O_PORTRAIT ? 0 : 1);
+       }
+    break;
+
+  case 166:
+#line 1724 "gram.y"
+    {
+               assign_vcombine(VC_NOOVERLAP, Currstruct_p);
+       }
+    break;
+
+  case 167:
+#line 1730 "gram.y"
+    {
+               assign_vcombine(yyvsp[0].intval, Currstruct_p);
+               Defining_multiple = NO;
+       }
+    break;
+
+  case 168:
+#line 1738 "gram.y"
+    {
+               yyval.intval = VC_NOOVERLAP;
+       }
+    break;
+
+  case 169:
+#line 1744 "gram.y"
+    {
+               yyval.intval = yyvsp[0].intval;
+       }
+    break;
+
+  case 170:
+#line 1751 "gram.y"
+    {
+               yyval.intval = yyvsp[0].intval;
+       }
+    break;
+
+  case 171:
+#line 1757 "gram.y"
+    {
+               if (yyvsp[0].intval != C_TOP) {
+                       l_yyerror(Curr_filename, yylineno,
+                                       "%s not valid here", yytext);
+               }
+               yyval.intval = ENDING_TOP;
+       }
+    break;
+
+  case 172:
+#line 1766 "gram.y"
+    {
+               yyval.intval = 1;
+       }
+    break;
+
+  case 173:
+#line 1772 "gram.y"
+    {
+               yyval.intval = -1;
+       }
+    break;
+
+  case 174:
+#line 1777 "gram.y"
+    {
+               yyval.intval = NO;
+       }
+    break;
+
+  case 175:
+#line 1783 "gram.y"
+    {
+               switch (yyvsp[0].intval) {
+               case MINOR:
+                       yyval.intval = YES;
+                       break;
+               case MAJOR:
+                       yyval.intval = NO;
+                       break;
+               default:
+                       yyval.intval = NO;
+                       yyerror("must be major or minor");
+                       break;
+               }
+       }
+    break;
+
+  case 176:
+#line 1799 "gram.y"
+    {
+               yyval.intval = P_LINE;
+       }
+    break;
+
+  case 177:
+#line 1805 "gram.y"
+    {
+               yyval.intval = P_ALTPEDSTAR;
+       }
+    break;
+
+  case 178:
+#line 1811 "gram.y"
+    {
+               yyval.intval = P_PEDSTAR;
+       }
+    break;
+
+  case 180:
+#line 1819 "gram.y"
+    {
+       }
+    break;
+
+  case 181:
+#line 1823 "gram.y"
+    {
+               if (yyvsp[0].intval == FONT_UNKNOWN) {
+                       yyvsp[0].intval = Curr_font;
+               }
+               if (yyvsp[-1].intval == FAMILY_DFLT) {
+                       /* user didn't specify a family. Use the current
+                        * family, unless we don't have one yet, in which
+                        * case look it up */
+                       if (Curr_family == FAMILY_DFLT) {
+                               Curr_family = Score.fontfamily;
+                       }
+                       Titlefont =  Curr_family + yyvsp[0].intval;
+               }
+               else {
+                       Titlefont = yyvsp[-1].intval + yyvsp[0].intval;
+               }
+       }
+    break;
+
+  case 182:
+#line 1842 "gram.y"
+    {
+               yyval.intval = FONT_UNKNOWN;
+       }
+    break;
+
+  case 183:
+#line 1848 "gram.y"
+    {
+               yyval.intval = yyvsp[0].intval;
+       }
+    break;
+
+  case 184:
+#line 1853 "gram.y"
+    {
+               yyval.intval = FAMILY_DFLT;
+       }
+    break;
+
+  case 185:
+#line 1858 "gram.y"
+    {
+               yyval.intval = yyvsp[0].intval;
+       }
+    break;
+
+  case 186:
+#line 1863 "gram.y"
+    {
+               Titlesize = Curr_size;
+       }
+    break;
+
+  case 187:
+#line 1869 "gram.y"
+    {
+               Titlesize = yyvsp[-1].intval;
+       }
+    break;
+
+  case 188:
+#line 1875 "gram.y"
+    {
+               Extra = extra_needed(Titlefont, Titlesize, yyvsp[0].stringval);
+               proc_printcmd(J_CENTER, (struct INPCOORD *) 0, yyvsp[0].stringval,
+                               Titlefont, Titlesize, YES, NO, Extra);
+       }
+    break;
+
+  case 189:
+#line 1883 "gram.y"
+    {
+               double tmp_extra;
+
+               /* if one is taller than the default for the font/size,
+                * figure out how much more to add on */
+               /* can't use MAX passing extra_needed() as arguments because
+                * it would get executed multiple times, which is a problem */
+               Extra = extra_needed(Titlefont, Titlesize, yyvsp[-1].stringval);
+               tmp_extra = extra_needed(Titlefont, Titlesize, yyvsp[0].stringval);
+               Extra = MAX(Extra, tmp_extra);
+
+
+               proc_printcmd(J_LEFT, (struct INPCOORD *) 0, yyvsp[-1].stringval,
+                               Titlefont, Titlesize, YES, NO, Extra);
+               proc_printcmd(J_RIGHT, (struct INPCOORD *) 0, yyvsp[0].stringval,
+                               Titlefont, Titlesize, NO, NO, (double) 0.0);
+       }
+    break;
+
+  case 190:
+#line 1903 "gram.y"
+    {
+               double tmp_extra;
+
+               Extra = extra_needed(Titlefont, Titlesize, yyvsp[-2].stringval);
+               tmp_extra = extra_needed(Titlefont, Titlesize, yyvsp[-1].stringval);
+               Extra = MAX(Extra, tmp_extra);
+               tmp_extra = extra_needed(Titlefont, Titlesize, yyvsp[0].stringval);
+               Extra = MAX(Extra, tmp_extra);
+
+               proc_printcmd(J_LEFT, (struct INPCOORD *) 0, yyvsp[-2].stringval,
+                               Titlefont, Titlesize, YES, NO, Extra);
+               proc_printcmd(J_CENTER, (struct INPCOORD *) 0, yyvsp[-1].stringval,
+                               Titlefont, Titlesize, NO, NO, (double) 0.0);
+               proc_printcmd(J_RIGHT, (struct INPCOORD *) 0, yyvsp[0].stringval,
+                               Titlefont, Titlesize, NO, NO, (double) 0.0);
+       }
+    break;
+
+  case 191:
+#line 1921 "gram.y"
+    {
+               char *p;                /* pointer through the string */
+               int backslash_count;    /* how many backslashes in a row */
+               int font, size;         /* at end of \n-delimited segment */
+               char *string_start;     /* where current segment begins */
+
+               /* Convert unescaped input newlines to spaces.
+                * The +2 in the 'for' initialization is to skip font/size.
+                */
+               backslash_count = 0;
+               string_start = yyvsp[-2].stringval;
+               /* If we are running on a file using \r or \r\n for
+                * line separator, normalize to \n instead */
+               for (p = string_start + 2; *p != 0; p++) {
+                       if (*p == '\r') {
+                               if ( *(p+1) != '\n') {
+                                       /* \r by itself. Use \n instead */
+                                       *p = '\n';
+                               }
+                               else {
+                                       /* delete the \r */
+                                       char *src, *dest;
+                                       for (src = p + 1, dest = p;  ; src++, dest++) { 
+                                               *dest = *src;
+                                               if (*src == '\0') {
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               font = Titlefont;
+               size = Titlesize;
+               for (p = string_start + 2; *p != 0; p++) {
+                       /* Real newlines not preceeded by an odd number
+                        * of backslashes are converted to spaces. */
+                       if (*p == '\n' && (backslash_count & 0x1) == 0) {
+                               *p = ' ';
+                       }
+
+                       /* Count up number of consecutive backslashes.
+                        * Also, if user explicitly uses \n, split into
+                        * a new paragraph
+                        */
+                       if (*p == '\\') {
+                               backslash_count++;
+                               if (((backslash_count & 0x1) == 1)
+                                               && ( *(p+1) == 'n') ) {
+                                       /* Need to split.
+                                        * Terminate the current string
+                                        * where we are in it, and process it,
+                                        * then arrange to continue processing
+                                        * on the rest of the string.
+                                        */
+                                       *p = '\0';
+                                       (void) fix_string(string_start,
+                                               font, size,
+                                               Curr_filename, yylineno);
+                                       proc_printcmd(yyvsp[-6].intval, (struct INPCOORD*) 0,
+                                               string_start, font, size,
+                                               YES, NO, 0.0);
+
+                                       /* The user could change font/size
+                                        * in mid-string with \f() and/or \s().
+                                        * so we have to determine what they
+                                        * are at the end of the current segment
+                                        * and use that for making the copy
+                                        * of the remainder of the string.
+                                        * The original copy of the remainder
+                                        * of the string gets "memory leaked,"
+                                        * but this is a rare case, so not
+                                        * worth worrying about.
+                                        */
+                                       end_fontsize(string_start, &font, &size);
+                                       string_start = copy_string(p+2, font, size);
+                                       p = string_start + 2;
+                               }
+                       }
+                       else {
+                               backslash_count = 0;
+                       }
+               }
+               (void) fix_string(string_start, font, size,
+                                       Curr_filename, yylineno);
+               proc_printcmd(yyvsp[-6].intval, (struct INPCOORD*) 0, string_start,
+                                       font, size, YES, NO, 0.0);
+       }
+    break;
+
+  case 192:
+#line 2012 "gram.y"
+    {
+               /* Use same paragraph time as last time (or default if
+                * this is the first paragraph ever in this song.) */
+               yyval.intval = Curr_paratype;
+       }
+    break;
+
+  case 193:
+#line 2020 "gram.y"
+    {
+               Curr_paratype = yyvsp[0].intval;
+               yyval.intval = yyvsp[0].intval;
+       }
+    break;
+
+  case 222:
+#line 2111 "gram.y"
+    {
+               /* strip the quotes from the string and make a copy for later use */
+               if (Curr_family == FAMILY_DFLT) {
+                       Curr_family = Score.fontfamily;
+               }
+               yyval.stringval = copy_string(stripquotes(yytext), Curr_family + Curr_font,
+                                                               Curr_size);
+       }
+    break;
+
+  case 223:
+#line 2122 "gram.y"
+    {
+               char *old_string;
+
+               /* append new string part to existing part */
+               old_string = yyvsp[-2].stringval;
+               /* new string part has quotes, so subtract 2 from needed length,
+                * but need space for null, so overall need 1 less. */
+               MALLOCA(char, yyval.stringval, strlen(old_string) + strlen(yytext) - 1);
+               sprintf(yyval.stringval, "%s%s", old_string, stripquotes(yytext));
+               FREE(old_string);
+       }
+    break;
+
+  case 224:
+#line 2135 "gram.y"
+    {
+               /* Here's the deal: the staff/voice specification
+                * could be lists of staff ranges and/or voices.
+                * We need a separate copy of the groupinfo
+                * for each staff/voice. So as we parse the sv_spec,
+                * we remember which staffs and voices are specified,
+                * and keep a pointer to the first STAFF in the measure.
+                * Then after collecting the groupinfo,
+                * we make copies of the group info for each staff/voice given.
+                * It has to be copies rather than just a pointer to the
+                * same stuff, because the coordinates will be different
+                * for each staff/voice. */
+
+               /* attach the groupinfo to each of the STAFF structs */
+               link_groups();
+       }
+    break;
+
+  case 225:
+#line 2154 "gram.y"
+    {
+               add_multirest(yyvsp[-1].intval);
+               /* If there are alternating time signatures, figure out
+                * which one should be in effect at the end of the multirest */
+               if (Alt_timesig_list != 0) {
+                       int m;
+
+                       /* The Next_alt_timesig is already pointing to
+                        * the value for after the first measure in the
+                        * multirest, so have to subtract 1 here */
+                       for (m = 0; m < yyvsp[-1].intval - 1; m++) {
+                               if (Next_alt_timesig == 0) {
+                                       /* Shouldn't really ever get here,
+                                        * since other code should do the
+                                        * wrap-around, but just in case... */
+                                       Next_alt_timesig = Alt_timesig_list;
+                                       continue;
+                               }
+                               do {
+                                       Next_alt_timesig++;
+                                       if (*Next_alt_timesig == TSR_END) {
+                                               Next_alt_timesig = Alt_timesig_list;
+                                               break;
+                                       }
+                               } while (*Next_alt_timesig != TSR_ALTERNATING);
+                       }
+                       if (*Next_alt_timesig == TSR_ALTERNATING) {
+                               Next_alt_timesig++;
+                       }
+               }
+               Currstruct_p = (struct MAINLL *) 0;
+       }
+    break;
+
+  case 226:
+#line 2189 "gram.y"
+    {
+               free_staffrange();
+       }
+    break;
+
+  case 227:
+#line 2194 "gram.y"
+    {
+               begin_range(PL_UNKNOWN);
+       }
+    break;
+
+  case 228:
+#line 2199 "gram.y"
+    {
+               Chord_at_a_time = NO;
+       }
+    break;
+
+  case 229:
+#line 2205 "gram.y"
+    {
+               Chord_at_a_time = YES;
+       }
+    break;
+
+  case 233:
+#line 2220 "gram.y"
+    {
+               begin_map();
+       }
+    break;
+
+  case 234:
+#line 2225 "gram.y"
+    {
+               end_map();
+       }
+    break;
+
+  case 235:
+#line 2230 "gram.y"
+    {
+               map_item();
+       }
+    break;
+
+  case 236:
+#line 2236 "gram.y"
+    {
+               map_item();
+               Defining_multiple = YES;
+       }
+    break;
+
+  case 237:
+#line 2242 "gram.y"
+    {
+               /* initialize grpsyl info */
+               Curr_grpsyl_p = Last_grpsyl_p = (struct GRPSYL *) 0;
+       }
+    break;
+
+  case 239:
+#line 2252 "gram.y"
+    {
+               /* prepare for a new set of ranges */
+               begin_range(Place);
+               Defining_multiple = YES;
+       }
+    break;
+
+  case 240:
+#line 2259 "gram.y"
+    {
+               /* data is for staff with only one voice */
+               save_vno_range(1, 1);
+               add_to_sv_list();
+       }
+    break;
+
+  case 241:
+#line 2267 "gram.y"
+    {
+               if (yyvsp[0].intval == YES) {
+                       add_to_sv_list();
+               }
+       }
+    break;
+
+  case 242:
+#line 2276 "gram.y"
+    {
+               /* set flag as to whether we are processing tab staff
+                * information or normal staff info */
+               Doing_tab_staff = is_tab_range();
+       }
+    break;
+
+  case 244:
+#line 2286 "gram.y"
+    {
+               /* several staffs have the same note data */
+               Defining_multiple = YES;
+       }
+    break;
+
+  case 245:
+#line 2292 "gram.y"
+    {
+               /* remember which staffs we are currently getting data for */
+               /* if only a single number, not a range, staff_range will be
+                * 0, so use staffnum as high and low of range */
+               save_staff_range(yyvsp[-1].intval, (yyvsp[0].intval == 0 ? yyvsp[-1].intval : yyvsp[0].intval));
+       }
+    break;
+
+  case 246:
+#line 2300 "gram.y"
+    {
+               /* empty - no range, just a single number */
+               yyval.intval = 0;
+       }
+    break;
+
+  case 247:
+#line 2307 "gram.y"
+    {
+               Defining_multiple = YES;
+               yyval.intval = yyvsp[0].intval;
+               if (yyvsp[0].intval == 0) {
+                       yyerror("staff of 0 is illegal");
+               }
+       }
+    break;
+
+  case 248:
+#line 2317 "gram.y"
+    {
+               /* note data applies to a single voice */
+               if (rangecheck(yyvsp[-1].intval, MINVOICES, MAXVOICES, "voice") == YES) {
+                       save_vno_range(yyvsp[-1].intval, yyvsp[-1].intval);
+                       yyval.intval = YES;
+               }
+               else {
+                       yyval.intval = NO;
+               }
+       }
+    break;
+
+  case 249:
+#line 2330 "gram.y"
+    {
+               /* note data applies to range of voices */
+               if (rangecheck(yyvsp[-3].intval, MINVOICES, MAXVOICES, "voice") == YES &&
+                               rangecheck(yyvsp[-1].intval, MINVOICES, MAXVOICES, "voice") == YES) {
+                       if (yyvsp[-1].intval < yyvsp[-3].intval) {
+                               l_yyerror(Curr_filename, yylineno,
+                                       "end of voice range is smaller than beginning");
+                               yyval.intval = NO;
+                       }
+                       else {
+                               save_vno_range(yyvsp[-3].intval, yyvsp[-1].intval);
+                               Defining_multiple = YES;
+                               yyval.intval = YES;
+                       }
+               }
+               else {
+                       yyval.intval = NO;
+               }
+       }
+    break;
+
+  case 251:
+#line 2355 "gram.y"
+    {
+               Defining_multiple = YES;
+       }
+    break;
+
+  case 255:
+#line 2370 "gram.y"
+    {
+               /* Associate any TIMEDSSVs with this group */
+               if (Curr_tssv_p != 0) {
+                       tssv_setgrpsyl(Curr_grpsyl_p);
+                       Curr_tssv_p = 0;
+               }
+
+               /* if no custom beaming indicated, fill in based on previous. */
+               if ( Curr_grpsyl_p->beamloc == NOITEM) {
+                       setbeamloc(Curr_grpsyl_p, Last_grpsyl_p);
+               }
+
+               /* later we check that if there is an 'm', it is
+                * the only thing in the measure */
+
+               link_notegroup(Curr_grpsyl_p, Last_grpsyl_p);
+               Curr_marklist = 0;
+               /* Save pointer to this group, in case there are additive
+                * times, and the next group gets its time value from this
+                * group. In that case, we need this group, not the last one
+                * of the added groups. */
+               Prev_grpsyl_p = Curr_grpsyl_p;
+               /* Add groups if there were additive time values. */
+               if (Extra_time_p != 0) {
+                       Curr_grpsyl_p = expandgrp(Curr_grpsyl_p, Extra_time_p);
+                       /* If there was a custom beam ebm on something with
+                        * additive time, we need make sure ENDITEM is on only
+                        * the last of the expanded groups. */
+                       if (Curr_grpsyl_p != Prev_grpsyl_p
+                                       && Prev_grpsyl_p->beamloc == ENDITEM) {
+                               struct GRPSYL *g_p;
+                               for (g_p = Prev_grpsyl_p; g_p != Curr_grpsyl_p;
+                                                       g_p = g_p->next) {
+                                       g_p->beamloc = INITEM;
+                               }
+                               Curr_grpsyl_p->beamloc = ENDITEM;
+                       }
+                       Last_grpsyl_p = Curr_grpsyl_p->prev;
+               }
+               Curr_timelist_p = 0;
+       }
+    break;
+
+  case 260:
+#line 2428 "gram.y"
+    {
+               if (Chord_at_a_time == YES) {
+                       yyerror("mid-measure changes not allowed on chord-at-a-time input");
+               }
+       }
+    break;
+
+  case 261:
+#line 2437 "gram.y"
+    {
+               Curr_tssv_p = tssv_create(C_SCORE);
+       }
+    break;
+
+  case 262:
+#line 2443 "gram.y"
+    {
+               Curr_tssv_p = tssv_create(C_STAFF);
+       }
+    break;
+
+  case 263:
+#line 2449 "gram.y"
+    {
+               Curr_tssv_p = tssv_create(C_VOICE);
+       }
+    break;
+
+  case 266:
+#line 2463 "gram.y"
+    {
+               if (Curr_grpsyl_p != 0 && Curr_grpsyl_p->grpsyl == GS_GROUP
+                               && Curr_grpsyl_p->grpvalue == GV_ZERO) {
+                       yyerror("mid-measure clef change not allowed after grace note\n");
+               }
+               tssv_update(Curr_tssv_p, yyvsp[-2].intval, yyvsp[0].intval);
+       }
+    break;
+
+  case 267:
+#line 2473 "gram.y"
+    {
+               switch (yyvsp[-2].intval) {
+
+               case DEFOCT:
+               case RELEASE:
+                       tssv_update(Curr_tssv_p, yyvsp[-2].intval, yyvsp[0].intval);
+                       break;
+
+               default:
+                       yyerror("parameter type cannot be changed mid-measure");
+                       break;
+               }
+       }
+    break;
+
+  case 269:
+#line 2493 "gram.y"
+    {
+               if (Good_till_canceled == NO) {
+                       /* use default attributes */
+                       Curr_grpsyl_p->grpvalue = GV_NORMAL;
+                       Curr_grpsyl_p->grpsize = GS_NORMAL;
+                       Curr_grpsyl_p->headshape = HS_UNKNOWN;
+               }
+               else {
+                       /* re-use previous style */
+                       copy_attributes(Curr_grpsyl_p, Last_grpsyl_p);
+               }
+       }
+    break;
+
+  case 270:
+#line 2508 "gram.y"
+    {
+               Good_till_canceled = NO;
+       }
+    break;
+
+  case 271:
+#line 2514 "gram.y"
+    {
+       }
+    break;
+
+  case 272:
+#line 2518 "gram.y"
+    {
+               Good_till_canceled = NO;
+       }
+    break;
+
+  case 273:
+#line 2524 "gram.y"
+    {
+               Good_till_canceled = YES;
+       }
+    break;
+
+  case 274:
+#line 2529 "gram.y"
+    {
+       }
+    break;
+
+  case 275:
+#line 2534 "gram.y"
+    {
+               if (Good_till_canceled == YES) {
+                       yyerror("can't use ... and more than one [] on same chord");
+               }
+       }
+    break;
+
+  case 276:
+#line 2541 "gram.y"
+    {
+               /* NULL token to cause allocation of a GRPSYL struct */
+               Last_grpsyl_p = Curr_grpsyl_p;
+               Curr_grpsyl_p = newGRPSYL(GS_GROUP);
+       }
+    break;
+
+  case 277:
+#line 2548 "gram.y"
+    {
+               /* an empty marklist means we should use
+                * the same attributes as the last time */
+               copy_attributes(Curr_grpsyl_p, Last_grpsyl_p);
+       }
+    break;
+
+  case 281:
+#line 2565 "gram.y"
+    {
+               Curr_grpsyl_p->nwith = (short) Item_count;
+               Curr_grpsyl_p->withlist = Curr_marklist;
+       }
+    break;
+
+  case 285:
+#line 2581 "gram.y"
+    {
+               if (Curr_grpsyl_p->stemdir != UNKNOWN &&
+                                       Curr_grpsyl_p->stemdir != yyvsp[0].intval) {
+                       l_warning(Curr_filename, yylineno,
+                               "both stem directions specified; using last instance");
+               }
+               if (Doing_tab_staff == YES) {
+                       yyerror("stem direction specification not allowed on tab staff");
+               }
+               else {
+                       Curr_grpsyl_p->stemdir = yyvsp[0].intval;
+               }
+       }
+    break;
+
+  case 286:
+#line 2597 "gram.y"
+    {
+               if (yyvsp[-2].intval != DIST) {
+                       yyerror("unexpected parameter name");
+               }
+               else {
+                       if (Curr_grpsyl_p->restdist != NORESTDIST &&
+                                       Curr_grpsyl_p->restdist != yyvsp[-1].intval * yyvsp[0].intval) {
+                               l_warning(Curr_filename, yylineno,
+                                               "more than one dist value specified; using last instance");
+                       }
+                       Curr_grpsyl_p->restdist = yyvsp[-1].intval * yyvsp[0].intval;
+               }
+       }
+    break;
+
+  case 287:
+#line 2613 "gram.y"
+    {
+               if (Curr_grpsyl_p->ho_usage != HO_NONE &&
+                               Curr_grpsyl_p->ho_usage != yyvsp[0].intval) {
+                       l_warning(Curr_filename, yylineno,
+                               "More than one ho type specified; last instance used");
+               }
+               Curr_grpsyl_p->ho_usage = yyvsp[0].intval;
+       }
+    break;
+
+  case 288:
+#line 2624 "gram.y"
+    {
+               if (Curr_grpsyl_p != 0) {
+                       if (Curr_grpsyl_p->headshape != HS_UNKNOWN) {
+                               l_warning(Curr_filename, yylineno,
+                                       "multiple head shapes specified, using last");
+                       }
+                       /* +2 to skip past extraneous font/size */
+                       if (Doing_tab_staff == YES && strcmp(yyvsp[0].stringval + 2, "allx") != 0) {
+                               yyerror("allx is the only headshape allowed on tab staffs");
+                       }
+                       if ((Curr_grpsyl_p->headshape = get_shape_num(yyvsp[0].stringval + 2))
+                                       == HS_UNKNOWN) {
+                               l_yyerror(Curr_filename, yylineno,
+                                       "'%s' is not a valid head shape name",
+                                       ascii_str(yyvsp[0].stringval, YES, NO, TM_NONE));
+                       }
+               }
+               else {
+                       pfatal("Curr_grpsyl_p was null for setting hs");
+               }
+               /* We don't need the name anymore; we have its corresponding
+                * number that we use internally. */
+               FREE(yyvsp[0].stringval);
+       }
+    break;
+
+  case 289:
+#line 2651 "gram.y"
+    {
+               if (Curr_grpsyl_p->stemlen != STEMLEN_UNKNOWN &&
+                               fabs(Curr_grpsyl_p->stemlen - yyvsp[0].floatval * STEPSIZE) > 0.0001) {
+                       l_warning(Curr_filename, yylineno,
+                               "more than one len specified; using last instance");
+               }
+               Curr_grpsyl_p->stemlen = yyvsp[0].floatval * STEPSIZE;
+       }
+    break;
+
+  case 290:
+#line 2662 "gram.y"
+    {
+               if (yyvsp[0].intval <= 0) {
+                       yyerror("slash number must be > 0");
+               }
+               else if (yyvsp[0].intval > 8) {
+                       /* we decided 8 slashes would be at least 256th note
+                        * or shorter, and 256th is the shortest note we
+                        * support, 8 slashes is plenty */
+                       yyerror("slash number must be <= 8");
+               }
+               if (Curr_grpsyl_p->slash_alt > 0 &&
+                                       Curr_grpsyl_p->slash_alt != yyvsp[0].intval) {
+                       l_warning(Curr_filename, yylineno,
+                               "more than one slash value specified; using last instance");
+               }
+               if (Curr_grpsyl_p->slash_alt < 0) {
+                       yyerror("only one slash/alt allowed per group");
+               }
+               Curr_grpsyl_p->slash_alt = yyvsp[0].intval;
+       }
+    break;
+
+  case 291:
+#line 2685 "gram.y"
+    {
+               yyval.intval = HO_RIGHT;
+       }
+    break;
+
+  case 292:
+#line 2691 "gram.y"
+    {
+               yyval.intval = HO_LEFT;
+       }
+    break;
+
+  case 293:
+#line 2697 "gram.y"
+    {
+               /* We want to silently accept identical values specified
+                * more than once, so use fuzzy compare to deal with roundoff */
+               if (Curr_grpsyl_p->ho_usage == HO_VALUE &&
+                               fabs(Curr_grpsyl_p->ho_value - yyvsp[-1].intval * yyvsp[0].floatval) > 0.0001) {
+                       l_warning(Curr_filename, yylineno,
+                               "More than one ho value specified; last instance used");
+               }
+               Curr_grpsyl_p->ho_value = yyvsp[-1].intval * yyvsp[0].floatval;
+               yyval.intval = HO_VALUE;
+       }
+    break;
+
+  case 294:
+#line 2711 "gram.y"
+    {
+               yyval.intval = 1;
+       }
+    break;
+
+  case 295:
+#line 2717 "gram.y"
+    {
+               yyval.intval = yyvsp[0].intval;
+       }
+    break;
+
+  case 301:
+#line 2739 "gram.y"
+    {
+               yyvsp[0].floatval *= yyvsp[-1].intval;
+               if (fabs(Curr_grpsyl_p->beamslope - NOBEAMANGLE) > 0.01) {
+                       l_warning(Curr_filename, yylineno,
+                               "multiple slope values specified; using last one");
+               }
+               if (frangecheck(yyvsp[0].floatval, MINBEAMANGLE, MAXBEAMANGLE, "slope") == YES) {
+                       Curr_grpsyl_p->beamslope = yyvsp[0].floatval;
+               }
+       }
+    break;
+
+  case 302:
+#line 2752 "gram.y"
+    {
+               if (yyvsp[0].intval <= 0) {
+                       yyerror("alt number must be > 0");
+               }
+               if (Curr_grpsyl_p->slash_alt != 0) {
+                       yyerror("only one slash/alt allowed per group");
+               }
+               if (Doing_tab_staff == YES) {
+                       yyerror("alt not allowed on tablature staff");
+               }
+               /* Keep small enough that 1 shifted left by this still
+                * fits in a 16-bit int. Should be more than enough! */
+               if (yyvsp[0].intval > 15) {
+                       warning("alt value too large");
+                       yyvsp[0].intval = 15;
+               }
+               Curr_grpsyl_p->slash_alt = -yyvsp[0].intval;
+       }
+    break;
+
+  case 303:
+#line 2773 "gram.y"
+    {
+               int n;
+
+               /* add a slur to each note in the chord. Don't know
+                * which pitch to slur to yet, just that it will be to
+                * the "matching" note in the next chord, so use
+                * special magic pitch of 'M' to convey this */
+               for (n = 0; n < Curr_grpsyl_p->nnotes; n++) {
+                       add_slurto(Curr_grpsyl_p, 'M', USE_DFLT_OCTAVE, n, yyvsp[-1].intval);
+                       set_slurdir(Curr_grpsyl_p, -1, yyvsp[0].intval);
+               }
+       }
+    break;
+
+  case 304:
+#line 2788 "gram.y"
+    {
+               int n;
+
+               Curr_grpsyl_p->tie = YES;
+               for (n = 0; n < Curr_grpsyl_p->nnotes; n++) {
+                       Curr_grpsyl_p->notelist[n].tie = YES;
+                       Curr_grpsyl_p->notelist[n].tiestyle = yyvsp[-1].intval;
+                       Curr_grpsyl_p->notelist[n].tiedir = yyvsp[0].intval;
+               }
+       }
+    break;
+
+  case 305:
+#line 2800 "gram.y"
+    {
+               if (Curr_marklist == 0) {
+                       /* allocate space for a list of marks */
+                       MALLOCA(char *, Curr_marklist, ITEMS);
+                       Item_count = 0;
+                       Max_items = ITEMS;
+               }
+       }
+    break;
+
+  case 306:
+#line 2810 "gram.y"
+    {
+               yyval.intval = UNKNOWN;
+       }
+    break;
+
+  case 307:
+#line 2816 "gram.y"
+    {
+               yyval.intval = yyvsp[0].intval;
+       }
+    break;
+
+  case 310:
+#line 2828 "gram.y"
+    {
+               /* if too many items, get some more space */
+               if (Item_count >= Max_items) {
+                       Max_items += ITEMS;
+                       if ((Curr_marklist = (char **) realloc(Curr_marklist,
+                                               Max_items * sizeof(char **)))
+                                               == (char **) 0) {
+                               l_no_mem(__FILE__, __LINE__);
+                       }
+               }
+               Curr_marklist[Item_count++] = yyvsp[0].stringval;
+       }
+    break;
+
+  case 311:
+#line 2842 "gram.y"
+    {
+               MALLOCA(char, yyval.stringval, strlen(yyvsp[0].stringval) + 3);
+               yyval.stringval[0] = FONT_TR;
+               yyval.stringval[1] = DFLT_SIZE;
+               sprintf(yyval.stringval + 2, yyvsp[0].stringval);
+       }
+    break;
+
+  case 313:
+#line 2855 "gram.y"
+    {
+               yyval.stringval = (Curr_grpsyl_p->grpsize == GS_NORMAL
+                                       ? "\\(dot)" : "\\(smdot)");
+       }
+    break;
+
+  case 314:
+#line 2862 "gram.y"
+    {
+               yyval.stringval = (Curr_grpsyl_p->grpsize == GS_NORMAL
+                                       ? "\\(leg)" : "\\(smleg)");
+       }
+    break;
+
+  case 315:
+#line 2869 "gram.y"
+    {
+               yyval.stringval = (Curr_grpsyl_p->grpsize == GS_NORMAL
+                                       ? "\\(acc_gt)" : "\\(smacc_gt)");
+       }
+    break;
+
+  case 316:
+#line 2876 "gram.y"
+    {
+               yyval.stringval = (Curr_grpsyl_p->grpsize == GS_NORMAL
+                                       ? "\\(acc_hat)" : "\\(smacc_hat)");
+       }
+    break;
+
+  case 317:
+#line 2882 "gram.y"
+    {
+               if (Curr_grpsyl_p->grpvalue == GV_ZERO) {
+                       l_warning(Curr_filename, yylineno,
+                               "both grace and cue specified; using last instance");
+               }
+               Curr_grpsyl_p->grpvalue = GV_NORMAL;
+               Curr_grpsyl_p->grpsize = GS_SMALL;
+       }
+    break;
+
+  case 318:
+#line 2893 "gram.y"
+    {
+               if (Curr_grpsyl_p->grpsize == GS_SMALL
+                                       && Curr_grpsyl_p->grpvalue != GV_ZERO) {
+                       l_warning(Curr_filename, yylineno,
+                               "both cue and grace specified; using last instance");
+               }
+
+               Curr_grpsyl_p->grpsize = GS_SMALL;
+               Curr_grpsyl_p->grpvalue = GV_ZERO;
+       }
+    break;
+
+  case 319:
+#line 2906 "gram.y"
+    {
+               if (Curr_grpsyl_p->headshape != HS_UNKNOWN) {
+                       l_warning(Curr_filename, yylineno,
+                               "diam is overriding previous headshapes specification");
+               }
+               Curr_grpsyl_p->headshape = get_shape_num("diam");
+       }
+    break;
+
+  case 320:
+#line 2916 "gram.y"
+    {
+               if (Curr_grpsyl_p->headshape != HS_UNKNOWN) {
+                       l_warning(Curr_filename, yylineno,
+                               "xnote is overriding previous headshapes specification");
+               }
+               Curr_grpsyl_p->headshape = get_shape_num(
+                                       Doing_tab_staff == YES ? "allx" : "x");
+       }
+    break;
+
+  case 321:
+#line 2927 "gram.y"
+    {
+               yyval.intval = UP;
+       }
+    break;
+
+  case 322:
+#line 2933 "gram.y"
+    {
+               yyval.intval = DOWN;
+       }
+    break;
+
+  case 323:
+#line 2939 "gram.y"
+    {
+               /* custom beaming cannot be nested */
+               struct GRPSYL *prev_like_gs_p;
+               /* Find previous group with same grace-ness. Can't use
+                * prevsimilar() here, since it looks at grpcont too. */
+               for (prev_like_gs_p = Last_grpsyl_p; prev_like_gs_p != 0 &&
+                       prev_like_gs_p->grpvalue != Curr_grpsyl_p->grpvalue;
+                       prev_like_gs_p = prev_like_gs_p->prev) {
+                       ;
+               }
+               if (prev_like_gs_p != 0 &&
+                               ((prev_like_gs_p->beamloc == STARTITEM)
+                               || (prev_like_gs_p->beamloc == INITEM)) ) {
+                       yyerror("custom beaming may not be nested");
+               }
+               /* Non-custom beaming, if any, is done later, in do_bar() */
+               else {
+                       /* begin custom beaming */
+                       Curr_grpsyl_p->beamloc = STARTITEM;
+                       if (Curr_grpsyl_p->basictime < 8 && yyvsp[0].intval == CS_SAME) {
+                               yyerror("beamed notes must be 8th or shorter");
+                       }
+               }
+               Curr_grpsyl_p->beamto = yyvsp[0].intval;
+       }
+    break;
+
+  case 324:
+#line 2967 "gram.y"
+    {
+               Curr_grpsyl_p->breakbeam = YES;
+       }
+    break;
+
+  case 325:
+#line 2973 "gram.y"
+    {
+               struct GRPSYL *last_nongrace_p;
+
+               /* find the previous group, skipping grace groups */
+               for (last_nongrace_p = Last_grpsyl_p;
+                               last_nongrace_p != (struct GRPSYL *) 0
+                               && last_nongrace_p->grpvalue == GV_ZERO;
+                               last_nongrace_p = last_nongrace_p->prev) {
+                       ;
+               }
+
+               /* check that a custom beam is in progress */
+               if ((last_nongrace_p == (struct GRPSYL *) 0)
+                               || ((last_nongrace_p != (struct GRPSYL *) 0)
+                               && (last_nongrace_p->beamloc != STARTITEM)
+                               && (last_nongrace_p->beamloc != INITEM) )) {
+                       yyerror("'ebm' unexpected: no custom beaming in progress");
+               }
+               else {
+                       Curr_grpsyl_p->beamloc = ENDITEM;
+                       Curr_grpsyl_p->beamto = last_nongrace_p->beamto;
+                       if (Curr_grpsyl_p->basictime < 8
+                                       && Last_grpsyl_p->beamto == CS_SAME) {
+                               yyerror("beamed notes must be 8th or shorter");
+                       }
+               }
+       }
+    break;
+
+  case 326:
+#line 3002 "gram.y"
+    {
+               /* Use the same as last time or default timeunit.
+                * If that involves additive time values,
+                * save pointer to that info in Extra_time_p for later use. */
+               Extra_time_p = copy_timeunit(Curr_grpsyl_p, Prev_grpsyl_p,
+                                               Extra_time_p);
+       }
+    break;
+
+  case 327:
+#line 3012 "gram.y"
+    {
+               if (Curr_grpsyl_p->is_meas == YES) {
+                       Curr_grpsyl_p->fulltime = Score.time;
+               }
+               else {
+                       Curr_grpsyl_p->fulltime = yyvsp[0].ratval;
+               }
+       }
+    break;
+
+  case 328:
+#line 3022 "gram.y"
+    {
+               yyval.intval = CS_SAME;
+       }
+    break;
+
+  case 329:
+#line 3028 "gram.y"
+    {
+               CSBused = YES;
+               switch (yyvsp[0].intval) {
+               case PL_ABOVE:
+                       yyval.intval = CS_ABOVE;
+                       break;
+               case PL_BELOW:
+                       yyval.intval = CS_BELOW;
+                       break;
+               default:
+                       yyerror("bm with staff must be 'above' or 'below'");
+                       yyval.intval = CS_SAME;
+               }
+       }
+    break;
+
+  case 330:
+#line 3044 "gram.y"
+    {
+               yyval.ratval.n = yyvsp[0].intval;
+               yyval.ratval.d = 1;
+
+               /* if filling in a GRPSYL struct, need to fill in basic time,
+                * could also be here due to beamstyle, in which case the
+                * Curr_grpsyl_p will be NULL, or when getting tuplet duration,
+                * in which case flag will be set */
+               if (Curr_grpsyl_p != (struct GRPSYL *) 0
+                                       && Getting_tup_dur == NO) {
+                       /* If we are gathering basictime as part of a list
+                        * of additive times, we will save the value a few
+                        * lines down from here. But in the normal case,
+                        * we set basictime in the current GRPSYL. */
+                       if (Extra_time_p == 0) {
+                               /* 1/2 is 0 internally. 1/4 is -1 internally */
+                                Curr_grpsyl_p->basictime = (yyvsp[0].intval == 2 ? 0 : -1);
+                       }
+               }
+               /* If doing additive times, need to save value. */
+               if (Extra_time_p != 0) {
+                       Extra_basictime = (yyvsp[0].intval == 2 ? 0 : -1);
+               }
+       }
+    break;
+
+  case 331:
+#line 3071 "gram.y"
+    {
+               /* check that a power of two from 1 to MAXBASICTIME */
+               if (power_of2check(yyvsp[0].intval, "note basic time value") == NO) {
+                       /* force to a power to two, so that other code
+                        * (like in expandgrp) that expect a sane value
+                        * to not blow up. This may lead to a somewhat
+                        * misleading "time does not add up to time                                      * signature message, but we don't know what
+                        * time they really meant, and this is better
+                        * than pfataling. */
+                       yyvsp[0].intval = 2;
+               }
+               /* can't use rangecheck here because the error message would
+                * say 0 and -1 are valid times, which is only true internally--
+                * the user has to use 1/2, 1/4 or m. */
+               if (yyvsp[0].intval < MINBASICTIME || yyvsp[0].intval > MAXBASICTIME) {
+                       l_yyerror(Curr_filename, yylineno,
+                               "time value must be between 1 and %d, or 1/2 or 1/4 or m",
+                               MAXBASICTIME);
+               }
+               yyval.ratval.n = 1;
+               /* avoid division by zero */
+               if (yyvsp[0].intval == 0) {
+                       yyvsp[0].intval = 1;
+               }
+               yyval.ratval.d = yyvsp[0].intval;
+               if (Curr_grpsyl_p != (struct GRPSYL *) 0
+                                       && Getting_tup_dur == NO) {
+                       if (Curr_timelist_p == 0) {
+                               Curr_grpsyl_p->basictime = yyvsp[0].intval;
+                       }
+               }
+               /* If doing additive times, need to save value */
+               if (Extra_time_p != 0) {
+                       Extra_basictime = yyvsp[0].intval;
+               }
+       }
+    break;
+
+  case 332:
+#line 3110 "gram.y"
+    {
+               free_extra_time();
+       }
+    break;
+
+  case 334:
+#line 3120 "gram.y"
+    {
+               /* Set basictime to what we saved in basic_time_val rule,
+                * then calculate fulltime from that and number of dots. */
+               Curr_timelist_p->basictime = Extra_basictime;
+               Curr_timelist_p->fulltime = calcfulltime(yyvsp[-1].ratval, yyvsp[0].intval);
+               /* handle subtracted times by negating the fulltime */
+               if (yyvsp[-3].intval == -1) {
+                       Curr_timelist_p->fulltime = rneg(Curr_timelist_p->fulltime);
+               }
+       }
+    break;
+
+  case 335:
+#line 3134 "gram.y"
+    {
+               struct TIMELIST *timelist_p;
+
+               MALLOC(TIMELIST, timelist_p, 1);
+               /* Add to end of linked list */
+               timelist_p->next = 0;
+               /* Init fulltime to something to avoid garbage if there
+                * in a user input error */
+               timelist_p->fulltime = Zero;
+               if (Extra_time_p == 0) {
+                       Last_alloced_timelist_p = Extra_time_p = timelist_p;
+               }
+               else {
+                       Curr_timelist_p->next = timelist_p;
+               }
+               /* Keep track of where to append next item to list, if any */
+               Curr_timelist_p = timelist_p;
+       }
+    break;
+
+  case 336:
+#line 3155 "gram.y"
+    {
+               User_meas_time = NO;
+       }
+    break;
+
+  case 337:
+#line 3161 "gram.y"
+    {
+               if (Curr_grpsyl_p != (struct GRPSYL *) 0
+                                       && Getting_tup_dur == NO) {
+                       Curr_grpsyl_p->is_meas = YES;
+                       User_meas_time = YES;
+               }
+               else {
+                       yyerror("'m' is not valid here");
+               }
+       }
+    break;
+
+  case 338:
+#line 3173 "gram.y"
+    {
+               yyval.intval = 0;
+       }
+    break;
+
+  case 339:
+#line 3179 "gram.y"
+    {
+               /* count up the number of dots */
+               yyval.intval = yyvsp[-1].intval + 1;
+       }
+    break;
+
+  case 340:
+#line 3185 "gram.y"
+    {
+               /* We can't distinguish between the default 0.0 and
+                * if user explicitly sets to 0.0, so if they set to 0.0
+                * then to something else, we won't catch that as setting
+                * twice, but that shouldn't be common. Besides, if they
+                * expect them to be additive, adding to zero will work
+                * as they expect... Because of roundoff, we can't do
+                * exact compare for specifying the same value more than once,
+                * so treat as identical if pretty close. */
+               if (Curr_grpsyl_p->padding != 0.0 && 
+                               fabs(Curr_grpsyl_p->padding - (yyvsp[0].floatval * STEPSIZE))
+                               > 0.0001) {
+                       l_warning(Curr_filename, yylineno,
+                               "padding specified more than once; using last instance");
+               }
+               Curr_grpsyl_p->padding = yyvsp[0].floatval * STEPSIZE;
+       }
+    break;
+
+  case 341:
+#line 3205 "gram.y"
+    {
+               yyval.floatval = (float) yyvsp[-1].intval * yyvsp[0].floatval;
+       }
+    break;
+
+  case 342:
+#line 3210 "gram.y"
+    {
+               /* no sign--must be a positive number */
+               yyval.intval = 1;
+       }
+    break;
+
+  case 343:
+#line 3217 "gram.y"
+    {
+               /* user wants a negative number */
+               yyval.intval = -1;
+       }
+    break;
+
+  case 344:
+#line 3223 "gram.y"
+    {
+               Curr_grpsyl_p->grpcont = GC_NOTES;
+               if (yyvsp[0].intval == 0) {
+                       /* no notes listed, use same as previous group */
+                       copy_notes(Curr_grpsyl_p, Last_grpsyl_p);
+               }
+               else {
+                       resize_notelist(Curr_grpsyl_p);
+               }
+       }
+    break;
+
+  case 348:
+#line 3248 "gram.y"
+    {
+               /* allocate GRPSYL for the case where everything is defaulted
+                * from the previous group, with just an extra attribute
+                * like ? or ~ specified. */
+               if (Curr_grpsyl_p == (struct GRPSYL *) 0) {
+                       /* shouldn't ever happen, but just in case... */
+                       Curr_grpsyl_p = newGRPSYL(GS_GROUP);
+               }
+               if (Last_grpsyl_p != (struct GRPSYL *) 0 &&
+                                       Last_grpsyl_p->nnotes >= 1) {
+                       copy_notes(Curr_grpsyl_p, Last_grpsyl_p);
+               }
+               else if (Last_grpsyl_p != (struct GRPSYL *) 0 && 
+                               Last_grpsyl_p->grpcont == GC_REST) {
+                       Curr_grpsyl_p->grpcont = GC_REST;
+               }
+       }
+    break;
+
+  case 349:
+#line 3268 "gram.y"
+    {
+               if (Curr_grpsyl_p->grpcont == GC_NOTES &&
+                                       Curr_grpsyl_p->nnotes > 0) {
+                       Curr_grpsyl_p->notelist[Curr_grpsyl_p->nnotes - 1]
+                                               .notesize = GS_SMALL;
+               }
+               else if (Curr_grpsyl_p->grpcont == GC_REST) {
+                       Curr_grpsyl_p->grpsize  = GS_SMALL;
+               }
+               else {
+                       yyerror("no note specified for '?'");
+               }
+       }
+    break;
+
+  case 350:
+#line 3284 "gram.y"
+    {
+               if (Curr_grpsyl_p->grpcont != GC_NOTES) {
+                       yyerror("can't tie a rest or space");
+               }
+               else if (Curr_grpsyl_p->nnotes > 0) {
+                       struct NOTE *n_p;
+                       n_p = &(Curr_grpsyl_p->notelist[Curr_grpsyl_p->nnotes - 1]);
+                       n_p->tie = YES;
+                       n_p->tiestyle = yyvsp[-1].intval;
+                       n_p->tiedir = yyvsp[0].intval;
+               }
+               else {
+                       yyerror("no note specified for '~'");
+               }
+       }
+    break;
+
+  case 351:
+#line 3302 "gram.y"
+    {
+               if (Curr_grpsyl_p->nnotes > 0) {
+                       switch (Curr_grpsyl_p->notelist
+                                        [Curr_grpsyl_p->nnotes - 1].letter) {
+                       case PP_REST:
+                       case PP_SPACE:
+                       case PP_RPT:
+                       case PP_NO_PITCH:  /* this one not really possible */
+                               addsym(yyvsp[0].stringval, Curr_grpsyl_p->c, CT_GRPSYL);
+                               break;
+                       default:
+                               addsym(yyvsp[0].stringval, Curr_grpsyl_p->notelist
+                                       [Curr_grpsyl_p->nnotes - 1].c, CT_NOTE);
+                               break;
+                       }
+                       var_valid();
+               }
+               else if (Curr_grpsyl_p->grpcont == GC_REST) {
+                       /* This should really never be hit anymore since
+                        * chord-at-a-time code was added, but shouldn't
+                        * hurt to leave it, just in case. */
+                       addsym(yyvsp[0].stringval, Curr_grpsyl_p->c, CT_GRPSYL);
+                       var_valid();
+               }
+               else {
+                       l_yyerror(Curr_filename, yylineno,
+                               "no note specified for location tag '%s'", yyvsp[0].stringval);
+               }
+       }
+    break;
+
+  case 352:
+#line 3334 "gram.y"
+    {
+               /* this is for bend on a non-tablature staff */
+               if (Doing_tab_staff == YES) {
+                       yyerror("^ bend not allowed on tablature staff; use quoted bend string");
+               }
+               else {
+                       add_slurto(Curr_grpsyl_p, yyvsp[-1].intval, yyvsp[0].intval,
+                                       Curr_grpsyl_p->nnotes - 1, L_NORMAL);
+                       if (Curr_grpsyl_p->nnotes > 0) {
+                               Curr_grpsyl_p->notelist
+                                               [Curr_grpsyl_p->nnotes - 1]
+                                               .is_bend = YES;
+                       }
+               }
+       }
+    break;
+
+  case 353:
+#line 3352 "gram.y"
+    {
+               /* this is for a small bend (1/4 step) on a non-tab staff */
+               if (Doing_tab_staff == YES) {
+                       yyerror("^/ not allowed on tablature staff; use quoted bend string");
+               }
+               else if (Curr_grpsyl_p != 0 && Curr_grpsyl_p->nnotes > 0) {
+                       Curr_grpsyl_p->notelist[Curr_grpsyl_p->nnotes - 1]
+                                       .smallbend = YES;
+               }
+       }
+    break;
+
+  case 354:
+#line 3365 "gram.y"
+    {
+               if (Curr_grpsyl_p->grpcont == GC_NOTES &&
+                                       Curr_grpsyl_p->nnotes > 0) {
+                       if ((Curr_grpsyl_p->notelist[Curr_grpsyl_p->nnotes - 1]
+                                       .headshape = get_shape_num(yyvsp[0].stringval + 2))
+                                       == HS_UNKNOWN) {
+                               l_yyerror(Curr_filename, yylineno,
+                                       "'%s' is not a valid head shape name",
+                                       ascii_str(yyvsp[0].stringval, YES, NO, TM_NONE));
+                       }
+               }
+               else {
+                       yyerror("no note specified for headshape");
+               }
+               FREE(yyvsp[0].stringval);
+       }
+    break;
+
+  case 358:
+#line 3394 "gram.y"
+    {
+               yyval.intval = yyvsp[-1].intval + yyvsp[0].intval;      /* total number of notes */
+       }
+    break;
+
+  case 359:
+#line 3400 "gram.y"
+    {
+               yyval.intval = 0;
+       }
+    break;
+
+  case 360:
+#line 3406 "gram.y"
+    {
+               switch (yyvsp[0].intval) {
+               case PL_ABOVE:
+                       Curr_grpsyl_p->stemto = CS_ABOVE;
+                       break;
+               case PL_BELOW:
+                       Curr_grpsyl_p->stemto = CS_BELOW;
+                       break;
+               default:
+                       yyerror("cross staff stem must be with 'above' or 'below'");
+                       Curr_grpsyl_p->stemto = CS_SAME;
+               }
+               if (yyvsp[-1].intval == 0) {
+                       /* Maybe this wouldn't really hurt to allow,
+                        * but it's rather silly--why would user bother to go
+                        * to the trouble of saying there are cross staff stem
+                        * notes, but then not list any?
+                        */
+                       yyerror("cross-staff stem note list is empty");
+               }
+               yyval.intval = yyvsp[-1].intval;
+       }
+    break;
+
+  case 361:
+#line 3430 "gram.y"
+    {
+               CSSused = YES;
+               Curr_grpsyl_p->stemto_idx = Curr_grpsyl_p->nnotes;
+       }
+    break;
+
+  case 362:
+#line 3436 "gram.y"
+    {
+               /* No notes.  If this is for the list of "normal" staff notes,
+                * and there are no "other" staff notes (for cross-staff stems),
+                * this means use the same notes as the last group. */
+               yyval.intval = 0;
+       }
+    break;
+
+  case 363:
+#line 3445 "gram.y"
+    {
+               /* return number of notes in notelist */
+               yyval.intval = yyvsp[-2].intval + 1;
+       }
+    break;
+
+  case 365:
+#line 3454 "gram.y"
+    {
+               add_note(Curr_grpsyl_p, (int) PP_REST, 0, USE_DFLT_OCTAVE,
+                                                       0, NO, (char *) 0);
+       }
+    break;
+
+  case 366:
+#line 3461 "gram.y"
+    {
+               /* temporarily stash uncompressibility (NO in this case)
+                * in the octave field */
+               add_note(Curr_grpsyl_p, (int) PP_SPACE, 0, NO,
+                                                       0, NO, (char *) 0);
+               if (Curr_grpsyl_p->is_meas == YES && User_meas_time == YES) {
+                       yyerror("cannot specify time value on measure space");
+               }
+       }
+    break;
+
+  case 367:
+#line 3473 "gram.y"
+    {
+               /* temporarily stash uncompressibility (YES in this case)
+                * in the octave field */
+               add_note(Curr_grpsyl_p, (int) PP_SPACE, 0, YES,
+                                                       0, NO, (char *) 0);
+               if (Curr_grpsyl_p->is_meas == YES && User_meas_time == YES) {
+                       yyerror("cannot specify time value on measure uncompressible space");
+               }
+       }
+    break;
+
+  case 368:
+#line 3485 "gram.y"
+    {
+               if (Curr_grpsyl_p->is_meas == YES) {
+                       if (User_meas_time == YES) {
+                               yyerror("cannot specify time value on m rpt");
+                       }
+               }
+               else {
+                       yyerror("rpt can only be used with m");
+               }
+               add_note(Curr_grpsyl_p, (int) PP_RPT, 0, USE_DFLT_OCTAVE,
+                                                       0, NO, (char *) 0);
+       }
+    break;
+
+  case 369:
+#line 3500 "gram.y"
+    {
+               if (yyvsp[0].intval == SINGLEBAR) {
+                       /* lexer thinks this is 'bar'
+                        * but is really 'b' 'a' 'r' */
+                       keyword_notes(yytext);
+               }
+               else if (yyvsp[0].intval == ENDBAR) {
+                       /* lexer thinks this is 'endbar'
+                        * but is really 'en' 'd' 'b' 'a' 'r' */
+                       add_note(Curr_grpsyl_p, (int) 'e', 'n',
+                               USE_DFLT_OCTAVE, 0, NO, (char *) 0);
+                       keyword_notes(yytext + 2);
+               }
+               else {
+                       yyerror("bar type not valid here");
+               }
+       }
+    break;
+
+  case 370:
+#line 3520 "gram.y"
+    {
+               /* lexer thinks this is 'grace' but really 'g' 'r' 'a' 'c' 'e' */
+               keyword_notes(yytext);
+       }
+    break;
+
+  case 371:
+#line 3527 "gram.y"
+    {
+               if (yyvsp[0].intval == ENDING_BARRED) {
+                       keyword_notes(yytext);
+               }
+               else {
+                       l_yyerror(Curr_filename, yylineno,
+                                       "%s not valid here", yytext);
+               }
+       }
+    break;
+
+  case 372:
+#line 3538 "gram.y"
+    {
+               if (yyvsp[0].intval == J_RAGPARA) {
+                       keyword_notes(yytext);
+               }
+               else {
+                       l_yyerror(Curr_filename, yylineno,
+                                       "%s not valid here", yytext);
+               }
+       }
+    break;
+
+  case 373:
+#line 3550 "gram.y"
+    {
+               if (yyvsp[0].intval == BRACELIST) {
+                       keyword_notes(yytext);
+               }
+               else {
+                       l_yyerror(Curr_filename, yylineno,
+                                       "%s not valid here", yytext);
+               }
+       }
+    break;
+
+  case 374:
+#line 3562 "gram.y"
+    {
+               if (yyvsp[0].intval == BASS) {
+                       keyword_notes(yytext);
+               }
+               else {
+                       l_yyerror(Curr_filename, yylineno,
+                                       "%s not valid here", yytext);
+               }
+       }
+    break;
+
+  case 375:
+#line 3574 "gram.y"
+    {
+               Curr_grpsyl_p->notelist[Curr_grpsyl_p->nnotes - 1].note_has_paren = YES;
+       }
+    break;
+
+  case 376:
+#line 3579 "gram.y"
+    {
+               if (Doing_tab_staff == YES) {
+                       add_note(Curr_grpsyl_p, yyvsp[-1].intval, 0, NOFRET, 0, NO, yyvsp[0].stringval);
+               }
+               else {
+                       add_note(Curr_grpsyl_p, yyvsp[-1].intval, 0, USE_DFLT_OCTAVE, 0, NO, yyvsp[0].stringval);
+               }
+       }
+    break;
+
+  case 377:
+#line 3590 "gram.y"
+    {
+               if (Doing_tab_staff == YES) {
+                       yyerror("extraneous parentheses around accidental");
+               }
+               add_note(Curr_grpsyl_p, yyvsp[-4].intval, yyvsp[-2].intval, yyvsp[0].intval, 0, YES, (char *) 0);
+       }
+    break;
+
+  case 378:
+#line 3599 "gram.y"
+    {
+               if (Doing_tab_staff == NO) {
+                       yyerror("extraneous parentheses around octave");
+               }
+               add_note(Curr_grpsyl_p, yyvsp[-4].intval, 0, yyvsp[-2].intval, 0, YES, yyvsp[0].stringval);
+       }
+    break;
+
+  case 379:
+#line 3608 "gram.y"
+    {
+               /* Whoops! The left paren was really for a new note,
+                * which happens to be parenthesized. But beause yacc only
+                * looks ahead one token, it finds out too late. So we
+                * catch it here, push the parenthesis and pitch back into
+                * the input and return back to the parent grammar rule,
+                * since we now have complete note. */
+               pushback(yytext[0]);
+               pushback('(');
+               add_note(Curr_grpsyl_p, yyvsp[-2].intval, 0,
+                       (Doing_tab_staff ? NOFRET : USE_DFLT_OCTAVE),
+                       0, NO, (char *) 0);
+       }
+    break;
+
+  case 380:
+#line 3624 "gram.y"
+    {
+               add_note(Curr_grpsyl_p, yyvsp[-4].intval, yyvsp[-3].intval, yyvsp[-1].intval, yyvsp[-2].intval, NO, yyvsp[0].stringval);
+       }
+    break;
+
+  case 381:
+#line 3630 "gram.y"
+    {
+               if (Doing_tab_staff == NO) {
+                       yyerror("extraneous parentheses around octave");
+               }
+               add_note(Curr_grpsyl_p, yyvsp[-6].intval, yyvsp[-5].intval, yyvsp[-2].intval, yyvsp[-4].intval, YES, yyvsp[0].stringval);
+       }
+    break;
+
+  case 382:
+#line 3639 "gram.y"
+    {
+               /* Whoops! The left paren was really for a new note,
+                * which happens to be parenthesized. But beause yacc only
+                * looks ahead one token, it finds out too late. So we
+                * catch it here, push the parenthesis and pitch back into
+                * the input and return back to the parent grammar rule,
+                * since we now have complete note. */
+               pushback(yytext[0]);
+               pushback('(');
+               add_note(Curr_grpsyl_p, yyvsp[-3].intval, yyvsp[-2].intval,
+                       (Doing_tab_staff ? NOFRET : USE_DFLT_OCTAVE),
+                       0, NO, (char *) 0);
+       }
+    break;
+
+  case 383:
+#line 3655 "gram.y"
+    {
+               add_note(Curr_grpsyl_p, yyvsp[-3].intval, 0, yyvsp[-1].intval, yyvsp[-2].intval, NO, yyvsp[0].stringval);
+       }
+    break;
+
+  case 384:
+#line 3661 "gram.y"
+    {
+               add_note(Curr_grpsyl_p, yyvsp[-5].intval, 0, yyvsp[-2].intval, yyvsp[-4].intval, YES, yyvsp[0].stringval);
+       }
+    break;
+
+  case 385:
+#line 3667 "gram.y"
+    {
+               if (Doing_tab_staff == YES && yyvsp[-1].intval != '\0') {
+                       yyerror("accidental must be before fret number");
+               }
+               add_note(Curr_grpsyl_p, yyvsp[-3].intval, yyvsp[-1].intval, yyvsp[-2].intval, 0, NO, yyvsp[0].stringval);
+       }
+    break;
+
+  case 386:
+#line 3676 "gram.y"
+    {
+               add_note(Curr_grpsyl_p, yyvsp[-4].intval, yyvsp[-1].intval, yyvsp[-3].intval, 0, YES, (char *) 0);
+       }
+    break;
+
+  case 387:
+#line 3682 "gram.y"
+    {
+               /* Whoops! The left paren was really for a new note,
+                * which happens to be parenthesized. But beause yacc only
+                * looks ahead one token, it finds out too late. So we
+                * catch it here, push the parenthesis and pitch back into
+                * the input and return back to the parent grammar rule,
+                * since we now have complete note. */
+               pushback(yytext[0]);
+               pushback('(');
+               add_note(Curr_grpsyl_p, yyvsp[-3].intval, 0, yyvsp[-2].intval, 0, NO, (char *) 0);
+       }
+    break;
+
+  case 388:
+#line 3695 "gram.y"
+    {
+               yyval.stringval = (char *) 0;
+       }
+    break;
+
+  case 389:
+#line 3701 "gram.y"
+    {
+               if (Doing_tab_staff == NO) {
+                       /* try to give helpful error message */
+                       if (get_shape_num(yyvsp[0].stringval + 2) != HS_UNKNOWN) {
+                               yyerror("missing 'hs' before headshape string");
+                       }
+                       else if (strcmp(yyvsp[0].stringval + 2, "full") == 0 || isdigit(yyvsp[0].stringval[2])) {
+                               yyerror("bend string not allowed on non-tablature staff; use ^");
+                       }
+                       else {
+                               yyerror("unexpected string");
+                       }
+                       yyval.stringval = (char *) 0;
+               }
+       }
+    break;
+
+  case 390:
+#line 3718 "gram.y"
+    {
+               /* return 'a' to 'g' value */
+               yyval.intval = (int) *yytext;
+       }
+    break;
+
+  case 391:
+#line 3724 "gram.y"
+    {
+               /* no accidental */
+               yyval.intval = 0;
+       }
+    break;
+
+  case 392:
+#line 3731 "gram.y"
+    {
+       }
+    break;
+
+  case 393:
+#line 3735 "gram.y"
+    {
+               /* no octave or fret designation */
+               yyval.intval = (Doing_tab_staff ? NOFRET : USE_DFLT_OCTAVE);
+       }
+    break;
+
+  case 394:
+#line 3742 "gram.y"
+    {
+       }
+    break;
+
+  case 395:
+#line 3747 "gram.y"
+    {
+               yyval.intval = '#';
+       }
+    break;
+
+  case 396:
+#line 3753 "gram.y"
+    {
+               yyval.intval = '&';
+       }
+    break;
+
+  case 397:
+#line 3759 "gram.y"
+    {
+               /* natural */
+               yyval.intval = 'n';
+       }
+    break;
+
+  case 398:
+#line 3766 "gram.y"
+    {
+               /* double sharp */
+               yyval.intval = 'x';
+       }
+    break;
+
+  case 399:
+#line 3773 "gram.y"
+    {
+               yyval.intval = 'B';
+       }
+    break;
+
+  case 400:
+#line 3779 "gram.y"
+    {
+               yyval.intval = yyvsp[0].intval;
+       }
+    break;
+
+  case 401:
+#line 3785 "gram.y"
+    {
+               /* we can't really fill in the actual octave yet, because
+                * it may be different on different staffs or voices, so
+                * we store the relative octave and fill in actual value
+                * later.
+                */
+               /* this will be a negative number */
+               yyval.intval = yyvsp[0].intval;
+       }
+    break;
+
+  case 402:
+#line 3797 "gram.y"
+    {
+               /* we can't really fill in the actual octave yet, because
+                * it may be different on different staffs or voices, so
+                * we store the relative octave and fill in actual value
+                * later.
+                */
+               yyval.intval = USE_DFLT_OCTAVE + yyvsp[0].intval;
+       }
+    break;
+
+  case 403:
+#line 3807 "gram.y"
+    {
+               yyval.intval = -1;
+       }
+    break;
+
+  case 404:
+#line 3813 "gram.y"
+    {
+               /* count up the number of minus signs */
+               yyval.intval = yyvsp[-1].intval - 1;
+       }
+    break;
+
+  case 405:
+#line 3819 "gram.y"
+    {
+               yyval.intval = 1;
+       }
+    break;
+
+  case 406:
+#line 3825 "gram.y"
+    {
+               /* count up the number of plus signs */
+               yyval.intval = yyvsp[-1].intval + 1;
+       }
+    break;
+
+  case 407:
+#line 3832 "gram.y"
+    {
+               set_slurdir(Curr_grpsyl_p, Curr_grpsyl_p->nnotes - 1, yyvsp[0].intval);
+       }
+    break;
+
+  case 408:
+#line 3839 "gram.y"
+    {
+               Slurstyle = yyvsp[0].intval;
+               begin_slur(Curr_grpsyl_p, Curr_grpsyl_p->nnotes - 1);
+       }
+    break;
+
+  case 409:
+#line 3845 "gram.y"
+    {
+               /* empty list. Only allowed if only one note in following
+                * group. However, we don't know that yet, so marked pitch
+                * as 'U' for unknown */
+               add_slurto(Curr_grpsyl_p, 'U', USE_DFLT_OCTAVE,
+                               Curr_grpsyl_p->nnotes - 1, Slurstyle);
+       }
+    break;
+
+  case 410:
+#line 3855 "gram.y"
+    {
+               add_slurto(Curr_grpsyl_p, 0, yyvsp[0].intval, Curr_grpsyl_p->nnotes - 1,
+                                               Slurstyle);
+       }
+    break;
+
+  case 414:
+#line 3873 "gram.y"
+    {
+               if (Doing_tab_staff == YES) {
+                       yyerror("cannot specify string inside <> on tab staffs");
+               }
+               else {
+                       add_slurto(Curr_grpsyl_p, yyvsp[-1].intval, yyvsp[0].intval,
+                                       Curr_grpsyl_p->nnotes - 1, Slurstyle);
+               }
+       }
+    break;
+
+  case 415:
+#line 3885 "gram.y"
+    {
+               /* save address associated with entire group */
+               if ( yyvsp[0].stringval != (char *) 0) {
+                       addsym(yyvsp[0].stringval, Curr_grpsyl_p->c, CT_GRPSYL);
+                       var_valid();
+               }
+       }
+    break;
+
+  case 416:
+#line 3894 "gram.y"
+    {
+               yyval.stringval = strcpy(Stringbuff, yytext);
+       }
+    break;
+
+  case 417:
+#line 3900 "gram.y"
+    {
+               /* a-g are usually pitches, but in this context, they
+                * are 1-character variable names. */
+               yyval.stringval = strcpy(Stringbuff, yytext);
+       }
+    break;
+
+  case 418:
+#line 3908 "gram.y"
+    {
+               /* usually m means measure, but here it is the variable m */
+               yyval.stringval = strcpy(Stringbuff, yytext);
+       }
+    break;
+
+  case 419:
+#line 3915 "gram.y"
+    {
+               /* usually rest, here variable r */
+               yyval.stringval = strcpy(Stringbuff, yytext);
+       }
+    break;
+
+  case 420:
+#line 3922 "gram.y"
+    {
+               /* usually space, here variable s */
+               yyval.stringval = strcpy(Stringbuff, yytext);
+       }
+    break;
+
+  case 421:
+#line 3929 "gram.y"
+    {
+               /* usually uncompressible, here variable u */
+               yyval.stringval = strcpy(Stringbuff, yytext);
+       }
+    break;
+
+  case 422:
+#line 3936 "gram.y"
+    {
+               /* usually natural, here variable n */
+               yyval.stringval = strcpy(Stringbuff, yytext);
+       }
+    break;
+
+  case 423:
+#line 3943 "gram.y"
+    {
+               /* usually double sharp, here variable x */
+               yyval.stringval = strcpy(Stringbuff, yytext);
+       }
+    break;
+
+  case 424:
+#line 3949 "gram.y"
+    {
+               /* longer variable -- one with more than one character name */
+               yyval.stringval = strcpy(Stringbuff, yytext);
+       }
+    break;
+
+  case 425:
+#line 3955 "gram.y"
+    {
+               end_tuplet(yyvsp[-3].intval, yyvsp[-1].ratval, yyvsp[-2].intval, yyvsp[-4].intval);
+               Getting_tup_dur = NO;
+       }
+    break;
+
+  case 426:
+#line 3961 "gram.y"
+    {
+               /* nothing -- use default of when to print tuplet number/bracket */
+               yyval.intval = PT_DEFAULT;
+       }
+    break;
+
+  case 427:
+#line 3968 "gram.y"
+    {
+               /* don't print tuplet or bracket */
+               yyval.intval = PT_NEITHER;
+       }
+    break;
+
+  case 428:
+#line 3975 "gram.y"
+    {
+               /* print number only */
+               yyval.intval = PT_NUMBER;
+       }
+    break;
+
+  case 429:
+#line 3982 "gram.y"
+    {
+               if (*yytext == 'y') {
+                       yyval.intval = PT_BOTH;
+               }
+               else {
+                       yyerror("tuplet number/bracket qualifier must be y or n or num");
+               }
+       }
+    break;
+
+  case 430:
+#line 3994 "gram.y"
+    {
+               begin_tuplet();
+       }
+    break;
+
+  case 431:
+#line 3999 "gram.y"
+    {
+               Getting_tup_dur = YES;
+       }
+    break;
+
+  case 432:
+#line 4004 "gram.y"
+    {
+               yyval.intval = PL_UNKNOWN;
+       }
+    break;
+
+  case 433:
+#line 4010 "gram.y"
+    {
+               if (yylval.intval == PL_BETWEEN) {
+                       yyerror("between not allowed for tuplet side");
+                       yyval.intval = PL_UNKNOWN;
+               }
+       }
+    break;
+
+  case 434:
+#line 4018 "gram.y"
+    {
+               /* optional time value is missing */
+               yyval.ratval.n = 0;
+               yyval.ratval.d = 1;
+       }
+    break;
+
+  case 435:
+#line 4026 "gram.y"
+    {
+               yyval.ratval = yyvsp[0].ratval;
+       }
+    break;
+
+  case 436:
+#line 4031 "gram.y"
+    {
+       }
+    break;
+
+  case 437:
+#line 4035 "gram.y"
+    {
+               Last_grpsyl_p = Curr_grpsyl_p = (struct GRPSYL *) 0;
+       }
+    break;
+
+  case 438:
+#line 4040 "gram.y"
+    {
+       }
+    break;
+
+  case 439:
+#line 4044 "gram.y"
+    {
+               /* empty, use default */
+               begin_range(PL_UNKNOWN);
+               yyval.intval = PL_UNKNOWN;
+       }
+    break;
+
+  case 440:
+#line 4052 "gram.y"
+    {
+               begin_range(yyvsp[0].intval);
+       }
+    break;
+
+  case 442:
+#line 4060 "gram.y"
+    {
+               /* means goes above or below all the staffs, regardless if
+                * some happen to be invisible at the moment, so find top
+                * or bottom visible staff as appropriate,and save that
+                * away as the staff range */
+               all();
+       }
+    break;
+
+  case 444:
+#line 4073 "gram.y"
+    {
+               /* if staff_range == 0, then only one staff specified, so
+                * use first staff number for both beginning and end of range */
+               save_staff_range(yyvsp[-1].intval, (yyvsp[0].intval == 0 ? yyvsp[-1].intval : yyvsp[0].intval) );
+       }
+    break;
+
+  case 445:
+#line 4080 "gram.y"
+    {
+               /* empty */
+               chk_range_type(NO);
+               yyval.intval = 0;
+       }
+    break;
+
+  case 446:
+#line 4088 "gram.y"
+    {
+               chk_range_type(NO);
+               yyval.intval = yyvsp[0].intval;
+               if (yyvsp[0].intval == 0) {
+                       yyerror("staff of 0 is illegal");
+               }
+       }
+    break;
+
+  case 447:
+#line 4098 "gram.y"
+    {
+               chk_range_type(YES);
+               yyval.intval = yyvsp[0].intval;
+       }
+    break;
+
+  case 449:
+#line 4107 "gram.y"
+    { Place = yyvsp[0].intval; }
+    break;
+
+  case 451:
+#line 4112 "gram.y"
+    {
+       }
+    break;
+
+  case 452:
+#line 4117 "gram.y"
+    {
+               if (*yytext != 'c') {
+                       yyerror("verse must be 'c' or number(s)");
+               }
+               else {
+                       save_vno_range(0, 0);
+               }
+       }
+    break;
+
+  case 453:
+#line 4128 "gram.y"
+    {
+       }
+    break;
+
+  case 454:
+#line 4133 "gram.y"
+    {
+       }
+    break;
+
+  case 455:
+#line 4138 "gram.y"
+    {
+               /* if end of range is 0, not really a range, use first number
+                * for both beginning and end */
+               lyr_verse(yyvsp[-1].intval, (yyvsp[0].intval == 0 ? yyvsp[-1].intval : yyvsp[0].intval));
+       }
+    break;
+
+  case 456:
+#line 4145 "gram.y"
+    {
+               /* empty */
+               yyval.intval = 0;
+       }
+    break;
+
+  case 457:
+#line 4152 "gram.y"
+    {
+               yyval.intval = yyvsp[0].intval;
+       }
+    break;
+
+  case 458:
+#line 4157 "gram.y"
+    {
+               /* null token to allocate a GRPSYL for a lyric */
+               Last_grpsyl_p = Curr_grpsyl_p;
+               Curr_grpsyl_p = newGRPSYL(GS_SYLLABLE);
+               if (Last_grpsyl_p == (struct GRPSYL *) 0) {
+                       Lyrics_p = Curr_grpsyl_p;
+               }
+       }
+    break;
+
+  case 459:
+#line 4167 "gram.y"
+    {
+               /* If user didn't specify a place, fix that. */
+               if (Place == PL_UNKNOWN) {
+                       Place = PL_BELOW;
+               }
+               /* copies of the lyrics info has been made for all staffs/verses
+                * at this point, so get rid of master copy */
+               free_grpsyls(Lyrics_p);
+       }
+    break;
+
+  case 460:
+#line 4178 "gram.y"
+    {
+               /* empty -- need to derive times from music */
+               Lyrics_p = derive_lyrtime();
+       }
+    break;
+
+  case 465:
+#line 4197 "gram.y"
+    {
+               link_notegroup(Curr_grpsyl_p, Last_grpsyl_p);
+               /* Save pointer to current GRPSYL in case the next
+                * group gets its time value based on this one,
+                * and there are additive times on this one. */
+               Prev_grpsyl_p = Curr_grpsyl_p;
+               /* If there are additive times, add those in.
+                * We don't need to make extra groups for lyrics, because we
+                * don't need to tie groups together--the lyrics time
+                * can hold any legal RATIONAL, even those that aren't
+                * specifiable with a single time value. */
+               if (Extra_time_p != 0) {
+                       struct TIMELIST *timelist_p;
+                       for (timelist_p = Extra_time_p; timelist_p != 0;
+                                               timelist_p = timelist_p->next) {
+                               Curr_grpsyl_p->fulltime = radd(Curr_grpsyl_p->fulltime, timelist_p->fulltime);
+                       }
+               }
+       }
+    break;
+
+  case 466:
+#line 4219 "gram.y"
+    {
+       }
+    break;
+
+  case 467:
+#line 4223 "gram.y"
+    {
+               end_tuplet(yyvsp[-1].intval, yyvsp[0].ratval, NO, PL_UNKNOWN);
+               Getting_tup_dur = NO;
+       }
+    break;
+
+  case 468:
+#line 4229 "gram.y"
+    {
+               /* empty, will fill in an actual syllable later */
+               Curr_grpsyl_p->syl = (char *) 0;
+       }
+    break;
+
+  case 469:
+#line 4236 "gram.y"
+    {
+               /* space, not a lyric, so mark for later use */
+               Curr_grpsyl_p->grpcont = GC_SPACE;
+       }
+    break;
+
+  case 472:
+#line 4249 "gram.y"
+    {
+               /* If no [verseno] is specified, use -1 as special flag
+                * to be resolved later to "one more than previous",
+                * or if there wasn't a previous, to verse 1.
+                */
+               lyr_verse(-1, -1);
+               proc_lyrics(Lyrics_p, yyvsp[-1].stringval);
+       }
+    break;
+
+  case 473:
+#line 4260 "gram.y"
+    {
+               proc_lyrics(Lyrics_p, yyvsp[-1].stringval);
+       }
+    break;
+
+  case 474:
+#line 4265 "gram.y"
+    {
+               Currstruct_p = (struct MAINLL *) 0;
+               /* If there are alternating time signature,
+                * add an implicit time signature SSV for the
+                * next time signature in the list.
+                */
+               if (Alt_timesig_list != 0) {
+                       end_prev_context();
+                       Context = C_SCORE;
+                       Currstruct_p = newMAINLLstruct(S_SSV, -1);
+                       Currstruct_p->u.ssv_p->context = Context;
+                       if (Tsig_visibility == PTS_ALWAYS &&
+                                       Next_alt_timesig != Alt_timesig_list) {
+                               /* If user wants alternating time signatures
+                                * printed on every measure, if there is
+                                * a multirest, we will print multiple
+                                * time signatures there, and might have to
+                                * wrap around to the beginning of the list.
+                                * So make a copy of the entire list,
+                                * starting from wherever we are now,
+                                * wrapping around to the beginning,
+                                * and ending just before where we are now.
+                                * Most of the time,
+                                * there probably won't be a multirest,
+                                * so this will be a waste, but unfortunately,
+                                * we don't know yet whether there will be
+                                * one or not, so need to do the whole list
+                                * just in case.
+                                *
+                                * Calculate length of the two pieces:
+                                * from where we are to end, and from
+                                * beginning to where we are.
+                                */
+                               int remlength;
+                               int wraplength;
+                               remlength = strlen(Next_alt_timesig);
+                               wraplength = strlen(Alt_timesig_list)
+                                               - remlength;
+                               /* need one more for terminator. */
+                               MALLOCA(char, Currstruct_p->u.ssv_p->timerep,
+                                               remlength + wraplength + 1);
+
+                               /* copy remainder into beginning */
+                               strcpy(Currstruct_p->u.ssv_p->timerep,
+                                               Next_alt_timesig);
+                               /* copy the wrap-around part of list,
+                                * but move the TSR_ALTERNATING from the
+                                * end of that part to between the two parts */
+                               Currstruct_p->u.ssv_p->timerep[remlength]
+                                               = TSR_ALTERNATING;
+                               strncpy(Currstruct_p->u.ssv_p->timerep +
+                                               remlength + 1, Alt_timesig_list,
+                                               wraplength - 1);
+                               /* Add the terminator */
+                               Currstruct_p->u.ssv_p->timerep
+                                               [remlength + wraplength]
+                                               = TSR_END;
+
+                               assign_timesig(Currstruct_p, PTS_ALWAYS,
+                                                       &Next_alt_timesig);
+
+
+                               /* Make this new copy the new
+                                * head of the list */
+                               Alt_timesig_list =
+                                               Currstruct_p->u.ssv_p->timerep;
+                       }
+                       else {
+                               /* make a copy of the remaining alternating
+                                * signatures and assign that */
+                               MALLOCA(char, Currstruct_p->u.ssv_p->timerep,
+                                       strlen(Next_alt_timesig) + 1);
+                               strcpy(Currstruct_p->u.ssv_p->timerep,
+                                                       Next_alt_timesig);
+                               assign_timesig(Currstruct_p,
+                                       (Tsig_visibility == PTS_ALWAYS ?
+                                       PTS_ALWAYS : PTS_NEVER),
+                                       &Next_alt_timesig);
+
+                               /* If we reached end of list, start over */
+                               if (Next_alt_timesig == 0) {
+                                       Next_alt_timesig = Alt_timesig_list;
+                               }
+                       }
+
+                       asgnssv(Currstruct_p->u.ssv_p);
+                       end_prev_context();
+                       Context = C_MUSIC;
+               }
+       }
+    break;
+
+  case 477:
+#line 4364 "gram.y"
+    {
+               struct MAINLL * mll_p;
+               char *name;
+
+
+               name = (yylval.intval == YES ? "newpage" : "newscore");
+
+               (void) contextcheck(C_MUSIC | C_BLOCK, name);
+               Currstruct_p = newMAINLLstruct(S_FEED, yylineno);
+               Currstruct_p->u.feed_p->pagefeed = yyvsp[0].intval;
+
+               /* make sure we're not in the middle of a measure. Go
+                * backwards in main list. If we hit STAFF before a BAR,
+                * then there is a problem.
+                */
+               for (mll_p = Mainlltc_p; mll_p != (struct MAINLL *) 0;
+                                       mll_p = mll_p->prev) {
+
+                       if (mll_p->str == S_BAR) {
+                               break;
+                       }
+                       else if (mll_p->str == S_STAFF) {
+                               l_yyerror(Curr_filename, yylineno,
+                                       "%s not allowed in middle of measure",
+                                       name);
+                               break;
+                       }
+                       else if (mll_p->str == S_FEED) {
+                               if (mll_p->prev != 0 &&
+                                               mll_p->prev->str == S_BLOCKHEAD) {
+                                       /* This is a feed following a block.
+                                        * If it was an implicit feed,
+                                        * we can get rid of it, because
+                                        * user now put an explicit one.
+                                        */
+                                       if (mll_p->inputlineno == -1) {
+                                               unlinkMAINLL(mll_p);
+                                               FREE(mll_p);
+                                       }
+                                       /* We must be in block context,
+                                        * so no need to check farther back.
+                                        */
+                                       break;
+                               }
+                               else {
+                                       l_yyerror(Curr_filename, yylineno,
+                                               "consecutive newscore/newpage not allowed");
+                               }
+                               break;
+                       }
+               }
+               insertMAINLL(Currstruct_p, Mainlltc_p);
+
+               /* If this is inside a block, we need to create a new block
+                * and feed after it.
+                */
+               if (Context == C_BLOCK) {
+                       CALLOC(BLOCKHEAD, Currblock_p, 1);
+                       set_win_coord(Currblock_p->c);
+                       Next_print_link_p_p = &(Currblock_p->printdata_p);
+                       insertMAINLL(newMAINLLstruct(S_BLOCKHEAD, yylineno),
+                                               Mainlltc_p);
+                       Mainlltc_p->u.blockhead_p = Currblock_p;
+                       insertMAINLL(newMAINLLstruct(S_FEED, -1), Mainlltc_p);
+               }
+
+       }
+    break;
+
+  case 478:
+#line 4432 "gram.y"
+    {
+               Currstruct_p = (struct MAINLL *) 0;
+       }
+    break;
+
+  case 482:
+#line 4448 "gram.y"
+    {
+               yyvsp[0].floatval = adjust2inches(yyvsp[0].floatval);   /* in case we are in centimeter mode */
+               if (yyvsp[-2].intval == RIGHTMARGIN) {
+                       if (Currstruct_p->u.feed_p->rightmargin >= 0) {
+                               l_warning(Curr_filename, yylineno,
+                                       "rightmargin specified more than once, using last instance");
+                               /* fall through to override the previous */
+                       }
+                       Currstruct_p->u.feed_p->rightmargin = yyvsp[0].floatval;
+               }
+               else if (yyvsp[-2].intval == LEFTMARGIN) {
+                       if (Currstruct_p->u.feed_p->leftmargin >= 0) {
+                               l_warning(Curr_filename, yylineno,
+                                       "leftmargin specified more than once, using last instance");
+                               /* fall through to override the previous */
+                       }
+                       Currstruct_p->u.feed_p->leftmargin = yyvsp[0].floatval;
+               }
+               else {
+                       yyerror("unexpected parameter; only 'leftmargin' or 'rightmargin' allowed here");
+               }
+               chkmargin(Score.topmargin, Score.botmargin,
+                               Currstruct_p->u.feed_p->leftmargin,
+                               Currstruct_p->u.feed_p->rightmargin);
+       }
+    break;
+
+  case 489:
+#line 4494 "gram.y"
+    {
+
+               /* build a BAR struct and add it to the main list */
+               if (contextcheck(C_MUSIC, "bar") == YES) {
+
+                       Currstruct_p = newMAINLLstruct(S_BAR, yylineno);
+                       Currstruct_p->u.bar_p->bartype = (short) yylval.intval;
+                       Currstruct_p->u.bar_p->endingloc = Endingloc;
+                       if (yyvsp[-2].intval != L_NORMAL) {
+                               if (yyvsp[-2].intval != L_DASHED && yyvsp[-2].intval != L_DOTTED) {
+                                       yyerror("bar modifier can only be 'dashed' or 'dotted'");
+                               }
+                               else if (yyvsp[0].intval != SINGLEBAR && yyvsp[0].intval != DOUBLEBAR) {
+                                       yyerror("only 'bar' or 'dblbar' can be dashed or dotted");
+                               }
+                       }
+                       Currstruct_p->u.bar_p->linetype = yyvsp[-2].intval;
+                       insertMAINLL(Currstruct_p, Mainlltc_p);
+                       Currstruct_p->u.bar_p->timedssv_p = tssv_sort();
+
+                       /* re-order things in the  bar,
+                        * make sure they are all consistent, etc */
+                       do_bar(yyvsp[0].intval);
+
+                       Got_ending = NO;
+               }
+               if (yyvsp[0].intval == RESTART && Endingloc != NOITEM) {
+                       yyerror("restart cannot be used inside an ending");
+               }
+
+               /* User can specify bar type to use on preceeding staff when
+                * a repeatstart gets moved to the next scores's pseudo-bar */
+               if (yyvsp[-1].intval != -1) {
+                       if (yyvsp[0].intval != REPEATSTART) {
+                               yyerror("bar type for preceeding score only allowed on repeatstart");
+                       }
+                       if (Currstruct_p != 0 && Currstruct_p->u.bar_p != 0) {
+                               Currstruct_p->u.bar_p->precbartype = yyvsp[-1].intval;
+                       }
+               }
+               else {
+                       /* Default is single bar. It could be argued that in
+                        * the case of a key change on this bar, it really
+                        * should be a dblbar, but user can force that
+                        * if they want it. */
+                       if (Currstruct_p != 0 && Currstruct_p->u.bar_p != 0) {
+                               Currstruct_p->u.bar_p->precbartype = SINGLEBAR;
+                       }
+               }
+       }
+    break;
+
+  case 490:
+#line 4547 "gram.y"
+    {
+               yyval.intval = -1;      /* special value to mean "none specified" */
+       }
+    break;
+
+  case 491:
+#line 4553 "gram.y"
+    {
+               /* Parens wouldn't be strictly necessary to be able to parse,
+                * but seem useful semantically to make it clear this is
+                * optional, only applying when repeatstart is moved to
+                * next score's pseudo bar. */
+               yyval.intval = yyvsp[-1].intval;
+       }
+    break;
+
+  case 494:
+#line 4569 "gram.y"
+    {
+               if (Currstruct_p != (struct MAINLL *) 0) {
+                       Currstruct_p->u.bar_p->padding += yyvsp[0].floatval * STEPSIZE;
+               }
+       }
+    break;
+
+  case 495:
+#line 4577 "gram.y"
+    {
+               if (Currstruct_p != (struct MAINLL *) 0) {
+                       /* fill in location info */
+                       if (yyvsp[0].stringval != (char *) 0) {
+                               addsym(yyvsp[0].stringval, Currstruct_p->u.bar_p->c, CT_BAR);
+                       }
+               }
+       }
+    break;
+
+  case 496:
+#line 4588 "gram.y"
+    {
+               if (Got_ending == YES) {
+                       yyerror("Only one ending allowed per bar");
+               }
+               Got_ending = YES;
+
+               if (Currstruct_p != (struct MAINLL *) 0) {
+                       if (Currstruct_p->u.bar_p->bartype == RESTART) {
+                               yyerror("ending not allowed on restart");
+                       }
+                       /* fill in ending label if any */
+                       Currstruct_p->u.bar_p->endinglabel = yyvsp[0].stringval;
+                       Currstruct_p->u.bar_p->endingloc = Endingloc;
+                       ped_endings(Endingloc);
+
+                       /* for next time around, figure out what endingloc will
+                        * be if user doesn't specify something different */
+                       switch (Endingloc) {
+                       case STARTITEM:
+                               Endingloc = INITEM;
+                               break;
+                       case ENDITEM:
+                               Endingloc = NOITEM;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+    break;
+
+  case 497:
+#line 4620 "gram.y"
+    {
+               if (Currstruct_p != 0) {
+                       if (Currstruct_p->u.bar_p->bartype == RESTART) {
+                               yyerror("hidechanges not allowed on restart");
+                       }
+                       Currstruct_p->u.bar_p->hidechanges = YES;
+               }
+       }
+    break;
+
+  case 498:
+#line 4630 "gram.y"
+    {
+               if (Currstruct_p != 0) {
+                       set_mnum(Currstruct_p->u.bar_p, yyvsp[0].intval);
+               }
+       }
+    break;
+
+  case 499:
+#line 4637 "gram.y"
+    {
+               /* +2 to skip font/size */
+               init_reh(-1, yyvsp[0].stringval + 2, Currstruct_p);
+       }
+    break;
+
+  case 500:
+#line 4643 "gram.y"
+    {
+               init_reh(yyvsp[0].intval, (char *)0, Currstruct_p);
+       }
+    break;
+
+  case 501:
+#line 4649 "gram.y"
+    {
+               if (Currstruct_p != (struct MAINLL *) 0) {
+                       set_reh_string(Currstruct_p->u.bar_p, yyvsp[-4].intval, yyvsp[-3].intval, yyvsp[-2].intval, yyvsp[-1].stringval);
+                       Currstruct_p->u.bar_p->dist = Dist;
+                       Currstruct_p->u.bar_p->dist_usage = Dist_usage;
+               }
+       }
+    break;
+
+  case 502:
+#line 4659 "gram.y"
+    {
+               yyval.stringval = yyvsp[0].stringval;
+               (void) fix_string(yyvsp[0].stringval, FONT_TR, DFLT_SIZE, Curr_filename, yylineno);
+               Endingloc = STARTITEM;
+       }
+    break;
+
+  case 503:
+#line 4667 "gram.y"
+    {
+               if (Endingloc == NOITEM) {
+                       yyerror("no ending in progress");
+               }
+               else {
+                       Endingloc = ENDITEM;
+               }
+               yyval.stringval = (char *) 0;
+       }
+    break;
+
+  case 504:
+#line 4678 "gram.y"
+    {
+               /* null token to check for more than one rehearsal mark
+                * on one BAR */
+               if (Currstruct_p != (struct MAINLL *) 0 &&
+                               Currstruct_p->u.bar_p->reh_type != REH_NONE) {
+                       yyerror("only one rehearsal mark allowed per bar");
+               }
+       }
+    break;
+
+  case 505:
+#line 4688 "gram.y"
+    {
+               if (Currstruct_p != (struct MAINLL *) 0) {
+                       Currstruct_p->u.bar_p->reh_type = REH_STRING;
+               }
+       }
+    break;
+
+  case 506:
+#line 4696 "gram.y"
+    {
+               if (Currstruct_p != (struct MAINLL *) 0) {
+                       Currstruct_p->u.bar_p->reh_type = REH_MNUM;
+               }
+               yyval.stringval = (char *) 0;
+       }
+    break;
+
+  case 507:
+#line 4705 "gram.y"
+    {
+               if (Currstruct_p != (struct MAINLL *) 0) {
+                       Currstruct_p->u.bar_p->reh_type = REH_NUM;
+               }
+               yyval.stringval = (char *) 0;
+       }
+    break;
+
+  case 508:
+#line 4714 "gram.y"
+    {
+               if (Currstruct_p != (struct MAINLL *) 0) {
+                       Currstruct_p->u.bar_p->reh_type = REH_LET;
+               }
+               yyval.stringval = (char *) 0;
+       }
+    break;
+
+  case 509:
+#line 4722 "gram.y"
+    {
+               yyval.inpcoord_p = yyvsp[-4].inpcoord_p;
+       }
+    break;
+
+  case 510:
+#line 4727 "gram.y"
+    {
+               /* null token to allocate an INPCOORD */
+               CALLOC(INPCOORD, Curr_loc_info_p, 1);
+               yyval.inpcoord_p = Curr_loc_info_p;
+               /* set to positive in case input starts with an absolute
+                * x coordinate */
+               Plus_minus = 1;
+       }
+    break;
+
+  case 511:
+#line 4737 "gram.y"
+    {
+               /* reset sign to positive in case y coordinate is absolute */
+               Plus_minus = 1;
+       }
+    break;
+
+  case 513:
+#line 4746 "gram.y"
+    {
+               /* only 1 of these allowed per location */
+               if (Curr_loc_info_p->hor_p != (float *) 0) {
+                       pfatal("only one horizontal location variable allowed per coordinate");
+               }
+               /* fill in the coord address and type */
+               Curr_loc_info_p->hor_p = symval(yyvsp[-2].stringval, &(Curr_loc_info_p->hor_p));
+               Curr_loc_info_p->htype = yyvsp[0].intval;
+       }
+    break;
+
+  case 515:
+#line 4762 "gram.y"
+    {
+               /* only valid letters is w */
+               if (*yytext != 'w') {
+                       yyerror("invalid direction: must be x, w, or e");
+               }
+               yyval.intval = AW;
+       }
+    break;
+
+  case 516:
+#line 4771 "gram.y"
+    {
+               yyval.intval = AX;
+       }
+    break;
+
+  case 517:
+#line 4777 "gram.y"
+    {
+               /* only valid value is e */
+               if (*yytext != 'e') {
+                       yyerror("invalid direction: must be x, w, or e");
+               }
+               yyval.intval = AE;
+       }
+    break;
+
+  case 521:
+#line 4794 "gram.y"
+    {
+               yyval.intval = Plus_minus = 1;
+       }
+    break;
+
+  case 522:
+#line 4800 "gram.y"
+    {
+               yyval.intval = Plus_minus = -1;
+       }
+    break;
+
+  case 523:
+#line 4805 "gram.y"
+    {
+               Curr_loc_info_p->hsteps += yyvsp[0].floatval * (float) Plus_minus;
+       }
+    break;
+
+  case 524:
+#line 4811 "gram.y"
+    {
+               if (Curr_loc_info_p->hor_p == (float *) 0) {
+                       yyerror("must specify location before giving time offset");
+               }
+               /* add or subtract time value from horizontal */
+               if (Plus_minus == 1) {
+                       Curr_loc_info_p->counts += yyvsp[0].floatval;
+               }
+               else {
+                       Curr_loc_info_p->counts -= yyvsp[0].floatval;
+               }
+       }
+    break;
+
+  case 527:
+#line 4831 "gram.y"
+    {
+               /* only one of these allowed per location */
+               if (Curr_loc_info_p->vert_p != (float *) 0) {
+                       pfatal("only one vertical location variable allowed per coordinate");
+               }
+               /* fill in the coord address and type */
+               Curr_loc_info_p->vert_p = symval(yyvsp[-2].stringval, &(Curr_loc_info_p->vert_p));
+               Curr_loc_info_p->vtype = yyvsp[0].intval;
+
+       }
+    break;
+
+  case 528:
+#line 4843 "gram.y"
+    {
+               yyval.intval = AN;
+       }
+    break;
+
+  case 529:
+#line 4849 "gram.y"
+    {
+               yyval.intval = AS;
+       }
+    break;
+
+  case 530:
+#line 4855 "gram.y"
+    {
+               /* only valid value here is y */
+               if (*yytext != 'y') {
+                       yyerror("invalid direction: must be y, n, or s");
+               }
+               yyval.intval = AY;
+       }
+    break;
+
+  case 533:
+#line 4870 "gram.y"
+    {
+       }
+    break;
+
+  case 534:
+#line 4875 "gram.y"
+    {
+               /* this is number of steps up (or down if negative) */
+               Curr_loc_info_p->vsteps += yyvsp[0].floatval * (float) Plus_minus;
+       }
+    break;
+
+  case 535:
+#line 4881 "gram.y"
+    {
+               yyval.floatval = (float) yyvsp[0].intval;
+       }
+    break;
+
+  case 536:
+#line 4886 "gram.y"
+    {
+               sprintf(Tmpbuff,"%d.%s", yyvsp[-2].intval, yyvsp[0].stringval);
+               yyval.floatval = (float) atof(Tmpbuff);
+       }
+    break;
+
+  case 537:
+#line 4892 "gram.y"
+    {
+               sprintf(Tmpbuff,"0.%s", yyvsp[0].stringval);
+               yyval.floatval = (float) atof(Tmpbuff);
+       }
+    break;
+
+  case 538:
+#line 4898 "gram.y"
+    {
+               /* no decimal fraction part of float number */
+               yyval.stringval = "";
+       }
+    break;
+
+  case 540:
+#line 4908 "gram.y"
+    {
+               yyval.stringval = yytext;
+       }
+    break;
+
+  case 542:
+#line 4916 "gram.y"
+    {
+               Currstruct_p->u.line_p->linetype = yyvsp[-6].intval;
+               Currstruct_p->u.line_p->start = *(yyvsp[-3].inpcoord_p);
+               Currstruct_p->u.line_p->end = *(yyvsp[-1].inpcoord_p);
+               rep_inpcoord(yyvsp[-3].inpcoord_p, &(Currstruct_p->u.line_p->start));
+               rep_inpcoord(yyvsp[-1].inpcoord_p, &(Currstruct_p->u.line_p->end));
+               Currstruct_p->u.line_p->string = yyvsp[0].stringval;
+
+               /* copies of the location info went into the LINE struct,
+                * so we can free the original copy of the information */
+               if (yyvsp[-3].inpcoord_p) {
+                       FREE(yyvsp[-3].inpcoord_p);
+               }
+               if (yyvsp[-1].inpcoord_p) {
+                       FREE(yyvsp[-1].inpcoord_p);
+               }
+               insertMAINLL(Currstruct_p, Mainlltc_p);
+               Currstruct_p = (struct MAINLL *) 0;
+       }
+    break;
+
+  case 543:
+#line 4937 "gram.y"
+    {
+               /* null token to cause allocation of LINE struct */
+               (void) contextcheck(C_MUSIC, "line");
+               Currstruct_p = newMAINLLstruct(S_LINE, yylineno);
+       }
+    break;
+
+  case 544:
+#line 4944 "gram.y"
+    {
+               yyval.intval = L_NORMAL;
+       }
+    break;
+
+  case 546:
+#line 4954 "gram.y"
+    {
+               yyval.stringval = 0;
+       }
+    break;
+
+  case 547:
+#line 4959 "gram.y"
+    {
+               yyval.stringval = fix_string(yyvsp[0].stringval, Titlefont, Titlesize, Curr_filename, yylineno);
+       }
+    break;
+
+  case 548:
+#line 4965 "gram.y"
+    {
+               if (yyvsp[-6].intval == L_WAVY) {
+                       l_yyerror(Curr_filename, yylineno,
+                                               "wavy curve not allowed");
+               }
+               Currstruct_p->u.curve_p->curvetype = yyvsp[-6].intval;
+               insertMAINLL(Currstruct_p, Mainlltc_p);
+               Currstruct_p = (struct MAINLL *) 0;
+       }
+    break;
+
+  case 549:
+#line 4976 "gram.y"
+    {
+               (void) contextcheck(C_MUSIC, "curve");
+               Currstruct_p = newMAINLLstruct(S_CURVE, yylineno);
+
+               /* get space for a list of locations and mark it as empty */
+               Item_count = 0;
+               Currstruct_p->u.curve_p->ncoord = (short) Item_count;
+               Currstruct_p->u.curve_p->nbulge = (short) Item_count;
+               MALLOC(INPCOORD, Currstruct_p->u.curve_p->coordlist, ITEMS);
+               Max_items = ITEMS;
+       }
+    break;
+
+  case 556:
+#line 5010 "gram.y"
+    {
+               /* get enough space to store some values if don't have enough */
+               if (Currstruct_p->u.curve_p->nbulge == 0) {
+                       MALLOCA(float, Currstruct_p->u.curve_p->bulgelist, ITEMS);
+               }
+               else if ( (Currstruct_p->u.curve_p->nbulge % ITEMS) == 0) {
+                       REALLOCA(float, Currstruct_p->u.curve_p->bulgelist,
+                               Currstruct_p->u.curve_p->nbulge + ITEMS);
+               }
+
+               /* fill in the value and increment the count of how many */
+               Currstruct_p->u.curve_p->bulgelist[Currstruct_p->u.curve_p->nbulge] = yyvsp[-1].intval * yyvsp[0].floatval;
+               (Currstruct_p->u.curve_p->nbulge)++;
+       }
+    break;
+
+  case 557:
+#line 5026 "gram.y"
+    {
+               struct INPCOORD *curve_inpcoord_p;
+
+               /* If ran off end of list, make list bigger.
+                * We cannot use REALLOC here, since we need to update
+                * the tag reference information on each individual array
+                * element, so we alloc all new space, copy the existing data,
+                * and update the tag references, then free the old space,
+                * and redirect the pointer to the new space. */
+               if (Currstruct_p->u.curve_p->ncoord >= Max_items) {
+                       struct INPCOORD *newlist_p;
+                       int n;
+                       Max_items += ITEMS;
+                       MALLOC(INPCOORD, newlist_p, Max_items);
+                       for (n = 0; n < Currstruct_p->u.curve_p->ncoord; n++) {
+                               newlist_p[n] = Currstruct_p->u.curve_p->coordlist[n];
+                               rep_inpcoord(
+                                   &(Currstruct_p->u.curve_p->coordlist[n]),
+                                   &(newlist_p[n]));
+                       }
+                       FREE(Currstruct_p->u.curve_p->coordlist);
+                       Currstruct_p->u.curve_p->coordlist = newlist_p;
+               }
+
+               /* Add this entry to the end of the list, update the
+                * tag reference to point to this permanent copy rather
+                * the temporary one we will be deleting, and update the
+                * count of how many elements in the list. */
+               curve_inpcoord_p = &(Currstruct_p->u.curve_p->coordlist
+                                       [Currstruct_p->u.curve_p->ncoord]);
+               *curve_inpcoord_p = *(yyvsp[0].inpcoord_p);
+               rep_inpcoord(yyvsp[0].inpcoord_p, curve_inpcoord_p);
+               (Currstruct_p->u.curve_p->ncoord)++;
+               FREE(yyvsp[0].inpcoord_p);
+       }
+    break;
+
+  case 558:
+#line 5063 "gram.y"
+    {
+               attach_stuff();
+               /* so reset flag */
+               Defining_multiple = NO;
+       }
+    break;
+
+  case 559:
+#line 5071 "gram.y"
+    {
+               chk_stuff_header(yyvsp[-4].intval, yyvsp[-3].intval, yyvsp[-2].intval, Dist_usage);
+               add_to_sv_list();
+       }
+    break;
+
+  case 560:
+#line 5078 "gram.y"
+    {
+               /* Separate rule for phrase because it has the linetype
+                * modifier in front, unlike any other STUFF. The size,
+                * and dist are not really allowed, but we match them
+                * if they are there in order to give more clear error
+                * message than just "syntax error," since there was
+                * already code elsewhere to check for these errors.
+                */
+               set_stuff_type(ST_PHRASE);
+               chk_stuff_header(yyvsp[-3].intval, yyvsp[-5].intval, yyvsp[-2].intval, Dist_usage);
+               add_to_sv_list();
+       }
+    break;
+
+  case 561:
+#line 5092 "gram.y"
+    {
+               /* need a separate rule for midi, because it can include
+                * a voice as well as staff. It also cannot have the chord,
+                * size or place, although those are checked elsewhere anyway */
+               chk_stuff_header(-1, NO, PL_UNKNOWN, SD_NONE);
+       }
+    break;
+
+  case 562:
+#line 5101 "gram.y"
+    {
+               set_stuff_type(ST_MIDI);
+               begin_range(PL_UNKNOWN);
+       }
+    break;
+
+  case 564:
+#line 5111 "gram.y"
+    {
+               all();
+               add_to_sv_list();
+       }
+    break;
+
+  case 565:
+#line 5118 "gram.y"
+    {
+               /* dummy token for sole purpose of saving away current
+                * stuff type. We have to do this in order to have it in
+                * time to figure out the default place for "all" */
+               set_stuff_type(yyvsp[0].intval);
+       }
+    break;
+
+  case 566:
+#line 5127 "gram.y"
+    {
+               Curr_family = yyvsp[-1].intval;
+
+               switch (yyvsp[0].intval) {
+               case FONT_TR:
+                       yyval.intval = ST_ROM;
+                       break;
+               case FONT_TI:
+                       yyval.intval = ST_ITAL;
+                       break;
+               case FONT_TB:
+                       yyval.intval = ST_BOLD;
+                       break;
+               case FONT_TX:
+                       yyval.intval = ST_BOLDITAL;
+                       break;
+               default:
+                       pfatal("unknown font");
+                       break;
+               }
+       }
+    break;
+
+  case 567:
+#line 5151 "gram.y"
+    {
+               if (yyvsp[0].intval != L_NORMAL) {
+                       /* user used 'dotted' or 'dashed' which applies only
+                        * to use of T_L_ANGLE for slurs. Use generic error
+                        * message so looks like any other similar error. */
+                       yyerror("syntax error");
+               }
+               yyval.intval = ST_CRESC;
+       }
+    break;
+
+  case 568:
+#line 5163 "gram.y"
+    {
+               yyval.intval = ST_DECRESC;
+       }
+    break;
+
+  case 569:
+#line 5169 "gram.y"
+    {
+               yyval.intval = ST_PEDAL;
+       }
+    break;
+
+  case 570:
+#line 5175 "gram.y"
+    {
+               yyval.intval = ST_MUSSYM;
+       }
+    break;
+
+  case 571:
+#line 5181 "gram.y"
+    {
+               yyval.intval = ST_OCTAVE;
+       }
+    break;
+
+  case 572:
+#line 5187 "gram.y"
+    {
+               /* use -1 to indicate user didn't specify so must use default */
+               yyval.intval = -1;
+       }
+    break;
+
+  case 573:
+#line 5194 "gram.y"
+    {
+               yyval.intval = yyvsp[-1].intval;
+       }
+    break;
+
+  case 574:
+#line 5199 "gram.y"
+    {
+               yyval.intval = TM_NONE;
+       }
+    break;
+
+  case 575:
+#line 5205 "gram.y"
+    {
+               yyval.intval = yyvsp[0].intval;
+       }
+    break;
+
+  case 576:
+#line 5210 "gram.y"
+    {
+               Dist = 0;
+               Dist_usage = SD_NONE;
+       }
+    break;
+
+  case 577:
+#line 5217 "gram.y"
+    {
+               if (yyvsp[-1].intval != DIST) {
+                       yyerror("unexpected parameter name instead of 'dist'");
+               }
+               else {
+                       if (rangecheck(yyvsp[0].intval, -MAXDIST, MAXDIST, "dist") == YES) {
+                               Dist = yyvsp[0].intval;
+                       }
+               }
+       }
+    break;
+
+  case 578:
+#line 5230 "gram.y"
+    {
+               yyval.intval = yyvsp[-1].intval;
+       }
+    break;
+
+  case 579:
+#line 5236 "gram.y"
+    {
+               if (Dist_usage != SD_FORCE) {
+                       l_warning(Curr_filename, yylineno,
+                               "negative dist requires !, setting to 0");
+                       yyval.intval = 0;
+               }
+               else {
+                       yyval.intval = - yyvsp[-1].intval;
+               }
+       }
+    break;
+
+  case 580:
+#line 5248 "gram.y"
+    {
+               Dist_usage = SD_MIN;
+       }
+    break;
+
+  case 581:
+#line 5254 "gram.y"
+    {
+               Dist_usage = SD_FORCE;
+       }
+    break;
+
+  case 584:
+#line 5267 "gram.y"
+    {
+               add_stuff_item(yyvsp[-4].floatval, yyvsp[-3].floatval, Gracebackup, yyvsp[-2].stringval, Til_bars, Til_offset,
+                                               Dist, Dist_usage);
+       }
+    break;
+
+  case 585:
+#line 5274 "gram.y"
+    {
+               Til_bars = 0;
+               Til_offset = 0.0;
+               yyval.floatval = yyvsp[-1].floatval;
+       }
+    break;
+
+  case 586:
+#line 5281 "gram.y"
+    {
+               Gracebackup = 0;
+       }
+    break;
+
+  case 587:
+#line 5287 "gram.y"
+    {
+               Gracebackup = yyvsp[-1].intval;
+       }
+    break;
+
+  case 588:
+#line 5292 "gram.y"
+    {
+               yyval.floatval = 0.0;
+       }
+    break;
+
+  case 589:
+#line 5298 "gram.y"
+    {
+               yyval.floatval = yyvsp[-1].floatval * (float) yyvsp[-2].intval;
+       }
+    break;
+
+  case 590:
+#line 5303 "gram.y"
+    {
+               yyval.stringval = (char *) 0;
+       }
+    break;
+
+  case 591:
+#line 5309 "gram.y"
+    {
+               if (get_stuff_type() != ST_PEDAL) {
+                       yyerror("'*' only valid with pedal");
+               }
+               MALLOCA(char, yyval.stringval, 12);
+               yyval.stringval[0] = FONT_MUSIC;
+               yyval.stringval[1] = DFLT_SIZE;
+               sprintf(yyval.stringval + 2, "\\(endped)");
+       }
+    break;
+
+  case 592:
+#line 5321 "gram.y"
+    {
+               yyval.stringval = yyvsp[0].stringval;
+       }
+    break;
+
+  case 593:
+#line 5326 "gram.y"
+    {
+       }
+    break;
+
+  case 594:
+#line 5331 "gram.y"
+    {
+       }
+    break;
+
+  case 595:
+#line 5336 "gram.y"
+    {
+               /** if there is a non-empty til_suffix, the floatnum better
+                ** have been an integer, and is really the number
+                * of bars. **/
+               if (yyvsp[0].intval == YES) {
+                       Til_bars = (int) yyvsp[-1].floatval;
+                       if (yyvsp[-1].floatval - Til_bars != 0.0) {
+                               yyerror("number of measures in til clause must be a whole number");
+                       }
+               }
+               else {
+                       /* only a number, that means it was really a beat offset */
+                       Til_offset = yyvsp[-1].floatval;
+               }
+       }
+    break;
+
+  case 596:
+#line 5353 "gram.y"
+    {
+               yyval.intval = NO;
+       }
+    break;
+
+  case 597:
+#line 5359 "gram.y"
+    {
+               yyval.intval = YES;
+       }
+    break;
+
+  case 598:
+#line 5364 "gram.y"
+    {
+               Til_offset = 0.0;
+       }
+    break;
+
+  case 599:
+#line 5370 "gram.y"
+    {
+               Til_offset = yyvsp[0].floatval;
+       }
+    break;
+
+  case 601:
+#line 5378 "gram.y"
+    {
+               newROLLINFO();
+       }
+    break;
+
+  case 602:
+#line 5384 "gram.y"
+    {
+               newROLLINFO();
+               setrolldir(UP);
+       }
+    break;
+
+  case 603:
+#line 5391 "gram.y"
+    {
+               newROLLINFO();
+               setrolldir(DOWN);
+       }
+    break;
+
+  case 605:
+#line 5402 "gram.y"
+    {
+               /* save staffnum and voice 1 for start of roll */
+               rollparam(yyvsp[0].intval, 1, -1, -1);
+       }
+    break;
+
+  case 606:
+#line 5409 "gram.y"
+    {
+               /* save staff and voice for start of roll */
+               rollparam(yyvsp[-1].intval, yyvsp[0].intval, -1, -1);
+       }
+    break;
+
+  case 608:
+#line 5418 "gram.y"
+    {
+               /* save staffnum, voice 1 for end of roll */
+               rollparam(-1, -1, yyvsp[0].intval, 1);
+       }
+    break;
+
+  case 609:
+#line 5425 "gram.y"
+    {
+               /* save staffnum and voice for end of roll */
+               rollparam(-1, -1, yyvsp[-1].intval, yyvsp[0].intval);
+       }
+    break;
+
+  case 610:
+#line 5432 "gram.y"
+    {
+               rolloffset( (double) yyvsp[-1].floatval);
+       }
+    break;
+
+  case 611:
+#line 5438 "gram.y"
+    {  
+               rolloffset( (double) yyvsp[-1].floatval);
+       }
+    break;
+
+  case 612:
+#line 5443 "gram.y"
+    {
+               if (Curr_family == FAMILY_DFLT) {
+                       Curr_family = Score.fontfamily;
+               }
+               Extra = extra_needed(Curr_family + Curr_font, Curr_size, yyvsp[0].stringval);
+               proc_printcmd(yyvsp[-2].intval, Curr_loc_info_p, yyvsp[0].stringval, Curr_family + Curr_font,
+                       Curr_size, yyvsp[-1].intval, NO, (yyvsp[-1].intval == YES ? Extra : (double) 0.0));
+       }
+    break;
+
+  case 613:
+#line 5454 "gram.y"
+    {
+               if (yyvsp[-1].intval == YES) {
+                       warning("nl ignored for postscript");
+               }
+               proc_printcmd(J_NONE, Curr_loc_info_p, yyvsp[0].stringval, FONT_UNKNOWN,
+                       DFLT_SIZE, NO, YES, (double) 0.0);
+               end_raw();
+       }
+    break;
+
+  case 614:
+#line 5465 "gram.y"
+    {
+               begin_raw();
+       }
+    break;
+
+  case 616:
+#line 5473 "gram.y"
+    {
+               /* this means print at default location */
+               Curr_loc_info_p = (struct INPCOORD *) 0;
+               yyval.intval = NO;
+       }
+    break;
+
+  case 617:
+#line 5481 "gram.y"
+    {
+               Curr_loc_info_p = (struct INPCOORD *) 0;
+               yyval.intval = YES;
+       }
+    break;
+
+  case 618:
+#line 5488 "gram.y"
+    {
+               yyval.intval = NO;
+       }
+    break;
+
+
+    }
+
+/* Line 1016 of /usr/share/bison/yacc.c.  */
+#line 7824 "y.tab.c"
+\f
+  yyvsp -= yylen;
+  yyssp -= yylen;
+
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "state stack now");
+      while (yyssp1 != yyssp)
+       YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (YYPACT_NINF < yyn && yyn < YYLAST)
+       {
+         YYSIZE_T yysize = 0;
+         int yytype = YYTRANSLATE (yychar);
+         char *yymsg;
+         int yyx, yycount;
+
+         yycount = 0;
+         /* Start YYX at -YYN if negative to avoid negative indexes in
+            YYCHECK.  */
+         for (yyx = yyn < 0 ? -yyn : 0;
+              yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+           if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+             yysize += yystrlen (yytname[yyx]) + 15, yycount++;
+         yysize += yystrlen ("parse error, unexpected ") + 1;
+         yysize += yystrlen (yytname[yytype]);
+         yymsg = (char *) YYSTACK_ALLOC (yysize);
+         if (yymsg != 0)
+           {
+             char *yyp = yystpcpy (yymsg, "parse error, unexpected ");
+             yyp = yystpcpy (yyp, yytname[yytype]);
+
+             if (yycount < 5)
+               {
+                 yycount = 0;
+                 for (yyx = yyn < 0 ? -yyn : 0;
+                      yyx < (int) (sizeof (yytname) / sizeof (char *));
+                      yyx++)
+                   if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+                     {
+                       const char *yyq = ! yycount ? ", expecting " : " or ";
+                       yyp = yystpcpy (yyp, yyq);
+                       yyp = yystpcpy (yyp, yytname[yyx]);
+                       yycount++;
+                     }
+               }
+             yyerror (yymsg);
+             YYSTACK_FREE (yymsg);
+           }
+         else
+           yyerror ("parse error; also virtual memory exhausted");
+       }
+      else
+#endif /* YYERROR_VERBOSE */
+       yyerror ("parse error");
+    }
+  goto yyerrlab1;
+
+
+/*----------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action.  |
+`----------------------------------------------------*/
+yyerrlab1:
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+        error, discard it.  */
+
+      /* Return failure if at end of input.  */
+      if (yychar == YYEOF)
+        {
+         /* Pop the error token.  */
+          YYPOPSTACK;
+         /* Pop the rest of the stack.  */
+         while (yyssp > yyss)
+           {
+             YYDPRINTF ((stderr, "Error: popping "));
+             YYDSYMPRINT ((stderr,
+                           yystos[*yyssp],
+                           *yyvsp));
+             YYDPRINTF ((stderr, "\n"));
+             yydestruct (yystos[*yyssp], *yyvsp);
+             YYPOPSTACK;
+           }
+         YYABORT;
+        }
+
+      YYDPRINTF ((stderr, "Discarding token %d (%s).\n",
+                 yychar, yytname[yychar1]));
+      yydestruct (yychar1, yylval);
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+
+  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+       {
+         yyn += YYTERROR;
+         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+           {
+             yyn = yytable[yyn];
+             if (0 < yyn)
+               break;
+           }
+       }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+       YYABORT;
+
+      YYDPRINTF ((stderr, "Error: popping "));
+      YYDSYMPRINT ((stderr,
+                   yystos[*yyssp], *yyvsp));
+      YYDPRINTF ((stderr, "\n"));
+
+      yydestruct (yystos[yystate], *yyvsp);
+      yyvsp--;
+      yystate = *--yyssp;
+
+
+#if YYDEBUG
+      if (yydebug)
+       {
+         short *yyssp1 = yyss - 1;
+         YYFPRINTF (stderr, "Error: state stack now");
+         while (yyssp1 != yyssp)
+           YYFPRINTF (stderr, " %d", *++yyssp1);
+         YYFPRINTF (stderr, "\n");
+       }
+#endif
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  YYDPRINTF ((stderr, "Shifting error token, "));
+
+  *++yyvsp = yylval;
+
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*----------------------------------------------.
+| yyoverflowlab -- parser overflow comes here.  |
+`----------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+  return yyresult;
+}
+
+
+#line 5493 "gram.y"
+
+
+#include <stdio.h>
+
+
+/* print error message along with current filename and line number */
+
+int
+yyerror(msg)
+
+char *msg;
+
+{
+       if (strncmp(msg, "syntax error", 12) == 0 ||
+                       strncmp(msg, "parse error", 11) == 0) {
+               /* beef up yacc's default syntax error message */
+               if (*yytext == '\n') {
+                       l_yyerror(Curr_filename, yylineno,
+                               "error detected at end of line (maybe missing semicolon or other required element?)");
+               }
+               else {
+                       l_yyerror(Curr_filename, yylineno,
+                               "error detected at '%s'", yytext);
+               }
+       }
+       else {
+               l_yyerror(Curr_filename, yylineno, "%s", msg);
+       }
+
+       /* return something to keep lint happy */
+       return(0);
+}
+\f
+
+/* if argument is surrounded by double quotes, remove them and return the
+ * unquoted string. Actually just NULL out the end quote and return a
+ * pointer to beyond the leading quote */
+
+static char *
+stripquotes(string)
+
+char *string;
+
+{
+       char *p;
+
+       p = string + strlen(string) - 1;
+       if (*p == '"') {
+               *p = '\0';
+       }
+       return( *string == '"' ? string + 1 : string);
+}
+
+
+/* make sure each header/footer type specified only once */
+
+static void
+chkdup_headfoot(flag, which)
+
+int flag;      /* if non-zero, had gotten this head/foot before */
+char *which;   /* header, footer, header2 or footer2 */
+
+{
+       if (flag != 0) {
+               l_yyerror(Curr_filename, yylineno,
+                               "%s context specified more than once", which);
+       }
+}
+\f
+
+/* when entering new context, need to save away everything about current one */
+
+static void
+end_prev_context()
+
+{
+       struct MAINLL *place_p;         /* where to insert SSV in main list */
+
+
+       /* assume we will place at the end of main list. Later we'll set
+        * the right value if that assumption is wrong */
+       place_p = Mainlltc_p;
+
+       /* If current main list item hasn't been added to list yet,
+        * do that now. */
+       if (Currstruct_p != (struct MAINLL *) 0 && Currstruct_p != place_p) {
+
+               if (Currstruct_p->str == S_SSV) {
+
+                       if (List_of_staffs_p != (struct MAINLL *) 0) {
+                               yyerror("can't change context inside a measure");
+                               Currstruct_p = (struct MAINLL *) 0;
+                               return;
+                       }
+
+                       /* if is an SSV struct, we also need to set the
+                        * correct values at this point, because the
+                        * parser needs to know current values of some
+                        * things (like font and point size) */
+                       asgnssv(Currstruct_p->u.ssv_p);
+
+                       /* if this SSV is after a FEED, we have to move it
+                        * before the FEED in order to follow the rules of
+                        * what comes when on the main list */
+                       for (   ; place_p != (struct MAINLL *) 0 &&
+                                       place_p->str == S_FEED;
+                                       place_p = place_p->prev) {
+                       }
+               }
+
+               insertMAINLL(Currstruct_p, place_p);
+       }
+
+       if (Currstruct_p != 0 && Currstruct_p->str == S_SSV) {
+               /* memorize or recall beamstyle and timeunit if appropriate */
+               remember_tsig_params(Currstruct_p);
+       }
+
+       Curr_grpsyl_p = (struct GRPSYL *) 0;
+       Currblock_p = (struct BLOCKHEAD *) 0;
+       set_win_coord(0);
+}
+\f
+
+/* if defining more than one voice at the moment, not valid to set
+ * a location variable. Print message and reset flag so we don't
+ * give any more of the same message this measure */
+
+static void
+var_valid()
+
+{
+       if (Defining_multiple == YES) {
+               yyerror("location tag is only allowed when defining a single voice");
+               Defining_multiple = NO;
+       }
+       else if (Chord_at_a_time == YES) {
+               yyerror("location tag not allowed with chord-at-a-time input");
+       }
+}
+\f
+
+/* do a print command like left, right, or center. Allocate a PRINTDATA
+ * struct and fill in all the information about what to print and where
+ * to print it. */
+
+static void
+proc_printcmd(justifytype, inpc_p, str, font, size, got_nl, isPostScript, extra)
+
+int justifytype;       /* J_LEFT, etc */
+struct INPCOORD *inpc_p;       /* where to print */
+char *str;             /* the string to print */
+int font;
+int size;
+int got_nl;    /* YES if should go to next line before printing */
+int isPostScript;      /* YES if is raw PostScript rather than normal print */
+double extra;  /* how much extra vetical padding to add */
+
+{
+       struct PRINTDATA *curr_print_p;
+
+
+       (void) contextcheck(C_MUSIC | C_BLOCKHEAD, "print");
+
+       /* save all the info in a PRINTDATA struct */
+       MALLOC(PRINTDATA, curr_print_p, 1);
+
+       if (inpc_p == (struct INPCOORD *) 0) {
+
+               /* print at default location */
+               curr_print_p->location.vert_p = symval("_cur", (float **) 0);
+
+               switch (justifytype) {
+               case J_LEFT:
+               case J_RAGPARA:
+               case J_JUSTPARA:
+                       /* default x is relative to _win.w */
+                       curr_print_p->location.hor_p = symval("_win", (float **) 0);
+                       curr_print_p->location.htype = AW;
+                       break;
+               case J_RIGHT:
+                       /* default x is relative to _win.e */
+                       curr_print_p->location.hor_p = symval("_win", (float **) 0);
+                       curr_print_p->location.htype = AE;
+                       break;
+               case J_CENTER:
+                       /* default x is relative to _win.x */
+                       curr_print_p->location.hor_p = symval("_win", (float **) 0);
+                       curr_print_p->location.htype = AX;
+                       break;
+               case J_NONE:
+               default:
+                       /* default is at current location */
+                       curr_print_p->location.hor_p = symval("_cur", (float **) 0);
+                       curr_print_p->location.htype = AX;
+                       break;
+               }
+
+               curr_print_p->location.hsteps = 0.0;
+               curr_print_p->location.counts = 0.0;
+               curr_print_p->location.vtype = AY;
+               curr_print_p->location.vsteps = -extra;
+
+               /* If this is the first print command in a block,
+                * we implicitly go down by the font ascent. */
+               if (isPostScript == NO && Currblock_p != 0
+                                       && Next_print_link_p_p
+                                       == &(Currblock_p->printdata_p) ) {
+                       curr_print_p->location.vsteps -= fontascent(font, size)
+                                               / STEPSIZE;
+                       got_nl = NO;
+               }
+
+       }
+       else {
+               curr_print_p->location = *(inpc_p);
+               rep_inpcoord(inpc_p, &(curr_print_p->location) );
+               FREE(inpc_p);
+       }
+
+       curr_print_p->isPostScript = isPostScript;
+       if (isPostScript == YES) {
+               curr_print_p->width = 0.0;
+       }
+       else {
+               curr_print_p->width = strwidth(str);
+       }
+       curr_print_p->justifytype = (short) justifytype;
+       curr_print_p->string = str;
+       curr_print_p->inputfile = Curr_filename;
+       curr_print_p->inputlineno = (short) yylineno;
+
+       /* special case of user asking that this be printed
+        * on the next line. In this case we go down by the
+        * current point size */
+       if (got_nl) {
+               curr_print_p->location.vsteps -=
+                                       fontheight(font, size) / STEPSIZE;
+       }
+
+       /* Now link onto proper list -- could be in BLOCKHEAD
+        * context or doing a PRHEAD. If we are in BLOCKHEAD context, we
+        * definitely have something in the main list to attach to.
+        * If in C_MUSIC, we may or may not depending on whether
+        * this is the first in a series of print commands. */
+       if ( ((Context & C_BLOCKHEAD) != 0)
+               || ((Currstruct_p != (struct MAINLL *) 0) &&
+               (Currstruct_p->str == S_PRHEAD) ) ) {
+                       if (Next_print_link_p_p == (struct PRINTDATA **) 0) {
+                               pfatal("Next_print_link_p_p is null");
+                       }
+                       /* this means the value of Next_print_link_p_p
+                        * is valid and will tell us where to link */
+                       *Next_print_link_p_p = curr_print_p;
+       }
+       else {
+               /* We must be in music context, but the last
+                * thing we saw wasn't a print command, so
+                * we have to allocate a PRHEAD and put it
+                * in the main list and attach to that. */
+               /* allocate a new struct, put on main list and attach
+                * the print command to it */
+               Currstruct_p = newMAINLLstruct(S_PRHEAD, yylineno);
+               insertMAINLL(Currstruct_p, Mainlltc_p);
+               Currstruct_p->u.prhead_p->printdata_p = curr_print_p;
+               Currstruct_p = (struct MAINLL *) 0;
+       }
+
+       /* in any case, if we get another print command right away, it
+        * should be linked onto this one, so remember where we are */
+       Next_print_link_p_p = &(curr_print_p->next);
+       curr_print_p->next = (struct PRINTDATA *) 0;
+}
+\f
+
+/* if the given string has a higher ascent than the given font/size, return
+ * the amount is it higher, in stepsizes */
+
+static double
+extra_needed(font, size, string)
+
+int font;      /* default font for this string */
+int size;      /* default size for this string */
+char *string;  /* string, which might contain \s(xx) to make it bigger
+                * than normal */
+
+{
+       double usual_ascent;
+       double this_string_ascent;
+
+
+       /* get expected ascent for this font/size and actual for string */
+       usual_ascent = fontascent(font, size);
+       (void) fix_string(string, font, size, Curr_filename, yylineno);
+       this_string_ascent = strascent(string);
+
+       /* if this string is too tall, return by how much it is too tall */
+       if (this_string_ascent > usual_ascent) {
+               return (this_string_ascent - usual_ascent) / STEPSIZE;
+       }
+       else {
+               return(0.0);
+       }
+}
+\f
+
+/* Sometimes lexer will recognize something as a keyword, but it's
+ * really a bunch of note letters, due to context. This function turns
+ * the mistaken keyword into notes. It handles a through g and r and s, but
+ * not n and u which would also be troublesome.
+ */
+
+static void
+keyword_notes(str)
+
+char *str;
+
+{
+       for (  ; *str != '\0'; str++) {
+               /* On the last letter, if it's a true pitch, have to
+                * push it back into input, because it could be followed
+                * by an accidental or octave mark or tick or something. */
+               if (*(str+1) == '\0' && *str >= 'a' && *str <= 'g') {
+                       pushback(*str);
+               }
+               else {
+                       add_note(Curr_grpsyl_p, (int) *str, 0, USE_DFLT_OCTAVE,
+                                                       0, NO, (char *) 0);
+               }
+       }
+}
+\f
+
+/* Free up the current additive time list, if any */
+
+static void
+free_extra_time()
+{
+       struct TIMELIST *tl_p;
+
+       /* If this was the most recently allocated list, we can free it.
+        * We can't free otherwise, since Extra_time_p might be
+        * pointing to one from an SSV, which must be kept around. */
+       if (Extra_time_p == Last_alloced_timelist_p) {
+               while (Extra_time_p != 0) {
+                       tl_p = Extra_time_p->next;
+                       FREE(Extra_time_p);
+                       Extra_time_p = tl_p;
+               }
+       }
+       Extra_time_p = 0;
+       Last_alloced_timelist_p = 0;
+       Curr_timelist_p = 0;
+}
+\f
+
+/* Add an item to the internal representation of the time signature
+ * currently being collected */
+
+static void
+tsig_item(item)
+
+int item;      /* the byte to add to timerep */
+
+{
+       if (Tsig_offset >= MAXTSLEN  - 1) {
+               l_ufatal(Curr_filename, yylineno,
+                               "time signature is too complicated");
+       }
+       Timerep[Tsig_offset++] = (char) item;
+}
+
diff --git a/mup/mup/ytab.h b/mup/mup/ytab.h
new file mode 100644 (file)
index 0000000..ce5234a
--- /dev/null
@@ -0,0 +1,363 @@
+/* A Bison parser, made from gram.y, by GNU bison 1.75.  */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+#ifndef BISON_Y_TAB_H
+# define BISON_Y_TAB_H
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     T_SCORE = 258,
+     T_STAFF = 259,
+     T_VOICE = 260,
+     T_GRIDS = 261,
+     T_BLOCKHEAD = 262,
+     T_NUMBER = 263,
+     T_EQUAL = 264,
+     T_SEMICOLON = 265,
+     T_NEWLINE = 266,
+     T_COLON = 267,
+     T_COMMA = 268,
+     T_LBRACKET = 269,
+     T_RBRACKET = 270,
+     T_LBRACE = 271,
+     T_RBRACE = 272,
+     T_VARIABLE = 273,
+     T_DASH = 274,
+     T_PLUS = 275,
+     T_PLACE = 276,
+     T_ALL = 277,
+     T_WITH = 278,
+     T_CUE = 279,
+     T_GRACE = 280,
+     T_XNOTE = 281,
+     T_DIAM = 282,
+     T_DOT = 283,
+     T_MULTIWHOLE = 284,
+     T_LET_M = 285,
+     T_LET_R = 286,
+     T_LET_S = 287,
+     T_LET_U = 288,
+     T_PITCH = 289,
+     T_SHARP = 290,
+     T_AMPERSAND = 291,
+     T_LET_N = 292,
+     T_LET_X = 293,
+     T_DBLFLAT = 294,
+     T_LETTER = 295,
+     T_LYRICS = 296,
+     T_PAD = 297,
+     T_LPAREN = 298,
+     T_RPAREN = 299,
+     T_LVAR = 300,
+     T_MUSIC = 301,
+     T_HEADSHAPES = 302,
+     T_HS = 303,
+     T_SWINGUNIT = 304,
+     T_POSTSCRIPT = 305,
+     T_SCOREFEED = 306,
+     T_BARTYPE = 307,
+     T_HAT = 308,
+     T_TILDE = 309,
+     T_QUESTION = 310,
+     T_LINETYPE = 311,
+     T_LINE = 312,
+     T_TO = 313,
+     T_STAR = 314,
+     T_BULGE = 315,
+     T_CURVE = 316,
+     T_TIE = 317,
+     T_PRINTTYPE = 318,
+     T_NL = 319,
+     T_STAFFLINES = 320,
+     T_FFAMILY = 321,
+     T_PARAGRAPH = 322,
+     T_PARATYPE = 323,
+     T_NUMVAR = 324,
+     T_FNUMVAR = 325,
+     T_2FNUMVAR = 326,
+     T_RATNUMLISTVAR = 327,
+     T_RANGELISTVAR = 328,
+     T_TIMEUNIT = 329,
+     T_FONTVAR = 330,
+     T_STRVAR = 331,
+     T_CLEFVAR = 332,
+     T_VVAR = 333,
+     T_BARSTLISTVAR = 334,
+     T_SCORESEP = 335,
+     T_FONT = 336,
+     T_SLASH = 337,
+     T_KEY = 338,
+     T_TIME = 339,
+     T_CUT = 340,
+     T_COMMON = 341,
+     T_CLEF = 342,
+     T_MULTIREST = 343,
+     T_YESNOVAR = 344,
+     T_BM = 345,
+     T_ESBM = 346,
+     T_EBM = 347,
+     T_INVISBAR = 348,
+     T_OCTAVE = 349,
+     T_ROLL = 350,
+     T_VISVAR = 351,
+     T_WHEREUSED = 352,
+     T_UNSET = 353,
+     T_VCOMBINE = 354,
+     T_VCOMBVAL = 355,
+     T_SCOREPAD = 356,
+     T_WORD = 357,
+     T_UP = 358,
+     T_DOWN = 359,
+     T_ENDING = 360,
+     T_ENDENDING = 361,
+     T_FAMILY = 362,
+     T_ENDSTYLE = 363,
+     T_ENDTYPE = 364,
+     T_SLASHMARK = 365,
+     T_ALT = 366,
+     T_TITLE = 367,
+     T_REHEARSAL = 368,
+     T_NUM = 369,
+     T_LET = 370,
+     T_MNUM = 371,
+     T_TRANSPOSE = 372,
+     T_XPOS_INT = 373,
+     T_PEDAL = 374,
+     T_PHRASE = 375,
+     T_MUSSYM = 376,
+     T_L_ANGLE = 377,
+     T_MODIFIER = 378,
+     T_R_ANGLE = 379,
+     T_TIL = 380,
+     T_MIDI = 381,
+     T_PEDSTYLE = 382,
+     T_PEDSTAR = 383,
+     T_HIDECHANGES = 384,
+     T_SLUR = 385,
+     T_UNITS = 386,
+     T_CENTIMETERS = 387,
+     T_UNITTYPE = 388,
+     T_TAB = 389,
+     T_TICKS = 390,
+     T_NOWHERE_SLIDE = 391,
+     T_LEN = 392,
+     T_EXCLAM = 393,
+     T_OTHERTEXT = 394,
+     T_ORDER = 395,
+     T_GRIDPLACE = 396,
+     T_GRPLVALUE = 397,
+     T_DRUM = 398,
+     T_RPT = 399,
+     T_STRING = 400,
+     T_HO = 401,
+     T_REH_STYLE = 402,
+     T_REHTYPE = 403,
+     T_L_DBLANGLE = 404,
+     T_R_DBLANGLE = 405,
+     T_SLOPE = 406,
+     T_PSVAR = 407,
+     T_PAGESIZE = 408,
+     T_ORIENTATION = 409
+   };
+#endif
+#define T_SCORE 258
+#define T_STAFF 259
+#define T_VOICE 260
+#define T_GRIDS 261
+#define T_BLOCKHEAD 262
+#define T_NUMBER 263
+#define T_EQUAL 264
+#define T_SEMICOLON 265
+#define T_NEWLINE 266
+#define T_COLON 267
+#define T_COMMA 268
+#define T_LBRACKET 269
+#define T_RBRACKET 270
+#define T_LBRACE 271
+#define T_RBRACE 272
+#define T_VARIABLE 273
+#define T_DASH 274
+#define T_PLUS 275
+#define T_PLACE 276
+#define T_ALL 277
+#define T_WITH 278
+#define T_CUE 279
+#define T_GRACE 280
+#define T_XNOTE 281
+#define T_DIAM 282
+#define T_DOT 283
+#define T_MULTIWHOLE 284
+#define T_LET_M 285
+#define T_LET_R 286
+#define T_LET_S 287
+#define T_LET_U 288
+#define T_PITCH 289
+#define T_SHARP 290
+#define T_AMPERSAND 291
+#define T_LET_N 292
+#define T_LET_X 293
+#define T_DBLFLAT 294
+#define T_LETTER 295
+#define T_LYRICS 296
+#define T_PAD 297
+#define T_LPAREN 298
+#define T_RPAREN 299
+#define T_LVAR 300
+#define T_MUSIC 301
+#define T_HEADSHAPES 302
+#define T_HS 303
+#define T_SWINGUNIT 304
+#define T_POSTSCRIPT 305
+#define T_SCOREFEED 306
+#define T_BARTYPE 307
+#define T_HAT 308
+#define T_TILDE 309
+#define T_QUESTION 310
+#define T_LINETYPE 311
+#define T_LINE 312
+#define T_TO 313
+#define T_STAR 314
+#define T_BULGE 315
+#define T_CURVE 316
+#define T_TIE 317
+#define T_PRINTTYPE 318
+#define T_NL 319
+#define T_STAFFLINES 320
+#define T_FFAMILY 321
+#define T_PARAGRAPH 322
+#define T_PARATYPE 323
+#define T_NUMVAR 324
+#define T_FNUMVAR 325
+#define T_2FNUMVAR 326
+#define T_RATNUMLISTVAR 327
+#define T_RANGELISTVAR 328
+#define T_TIMEUNIT 329
+#define T_FONTVAR 330
+#define T_STRVAR 331
+#define T_CLEFVAR 332
+#define T_VVAR 333
+#define T_BARSTLISTVAR 334
+#define T_SCORESEP 335
+#define T_FONT 336
+#define T_SLASH 337
+#define T_KEY 338
+#define T_TIME 339
+#define T_CUT 340
+#define T_COMMON 341
+#define T_CLEF 342
+#define T_MULTIREST 343
+#define T_YESNOVAR 344
+#define T_BM 345
+#define T_ESBM 346
+#define T_EBM 347
+#define T_INVISBAR 348
+#define T_OCTAVE 349
+#define T_ROLL 350
+#define T_VISVAR 351
+#define T_WHEREUSED 352
+#define T_UNSET 353
+#define T_VCOMBINE 354
+#define T_VCOMBVAL 355
+#define T_SCOREPAD 356
+#define T_WORD 357
+#define T_UP 358
+#define T_DOWN 359
+#define T_ENDING 360
+#define T_ENDENDING 361
+#define T_FAMILY 362
+#define T_ENDSTYLE 363
+#define T_ENDTYPE 364
+#define T_SLASHMARK 365
+#define T_ALT 366
+#define T_TITLE 367
+#define T_REHEARSAL 368
+#define T_NUM 369
+#define T_LET 370
+#define T_MNUM 371
+#define T_TRANSPOSE 372
+#define T_XPOS_INT 373
+#define T_PEDAL 374
+#define T_PHRASE 375
+#define T_MUSSYM 376
+#define T_L_ANGLE 377
+#define T_MODIFIER 378
+#define T_R_ANGLE 379
+#define T_TIL 380
+#define T_MIDI 381
+#define T_PEDSTYLE 382
+#define T_PEDSTAR 383
+#define T_HIDECHANGES 384
+#define T_SLUR 385
+#define T_UNITS 386
+#define T_CENTIMETERS 387
+#define T_UNITTYPE 388
+#define T_TAB 389
+#define T_TICKS 390
+#define T_NOWHERE_SLIDE 391
+#define T_LEN 392
+#define T_EXCLAM 393
+#define T_OTHERTEXT 394
+#define T_ORDER 395
+#define T_GRIDPLACE 396
+#define T_GRPLVALUE 397
+#define T_DRUM 398
+#define T_RPT 399
+#define T_STRING 400
+#define T_HO 401
+#define T_REH_STYLE 402
+#define T_REHTYPE 403
+#define T_L_DBLANGLE 404
+#define T_R_DBLANGLE 405
+#define T_SLOPE 406
+#define T_PSVAR 407
+#define T_PAGESIZE 408
+#define T_ORIENTATION 409
+
+
+
+
+#ifndef YYSTYPE
+#line 152 "gram.y"
+typedef union {
+int    intval;         /* for tokens/nonterminals that return int values */
+char   *stringval;     /* for tokens/nonterminals that return strings */
+float  floatval;       /* for nonterminals that return floats */
+RATIONAL ratval;       /* for nonterminals that return rational numbers */
+struct INPCOORD *inpcoord_p;   /* for nonterminals that return coord info */
+} yystype;
+/* Line 1281 of /usr/share/bison/yacc.c.  */
+#line 356 "y.tab.h"
+# define YYSTYPE yystype
+#endif
+
+extern YYSTYPE yylval;
+
+
+#endif /* not BISON_Y_TAB_H */
+
diff --git a/mup/mupdisp/at386.c b/mup/mupdisp/at386.c
new file mode 100644 (file)
index 0000000..abe96d8
--- /dev/null
@@ -0,0 +1,262 @@
+
+/* Copyright (c) 1995, 1996, 1998, 2000 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions to support displaying multipage bitmap
+ * (as from Ghostscript -sDEVICE=bit) to AT386 console.
+ */
+
+#include "mupdisp.h"
+
+#if defined(AT386) && ! defined(linux) && ! defined(__DOS__)
+
+#include <sys/kd.h>
+#include <termio.h>
+
+#define BPL            (80)    /* bytes per line on screen, AT386 mode */
+
+unsigned char *Video_memory;
+int Orig_video_mode;           /* to put video back the way it was */
+struct termio Orig_ttyinfo;    /* to put keyboard back from raw mode */
+
+static void setup_keyboard P((void));
+\f
+
+/* set up for TERM=AT386. Put video and keyboard in proper mode */
+
+void
+at386_setup()
+
+{
+       register int n;                 /* for setting signal catching */
+
+
+       /* get current video mode, so we can put it back when we're done */
+       if ((Orig_video_mode = ioctl(1, CONS_GET, 0)) < 0) {
+               fprintf(stderr, "failed to determine current video mode\n");
+               generalcleanup(1);
+       }
+
+       /* need to put keyboard into raw mode, save current state */
+       if (ioctl(0, TCGETA, &Orig_ttyinfo) < 0) {
+               fprintf(stderr, "failed to get tty info\n");
+               generalcleanup(1);
+       }
+
+       /* make sure we always clean up, so user isn't left stuck in raw and/or
+        * graphics mode. */
+       for (n = 1; n < NSIG; n++) {
+               if ( n != SIGKILL && n != SIGCLD) {
+                       sigset(n, Conf_info_p->cleanup);
+               }
+       }
+       sigset(SIGWINCH, SIG_IGN);
+
+       /* put keyboard into raw mode */
+       setup_keyboard();
+
+       /* put screen into graphics mode */
+       if (ioctl(1, SW_CG640x350, 0) < 0) {
+               generalcleanup(1);
+       }
+
+       /* get access to video memory */
+       Video_memory = (unsigned char *) ioctl(1, MAPCONS, 0);
+}
+\f
+
+/* draw stuff onto screen. Draw starting at specified line of page */
+
+void
+at386_draw(line, small)
+
+int line;      /* draw starting from this raster line of page */
+int small;     /* YES if should draw small view of full page */
+
+{
+       register int i;
+       register int j;
+       unsigned char buff[MAX_BYTES_PER_LINE]; /* a row of bits to display */
+       int extra;              /* how many unused bits in rightmost byte */
+       int mask;               /* to clear out unused bits */
+       unsigned char *v;       /* pointer into video memory */
+       long offset;            /* into bitmap file */
+       int fd;                 /* file to read bitmap from */
+
+
+       /* make sure we have a valid page to draw */
+       if (Currpage_p == (struct Pginfo *) 0) {
+               ( *(Conf_info_p->error) ) ("page # out of range");
+               return;
+       }
+
+       /* figure out where in the bitmap file this page is */
+       offset = Currpage_p->seqnum * BYTES_PER_PAGE;
+       fd = gen1file(small);
+       lseek(fd, offset + line * BYTES_PER_LINE, SEEK_SET);
+
+       /* read from file and put into video memory, inverting to
+        * black on white */
+       for (i = 0; i < Conf_info_p->vlines; i++) {
+               read(fd, buff, BYTES_PER_LINE);
+
+               /* if the page width is not on a byte boundary, blank
+                * out the partial byte at the edge */
+               mask = 1;
+               for (mask = 1, extra = BYTES_PER_LINE & 0x7;
+                                       extra > 0; mask <<= 1, extra--) {
+                       buff[BYTES_PER_LINE - 1] |= mask;
+               }
+
+               /* point to row in video memory and transfer bitmap row */
+               v = Video_memory + i * BPL;
+               for (j = 0; j < BYTES_PER_LINE; j++) {
+                       v[j] = buff[j] ^ 0xff;
+               }
+       }
+}
+\f
+
+/* AT386 cleanup function.
+ * Put screen back into previous mode. Some day maybe we should save the data
+ * on the original screen and put it back when we're done... */
+
+void
+at386_cleanup(status)
+
+int status;
+
+{
+       /* put video back to normal */
+       ioctl(1, MODESWITCH | Orig_video_mode, 0);
+
+       /* put keyboard back to normal */
+       ioctl(0, TCSETA, &Orig_ttyinfo);
+       
+       /* call the non-terminal-type specific cleanup */
+       generalcleanup(status);
+}
+\f
+
+/* read from keyboard and call do_cmd for each key read.
+ * Commands are described in
+ * the comment at the beginning of do_cmd() */
+
+void
+at386_user_interf()
+
+{
+       int c;                  /* char read from keyboard */
+       int special = 0;        /* 1 = got an escape, 2 = got escape followed
+                                * by [, 0 = not doing any special processing.
+                                * This is to handle special function keys. */
+
+       while ( (c = getchar() ) != EOF) {
+               if (c == 0x1b) {
+                       /* got ESC, could be a special function key */
+                       special = 1;
+                       continue;
+               }
+               else if (special == 1 && c == '[') {
+                       /* got ESC-[ */
+                       special = 2;
+                       continue;
+               }
+               else if (special == 2) {
+                       /* map special functions to their equivalent commands */
+                       if (c == 'V') {
+                               c = 'p';        /* Page Up key ==> previous */
+                       }
+                       else if (c == 'U') {
+                               c = 'n';        /* Page Down key ==> next */
+                       }
+                       else if (c == 'A') {
+                               c = 'b';        /* Up key ==> backwards */
+                       }
+                       else if (c == 'B') {
+                               c = 'f';        /* Down key ==> forwards */
+                       }
+               }
+               special = 0;
+               do_cmd(c);
+       }
+}
+\f
+
+/* Error handler.
+ * For now just beep. Maybe eventually pop up an error message */
+
+void
+at386_error(msg)
+
+char *msg;
+
+{
+       ioctl(1, KDMKTONE, (150L << 16) | 3600L);
+}
+\f
+
+/* overlay a raster centered on the window */
+
+void
+at386_raster(bitmap, width, height)
+
+unsigned char *bitmap; /* what to display */
+int width, height;     /* of bitmap, width is in bytes */
+
+{
+       int i, j;
+       int x, y;       /* upper left corner of where to put bitmap, x in bytes */
+
+
+       /* figure out how to center on screen */
+       x = (BYTES_PER_LINE - width) / 2;
+       y = (Conf_info_p->vlines - height) / 2;
+
+       /* copy bitmap to screen */
+       for (i = 0; i < height; i++) {
+               for (j = 0; j < width; j++) {
+                       Video_memory[(y + i) * BPL + (x + j)] =
+                               bitmap[ (i * width) + j];
+               }
+       }
+}
+\f
+
+/* put keyboard in raw mode */
+
+static void
+setup_keyboard()
+
+{
+       struct termio ttyinfo;
+
+
+       if (isatty(0) != 1) {
+               fprintf(stderr, "stdin is not a tty\n");
+               generalcleanup(1);
+       }
+
+       if (ioctl(0, TCGETA, &ttyinfo) < 0) {
+               fprintf(stderr, "failed to get tty info\n");
+               generalcleanup(1);
+       }
+
+       /* turn off echo and canonical */
+       ttyinfo.c_lflag &= ~(ICANON | ECHO);
+       ttyinfo.c_cc[VMIN] = 1;
+       ttyinfo.c_cc[VTIME] = 3;
+       if (ioctl(0, TCSETA, &ttyinfo) < 0) {
+               fprintf(stderr, "failed to set keyboard modes, errno %d\n", errno);
+               generalcleanup(1);
+       }
+}
+\f
+
+#else
+
+/* some compilers complain about files that are effectively empty,
+ * so put in something even when entire file is effectively ifdef-ed out */
+static short dummy;
+
+#endif
diff --git a/mup/mupdisp/dispttyp.h b/mup/mupdisp/dispttyp.h
new file mode 100644 (file)
index 0000000..1ede728
--- /dev/null
@@ -0,0 +1,20 @@
+
+/* Copyright (c) 1995, 1996, 1998 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* to compile Mup/Ghostscript display program
+ * to allow working on AT386 terminal type, make sure AT386 is
+ * defined. To compile to work on X-windows, make sure XWINDOW is defined.
+ * To work with either, define both.
+ * Support for other terminal types could be added in the future. */
+
+#ifdef i386
+#if !defined(linux) && !defined(__EMX__)
+#define AT386  1
+#endif
+#endif
+
+#ifdef unix
+#define XWINDOW        1
+#endif
+
diff --git a/mup/mupdisp/do_cmd.c b/mup/mupdisp/do_cmd.c
new file mode 100644 (file)
index 0000000..deca4c6
--- /dev/null
@@ -0,0 +1,222 @@
+
+/* Copyright (c) 1995 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* command processing function for Mup/Ghostscript display program.
+ * Given a input input character, does the appropriate command */
+
+
+/* The user interface commands are:
+ *     + or <space> or ^e or ^f        scroll forwards 1/8"
+ *     - or <backsp> or ^y or ^b       scroll backwards 1/8"
+ *     f or <enter> or ^d              scroll forwards 1"
+ *     b or ^u                         scroll backwards 1"
+ *     h or ?          help
+ *     m               toggle between full page and scrolled mode
+ *     n               go to top of next page
+ *     p               go to top of previous page
+ *     q               quit
+ *     r               repaint current page
+ *     Num\n           go to page Num
+ * Upper case versions work too.
+ *     ZZ is synonym for quit
+ */
+
+#include "mupdisp.h"
+
+/* bitmap for the help screen. Have to manually make sure this is smaller
+ * than the minimum screen/window size */
+#include "help.bm"
+\f
+
+/* command processing function for Mup/Ghostscript display program.
+ * Given a input input character, does the appropriate command */
+
+void
+do_cmd(c)
+
+int c;         /* character read from user */
+
+{
+       static int line = 0;    /* current line on page that
+                                * is at top of screen */
+       static int got1z = 0;   /* if got one Z for vi-like ZZ exit */
+       static int pgnum = -1;  /* page number */
+       static int count = 0;   /* how many times called */
+       static int lasterr = 0; /* value of count for last error */
+       static int goofs = 0;   /* how many consecutive user errors */
+
+
+       /* count of times called, to implement auto-help if user goofs too
+        * many times in a row */
+       count++;
+
+       c = tolower(c);
+
+       switch(c) {
+
+       case '0': case '1':
+       case '2': case '3':
+       case '4': case '5':
+       case '6': case '7':
+       case '8': case '9':
+               /* gathering page number for specific page */
+               if (pgnum < 0) {
+                       /* first digit, so initialize page number */
+                       pgnum = 0;
+               }
+               pgnum = (pgnum * 10) + c - '0';
+               break;
+
+       case '+':
+       case ' ':
+       case '\5':      /* control-E for vi users */
+       case '\6':      /* control-F for emacs users */
+               /* scroll forward a little bit */
+               if (Fullpgmode) {
+                       ( *(Conf_info_p->error) ) ("command invalid in full page mode");
+               }
+               else {
+                       line = scroll(line, 9);
+               }
+               break;
+
+       case '-':
+       case '\b':
+       case '\31':     /* control-Y for vi users */
+       case '\2':      /* control-B for emacs users */
+               /* backward a little bit */
+               if (Fullpgmode) {
+                       ( *(Conf_info_p->error) ) ("command invalid in full page mode");
+               }
+               else {
+                       line = scroll(line, -9);
+               }
+               break;
+
+       case '\n':
+       case '\r':
+               if (pgnum >= 0) {
+                       /* ending page number command */
+                       if (getpginfo(pgnum) == YES) {
+                               ( *(Conf_info_p->draw) )  (0, Fullpgmode);
+                               line = 0;
+                       }
+                       else {
+                               ( *(Conf_info_p->error) ) ("invalid page number");
+                       }
+                       pgnum = -1;
+                       break;
+               }
+               /* else fall through to moving forward on page*/
+               /*FALLTHRU*/
+
+       case 'f':
+       case '\4':      /* control-D */
+       case '\16':     /* control-N */
+               /* forward an inch */
+               if (Fullpgmode) {
+                       ( *(Conf_info_p->error) ) ("command invalid in full page mode");
+               }
+               else {
+                       line = scroll(line, 72);
+               }
+               break;
+
+       case 'b':
+       case '\25':     /* control-U */
+       case '\20':     /* control-P */
+               /* back an inch */
+               if (Fullpgmode) {
+                       ( *(Conf_info_p->error) ) ("command invalid in full page mode");
+               }
+               else {
+                       line = scroll(line, -72);
+               }
+               break;
+
+       case 'h':
+       case '?':
+               /* display help screen */
+               ( *(Conf_info_p->bitmap) ) (Help_bitmap, Help_width, Help_height);
+               break;
+
+       case 'n':
+               /* go to next page */
+               if (Currpage_p->next != (struct Pginfo *) 0) {
+                       Currpage_p = Currpage_p->next;
+                       line = 0;
+                       ( *(Conf_info_p->draw) ) (line, Fullpgmode);
+               }
+               else {
+                       ( *(Conf_info_p->error) ) ("already at last page");
+               }
+               break;
+
+       case 'p':
+               /* go to previous page */
+               if (Currpage_p->prev != (struct Pginfo *) 0) {
+                       Currpage_p = Currpage_p->prev;
+                       line = 0;
+                       ( *(Conf_info_p->draw) ) (line, Fullpgmode);
+               }
+               else {
+                       ( *(Conf_info_p->error) ) ("already at first page");
+               }
+               break;
+
+       case 'q':
+               /* quit */
+               ( *(Conf_info_p->cleanup) )  (0);
+               break;
+
+       case 'r':
+               /* repaint current screen */
+               /* if redraw is because window was resized, make sure we don't
+                * run off the bottom */
+               if (line + Conf_info_p->vlines > LINES_PER_PAGE * Conf_info_p->adjust) {
+                       line = LINES_PER_PAGE * Conf_info_p->adjust - Conf_info_p->vlines;
+               }
+               ( *(Conf_info_p->draw) ) (line, Fullpgmode);
+               break;
+               
+       case 'z':
+               /* 2 Z's is symonym for quit, to match with common
+                * way to exit vi */
+               if (got1z) {
+                       ( *(Conf_info_p->cleanup) )  (0);
+               }
+               break;
+
+       case 'm':
+               /* switch between full page and scrolled modes */
+               Fullpgmode = (Fullpgmode == YES ? NO : YES);
+               line = 0;
+               ( *(Conf_info_p->draw) ) (line, Fullpgmode);
+               break;
+
+       default:
+               ( *(Conf_info_p->error) ) ("unknown command");
+               /* auto-help feature:
+                * if user puts in something illegal too many times in a row,
+                * figure they're confused and desperate, so give them the
+                * help screen */
+               if (lasterr == count - 1) {
+                       goofs++;
+                       if (goofs > 9) {
+                               ( *(Conf_info_p->bitmap) ) (Help_bitmap,
+                                               Help_width, Help_height);
+                               goofs = 0;
+                       }
+               }
+               else {
+                       goofs = 1;
+               }
+               lasterr = count;
+               break;
+       }
+
+       /* set flag if got Z, so can check for Z consecutive Z's for
+        * vi-style exit */
+       got1z = (c == 'Z' || c == 'z');
+}
diff --git a/mup/mupdisp/dos.c b/mup/mupdisp/dos.c
new file mode 100644 (file)
index 0000000..b609df6
--- /dev/null
@@ -0,0 +1,295 @@
+
+/* Copyright (c) 1995, 1998 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* Functions for displaying Mup/Ghostscript output on screen using
+ * Watcom C */
+
+#ifdef __WATCOMC__
+#include "mupdisp.h"
+#include <graph.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <conio.h>
+#include <fcntl.h>
+#include <io.h>
+
+/* hard code X and Y sizes for the moment */
+#define XSIZE          640
+#define YSIZE          480
+
+/* image to be calloc'ed has 6 header bytes, then each row consecutively */
+#define BITS2BYTES(bits)       (((bits) + 7) / 8)      /* round upwards */
+#define SIZEIMAGE      (6 + ((long)BITS2BYTES(XSIZE)*4) * (long)YSIZE)
+static char *Image;
+
+static void zapblock P((char *area, long size));
+\f
+
+/* initialize graphics driver, etc */
+
+void
+dos_setup()
+
+{
+       struct videoconfig vidinfo;
+
+
+       /* initalize best graphics mode */
+       if (_setvideomode(_VRES16COLOR) == 0) {
+               fprintf(stderr, "can't set graphics mode\n");
+               generalcleanup(1);
+       }
+
+       _getvideoconfig(&vidinfo);
+
+       if (vidinfo.numxpixels != XSIZE || vidinfo.numypixels != YSIZE) {
+               _setvideomode(_DEFAULTMODE);
+               fprintf(stderr, "video mode %dx%d not supported\n",
+                               vidinfo.numxpixels, vidinfo.numypixels);
+               generalcleanup(0);
+       }
+
+       /*
+        * Allocate the image buffer.  Note that both parameters must be less
+        * than 65536, but the total size (product) can be greater.  The +1
+        * is to allow room for the header bytes (and then some).
+        */
+       Image = (char *)calloc(BITS2BYTES(YSIZE)*4 + 1, XSIZE);
+       if (Image == NULL) {
+               _setvideomode(_DEFAULTMODE);
+               fprintf(stderr, "can't allocate image buffer\n");
+               generalcleanup(0);
+       }
+
+       /* set aspect ratio adjust */
+       Conf_info_p->adjust = 1.375 * (double) vidinfo.numypixels
+                                       / (double) vidinfo.numxpixels;
+       Conf_info_p->vlines = vidinfo.numypixels;
+
+       /* set screen to all white */
+       _setbkcolor(_BRIGHTWHITE);
+       _clearscreen(_GCLEARSCREEN);
+}
+\f
+
+/* before exiting, clean up graphics, then call the general cleanup routine */
+
+void
+dos_cleanup(int status)
+{
+        _setvideomode(_DEFAULTMODE);
+        generalcleanup(status);
+}
+\f
+
+/* draw a screen worth of the bitmap, starting at specified raster line */
+
+void
+dos_draw(line, small)
+
+int line;       /* start at this raster line */
+int small;      /* YES or NO for small or large page image */
+
+{
+       int r;                          /* row index */
+       long offset;                    /* into bitmap file */
+       int fd;                         /* file descriptor */
+       int himage_bytes;               /* horizontal image bytes */
+       char *row_ptr;                  /* point at a row of the image */
+       int n;                          /* loop variable */
+
+
+       /* make sure we have a valid page to draw */
+       if (Currpage_p == (struct Pginfo *) 0) {
+               ( *(Conf_info_p->error) ) ("page # out of range");
+               return;
+       }
+
+       /* figure out where in the bitmap file this page is */
+       offset = Currpage_p->seqnum * BYTES_PER_PAGE;
+       fd = gen1file(small);
+       lseek(fd, offset + (long)line * BYTES_PER_LINE, SEEK_SET);
+
+       /* zero out the image buffer */
+       zapblock(Image, SIZEIMAGE);
+
+       /* number of bytes representing one horizontal row in full page image */
+       himage_bytes = BITS2BYTES(XSIZE) * 4;
+
+       /* set the header bytes in the image */
+       Image[0] = XSIZE % 256;
+       Image[1] = XSIZE / 256;
+       Image[2] = YSIZE % 256;
+       Image[3] = YSIZE / 256;
+       Image[4] = 4;
+       Image[5] = 0;
+
+       /* set screen to all white */
+       _setbkcolor(_BRIGHTWHITE);
+       _clearscreen(_GCLEARSCREEN);
+
+       /* for each row */
+       for (r = 0; r < Conf_info_p->vlines; r++) {
+               /* read it directly into the image */
+               row_ptr = &Image[ 6 + r * himage_bytes ];
+               if (read(fd, row_ptr, BYTES_PER_LINE) != BYTES_PER_LINE) {
+                       break;
+               }
+
+               if (small) {
+                       /* black out the unused strip on the right */
+                       for (n = BITS_PER_LINE; n < XSIZE; n++)
+                               row_ptr[n/8] |= 1 << (7 - n%8);
+               }
+       }
+       /* put at upper left corner, (0, 0) */
+       _putimage(0, 0, Image, _GPSET);
+}
+\f
+
+/* for now we just beep on errors */
+/*ARGSUSED*/
+void
+dos_error(msg)
+
+char *msg;
+
+{
+       putc('\7', stderr);
+}
+\f
+
+/* for user interface, call command processor for each character read */
+
+void
+dos_user_interf()
+
+{
+       int c;
+       int special = 0;        /* 1 = got a null, which is first character
+                                * of special key sequence */
+       for ( ; ; ) {
+               c = getch();
+               if (c == '\0') {
+                       special = 1;
+                       continue;
+               }
+               if (special == 1) {
+                       switch (c) {
+                       case 0x49:
+                               /* PgUp key */
+                               c = 'p';
+                               break;
+                       case 0x51:
+                               /* PgDown key */
+                               c = 'n';
+                               break;
+                       case 0x48:
+                               /* Up arrow key */
+                               c = 'b';
+                               break;
+                       case 0x50:
+                               /* Down arrow key */
+                               c = 'f';
+                               break;
+                       default:
+                               special = 0;
+                               continue;
+                       }
+               }
+               do_cmd(c);
+               special = 0;
+       }
+}
+\f
+
+/* display a raster centered on window */
+
+void
+dos_raster(bitmap, width, height)
+
+unsigned char *bitmap;  /* what to display */
+int width, height;      /* of bitmap, width is in bytes */
+
+{
+       int r, c;       /* row and column indices */
+       int b;          /* index through bits */
+       int x, y;       /* upper left corner of where to put bitmap,
+                        * x in bytes */
+       int himage_bytes;       /* bytes needed for one row in image */
+       int n;          /* loop variable */
+       char *row_ptr;  /* point at a row of the image */
+
+
+       himage_bytes = 4 * width;
+
+       /* figure out how to center on screen */
+       x = (BYTES_PER_LINE - width) / 2 * 8;
+       y = (Conf_info_p->vlines - height) / 2;
+
+       /* zero out the image buffer */
+       zapblock(Image, SIZEIMAGE);
+
+       /* set the header bytes in the image */
+       Image[0] = (width * 8) % 256;
+       Image[1] = (width * 8) / 256;
+       Image[2] = height % 256;
+       Image[3] = height / 256;
+       Image[4] = 4;
+       Image[5] = 0;
+
+       /* for each row */
+       for (r = 0; r < height; r++) {
+               row_ptr = &Image[ 6 + r * himage_bytes ];
+               for (c = 0; c < width; c++) {
+                       for (b = 0; b < 8; b++) {
+                               if (bitmap[r*width+c] & (1 << (7-b))) {
+                                       /* white (15); set 4 copies of bit */
+                                       for (n = 0; n < 4; n++)
+                                               row_ptr[n*width + c] |=
+                                                       (1 << (7-b));
+                               } else {
+                                       /* black (8); set only the first */
+                                       row_ptr[c] |= (1 << (7-b));
+                               }
+                       }
+               }
+       }
+
+       _putimage(x, y, Image, _GPSET);
+}
+\f
+/* zero out a block of memory that may be bigger than 32K */
+
+#define        BLOCKSIZE       0x3fff
+
+static void
+zapblock(area, size)
+
+char *area;
+long size;
+
+{
+       long k;
+
+       /*
+        * memset's third parm is "unsigned int", so we can't do the whole
+        * area at once.
+        */
+       for (k = 0; k < size; k += BLOCKSIZE) {
+               if (size - k >= BLOCKSIZE)
+                       (void)memset(&area[k], 0, BLOCKSIZE);
+               else
+                       (void)memset(&area[k], 0, size - k);
+       }
+}
+
+#else
+
+/* some compilers don't like empty files, so if __WATCOMC__ isn't defined,
+ * put something here to keep those compilers happy */
+static short dummy;
+
+#endif
diff --git a/mup/mupdisp/genfile.c b/mup/mupdisp/genfile.c
new file mode 100644 (file)
index 0000000..e45669e
--- /dev/null
@@ -0,0 +1,422 @@
+
+/* Copyright (c) 1995, 1998, 1999, 2000, 2001 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions to generate the bitmap output file from the Mup input.
+ * Includes functions for running Mup to produce PostScript, and to run
+ * Ghostscript on the output of Mup */
+
+
+#ifdef __WATCOMC__
+#include <process.h>
+#include <errno.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "mupdisp.h"
+
+#ifdef unix
+#include <sys/wait.h>
+#endif
+
+/* bitmap for message to tell user to wait while we do our thing... */
+#include "waitmsg.bm"
+
+char Small_adjust[200]; /* PostScript instructions to add to get small
+                        * version of output (small enough for a whole page
+                        * to fit on the screen) */
+char Large_adjust[200]; /* PostScript instructions to add for the large,
+                        * scroll-able version of the output */
+double Reduction_factor;/* how to adjust for small version */
+char Papersize[32];    /* -sPAPERSIZE argument to Ghostscript */
+
+static void do_genfile P((int fd, int do_full));
+static void copyfile P((int srcfile, long start, long end, int destfile));
+static void genfile P((char *outfile, int do_full));
+\f
+
+/* generate one of the bitmap files if not already generated,
+ * either full or partial page based on value of fullpgmode.
+ * Return file descriptor of appropriate bitmap */
+
+int
+gen1file(fullpgmode)
+
+int fullpgmode;                /* if YES, generate full-page version */
+
+{
+       if (fullpgmode == YES) {
+               /* if bitmap file not already created, make it now */
+               if (Fullbitmaps <= 0) {
+                       Fullbitmaps = create_tmpfile(Fullfile);
+
+                       /* generate Postscript to scale and translate
+                        * output appropriately */
+                       sprintf(Small_adjust, "%f %f translate\n%f %f scale\n",
+                                       BITS_PER_LINE
+                                       * ((1.0 - Reduction_factor) / 2.0),
+                                       LINES_PER_PAGE - (LINES_PER_PAGE
+                                       * Reduction_factor
+                                       * Conf_info_p->adjust) - 4,
+                                       Reduction_factor,
+                                       Reduction_factor * Conf_info_p->adjust);
+
+                       /* tell user to wait */
+                       ( *(Conf_info_p->bitmap) ) (Waitmsg_bitmap,
+                                       Waitmsg_width, Waitmsg_height);
+                       /* generate the bitmap */
+                       genfile(Fullfile, YES);
+               }
+               close (Fullbitmaps);
+#ifdef O_BINARY
+               Fullbitmaps = open(Fullfile, O_RDONLY | O_BINARY, 0);
+#else
+               Fullbitmaps = open(Fullfile, O_RDONLY, 0);
+#endif
+               return(Fullbitmaps);
+       }
+       else {
+               /* if bitmap file not already created, make it now */
+               if (Partbitmaps <= 0) {
+                       Partbitmaps = create_tmpfile(Partfile);
+
+                       sprintf(Large_adjust, "%f %f translate\n%f %f scale\n",
+                                       0.0, (1.0 - Conf_info_p->adjust)
+                                       * LINES_PER_PAGE,
+                                       1.0, Conf_info_p->adjust);
+
+                       /* tell user to wait */
+                       ( *(Conf_info_p->bitmap) ) (Waitmsg_bitmap,
+                                       Waitmsg_width, Waitmsg_height);
+                       /* generate the bitmap */
+                       genfile(Partfile, NO);
+               }
+               close (Partbitmaps);
+#ifdef O_BINARY
+               Partbitmaps = open(Partfile, O_RDONLY | O_BINARY, 0);
+#else
+               Partbitmaps = open(Partfile, O_RDONLY, 0);
+#endif
+               return(Partbitmaps);
+       }
+}
+\f
+
+/* generate a file containing bitmap representations of pages */
+
+static void
+genfile(outfile, do_full)
+
+char *outfile;          /* put bitmaps in this file */
+int do_full;            /* YES if to do full version of page */
+
+{
+       char outfileopt[L_tmpnam+14];   /* space for -sOutputFile=outfile */
+       int ret;                /* return value from Ghostscript */
+       struct stat statinfo;
+#ifdef unix
+       int pip[2];     /* for pipe to gs */
+       int child;      /* Ghostscript's process ID */
+       
+
+       /* create a pipe to Ghostscript */
+       if (pipe(pip) != 0) {
+               Exit_errmsg = "can't set up pipe\n";
+               (*Conf_info_p->cleanup) (1);
+       }
+
+       /* execute Ghostscript */
+       switch (child = fork()) {
+       case 0:
+               /* connect its input to the pipe. Discard stdout and stderr */
+               close(0);
+               dup(pip[0]);
+               close(1);
+               dup(Nulldev);
+               close(2);
+               dup(Nulldev);
+               sprintf(outfileopt, "-sOutputFile=%s", outfile);
+               execlp("gs", "gs", "-sDEVICE=bit", Papersize, "-dQUIET",
+                                        outfileopt, "-", (char *) 0);
+               /*FALLTHRU*/
+       case -1:
+               Exit_errmsg = "can't exec Ghostscript";
+               (*Conf_info_p->cleanup) (1);
+               break;
+       default:
+               close(pip[0]);
+
+               /* generate the file */
+               do_genfile(pip[1], do_full);
+               close(pip[1]);
+
+               /* wait for Ghostscript to complete */
+               while ( wait(&ret) != child )
+                       ;
+               if (ret != 0 || stat(Gs_errfile, &statinfo) == 0) {
+                       Exit_errmsg = "Ghostscript failed\n";
+                       (*Conf_info_p->cleanup) (1);
+               }
+       }
+#else
+#ifdef __WATCOMC__
+       /* DOS can't do pipes, so use a temp file instead. */
+       int tmpf;
+       char pstmpfile[L_tmpnam];
+       static char message[128]; /* buffer for error message */
+
+
+       /* make a temp file for the modified PostScript */
+       tmpf = create_tmpfile(pstmpfile);
+       do_genfile(tmpf, do_full);
+       close(tmpf);
+
+       /* execute Ghostscript on the temp file */
+       sprintf(outfileopt, "-sOutputFile=%s", outfile);
+       ret = spawnlp(P_WAIT, "gs", "gs", "-sDEVICE=bit", Papersize,
+               "-dQUIET", "-dNOPAUSE", outfileopt, pstmpfile, (char *) 0);
+
+       if (ret != 0) {
+               /* try executing gs386 instead */
+               /**** probably should check for a specific return code ****/
+               ret = spawnlp(P_WAIT, "gs386", "gs386", "-sDEVICE=bit",
+                               Papersize, "-dQUIET", "-dNOPAUSE",
+                               outfileopt, pstmpfile, (char *) 0);
+       }
+
+       /* remove the temp file */
+        unlink(pstmpfile);
+       if (ret != 0 || stat(Gs_errfile, &statinfo) == 0) {
+               unlink(outfile);
+               if (ret == -1) {
+                       sprintf(message, "Ghostscript error %d (gs386 may be missing from your PATH?)\n", ret);
+               }
+               else {
+                       sprintf(message, "Ghostscript error %d\n", ret);
+               }
+               Exit_errmsg = message;
+               (*Conf_info_p->cleanup) (1);
+       }
+#else
+       Exit_errmsg = "unsupported platform\n";
+       (*Conf_info_p->cleanup) (1);
+#endif
+#endif
+}
+\f
+
+/* determine proper PAPERSIZE, and set parameter appropirately for that
+ * page size */
+
+/* table to translate width and height to PAPERSIZE name */
+struct PaperSizeInfo {
+       int x;          /* width, must be <= MAX_BITS_PER_LINE */
+       int y;          /* height, must be <= MAX_LINES_PER_PAGE */
+       char *sizename; /* name of paper size */
+       double reduction;       /* how much to multiply by in small mode */
+} Size_table[] = {
+       { 612, 792, "letter", 0.48 },   /* default has to be first */
+       { 540, 720, "note", 0.525 },
+       { 612, 1008, "legal", 0.375 },
+       { 595, 842, "a4", 0.46 },
+       { 421, 595, "a5", 0.65 },
+       { 297, 421, "a6", 0.8 },
+       { 612, 936, "flsa", 0.41 },
+       { 396, 612, "halfletter", 0.63 },
+       { 0, 0, (char *) 0 }
+};
+
+/* How many points away from a standard paper size we allow to
+ * account for roundoffs, since user was specifying in inches or cm
+ * rather than points, so they may be off somewhat */
+#define FUZZ   24
+
+void
+get_paper_size(x, y)
+
+int x, y;
+
+{
+       int i;
+
+       /* if we've already been called once, we're already done */
+       if (Papersize[0] == '-') {
+               return;
+       }
+
+       /* go through table till we find a standard size that matches */
+       for (i = 0; Size_table[i].x != 0; i++) {
+               if ( (x > Size_table[i].x - FUZZ)
+                               && (x < Size_table[i].x + FUZZ)
+                               && (y > Size_table[i].y - FUZZ)
+                               && (y < Size_table[i].y + FUZZ) ) {
+
+                       /* close enough to a standard size,
+                        * so we'll go with it */
+                       break;
+               }
+       }
+
+       if (Size_table[i].x == 0) {
+               /* if not found in table, use the default (letter) */
+               i = 0;
+       }
+
+       /* set appropriate parameters */
+       Bits_per_line = Size_table[i].x;
+       Lines_per_page = Size_table[i].y;
+       Bytes_per_line = (Bits_per_line >> 3) + ((Bits_per_line & 0x7) ? 1 : 0);
+       Reduction_factor = Size_table[i].reduction;
+       sprintf(Papersize, "-sPAPERSIZE=%s", Size_table[i].sizename);
+}
+\f
+
+/* generate bitmap from PostScript by calling Ghostscript */
+
+static void
+do_genfile(fd, do_full)
+
+int fd;                /* file descriptor to write to */
+int do_full;   /* if YES, do full page mode */
+
+{
+       struct Pginfo *pg_p;    /* for info about each page */
+       char errhandler[200];   /* PostScript error handler redefinition */
+
+
+       /* arrange to quit Ghostscript on errors (shouldn't get errors
+        * from Mup output, but could run out of memory, causing VMerror) */
+       sprintf(errhandler, "/handleerror { $error begin (%s) (w) file dup errorname 100 string cvs writestring (\\n) writestring end quit } def\n", Gs_errfile);
+       write(fd, errhandler, strlen(errhandler));
+
+       /* copy the prolog */
+       copyfile(Psfile, Beginprolog, Endprolog, fd);
+       
+       /* for each page add proper scaling, etc information */
+       for (pg_p = Pagehead; pg_p != (struct Pginfo *) 0;
+                                                       pg_p = pg_p->next) {
+               write(fd, "save\n", 5);
+               if (do_full == YES) {
+                       char tmpbuff[100];
+
+                       write(fd, "0.2 setgray\n", 12);
+                       sprintf(tmpbuff, "0 0 moveto 0 %d lineto %d %d lineto %d 0 lineto closepath fill\n",
+                                       Lines_per_page,
+                                       Bits_per_line,
+                                       Lines_per_page,
+                                       Bits_per_line);
+                       write(fd, tmpbuff, strlen(tmpbuff));
+
+                       write(fd, Small_adjust, strlen(Small_adjust));
+                       write(fd, "1 setgray\n", 10);
+                       write(fd, tmpbuff, strlen(tmpbuff));
+                       write(fd, "0 setgray\n", 10);
+               }
+               else {
+                       write(fd, Large_adjust, strlen(Large_adjust));
+               }
+
+               /* copy a page worth of PostScript */
+               copyfile(Psfile, pg_p->begin, pg_p->end, fd);
+               write(fd, "restore\n", 8);
+       }
+
+       /* finish up the Ghostscript input */
+       write(fd, "quit\n", 5);
+}
+\f
+
+/* copy a portion of one file descriptor to another file description */
+
+static void
+copyfile(srcfile, start, end, destfile)
+
+int srcfile;    /* read from this file */
+long start;     /* start at this offset in srcfile */
+long end;       /* go this far in srcfile */
+int destfile;   /* write to current position in this file */
+
+{
+       char buff[BUFSIZ];      /* buffer for copying */
+       int size;               /* how much to copy at once */
+       long remaining;         /* how much still to be copied */
+
+       /* go to specified spot in source file */
+       lseek(srcfile, start, SEEK_SET);
+
+       /* copy a block at a time, last piece will be wahatever is left */
+       for (remaining = end - start; remaining > 0L; remaining -= BUFSIZ) {
+               size = (remaining >= BUFSIZ ? BUFSIZ : remaining);
+               
+               if (read(srcfile, buff, size) == size) {
+                       if (write(destfile, buff, size) != size) {
+                               Exit_errmsg = "File write failed (probably out of disk space)\n";
+                               ( *(Conf_info_p)->cleanup) (1);
+                       }
+               }
+               else {
+                       Exit_errmsg = "Read failed\n";
+                       ( *(Conf_info_p)->cleanup) (1);
+               }
+       }
+}
+\f
+
+/* execute Mup, putting output in Psfile */
+
+void
+run_mup(argv)
+
+char **argv;    /* arguments to pass to Mup */
+
+{
+       int ret;
+       int child;
+
+
+#ifdef unix
+       switch(child = fork()) {
+       case 0:
+               /* arrange to put output in Psfile */
+               close(1);
+               dup(Psfile);
+
+               /* execute Mup */
+               execvp("mup", argv);
+               fprintf(stderr, "failed to execute Mup\n");
+               exit(1);
+       case -1:
+               fprintf(stderr, "failed to fork Mup\n");
+               generalcleanup(1);
+               /*NOTREACHED*/
+               break;
+       default:
+               /* wait for Mup to complete */
+               while (wait(&ret) != child)
+                       ;
+               if (ret != 0) {
+                       unlink(Mupfile);
+                       generalcleanup(ret);
+               }
+               break;
+       }
+#else
+#ifdef __WATCOMC__
+       /* arrange to put output in Psfile */
+       close(1);
+       dup(Psfile);
+
+       /* execute Mup */
+       if ((ret = spawnvp(P_WAIT, "mup", argv)) != 0) {
+               if (errno != 0) {
+                       perror("Mup failed");
+               }
+               unlink(Mupfile);
+               exit(ret);
+       } 
+#else
+       fprintf(stderr, "unsupported platform\n");
+#endif
+#endif
+}
diff --git a/mup/mupdisp/help.bm b/mup/mupdisp/help.bm
new file mode 100644 (file)
index 0000000..0fc2e18
--- /dev/null
@@ -0,0 +1,327 @@
+/* Copyright (c) 1995 by Arkkra Enterprises */
+/* All rights reserved */
+
+int Help_width = 64;
+int Help_height = 319;
+unsigned char Help_bitmap[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xc3, 0xe1, 0xff, 0xfe, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3e, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xe3, 0xf3, 0xff, 0xff, 0x9f, 0x1f, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xe1, 0xf7, 0xff, 0xff, 0x9f, 0x9f, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xe9, 0xf7, 0xff, 0xff, 0x9f, 0x9f, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x9f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xec, 0xf7, 0xff, 0xf3, 0x9d, 0xf8, 0xff, 0x07, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xf0, 0x7f, 0xff, 0x8f, 0xff, 0xff, 0xe3, 0xff, 0xfe, 0xcf, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xec, 0xe7, 0xff, 0xc7, 0x98, 0xf0, 0x07, 0x9f, 0x86, 0x31, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0x0f, 0xf9, 0xf8, 0x7f, 0x00, 0xf0, 0x3c, 0x03, 0x87, 0xfe, 0xce, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcc, 0x6f, 0xfe, 0x1f, 0x80, 0xfc, 0x67, 0x9e, 0x73, 0x89, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x9e, 0x4f, 0xf9, 0xf2, 0x7f, 0xc6, 0x67, 0x39, 0xce, 0x73, 0xfc, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x6f, 0xf8, 0x7f, 0x9c, 0xfc, 0xe7, 0x9e, 0x73, 0x9f, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x9c, 0xe7, 0xf9, 0xe7, 0x3f, 0xcf, 0x27, 0x39, 0xce, 0x73, 0xfc, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xde, 0x0f, 0xf9, 0xff, 0x9c, 0xdc, 0xe7, 0x9e, 0x01, 0x9f, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x9c, 0xe7, 0xf9, 0xe7, 0x3f, 0xcf, 0x38, 0x39, 0xce, 0x01, 0xfd, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xdf, 0x1f, 0xfc, 0x7f, 0x9f, 0xdc, 0xe7, 0x9c, 0x7f, 0x9f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3c, 0xe7, 0xf9, 0xe7, 0x3f, 0xcf, 0x33, 0x3c, 0x1c, 0x7f, 0xfd, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x9f, 0x1f, 0xff, 0x1f, 0x9f, 0x9c, 0xe7, 0x9a, 0x7f, 0x9f, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0xe7, 0xf9, 0xa7, 0x3f, 0xcf, 0x27, 0x38, 0xfe, 0x7f, 0xf9, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x9f, 0x9f, 0xff, 0xc3, 0x9f, 0x1c, 0xe7, 0x92, 0x3b, 0x9f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xfe, 0x4f, 0xf9, 0x32, 0x7f, 0xc6, 0x67, 0x3b, 0xfe, 0x3b, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xfe, 0x0f, 0x9f, 0xff, 0xf2, 0x00, 0x10, 0x41, 0x87, 0x06, 0x0f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0x1f, 0xf8, 0x78, 0xff, 0xc0, 0xf0, 0x88, 0x07, 0x07, 0xe0, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xf9, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xf3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xf1, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xfe, 0x00, 0xc1, 0xfc, 0x7f, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0x87, 0x18, 0xe7, 0xf8, 0x07, 0x81, 0xe0, 0x1c, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xc6, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xce, 0x73, 0x9b, 0xe7, 0xfe, 0x33, 0x39, 0xce, 0x73, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xc7, 0xe7, 0xfe, 0x79, 0x39, 0xce, 0x73, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x01, 0xc7, 0xe7, 0xfe, 0x79, 0xc1, 0xce, 0x70, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xcc, 0x7f, 0xc7, 0xe7, 0xfe, 0x79, 0x99, 0xe0, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x7f, 0xd3, 0xe6, 0xfe, 0x79, 0x39, 0xc7, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x3b, 0xb9, 0xe4, 0xfe, 0x33, 0x39, 0xdf, 0xf1, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x04, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x83, 0x06, 0x10, 0xe1, 0xfe, 0x07, 0x84, 0x40, 0x38, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0x9f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0x8e, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xfe, 0x08, 0x5f, 0xff, 0x1d, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1c, 0x63, 0x87, 0x1c, 0x0f, 0x86, 0x18, 0xf0, 0x3e, 0x01, 0xf0, 0x3c, 0x03, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xc6, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xcf, 0x12, 0x73, 0x9d, 0xcf, 0x27, 0x9c, 0xef, 0x3f, 0x8c, 0xe7, 0x39, 0xcc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0x3e, 0x73, 0x9d, 0xce, 0x73, 0x9c, 0xe3, 0x3f, 0x9e, 0x67, 0x39, 0xcc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0x3e, 0x01, 0x9b, 0xce, 0x73, 0x9c, 0xf0, 0x7f, 0x9e, 0x78, 0x39, 0xcc, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0x3c, 0x7f, 0xcb, 0xce, 0x73, 0x9c, 0xf8, 0x3f, 0x9e, 0x73, 0x3c, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0x3e, 0x7f, 0xc7, 0xce, 0x73, 0x9c, 0xef, 0xbf, 0x9e, 0x67, 0x38, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xc6, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xcf, 0x3e, 0x3b, 0xe7, 0xcf, 0x27, 0x98, 0xe7, 0xbf, 0x8c, 0xe7, 0x3b, 0xfc, 0x77, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1c, 0x1f, 0x07, 0xef, 0x07, 0x8f, 0xc4, 0x20, 0x7f, 0x81, 0xf0, 0x88, 0x06, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf9, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf1, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xdf, 0xff, 0xff, 0xff, 0x1f, 0xe0, 0xfe, 0x3f, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x1c, 0x3e, 0x06, 0x31, 0x81, 0x08, 0x43, 0xfc, 0x01, 0x8c, 0x60, 0x63, 0x86, 0x00, 0xf3, 0xfc, 0x03, 0xe0, 0x78, 0x06, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xc4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x93, 0x9d, 0xc7, 0x89, 0x39, 0xcc, 0xef, 0xf9, 0x19, 0xcf, 0x13, 0x12, 0x73, 0x8c, 0xf3, 0xff, 0x19, 0xce, 0x73, 0x99, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf3, 0x99, 0xc7, 0x9f, 0x39, 0xcc, 0x6f, 0xf3, 0xb9, 0xcf, 0x3f, 0x3e, 0x73, 0x9c, 0xf3, 0xff, 0x3c, 0xce, 0x73, 0x99, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf0, 0x09, 0xc7, 0x9f, 0xc1, 0xcc, 0x6f, 0xf3, 0xf9, 0xcf, 0x3f, 0x3e, 0x01, 0x9c, 0xf3, 0xff, 0x3c, 0xf0, 0x73, 0x98, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe3, 0xf9, 0xc7, 0x9f, 0x99, 0xe3, 0x1f, 0xf3, 0xf9, 0xcf, 0x3f, 0x3c, 0x7f, 0x9c, 0xf3, 0xff, 0x3c, 0xe6, 0x78, 0x31, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf3, 0xf9, 0xc7, 0x9f, 0x39, 0xe3, 0x1f, 0xf3, 0xd9, 0xcf, 0x3f, 0x3e, 0x7f, 0x9c, 0xf3, 0x7f, 0x3c, 0xce, 0x71, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf1, 0xdc, 0xc7, 0x9f, 0x39, 0xf3, 0x3f, 0xf9, 0xb9, 0x8f, 0x3f, 0x3e, 0x3b, 0x9c, 0xf2, 0x7f, 0x19, 0xce, 0x77, 0xf8, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xf8, 0x3e, 0x22, 0x0f, 0x84, 0x77, 0xbf, 0xf8, 0x7c, 0x40, 0x1c, 0x1f, 0x06, 0x08, 0x30, 0xff, 0x03, 0xe1, 0x10, 0x0c, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xe7, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xe3, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0x84, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xff, 0xe7, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xcd, 0xff, 0xe7, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xe7, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xc7, 0xf1, 0x9f, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xe7, 0xf0, 0x3f, 0xff, 0xfb, 0xff, 0xff, 0x02, 0x3b, 0xe7, 0x3f, 0xc7, 0xff, 0xff, 0xf1, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x00, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf8, 0x78, 0x06, 0x01, 0x9e, 0x1f, 0xf3, 0xf0, 0xff, 0x81, 0x80, 0x3e, 0x07, 0xfc, 0xc6, 0x38, 0x60, 0x10, 0x7f, 0xcc, 0x31, 0xe7, 0x3f, 0x80, 0x78, 0x1e, 0x01, 0xc3, 0xf8, 0x04, 0x1f, 0x0f, 0x81, 0xe1, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xc6, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf2, 0x73, 0x9c, 0xe7, 0x99, 0xcf, 0xf3, 0xe4, 0xff, 0x39, 0xe3, 0x3d, 0xc7, 0xfc, 0xf1, 0x32, 0x78, 0xc6, 0x7f, 0xcf, 0x39, 0xe7, 0x3f, 0xe3, 0x33, 0x9c, 0xe7, 0x39, 0xfe, 0x31, 0x9e, 0x4f, 0x71, 0x9c, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0x33, 0x9c, 0xe7, 0x99, 0xcf, 0xf3, 0xce, 0x7f, 0x39, 0xe7, 0x39, 0xc7, 0xfc, 0xf3, 0xe7, 0x39, 0xce, 0x7f, 0xcf, 0x39, 0xe7, 0x3f, 0xe7, 0x93, 0x9c, 0xe7, 0x39, 0xfe, 0x73, 0x9c, 0xe6, 0x71, 0x9c, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0x33, 0x9c, 0xe7, 0x98, 0x07, 0xf3, 0xce, 0x7f, 0xc1, 0xe7, 0x39, 0xc7, 0xfc, 0xf3, 0xe7, 0x39, 0xce, 0x7f, 0xcf, 0x39, 0xe7, 0x3f, 0xe7, 0x9c, 0x1c, 0xe7, 0x00, 0xfe, 0x73, 0x9c, 0xe6, 0x71, 0x80, 0x7f, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0x38, 0x3e, 0x0f, 0x91, 0xff, 0xf3, 0xce, 0x7f, 0x99, 0xe7, 0x39, 0xc7, 0xfc, 0xf3, 0xe7, 0x39, 0xce, 0x7f, 0xcf, 0x39, 0xe7, 0x3f, 0xe7, 0x99, 0x9e, 0x0e, 0x3f, 0xfe, 0x73, 0x9c, 0xe6, 0x71, 0x1f, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xa7, 0x31, 0xfc, 0x7f, 0x99, 0xff, 0xf3, 0x4e, 0x7f, 0x39, 0xe7, 0x39, 0xc7, 0xfc, 0xf3, 0xe7, 0x39, 0xce, 0x7f, 0xcf, 0x39, 0xe7, 0x3f, 0xe7, 0x93, 0x9c, 0x7f, 0x3f, 0xfe, 0x73, 0x9c, 0xe6, 0x71, 0x9f, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x32, 0x77, 0xfd, 0xff, 0x98, 0xef, 0xf2, 0x64, 0xff, 0x39, 0xe7, 0x3c, 0xc7, 0xfc, 0xf3, 0xf2, 0x79, 0xce, 0x7f, 0xcf, 0x31, 0xe7, 0x3f, 0xe3, 0x33, 0x9d, 0xff, 0x1d, 0xfe, 0x73, 0x9e, 0x4f, 0x31, 0x8e, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x78, 0xf0, 0x0c, 0x02, 0x0c, 0x1f, 0xf0, 0xf1, 0xff, 0x84, 0x02, 0x0e, 0x23, 0xf0, 0x41, 0xf8, 0xe0, 0x84, 0x1f, 0x07, 0x88, 0x00, 0x1f, 0xe0, 0x78, 0x44, 0x03, 0x83, 0xf8, 0x21, 0x07, 0x1f, 0x88, 0xc1, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcc, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xfc, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc9, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xf9, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x88, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xf8, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x3c, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x0f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x7c, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcf, 0x71, 0xff, 0xf8, 0xff, 0xff, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0xff, 0x8f, 0xff, 0xcf, 0xff, 0xf1, 0xc7, 0xff, 0xff, 0xfc, 0x1d, 0xff, 0xfc, 0xfe, 0x3f, 0xff, 0xff, 0xc7, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xfc, 0x7f, 0xc8, 0x21, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x70, 0x0c, 0x70, 0xf3, 0xcc, 0x20, 0x0f, 0x00, 0xff, 0x07, 0x0c, 0x02, 0x0c, 0x02, 0x0f, 0x03, 0x00, 0x7c, 0x0e, 0x07, 0xf3, 0x80, 0x78, 0x18, 0xc6, 0x70, 0xf0, 0x3c, 0xfc, 0x03, 0xe0, 0x78, 0x06, 0x1f, 0xc0, 0x20, 0xf8, 0x7c, 0x0f, 0x87, 0xfe, 0x18, 0x03, 0xcc, 0x63, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xde, 0x64, 0x62, 0x64, 0xf3, 0xcf, 0x38, 0xce, 0x73, 0xfe, 0x46, 0x4f, 0x18, 0xcf, 0x18, 0xce, 0x73, 0xc6, 0x7b, 0x8d, 0xe7, 0xf3, 0xe3, 0x33, 0x9e, 0x26, 0x7c, 0xe7, 0x3c, 0xff, 0x19, 0xce, 0x73, 0x99, 0xcf, 0xf1, 0x8c, 0xf2, 0x7b, 0x8e, 0x73, 0xfc, 0x9e, 0x33, 0xce, 0x77, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc6, 0x4e, 0xe7, 0xce, 0x73, 0xcf, 0x39, 0xce, 0x73, 0xfc, 0xec, 0xe7, 0x39, 0xcf, 0x39, 0xce, 0x73, 0xce, 0x73, 0x8c, 0x67, 0xf3, 0xe7, 0x93, 0x9e, 0x7e, 0x7c, 0xe7, 0x3c, 0xff, 0x3c, 0xce, 0x73, 0x99, 0xcf, 0xf3, 0x9c, 0xe7, 0x33, 0x8e, 0x73, 0xf9, 0xce, 0x73, 0xce, 0x77, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xcf, 0xe7, 0xce, 0x73, 0xcf, 0x39, 0xce, 0x73, 0xfc, 0xfc, 0xe7, 0x39, 0xcf, 0x39, 0xcf, 0x83, 0xce, 0x73, 0x8e, 0x0f, 0xf3, 0xe7, 0x9c, 0x1e, 0x7e, 0x7c, 0xf8, 0x3c, 0xff, 0x3c, 0xf0, 0x73, 0x98, 0x07, 0xf3, 0x9c, 0xe7, 0x33, 0x8e, 0x01, 0xf9, 0xce, 0x73, 0xcf, 0x2f, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x4f, 0xe7, 0xce, 0x73, 0xcf, 0x39, 0xcf, 0x07, 0xfc, 0xfc, 0xe7, 0x39, 0xcf, 0x39, 0xcf, 0x33, 0xce, 0x73, 0x8f, 0x07, 0xf3, 0xe7, 0x99, 0x9e, 0x7e, 0x7c, 0xf3, 0x3c, 0xff, 0x3c, 0xe6, 0x78, 0x31, 0xff, 0xf3, 0x9c, 0xe7, 0x33, 0x8c, 0x7f, 0xf9, 0xce, 0x73, 0xcf, 0x2f, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x4f, 0x67, 0xce, 0x73, 0xcf, 0x39, 0xce, 0x3f, 0xfc, 0xf4, 0xe7, 0x39, 0xcf, 0x39, 0xce, 0x73, 0xce, 0x73, 0x8d, 0xf7, 0xf3, 0xe7, 0x93, 0x9e, 0x7e, 0x6c, 0xe7, 0x3c, 0xff, 0x3c, 0xce, 0x71, 0xf9, 0xff, 0xf3, 0x9c, 0xe7, 0x33, 0x8e, 0x7f, 0xf9, 0xce, 0x73, 0xcf, 0x0f, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x66, 0xe7, 0xe4, 0xf3, 0xcf, 0x39, 0xce, 0xff, 0xfe, 0x6e, 0x4f, 0x39, 0xcf, 0x39, 0xce, 0x73, 0xce, 0x79, 0x8c, 0xf7, 0xf9, 0xe3, 0x33, 0x9e, 0x7e, 0x4c, 0xe7, 0x3c, 0xff, 0x19, 0xce, 0x77, 0xf8, 0xef, 0xf3, 0x9c, 0xf2, 0x79, 0x8e, 0x3b, 0xfc, 0x9e, 0x73, 0xcf, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xe1, 0x83, 0xf1, 0xc1, 0x04, 0x00, 0x82, 0x01, 0xfe, 0x1f, 0x1c, 0x10, 0x80, 0x10, 0x83, 0x08, 0x04, 0x1c, 0x44, 0x0f, 0xf9, 0xe0, 0x78, 0x40, 0x3e, 0x10, 0x70, 0x80, 0x7f, 0x03, 0xe1, 0x10, 0x0c, 0x1f, 0xc1, 0x08, 0x38, 0xfc, 0x47, 0x07, 0xfe, 0x38, 0x20, 0x07, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x79, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xe7, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xbf, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x71, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xe3, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xef, 0xff, 0xf9, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xf7, 0xfe, 0x1f, 0xee, 0x0f, 0xf9, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xfe, 0x1f, 0xc9, 0xc7, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x9f, 0xd9, 0xe7, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xfe, 0x3b, 0xc1, 0xff, 0x9f, 0xd8, 0xe7, 0xfb, 0xc7, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xf3, 0xff, 0xe1, 0x8c, 0x7f, 0xf1, 0xe0, 0x00, 0x78, 0x1f, 0x07, 0x0f, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf0, 0xc6, 0x02, 0x10, 0xc0, 0xc6, 0x38, 0x1f, 0xe0, 0x70, 0x1f, 0x0c, 0x31, 0xe7, 0xff, 0x9f, 0x9c, 0x0f, 0xe1, 0x80, 0x3e, 0x0c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xf3, 0xff, 0xc9, 0xe2, 0x7f, 0x87, 0xde, 0x63, 0x33, 0x9e, 0x44, 0xe7, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe4, 0xf1, 0x33, 0x3b, 0x9c, 0xf1, 0x37, 0x1f, 0xce, 0x71, 0x8e, 0x4f, 0x39, 0xe7, 0xff, 0x9f, 0xbe, 0x0f, 0xf9, 0xe3, 0x3c, 0x8c, 0x67, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xf3, 0xff, 0x9c, 0xe7, 0xfe, 0x1f, 0xc6, 0x67, 0x93, 0x9c, 0xec, 0xe7, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf3, 0x1b, 0x9c, 0xf3, 0xe7, 0x1f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0x3c, 0x07, 0xf9, 0xe7, 0x39, 0xdc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x80, 0x3f, 0x9c, 0xe7, 0xfe, 0x7f, 0xe0, 0xe7, 0x9c, 0x1c, 0xfc, 0x03, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf3, 0x1b, 0xe0, 0xf3, 0xe7, 0x1f, 0xf0, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0x79, 0xe3, 0xf9, 0xe7, 0x39, 0xfc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xf3, 0xff, 0x9c, 0xe7, 0xff, 0x1f, 0xf0, 0x67, 0x99, 0x9c, 0xf8, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf8, 0xc7, 0xcc, 0xf3, 0xe7, 0x1f, 0xe6, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0x73, 0xf3, 0xf9, 0xe7, 0x39, 0xfc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xf3, 0xff, 0x9c, 0xe7, 0xff, 0xc7, 0xdf, 0x67, 0x93, 0x9c, 0xf4, 0xff, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf8, 0xc7, 0x9c, 0xf3, 0xe7, 0x1f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe6, 0xff, 0x9e, 0x73, 0xf3, 0xf9, 0xe7, 0x39, 0xec, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xf3, 0xff, 0xc9, 0xe7, 0xff, 0xf0, 0xcf, 0x63, 0x33, 0x9e, 0x6c, 0x76, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe4, 0xf3, 0xfc, 0xcf, 0x9c, 0xf3, 0xf3, 0x1f, 0xce, 0x71, 0x9e, 0x4f, 0x31, 0xe4, 0xff, 0x9e, 0xf9, 0xe7, 0xf9, 0xe7, 0x3c, 0xdc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xf3, 0xff, 0xe3, 0x83, 0xff, 0xfc, 0xc0, 0xe0, 0x78, 0x46, 0x1e, 0x0e, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xf1, 0xc1, 0xfd, 0xef, 0xc2, 0x01, 0xf8, 0x8f, 0xe1, 0x14, 0x3f, 0x1f, 0x88, 0x61, 0xfe, 0x02, 0xfc, 0x0f, 0xe0, 0x82, 0x0c, 0x30, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xef, 0xff, 0xf9, 0xff, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xf7, 0xfe, 0x1f, 0xee, 0x0f, 0xf9, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xfe, 0x1f, 0xc9, 0xc7, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x9f, 0xd9, 0xe7, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x9f, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xfe, 0x3b, 0xc1, 0xff, 0x9f, 0xd8, 0xe7, 0xfb, 0x8f, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x18, 0xff, 0xe3, 0x80, 0xf0, 0x3e, 0x0c, 0x87, 0x02, 0x01, 0xe0, 0x7c, 0x1c, 0x3c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x1e, 0x07, 0xc1, 0x90, 0xc2, 0x10, 0x81, 0x8c, 0x70, 0x3f, 0xe0, 0x70, 0x1f, 0x0c, 0x31, 0xe7, 0xff, 0x9f, 0x9c, 0x0f, 0xe1, 0x00, 0x7c, 0x18, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x93, 0xc4, 0xff, 0x0f, 0x8c, 0x67, 0x3c, 0x8c, 0xde, 0xf3, 0x8c, 0xce, 0x79, 0x13, 0x9f, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8c, 0xe7, 0x91, 0x9b, 0xf3, 0x3b, 0x39, 0xe2, 0x6e, 0x3f, 0xce, 0x71, 0x8e, 0x4f, 0x39, 0xe7, 0xff, 0x9f, 0xbe, 0x0f, 0xf9, 0xc6, 0x79, 0x18, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xcf, 0xfc, 0x3f, 0x9e, 0x67, 0x39, 0xdc, 0xbe, 0x33, 0x9e, 0x4e, 0x73, 0xb3, 0x9f, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcc, 0xe7, 0x3b, 0x97, 0xf3, 0x1b, 0x39, 0xe7, 0xce, 0x3f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0x3c, 0x07, 0xf9, 0xce, 0x73, 0xb9, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x00, 0x00, 0x3f, 0x39, 0xcf, 0xfc, 0xff, 0x9e, 0x78, 0x39, 0xfc, 0x1f, 0x07, 0x9e, 0x70, 0x73, 0xf0, 0x0f, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcf, 0x07, 0x3f, 0x83, 0xf3, 0x1b, 0xc1, 0xe7, 0xce, 0x3f, 0xf0, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0x79, 0xe3, 0xf9, 0xce, 0x73, 0xf9, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xcf, 0xfe, 0x3f, 0x9e, 0x73, 0x39, 0xfc, 0x9f, 0x83, 0x9e, 0x66, 0x73, 0xe3, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xce, 0x67, 0x3f, 0x93, 0xf8, 0xc7, 0x99, 0xe7, 0xce, 0x3f, 0xe6, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0x73, 0xf3, 0xf9, 0xce, 0x73, 0xf9, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xcf, 0xff, 0x8f, 0x9e, 0x67, 0x39, 0xec, 0xce, 0xfb, 0x9e, 0x4e, 0x73, 0xd3, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcc, 0xe7, 0x3d, 0x99, 0xf8, 0xc7, 0x39, 0xe7, 0xce, 0x3f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe6, 0xff, 0x9e, 0x73, 0xf3, 0xf9, 0xce, 0x73, 0xd9, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x93, 0xcf, 0xff, 0xe1, 0x8c, 0xe7, 0x3c, 0xdc, 0xe6, 0x7b, 0x8c, 0xce, 0x79, 0xb1, 0xd8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x9c, 0xe7, 0x9b, 0x9c, 0xfc, 0xcf, 0x39, 0xe7, 0xe6, 0x3f, 0xce, 0x71, 0x9e, 0x4f, 0x31, 0xe4, 0xff, 0x9e, 0xf9, 0xe7, 0xf9, 0xce, 0x79, 0xb9, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x07, 0xff, 0xf9, 0xa1, 0xf0, 0x8c, 0x30, 0x42, 0x07, 0x81, 0xe1, 0x18, 0x78, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x3e, 0x11, 0x86, 0x08, 0x7d, 0xef, 0x84, 0x03, 0xf1, 0x1f, 0xe1, 0x14, 0x3f, 0x1f, 0x88, 0x61, 0xfe, 0x02, 0xfc, 0x0f, 0xe0, 0x04, 0x18, 0x60, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xfc, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcc, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf8, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xf7, 0xfe, 0x1f, 0xfc, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcd, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0xff, 0x9c, 0xef, 0xc7, 0xf8, 0x3f, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xfe, 0x3b, 0xc1, 0xff, 0x9f, 0xfd, 0xe3, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xfc, 0x31, 0x8f, 0xfe, 0x3c, 0xc7, 0x80, 0x3c, 0xfc, 0x31, 0x8c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf0, 0xc6, 0x02, 0x10, 0xc0, 0xc6, 0x38, 0x1f, 0xe0, 0x70, 0x1f, 0x0c, 0x31, 0xe7, 0xff, 0x9f, 0xf0, 0xc0, 0x1f, 0x06, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xf9, 0x3c, 0x4f, 0xf0, 0xfc, 0x07, 0xe3, 0x3c, 0xf3, 0x9c, 0x4f, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe4, 0xf1, 0x33, 0x3b, 0x9c, 0xf1, 0x37, 0x1f, 0xce, 0x71, 0x8e, 0x4f, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xf1, 0x9e, 0x46, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xf3, 0x9c, 0xff, 0xc3, 0xfc, 0xe7, 0xe7, 0x3c, 0xf3, 0x9c, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf3, 0x1b, 0x9c, 0xf3, 0xe7, 0x1f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xf3, 0x9c, 0xee, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xf3, 0x9c, 0xff, 0xcf, 0xfc, 0xe6, 0xe7, 0x3c, 0xf0, 0x0c, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf3, 0x1b, 0xe0, 0xf3, 0xe7, 0x1f, 0xf0, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xf3, 0x9c, 0xfe, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xf3, 0x9c, 0xff, 0xe3, 0xfc, 0xfe, 0xe7, 0x3c, 0xe3, 0xfc, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf8, 0xc7, 0xcc, 0xf3, 0xe7, 0x1f, 0xe6, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xf3, 0x9c, 0xfe, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xf3, 0x9c, 0xff, 0xf8, 0xfc, 0xfc, 0xe7, 0x3c, 0xd3, 0xfc, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf8, 0xc7, 0x9c, 0xf3, 0xe7, 0x1f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe6, 0xff, 0x9f, 0xfc, 0xf3, 0x9c, 0xf6, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xf9, 0x3c, 0xff, 0xfe, 0x1c, 0xf8, 0xe7, 0x3c, 0x91, 0xdc, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe4, 0xf3, 0xfc, 0xcf, 0x9c, 0xf3, 0xf3, 0x1f, 0xce, 0x71, 0x9e, 0x4f, 0x31, 0xe4, 0xff, 0x9f, 0xfc, 0xf3, 0x9e, 0x6e, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x07, 0xfc, 0x70, 0x7f, 0xff, 0x90, 0x00, 0x82, 0x0c, 0x38, 0x30, 0x79, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xf1, 0xc1, 0xfd, 0xef, 0xc2, 0x01, 0xf8, 0x8f, 0xe1, 0x14, 0x3f, 0x1f, 0x88, 0x61, 0xfe, 0x03, 0xf0, 0x41, 0x06, 0x18, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xfc, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xf7, 0xfe, 0x1f, 0xfc, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xfe, 0x3b, 0xc1, 0xff, 0x9f, 0xfd, 0xc7, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x1e, 0x07, 0xc1, 0x90, 0xc2, 0x10, 0x81, 0x8c, 0x70, 0x3f, 0xe0, 0x70, 0x1f, 0x0c, 0x31, 0xe7, 0xff, 0x9f, 0xf0, 0x80, 0x3e, 0x0c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x8c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8c, 0xe7, 0x91, 0x9b, 0xf3, 0x3b, 0x39, 0xe2, 0x6e, 0x3f, 0xce, 0x71, 0x8e, 0x4f, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xe3, 0x3c, 0x8c, 0x67, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x9e, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcc, 0xe7, 0x3b, 0x97, 0xf3, 0x1b, 0x39, 0xe7, 0xce, 0x3f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xe7, 0x39, 0xdc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x9e, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcf, 0x07, 0x3f, 0x83, 0xf3, 0x1b, 0xc1, 0xe7, 0xce, 0x3f, 0xf0, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xe7, 0x39, 0xfc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x9e, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xce, 0x67, 0x3f, 0x93, 0xf8, 0xc7, 0x99, 0xe7, 0xce, 0x3f, 0xe6, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xe7, 0x39, 0xfc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x9e, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcc, 0xe7, 0x3d, 0x99, 0xf8, 0xc7, 0x39, 0xe7, 0xce, 0x3f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe6, 0xff, 0x9f, 0xfc, 0xe7, 0x39, 0xec, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x9c, 0xe7, 0x9b, 0x9c, 0xfc, 0xcf, 0x39, 0xe7, 0xe6, 0x3f, 0xce, 0x71, 0x9e, 0x4f, 0x31, 0xe4, 0xff, 0x9f, 0xfc, 0xe7, 0x3c, 0xdc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xa1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x3e, 0x11, 0x86, 0x08, 0x7d, 0xef, 0x84, 0x03, 0xf1, 0x1f, 0xe1, 0x14, 0x3f, 0x1f, 0x88, 0x61, 0xfe, 0x03, 0xf0, 0x02, 0x0c, 0x30, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x01, 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf1, 0x9e, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xf3, 0xbe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xe3, 0xbc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x77, 0xde, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xe0, 0x7f, 0xc3, 0x18, 0xff, 0xcf, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x08, 0x63, 0x0f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcc, 0x7f, 0x93, 0xc4, 0xff, 0x8f, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x8e, 0x73, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x9e, 0x7f, 0x39, 0xcf, 0xff, 0x1f, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xce, 0x73, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x9e, 0x7f, 0x39, 0xcf, 0xff, 0x3d, 0xe7, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xce, 0x73, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x9e, 0x7f, 0x39, 0xcf, 0xfe, 0x3c, 0xc7, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xce, 0x73, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x9e, 0x7f, 0x39, 0xcf, 0xfe, 0x7c, 0xcf, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xce, 0x73, 0xcf, 0x37, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcc, 0x7f, 0x93, 0xcf, 0xfc, 0xf9, 0x9f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x8e, 0x63, 0xcf, 0x27, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xc2, 0x7f, 0xc7, 0x07, 0xf8, 0x01, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x4f, 0x10, 0x07, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xfc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xfc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xfe, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x9c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xc0, 0x7f, 0xe1, 0x8c, 0x7f, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0f, 0x87, 0x98, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xc6, 0x7f, 0xc9, 0xe2, 0x7f, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xce, 0x73, 0x9e, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x7f, 0x9c, 0xe7, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0x9e, 0x79, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x7f, 0x9c, 0xe7, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x01, 0x9e, 0x79, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x7f, 0x9c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xcc, 0x7f, 0x9e, 0x79, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x7f, 0x9c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x7f, 0x9e, 0x79, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xce, 0x7f, 0xc9, 0xe7, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x3b, 0x9e, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0x04, 0x1f, 0xe3, 0x83, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x83, 0x06, 0x0e, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
diff --git a/mup/mupdisp/init.c b/mup/mupdisp/init.c
new file mode 100644 (file)
index 0000000..0c34321
--- /dev/null
@@ -0,0 +1,195 @@
+
+/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2002 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* initialization table and routine for Mup/Ghostscript display program */
+
+/* when adding support for additional terminal types, you will need to
+ * add the declarations of relevant functions and add an entry to the
+ * Config table */
+
+
+#include <string.h>
+#include <stdlib.h>
+#include "mupdisp.h"
+
+/* declare the functions, etc for each supported terminal type */
+
+#ifdef XWINDOW
+extern void parse_X_options P((void));
+extern void xterm_setup P((void));
+extern void xterm_cleanup P((int status));
+extern void xterm_draw P((int line, int small));
+extern void xterm_user_interf P((void));
+extern void xterm_error P((char *msg));
+extern void xterm_raster P((unsigned char *bitmap, int width, int height));
+#define XVIDLINES       (400)   /* request 400 lines when in 640x480 mode */
+#endif
+
+#if defined(AT386) && ! defined(__DOS__)
+extern void at386_setup P((void));
+extern void at386_cleanup P((int status));
+extern void at386_draw P((int line, int small));
+extern void at386_user_interf P((void));
+extern void at386_error P((char *msg));
+extern void at386_raster P((unsigned char *bitmap, int width, int height));
+#define VIDLINES        (350)   /* for 640x350 display mode */
+#endif
+
+#if defined(linux) && ! defined(NO_VGA_LIB)
+extern void vgalib_setup P((void));
+extern void vgalib_cleanup P((int status));
+extern void vgalib_draw P((int line, int small));
+extern void vgalib_user_interf P((void));
+extern void vgalib_error P((char *msg));
+extern void vgalib_raster P((unsigned char *bitmap, int width, int height));
+#define LINVGAVIDLINES        (480)   /* for 640x480 display mode */
+#endif
+
+#ifdef __WATCOMC__
+extern void dos_setup P((void));
+extern void dos_cleanup P((int status));
+extern void dos_draw P((int line, int small));
+extern void dos_user_interf P((void));
+extern void dos_error P((char *msg));
+extern void dos_raster P((unsigned char *bitmap, int width, int height));
+/* video lines determined at run time */
+#endif
+\f
+
+
+/* list of supported $TERM types and which functions and parameters to use
+ * to implement them. To support a new terminal type, write appropriate
+ * functions, and add to the Config table.
+ */
+struct CONFIG Config [] = {
+
+#if defined(AT386) && ! defined(__DOS__)
+       {
+               "AT386",                /* terminal type name */
+               at386_setup,            /* setup function */
+               at386_cleanup,          /* cleanup function */
+               at386_draw,             /* function for drawing a screen full of bits */
+               at386_user_interf,      /* function to read user input and call do_cmd on it */
+               at386_error,            /* error reporting function */
+               at386_raster,           /* function to display a raster bitmap centered on screen */
+               VIDLINES,               /* screen vertical lines */
+               0.75                    /* aspect ratio */
+       },
+#endif
+
+#ifdef XWINDOW
+       {
+               "xterm",                /* terminal type name */
+               xterm_setup,            /* setup function */
+               xterm_cleanup,          /* cleanup function */
+               xterm_draw,             /* function for drawing a screen full of bits */
+               xterm_user_interf,      /* function to read user input and call do_cmd on it */
+               xterm_error,            /* error reporting function */
+               xterm_raster,           /* function to display a raster bitmap centered on screen */
+               XVIDLINES,              /* screen vertical lines */
+               1.0                     /* aspect ratio */
+       },
+#endif
+
+#if defined(linux) && ! defined(NO_VGA_LIB)
+       {
+               "linux",                /* terminal type name */
+               vgalib_setup,           /* setup function */
+               vgalib_cleanup,         /* cleanup function */
+               vgalib_draw,            /* function for drawing a screen full of bits */
+               vgalib_user_interf,     /* function to read user input and call do_cmd on it */
+               vgalib_error,           /* error reporting function */
+               vgalib_raster,          /* function to display a raster bitmap centered on screen */
+               LINVGAVIDLINES,         /* screen vertical lines */
+               1.0                     /* aspect ratio */
+       },
+
+#endif
+#ifdef __WATCOMC__
+       {
+               "DOS",                  /* terminal type name */
+               dos_setup,              /* setup function */
+               dos_cleanup,            /* cleanup function */
+               dos_draw,               /* function for drawing a screen full of bits */
+               dos_user_interf,        /* function to read user input and call do_cmd on it */
+               dos_error,              /* error reporting function */
+               dos_raster,             /* function to display a raster bitmap centered on screen */
+               0,                      /* screen vertical lines--will get set at run time */
+               0.0                     /* aspect ratio adjust--will get set at run time */
+       }
+#endif
+};
+\f
+
+/* initialize. Make sure TERM is supported, and set up for it. */
+
+void
+init()
+
+{
+       struct CONFIG *c_p;     /* terminal configuration info */
+       char *termname;         /* $TERM */
+       int numtypes;
+#ifdef XWINDOW
+       struct CONFIG *xwindow_conf_p = 0;      /* info for running under X */
+#endif
+
+
+#ifdef __WATCOMC__
+       termname = "DOS";
+#else
+       if ((termname = getenv("TERM")) == NULL) {
+               fprintf(stderr, "can't determine $TERM\n");
+               generalcleanup(1);
+       }
+#endif
+
+       /* find appropriate functions to use based on terminal type */
+       numtypes = sizeof(Config) / sizeof(struct CONFIG);
+       for (c_p = Config; numtypes > 0; c_p++, numtypes--) {
+               if (strcmp(c_p->termname, termname) == 0) {
+                       Conf_info_p = c_p;
+                       break;
+               }
+#ifdef XWINDOW
+               /* save the xwindow config. If we don't find a
+                * matching terminal type here, we're try some other
+                * tricks later to guess if we're running under X */
+               if (strcmp(c_p->termname, "xterm") == 0) {
+                       xwindow_conf_p = c_p;
+               }
+#endif
+       }
+
+#ifdef XWINDOW
+       if (Conf_info_p == (struct CONFIG *) 0) {
+               /* There can be several variations on xterm, so
+                * if $TERM at least starts with xterm, consider that
+                * good enough to try. And to try even harder to
+                * recognize if we're probably running under X, and
+                * thus the 'xterm' type will probably work, check if
+                * $DISPLAY is set. Chances are, if it is, we're probably
+                * in X. If it turns out we're not, we'll fail eventually,
+                * but we will have at least tried pretty hard
+                * to find something that would work... */
+               if (strncmp(termname, "xterm", 5) == 0 ||
+                               getenv("DISPLAY") != (char *) 0) {
+                       Conf_info_p = xwindow_conf_p;
+               }
+       }
+#endif
+
+       /* Make sure we managed to find a $TERM we can work with */
+       if (Conf_info_p == (struct CONFIG *) 0 ) {
+               fprintf(stderr, "$TERM type not supported\n");
+               generalcleanup(1);
+       }
+
+#ifdef XWINDOW
+       /* X has some extra options, so handle them */
+       if (strcmp(Conf_info_p->termname, "xterm") == 0) {
+               parse_X_options();
+       }
+#endif
+}
diff --git a/mup/mupdisp/linvga.c b/mup/mupdisp/linvga.c
new file mode 100644 (file)
index 0000000..20ac83a
--- /dev/null
@@ -0,0 +1,357 @@
+
+/* Copyright (c) 1997, 1998, 1999, 2000, 2002 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* Functions to support displaying multipage bitmap
+ * (as from Ghostscript -sDEVICE=bit) using Linux svgalib.
+ * This was derived from the AT386 version, so maybe some things
+ * would have been done a bit differently if it were written from
+ * scratch for Linux, but this seems to work fine and to be
+ * plenty fast enough (at least on a Pentium or better ;-)
+ *
+ * Note that using mupdisp in non-X-window mode on Linux requires that it
+ * can write to the console device. To allow this, make mupdisp setuid to root:
+ *     chown root mupdisp
+ *     chmod 4755 mupdisp
+ */
+
+#if defined(linux) && ! defined(NO_VGA_LIB)
+
+
+#include "mupdisp.h"
+
+#include <stdio.h>
+#include <vga.h>
+#include <termio.h>
+#include <sys/kd.h>
+#include <sys/ioctl.h>
+
+#define BPL            (80)    /* bytes per line on screen */
+
+int Orig_video_mode;
+struct termio Orig_ttyinfo;    /* to put keyboard back from raw mode */
+unsigned char Savefont[8192];  /* to put font back when we are done */
+int Console;
+
+static char *explanation =
+"\n\
+Note: The libvga used by this program\n\
+requires write permissions to /dev/console.\n\
+\n\
+The best way to enable that is to do the following (as root):\n\
+\tchown root mupdisp\n\
+\tchmod 4755 mupdisp\n\
+This makes mupdisp \"set user id\" to root.\n\
+\n\
+An alternate method would be to make /dev/console writeable by all:\n\
+\tchmod 666 /dev/console\n\
+but that method would pose a security risk, so it is not recommended.\n\n";
+static void setup_keyboard P((void));
+static void fix_keyboard P((void));
+\f
+
+/* set up for svgalib. Put video and keyboard in proper mode */
+
+void
+vgalib_setup()
+
+{
+       register int n;                 /* for setting signal catching */
+
+
+       /* will need to put keyboard into raw mode, save current state */
+       if (ioctl(0, TCGETA, &Orig_ttyinfo) < 0) {
+               (void) fprintf(stderr, "failed to get tty info\n");
+               generalcleanup(1);
+       }
+
+       /* some version of vgalib apparently do an atexit() call that causes
+        * the stty to be put in noecho mode. So arrange to undo that. */
+       atexit(fix_keyboard);
+
+       /* For some reason, vga_puttextmode doesn't seem to work on my
+        * system, but using the *IO_FONT ioctls does, so go with that.
+        * Save the current console font. */
+       if ((Console = open("/dev/console", 0)) < 0) {
+               (void) fprintf(stderr, "can't open /dev/console\n");
+               (void) fprintf(stderr, explanation);
+               generalcleanup(1);
+       }
+       if (ioctl(Console, GIO_FONT, Savefont) < 0) {
+               (void) fprintf(stderr, "unable to save console font\n");
+               generalcleanup(1);
+       }
+
+       vga_init();
+
+       /* get current video mode, so we can put it back when we're done */
+       Orig_video_mode = vga_getcurrentmode();
+
+       /* make sure we always clean up, so user isn't left stuck in raw and/or
+        * graphics mode. */
+       for (n = 1; n < NSIG; n++) {
+               if ( n != SIGKILL && n != SIGCLD) {
+                       (void) signal(n, Conf_info_p->cleanup);
+               }
+       }
+       (void) signal(SIGWINCH, SIG_IGN);
+
+       /* put keyboard into raw mode */
+       setup_keyboard();
+
+       /* put screen into graphics mode */
+       vga_setmode(G640x480x16);
+}
+\f
+
+/* draw stuff onto screen. Draw starting at specified line of page */
+
+void
+vgalib_draw(line, small)
+
+int line;      /* draw starting from this raster line of page */
+int small;     /* YES if should draw small view of full page */
+
+{
+       register int i;
+       register int j;
+       unsigned char buff[MAX_BYTES_PER_LINE]; /* a row of bits to display */
+       int extra;              /* how many unused bits in rightmost byte */
+       int mask;               /* to clear out unused bits */
+       long offset;            /* into bitmap file */
+       int fd;                 /* file to read bitmap from */
+       unsigned char vbuff[BPL * 8]; /* for one video scan line */
+       int jx8;                /* j times 8 (to convert bits to bytes) */
+       int vbytes;
+
+
+       /* make sure we have a valid page to draw */
+       if (Currpage_p == (struct Pginfo *) 0) {
+               ( *(Conf_info_p->error) ) ("page # out of range");
+               return;
+       }
+
+       /* figure out where in the bitmap file this page is */
+       offset = Currpage_p->seqnum * BYTES_PER_PAGE;
+       fd = gen1file(small);
+       (void) lseek(fd, offset + line * BYTES_PER_LINE, SEEK_SET);
+
+       /* vgalib wants 1 byte per pixel, we have 1 bit per pixel,
+        * so multiply by 8 */
+       vbytes = BYTES_PER_LINE << 3;
+
+       /* read from file and put into form for vga library to use */
+       for (i = 0; i < Conf_info_p->vlines; i++) {
+               read(fd, buff, BYTES_PER_LINE);
+
+               /* if the page width is not on a byte boundary, blank
+                * out the partial byte at the edge */
+               for (mask = 1, extra = BYTES_PER_LINE & 0x7;
+                                       extra > 0; mask <<= 1, extra--) {
+                       buff[BYTES_PER_LINE - 1] |= mask;
+               }
+
+               /* set line to all white except for area beyond right edge,
+                * which is set to all black */
+               memset(vbuff, 0xf, vbytes);
+               memset(vbuff + vbytes, 0, (BPL - BYTES_PER_LINE) << 3);
+
+               /* transfer bitmap row to vbuff, 1 bit of bitmap to 1 byte
+                * of vbuff. */
+               for (j = 0; j < BYTES_PER_LINE; j++) {
+                       /* get j times 8 bits per byte */
+                       jx8 = j << 3;
+
+                       /* for each black bit, set appropriate
+                        * vbuff byte to 0 */
+                       for (mask = 0; mask < 8; mask++) {
+                               if (buff[j] & (0x80 >> mask)) {
+                                       vbuff[jx8 + mask] = 0;
+                               }
+                       }
+               }
+
+               /* display this line */
+               vga_drawscanline(i, vbuff);
+       }
+}
+\f
+
+/* cleanup function.
+ * Put screen back into previous mode.
+ */
+
+void
+vgalib_cleanup(status)
+
+int status;
+
+{
+       /* put video back to normal */
+       vga_setmode(Orig_video_mode);
+       (void) ioctl(Console, PIO_FONT, Savefont);
+       close(Console);
+
+       /* put keyboard back to normal */
+       (void) ioctl(0, TCSETA, &Orig_ttyinfo);
+       
+       /* call the non-terminal-type specific cleanup */
+       generalcleanup(status);
+}
+
+/* some versions of vgalib seem to put things into noecho mode. So undo that. */
+
+static void
+fix_keyboard()
+{
+       (void) ioctl(0, TCSETA, &Orig_ttyinfo);
+}
+\f
+
+/* read from keyboard and call do_cmd for each key read.
+ * Commands are described in
+ * the comment at the beginning of do_cmd() */
+
+void
+vgalib_user_interf()
+
+{
+       int c;                  /* char read from keyboard */
+       int special = 0;        /* 1 = got an escape, 2 = got escape followed
+                                * by [, 0 = not doing any special processing.
+                                * This is to handle special function keys. */
+
+       while ( (c = getchar() ) != EOF) {
+               if (c == 0x1b) {
+                       /* got ESC, could be a special function key */
+                       special = 1;
+                       continue;
+               }
+               else if (special == 1 && c == '[') {
+                       /* got ESC-[ */
+                       special = 2;
+                       continue;
+               }
+               else if (special == 2) {
+                       /* map special functions to their equivalent commands */
+                       if (c == '5') {
+                               if ((c = getchar()) == '~') {
+                                       c = 'p'; /* Page Up key ==> previous */
+                               }
+                       }
+                       else if (c == '6') {
+                               if ((c = getchar()) == '~') {
+                                       c = 'n'; /* Page Down key ==> next */
+                               }
+                       }
+                       else if (c == 'A') {
+                               c = 'b';        /* Up key ==> backwards */
+                       }
+                       else if (c == 'B') {
+                               c = 'f';        /* Down key ==> forwards */
+                       }
+               }
+               special = 0;
+               do_cmd(c);
+       }
+}
+\f
+
+/* Error handler.
+ * For now just beep. Maybe eventually pop up an error message */
+
+void
+vgalib_error(msg)
+
+char *msg;
+
+{
+       (void) ioctl(Console, KDMKTONE, (150L << 16) | 3600L);
+}
+\f
+
+/* overlay a raster centered on the window */
+
+void
+vgalib_raster(bitmap, width, height)
+
+unsigned char *bitmap; /* what to display */
+int width, height;     /* of bitmap, width is in bytes */
+
+{
+       int i, j;
+       int x, y;       /* upper left corner of where to put bitmap,
+                        * x in bytes */
+       unsigned char vbuff[BPL * 8];
+       int mask;
+       int byte;
+       int jx8;        /* j times 8 */
+       int width8;     /* width times 8 */
+       int ixwidth;    /* i times width */
+
+
+       /* figure out how to center on screen */
+       x = ((BYTES_PER_LINE - width) / 2) * 8;
+       y = (Conf_info_p->vlines - height) / 2;
+
+       /* width translating bits to bytes */
+       width8 = width << 3;
+
+       /* copy bitmap to screen */
+       for (i = 0; i < height; i++) {
+               memset(vbuff, 0, width8);
+               ixwidth = i * width;
+
+               for (j = 0; j < width; j++) {
+                       byte = bitmap [ ixwidth + j ];
+                       jx8 = j << 3;
+                       for (mask = 0; mask < 8; mask++) {
+                               if (byte & (0x80 >> mask)) {
+                                       vbuff[jx8 + mask] = 0xf;
+                               }
+                       }
+               }
+               vga_drawscansegment(vbuff, x, y + i, width8);
+       }
+}
+\f
+
+/* put keyboard in raw mode */
+/* ported without change from the AT386 version. */
+
+static void
+setup_keyboard()
+
+{
+       struct termio ttyinfo;
+
+
+       if (isatty(0) != 1) {
+               (void) fprintf(stderr, "stdin is not a tty\n");
+               generalcleanup(1);
+       }
+
+       if (ioctl(0, TCGETA, &ttyinfo) < 0) {
+               (void) fprintf(stderr, "failed to get tty info\n");
+               generalcleanup(1);
+       }
+
+       /* turn off echo and canonical */
+       ttyinfo.c_lflag &= ~(ICANON | ECHO);
+       ttyinfo.c_cc[VMIN] = 1;
+       ttyinfo.c_cc[VTIME] = 3;
+       if (ioctl(0, TCSETA, &ttyinfo) < 0) {
+               (void) fprintf(stderr,
+                       "failed to set keyboard modes, errno %d\n", errno);
+               generalcleanup(1);
+       }
+}
+\f
+
+#else
+
+/* some compilers complain about files that are effectively empty,
+ * so put in something even when entire file is effectively ifdef-ed out */
+static short dummy;
+
+#endif
diff --git a/mup/mupdisp/mupdisp.c b/mup/mupdisp/mupdisp.c
new file mode 100644 (file)
index 0000000..8f68d3b
--- /dev/null
@@ -0,0 +1,464 @@
+
+/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+
+
+/* Program to display ghostscript bitmap output on screen.
+ * Works either on an AT386 or linux console
+ * or under X-windows from an xterm window or under DOS (with Watcom C).
+ * It could be extended to other
+ * TERM types by writing appropriate functions and adding to the Config
+ * array. Use the existing functions as models.
+ * Passes all arguments on to Mup.
+ */
+
+/* for compiling under UNIX on x86, try
+ *      cc -DSYSV -D_USHORT_H -s -O -o mupdisp *.c -lX11 -lnsl_i
+ * If you compile without XWINDOW, you can get by with just:
+ *      cc -s -O -o mupdisp *.c
+ *
+ * For Watcom C under DOS,
+ * Put the following 4 lines in a batch script and execute it
+ * 
+ *     for %%f in (*.c) do wcc386 %%f -dDEBUG -on -4r
+ *     echo NAME mup > mup.lnk
+ *     for %%f in (*.obj) do echo FIL %%f >> mup.lnk
+ *     wlink sys dos4g op st=32k @mup.lnk
+ * 
+ * Note that all the mupdisp *.c and *.h files should be in the
+ * current directory, but there must be no other *.c files there, and no *.obj
+ * files (except that *.obj files from a previous attempt would be okay).
+ *
+ * For Linux,
+ *     cc -L/usr/X11/lib -o mupdisp *.c -lvga -lX11 -lm
+ * Depending on the versions of libraries you have,
+ * you might not really need the -lm, but it doesn't hurt.
+ * If you don't have libvga on your system, and only intend to use the X11
+ * mode, not the console mode, you can use
+ *     cc -L/usr/X11/lib -o mupdisp -DNO_VGA_LIB *.c -lX11
+ *
+ * Other environments may require different options
+ *
+ * Note that using mupdisp in non-X-window mode on Linux requires that it
+ * can write to the console device. To allow this, make mupdisp setuid to root:
+ *     chown root mupdisp
+ *     chmod 4755 mupdisp
+ */
+
+
+#include "mupdisp.h"
+#ifdef __WATCOMC__
+#include <io.h>
+#endif
+
+
+struct CONFIG *Conf_info_p; /*  the info for the actual $TERM */
+struct Pginfo *Pagehead = (struct Pginfo *) 0;  /* all page's bitmap info */
+struct Pginfo *Pagetail = (struct Pginfo *) 0;  /* where to add to list */
+struct Pginfo *Currpage_p;      /* current page */
+int Pagenum;            /* current page number */
+long Beginprolog;       /* where in PostScript file the prolog begins */
+long Endprolog;         /* where in PostScript file the prolog ends */
+long Begin_offset;      /* offset in file where current page begins */
+int Pagenum;            /* current page number */
+int Psfile;             /* PostScript temp file, file descriptor */
+FILE *PS_file;          /* PostScript temp file */
+int Fullbitmaps;        /* temp file of full page bitmaps */
+int Partbitmaps;        /* temp file for bitmaps for scrollable pages */
+int Nulldev;            /* /dev/null */
+#ifdef linux
+char Fullfile[] = "mupdispfXXXXXX"; /* name of gs output tmp file, full page */
+char Partfile[] = "mupdisppXXXXXX"; /* name of gs output tmp file, partial page */
+char Mupfile[] = "mupdispmXXXXXX"; /* Mup output temp file */
+#else
+char Fullfile[L_tmpnam];        /* name of gs output tmp file, full page */
+char Partfile[L_tmpnam];        /* name of gs output tmp file, partial page */
+char Mupfile[L_tmpnam]; /* Mup output temp file */
+#endif
+char **Argv;            /* global version of argv */
+int Argc;               /* global version of argc */
+int Fullpgmode = DFLT_MODE;     /* full page or partial page mode, YES if full */
+char *Exit_errmsg = (char *) 0; /* error message to print upon exit, if any */
+char *Gs_errfile = "mupdispg.err";      /* ghostscript error file */
+int Bits_per_line = 612;       /* pixels per line */
+int Bytes_per_line = 77;       /* pixels per line divided by 8 rounded up */
+int Lines_per_page = 792;      /* vertical pixels */
+char *Version = "5.3";
+
+/* misc function declarations */
+static void parsePS P((FILE *file));
+static void save_endpage P((void));
+
+\f
+
+/* main function. Run Mup, run ghostscript, then do user interface */
+
+int
+main(argc, argv)
+
+int argc;
+char **argv;
+
+{
+       int n;
+
+
+       /* initialize */
+       Argv = argv;
+       Argc = argc;
+       init();
+
+#ifdef unix
+       /* arrange to clean up temp files. Note that the user interface
+        * will probably have its own cleanup */
+       for (n = 0; n < NSIG; n++) {
+               if (n != SIGKILL && n != SIGCLD && n != SIGWINCH) {
+                       signal(n, generalcleanup);
+               }
+       }
+       signal(SIGWINCH, SIG_IGN);
+#endif
+
+       if (getenv("MUPQUIET") == 0) {
+               fprintf(stderr, "Mupdisp - Version %s\n", Version);
+       }
+
+       /* There are several Mup options we want to turn off, because
+        * they don't produce PostScript output. This magic environment
+        * variable tells Mup to make the listed options illegal. */
+       putenv("MUPDELOP=CEfFmMrv");
+
+       /* make a temp file for PostScript */
+       Psfile = create_tmpfile(Mupfile);
+#ifdef linux
+       chown(Mupfile, getuid(), getgid());
+#endif
+
+       /* run Mup with given arguments */
+       run_mup(Argv);
+       if ((PS_file = fopen(Mupfile, "r")) == (FILE *) 0) {
+               fprintf(stderr, "can't open Mup output file\n");
+               generalcleanup(1);
+       }
+
+       /* find where pages begin in PostScript file */
+       parsePS(PS_file);
+
+#ifdef unix
+       if ((Nulldev = open("/dev/null", O_WRONLY, 0)) < 0) {
+               fprintf(stderr, "can't open /dev/null\n");
+               generalcleanup(1);
+       }
+#endif
+
+       /* if environment variable MUPDISPMODE is set, use the small full page
+        * mode as the default */
+       if (getenv("MUPDISPMODE") != (char *) 0) {
+               Fullpgmode = YES;
+       }
+
+       /* do user interface */
+       user_interf();
+       return(0);
+}
+\f
+
+/* given a page number, set Currpage_p to the info for that page
+ * and return YES. Else leave as is and return NO */
+
+int
+getpginfo(pgnum)
+
+int pgnum;      /* which page */
+
+{
+       struct Pginfo *pginfo_p;
+
+
+       /* use -1 as special page number to mean first on list */
+       if (pgnum == -1) {
+               Currpage_p = Pagehead;
+               return(Currpage_p == (struct Pginfo *) 0 ? NO : YES);
+       }
+
+       /* search list for requested page */
+       for (pginfo_p = Pagehead; pginfo_p != (struct Pginfo *) 0;
+                               pginfo_p = pginfo_p->next) {
+               if (pginfo_p->pagenum == pgnum) {
+                       /* found it */
+                       Currpage_p = pginfo_p;
+                       return(YES);
+               }
+       }
+
+       /* page not on list */
+       return (NO);
+}
+\f
+
+/* set up and call appropriate user interface routine */
+
+void
+user_interf()
+
+{
+       /* init, draw first page, do user interface */
+       ( *(Conf_info_p->setup) )  ();
+       getpginfo(-1);
+       ( *(Conf_info_p->draw) )  (0, Fullpgmode);
+       ( *(Conf_info_p->user_interf) )  ();
+       ( *(Conf_info_p->cleanup) )  (0);
+}
+\f
+
+/* check if scrolling by specified distance from line would leave the
+ * whole screen area within the page. If so, redraw the screen with that
+ * much of a scroll and return the new line number. Otherwise just return
+ * the original line number.
+ */
+
+int
+scroll(line, distance)
+
+int line;
+int distance;
+
+{
+       int newlineno;          /* line number after scrolling */
+       int pagebotline;        /* bottom line of page to display */
+
+
+       newlineno = line + (int)(distance * Conf_info_p->adjust);
+       if (newlineno < 0 && line > 0) {
+               newlineno = 0;
+       }
+       pagebotline = Conf_info_p->adjust * LINES_PER_PAGE - 1;
+       if (newlineno + Conf_info_p->vlines - 1 > pagebotline) {
+               newlineno = pagebotline - Conf_info_p->vlines + 1;
+       }
+       
+       if ( (newlineno != line) && (newlineno >= 0)
+                       && (newlineno + Conf_info_p->vlines - 1
+                       <= pagebotline) ) {
+               ( *(Conf_info_p->draw) )  (newlineno, Fullpgmode);
+               return(newlineno);
+       }
+       if (getenv("MUPQUIET") == (char *) 0) {
+               /* some people don't want to be beeped when hitting end of
+                * page, so only exclaim if quiet flag is off */
+               ( *(Conf_info_p->error) )  ("can't scroll any farther");
+       }
+       return(line);
+}
+\f
+
+/* general cleanup function to delete temp files. All other cleanup functions
+ * should call this function last, since it exits */
+
+void
+generalcleanup(status)
+
+int status;
+
+{
+       if (Mupfile[0]) {
+               close(Psfile);
+               if (PS_file != 0) {
+                       fclose(PS_file);
+               }
+               unlink(Mupfile);
+       }
+       if (Fullfile[0]) {
+               close(Fullbitmaps);
+               unlink(Fullfile);
+       }
+       if (Partfile[0]) {
+               close(Partbitmaps);
+               unlink(Partfile);
+       }
+       /* if there is an error message to print, do so */
+       if (Exit_errmsg != (char *) 0) {
+               fprintf(stderr, Exit_errmsg);
+               
+               /* if there is a ghostscript error file, print it */
+               if (status != 0) {
+                       FILE *f;
+                       char buff[BUFSIZ];
+
+                       if ((f = fopen(Gs_errfile, "r")) != NULL) {
+                               while (fgets(buff, BUFSIZ, f)) {
+                                       fprintf(stderr, "%s", buff);
+                               }
+                               fclose(f);
+                               unlink(Gs_errfile);
+                       }
+               }
+       }
+       exit(status);
+}
+\f
+
+/* Create a temporary file. It is passed an array in which the filename is
+ * stored. Newer versions of gcc claim that tmpnam is dangerous and that you
+ * should use mkstemp instead. But some other systems say using mkstemp
+ * is discouraged. Being unable to please everyone, we use mkstemp on linux
+ * and tmpnam elsewhere. So on linux, the argument should be a character
+ * array initialized to end with "XXXXXX" as per what mkstemp wants,
+ * On other systems it should be a character array at least L_tmpnam bytes long.
+ * Returns the file descriptor, opened read/write. */
+
+int
+create_tmpfile(char *tmpfname)
+
+{
+       int fd;
+
+
+#ifdef linux
+       if ((fd = mkstemp(tmpfname)) < 0) {
+               fprintf(stderr, "can't create temp file\n");
+               generalcleanup(1);
+       }
+#else
+       /* create the file name */
+       if (tmpnam(tmpfname) == (char *) 0) {
+               fprintf(stderr, "can't create temp file\n");
+               generalcleanup(1);
+       }
+
+       /* open the file */
+#ifdef O_BINARY
+       if ((fd = open(tmpfname, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0644)) < 0) {
+#else        
+       if ((fd = open(tmpfname, O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) {
+#endif
+               fprintf(stderr, "can't open temp file\n");
+               generalcleanup(1);
+       }
+#endif
+
+       return(fd);
+}
+\f
+
+/* 
+ * Read a PostScript file and save pointer to where the description of
+ * each page begins.
+ * Go through input file. Skip to %%EndProlog. Then for each page,
+ * save file offset where page begins.
+ * This function know about how Mup formats parts of its output. If Mup
+ * ever changes to add extra white space or comments or something in
+ * the specific lines this function cares about, this function will
+ * have to change too.
+ */
+
+static void
+parsePS(file)
+
+FILE *file;
+
+{
+       char buff[BUFSIZ];
+       long linebegin;         /* where in file current line begins */
+
+
+       /* read whole file */
+       linebegin = ftell(file);
+       while (fgets(buff, BUFSIZ, file)) {
+
+               if (strncmp(buff, "%!PS-Adobe", 10) == 0) {
+                       /* remember where prolog begins. Because of how DOS
+                        * deals with cr/nl we can't just back up the length
+                        * of the string from the current ftell position and
+                        * be assured of being at the %, so that's why we
+                        * save the current beginning of each line and then
+                        * assign it here. Normally, the %!Adobe line will
+                        * be the first line anyway and we wouldn't need this
+                        * code at all, but some versions of dos4gw write stuff
+                        * to stdout, which ends up in the PostScript file,
+                        * which then confuses us, so we want to throw that
+                        * away if it is present. */
+                       Beginprolog = linebegin;
+               }
+               else if (strncmp(buff, "%%BoundingBox:", 14) == 0) {
+                       int x, y;
+
+                       /* adjust for page size */
+                       if (sscanf(buff + 14, "%*d %*d %d %d", &x, &y) == 2) {
+                               if ( (x <= MAX_BYTES_PER_LINE * 8)
+                                               && (x > 0) && (y > 0) &&
+                                               (y <= MAX_LINES_PER_PAGE) ) { 
+                                       get_paper_size(x, y);
+                               }
+                               else {
+                                       fprintf(stderr, "Page is too big to display completely\n");
+                               }
+                       }
+               }
+               else if (strncmp(buff, "%%EndProlog", 11) == 0) {
+                       /* remember where prolog ends */
+                       Endprolog = ftell(PS_file);
+               }
+
+               else if (strncmp(buff, "%%Page: ", 8) == 0) {
+                       Pagenum = atoi(buff + 8);
+               
+                       /* Page followed by save, save info about page */
+                       fgets(buff, BUFSIZ, file);
+                       if (strncmp(buff, "save", 4) == 0) {
+                               Begin_offset = linebegin;
+                       }
+               }
+
+               else if (strncmp(buff, "showpage", 8) == 0) {
+                       /* showpage followed by restore, save info about
+                        * where page ends */
+                       fgets(buff, BUFSIZ, file);
+                       if (strncmp(buff, "restore", 7) == 0) {
+                               save_endpage();
+                       }
+               }
+               linebegin = ftell(file);
+       }
+       
+       /* file was not valid -- something went wrong */
+       if (Endprolog == 0) {
+               generalcleanup(1);
+       }
+}
+\f
+
+/* at the end of a PostScript page, save info about it */
+
+static void
+save_endpage()
+
+{
+       struct Pginfo *new_p;   /* newly allocated struct for info about page */
+       static int seqnum = 0;      /* sequential count of pages */
+
+
+       /* allocate space to save info about page */
+       if ((new_p = (struct Pginfo *) malloc (sizeof(struct Pginfo)))
+                                               == (struct Pginfo *) 0) {
+               fprintf(stderr, "malloc failed\n");
+               generalcleanup(1);
+       }
+
+       /* fill in info */
+       new_p->pagenum = Pagenum;
+       new_p->seqnum = seqnum++;
+       new_p->begin = Begin_offset;
+       new_p->end = ftell(PS_file);
+       new_p->prev = Pagetail;
+       new_p->next = (struct Pginfo *) 0;
+
+       /* link onto list */
+       if (Pagehead == (struct Pginfo *) 0) {
+               Pagehead = new_p;
+       }
+       if (Pagetail != (struct Pginfo *) 0) {
+               Pagetail->next = new_p;
+       }
+       Pagetail = new_p;
+}
diff --git a/mup/mupdisp/mupdisp.h b/mup/mupdisp/mupdisp.h
new file mode 100644 (file)
index 0000000..892d323
--- /dev/null
@@ -0,0 +1,155 @@
+
+/* Copyright (c) 1995, 1996, 1998, 2000, 2001, 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* include file for Mup/Ghostscript display program */
+
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+#if !defined(linux) && !defined(__EMX__)
+/* undef SIGCHLD to avoid conflict with Xos.h */
+#undef SIGCHLD
+#endif
+#include <errno.h>
+
+#ifdef __WATCOMC__
+#ifndef __DOS__
+#define __DOS__ 1
+#endif
+#endif
+
+#if defined(__DOS__) || defined (__EMX__)
+#include <io.h>
+#endif
+
+#ifdef __EMX__
+#define unix   /* not really unix, but acts like it */
+#endif
+#include "dispttyp.h"
+
+#ifdef XWINDOW
+#ifdef linux
+#undef SYSV
+#undef _USHORT_H
+#endif
+/* X window includes */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+/* define XK_MISCELLANY so we can use XK_Return, etc */
+#define XK_MISCELLANY 1
+#include <X11/keysymdef.h>
+#endif
+
+/* macro for function templates if using ANSI C */
+#ifdef __STDC__
+#define        P(parms)        parms
+#else
+#define        P(parms)        ()
+#endif
+
+#define YES     1
+#define NO      0
+
+/* define screen and page dimensions */
+/* we only handle the standard sizes that are less than 640 pixels wide.
+ * This includes letter, note, legal, a3, a4, a5, a6, flsa, flse,
+ * and halfletter  */
+#define MAX_BYTES_PER_LINE     77      /* 612/8 rounded up */
+#define MAX_LINES_PER_PAGE     1008    /* to handle legal size */
+
+#define BITS_PER_LINE   Bits_per_line    /* horizontal pixels */
+#define BYTES_PER_LINE  Bytes_per_line   /* Bits_per_line / 8 rounded up */
+#define LINES_PER_PAGE  Lines_per_page   /* vertical pixels */
+#define BYTES_PER_PAGE  (BYTES_PER_LINE * LINES_PER_PAGE)
+
+
+/* default mode is not full page */
+#define DFLT_MODE       NO
+
+typedef void (*FUNC)();
+
+/* list of supported $TERM types and which functions and parameters to use
+ * to implement them. To support a new terminal type, write appropriate
+ * functions, and add to the Config table in init.c.
+ */
+struct CONFIG {
+       char    *termname;      /* $TERM value */
+       FUNC    setup;          /* call this to initialize */
+       FUNC    cleanup;        /* call this to clean up and exit */
+       FUNC    draw;           /* call this to draw a screen of the page */
+       FUNC    user_interf;    /* call this to read user input */
+       FUNC    error;          /* call this on bad user input */
+       FUNC    bitmap;         /* call this to display a bitmap */
+       int     vlines;         /* number of lines vertically on screen */
+       float   adjust;         /* aspect ratio adjustment */
+};
+
+
+/* information about a particular bitmap-ed page. */
+struct Pginfo {
+       int     pagenum;        /* actual designated page number. If the mup
+                                * -p option is used, this may start somewhere
+                                * other than 1, and if -o is used, there
+                                * may be gaps in the list */
+       int     seqnum;         /* page number from 0 to n-1. Multiplying this
+                                * by the number of bytes per page in a bitmap
+                                * gives the file offset for the page. */
+       long    begin;          /* where page begins in input */
+       long    end;            /* where page ends in input */
+       struct Pginfo   *next;  /* linked list link */
+       struct Pginfo   *prev;
+};
+
+/* globals */
+extern struct CONFIG *Conf_info_p;
+extern struct Pginfo *Pagehead; /* all page bitmaps */
+extern struct Pginfo *Pagetail; /* where to add to list */
+extern struct Pginfo *Currpage_p;       /* current page */
+extern int Fullpgmode;  /* full page or partial page */
+extern long Beginprolog;/* where in PostScript file the prolog begins */
+extern long Endprolog;  /* where in PostScript file the prolog ends */
+extern long Begin_offset;/* offset in file where current page begins */
+extern int Pagenum;     /* current page number */
+extern int Psfile;      /* PostScript temp file, file descriptor */
+extern FILE *PS_file;   /* PostScript temp file */
+extern int Fullbitmaps; /* temp file of full page bitmaps */
+extern int Partbitmaps; /* temp file for bitmaps for scrollable pages */
+extern int Nulldev;     /* /dev/null */
+extern char Fullfile[]; /* name of gs output tmp file */
+extern char Partfile[]; /* name of gs output tmp file */
+extern char Mupfile[];  /* mup output temp file */
+extern char **Argv;     /* global version of argv */
+extern int Argc;        /* global version of argc */
+extern char *Exit_errmsg;/* error message to print upon exit */
+extern char *Gs_errfile;/* Ghostscript error file */
+extern int Bits_per_line; /* pixels per line */
+extern int Bytes_per_line;/* pixels per line divided by 8 and rounded up */
+extern int Lines_per_page;/* vertical pixels */
+
+/* misc functions */
+extern int getpginfo P((int pgnum));
+extern void user_interf P((void));
+extern int scroll P((int line, int distance));
+extern void generalcleanup P((int status));
+extern int create_tmpfile P((char *tmpfname));
+extern int gen1file P((int fullpgmode));
+extern void get_paper_size P((int x, int y));
+extern void run_mup P((char **argv));
+extern void init P((void));
+extern void do_cmd P((int c));
+
+extern char *getenv();
+extern long ftell();
+#ifdef __STDC__
+#include <unistd.h>
+#else
+extern long lseek();
+#endif
diff --git a/mup/mupdisp/waitmsg.bm b/mup/mupdisp/waitmsg.bm
new file mode 100644 (file)
index 0000000..54666ea
--- /dev/null
@@ -0,0 +1,56 @@
+/* Copyright (c) 1995 by Arkkra Enterprises */
+/* All rights reserved */
+
+int Waitmsg_width = 29;
+int Waitmsg_height = 48;
+unsigned char Waitmsg_bitmap[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x33, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xc7, 0x9f, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x33, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xcf, 0xdf, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0x8f, 0xdf, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0x9f, 0xf9, 0x30, 0xf0, 0xc3, 0x38, 0x1e, 0x03, 0xe0, 0x38, 0x78, 0x0c, 0x38, 0x3f, 0x0e, 0x0f, 0xf0, 0x33, 0x83, 0x01, 0xce, 0x1c, 0x67, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0x9f, 0xf9, 0xae, 0x66, 0x67, 0x38, 0xcc, 0xc7, 0xe3, 0x13, 0x33, 0x1b, 0x93, 0x9f, 0x9c, 0xe7, 0xe6, 0x33, 0x39, 0x18, 0xcc, 0xcc, 0xf7, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0x9f, 0xf9, 0xe0, 0x6e, 0x67, 0x39, 0xcc, 0xe7, 0xe7, 0x97, 0x33, 0x98, 0x11, 0xff, 0x99, 0xe3, 0xcf, 0x33, 0x1f, 0x3c, 0xcd, 0xce, 0x6f, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0x9f, 0xf9, 0xcf, 0xf8, 0x67, 0x39, 0xcc, 0xe7, 0xe7, 0x9c, 0x33, 0x93, 0xf8, 0x7f, 0x99, 0xf3, 0xcf, 0x33, 0x87, 0x3c, 0xcf, 0x0e, 0x6f, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0x9f, 0xf9, 0xcf, 0xf6, 0x67, 0x39, 0xce, 0x4f, 0xe7, 0x9b, 0x39, 0x33, 0xfe, 0x3f, 0x99, 0xf3, 0xcf, 0x33, 0xe3, 0x3c, 0xce, 0xcf, 0x1f, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0x8f, 0xf9, 0xcf, 0xa6, 0x67, 0x39, 0xce, 0x1f, 0xe7, 0x93, 0x38, 0x73, 0xe7, 0x1f, 0x98, 0xf3, 0xc7, 0x33, 0x71, 0x3c, 0xcc, 0xcf, 0x1f, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xc7, 0x99, 0xe7, 0x44, 0x67, 0x39, 0xcc, 0xff, 0xe7, 0x22, 0x33, 0xf9, 0xd3, 0x9f, 0x9c, 0xe7, 0xe7, 0x33, 0x39, 0x39, 0xc8, 0x8f, 0x9e, 0xf7, 0x7b, 0xff, 0x00,
+0x00, 0xff, 0xe0, 0x30, 0x70, 0xe0, 0x21, 0x18, 0x8c, 0x07, 0xe0, 0x70, 0x10, 0x1c, 0x30, 0x3f, 0x86, 0x0f, 0xf0, 0x31, 0x03, 0x03, 0x8c, 0x07, 0xbc, 0xe6, 0x73, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x83, 0xe7, 0xff, 0xf6, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xfb, 0xe7, 0xff, 0xe7, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xe7, 0xe7, 0xff, 0xe3, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0f, 0xc7, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
diff --git a/mup/mupdisp/xterm.c b/mup/mupdisp/xterm.c
new file mode 100644 (file)
index 0000000..95f5698
--- /dev/null
@@ -0,0 +1,644 @@
+
+/* Copyright (c) 1995, 1996, 1998, 1999, 2000, 2001, 2004, 2005 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* functions for displaying Mup/Ghostscript output under X windows. */
+
+#include "mupdisp.h"
+
+#ifdef XWINDOW
+
+#include <X11/Xlib.h>
+#include <X11/Xresource.h>
+
+/* size for XLookupString buffer */
+#define IBUFSIZ                8
+
+/* X window icon to use when window is icon-ized.
+ * Shows musical notes. This was generated using the bitmap tool */
+#define Disp_icon_width 32
+#define Disp_icon_height 32
+static unsigned char Disp_icon_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00,
+   0x00, 0xc0, 0x0b, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf8, 0x08, 0x00,
+   0x00, 0x1e, 0x08, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00,
+   0xff, 0xff, 0xff, 0xff, 0x00, 0x02, 0x08, 0x14, 0x00, 0x02, 0x08, 0x22,
+   0x00, 0x02, 0x08, 0x23, 0x00, 0x02, 0x08, 0x15, 0xff, 0xff, 0xff, 0xff,
+   0x00, 0x02, 0x08, 0x01, 0x00, 0x02, 0x08, 0x01, 0x00, 0x82, 0x0f, 0x01,
+   0x00, 0xc2, 0x0f, 0x01, 0xff, 0xff, 0xff, 0xff, 0x00, 0x82, 0x07, 0x01,
+   0x00, 0x02, 0x00, 0x01, 0xe0, 0x03, 0x02, 0x01, 0xf0, 0x03, 0x01, 0x01,
+   0xff, 0xff, 0xff, 0xff, 0xe0, 0x81, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01,
+   0x80, 0x31, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+#define MINHEIGHT      (400)   /* allow this short a window in X window mode */
+#define MAXHEIGHT      LINES_PER_PAGE  /* tallest window we allow */
+
+#define SMALL 1
+#define OK 0
+
+/* bitmap of whether control key is pressed */
+#define LEFTC  0x1
+#define RIGHTC 0x2
+
+extern unsigned char Waitmsg_bitmap[]; /* message to tell user to wait */
+extern int Waitmsg_width, Waitmsg_height;
+
+/* define X window screen and display things */
+static Display *Display_p;
+static int Xscreen;
+static XImage *Image_p;
+static XFontStruct *Font_info_p;
+static GC gc;                  /* X graphics context */
+static Window Win;
+static unsigned int Width, Height;
+static XSizeHints Size_hints;  /* tell window manager what size we want */
+static unsigned long Foreground; /* color */
+static unsigned long Background; /* color */
+static char Mupdisp[] = "mupdisp";
+
+/* X resource manager things */
+static XrmOptionDescRec Option_table[] = {
+       { "-geometry",  ".geometry",    XrmoptionSepArg, (caddr_t) 0 },
+       { "-background","*background",  XrmoptionSepArg, (caddr_t) 0 },
+       { "-bg",        "*background",  XrmoptionSepArg, (caddr_t) 0 },
+       { "-foreground","*foreground",  XrmoptionSepArg, (caddr_t) 0 },
+       { "-fg",        "*foreground",  XrmoptionSepArg, (caddr_t) 0 },
+};
+static int Opt_table_size = sizeof(Option_table) / sizeof (XrmOptionDescRec);
+static char Xoptions_usage[] =
+"MUPADDOP=\
+ Also the following X options:\n\
+   -bg color            set background color\n\
+   -fg color            set foreground color\n\
+   -geometry XxY+N+M    set window size and location\n";
+XrmDatabase Resource_db;
+
+
+/* local functions */
+static char * get_cmd_resource P((char *resource_name));
+static unsigned long get_color P((char *resource_name,
+               unsigned long default_value));
+static int color_ok P((char *resource_name, char *value, XColor *color_p));
+static void create_image P((int wid, int height));
+static void get_GC P((Window win));
+static void load_font P((void));
+static void TooSmall P((Window win));
+\f
+
+/* parse any X-specific aguments */
+
+void
+parse_X_options()
+{
+       XrmInitialize();
+       XrmParseCommand( &Resource_db, Option_table, Opt_table_size,
+                       Mupdisp, &Argc, Argv);
+       /* tell Mup about these additional options */
+       putenv(Xoptions_usage);
+}
+\f
+
+/* setup for X-window operation. Basically copy things from the X manual,
+ * and customize as appropriate. */
+
+
+void
+xterm_setup()
+
+{
+       int x = 0, y = 0;
+       unsigned int border_width = 4;
+       unsigned int display_width, display_height;
+       char *window_name = Mupdisp;
+       char *icon_name = Mupdisp;
+       Pixmap icon_pixmap;
+       char *display_name = NULL;
+       XEvent event;
+       char * value;
+       unsigned int dummy_width;       /* we don't allow Width to change */
+       XWindowAttributes attributes;
+       int got_geometry = 0;
+
+
+       /* If mupdisp is setuid to root so that libsvga can work on
+        * console devices, Ghostscript can fail under X.
+        * So relinquish our superuser-ism.
+        */
+       if (getuid() != geteuid()) {
+               seteuid(getuid());
+       }
+
+       /* set up display */
+       if ( (Display_p = XOpenDisplay(display_name)) == NULL) {
+               fprintf(stderr, "%s: can't connect to X server %s\n", Argv[0],
+                               XDisplayName(display_name));
+               generalcleanup(1);
+       }
+
+       Xscreen = DefaultScreen(Display_p);
+
+       display_width = DisplayWidth(Display_p, Xscreen);
+       display_height = DisplayHeight(Display_p, Xscreen);
+
+       /* this is our ideal size. Window manager may have other ideas */
+       Width = BITS_PER_LINE;
+       /* Use a height a little smaller than the screen height (to allow
+        * for window borders), or at a minimum, what's in Conf_info_p */
+       if (display_height - 50 > Conf_info_p->vlines) {
+               Height = display_height - 50;
+       }
+       else {
+               Height = Conf_info_p->vlines;
+       }
+
+       /* If user specified colors, get those, otherwise use black on white */
+       Background = get_color("background", WhitePixel(Display_p, Xscreen));
+       Foreground = get_color("foreground", BlackPixel(Display_p, Xscreen));
+       
+       /* Now see if user specified geometry, either from command line,
+        * or failing that, from default database. */
+       if ((value = get_cmd_resource("geometry")) != (char *) 0) {
+               XParseGeometry(value, &x, &y, &dummy_width, &Height);
+               got_geometry = 1;
+       }
+       else if ((value = XGetDefault(Display_p, Mupdisp, "geometry")) != 0) {
+               XParseGeometry(value, &x, &y, &dummy_width, &Height);
+               got_geometry = 1;
+       }
+       if (Height < MINHEIGHT) {
+               Height = MINHEIGHT;
+       }
+       if (Height > MAXHEIGHT) {
+               Height = MAXHEIGHT;
+       }
+
+
+       /* create window and icon */
+       Win = XCreateSimpleWindow(Display_p, RootWindow(Display_p, Xscreen),
+                       x, y, Width, Height, border_width,
+                       Foreground, Background);
+
+       icon_pixmap = XCreateBitmapFromData(Display_p, Win,
+                       (char *) Disp_icon_bits, Disp_icon_width,
+                       Disp_icon_height);
+
+       /* we want the width to be exactly the width of a page. The height
+        * can vary because we scroll in that direction */
+       if (got_geometry) {
+               Size_hints.flags = PSize | PMinSize | PMaxSize | PPosition;
+               Size_hints.x = x;
+               Size_hints.y = y;
+       }
+       else {
+               Size_hints.flags = PSize | PMinSize | PMaxSize;
+       }
+       Size_hints.width = Width;
+       Size_hints.height = Height;
+       Size_hints.min_width = Width;
+       Size_hints.max_width = Width;
+       Size_hints.min_height = MINHEIGHT;
+       Size_hints.max_height = (display_height < MAXHEIGHT
+                                       ? display_height : MAXHEIGHT);
+
+       XSetStandardProperties(Display_p, Win, window_name, icon_name,
+                       icon_pixmap, Argv, Argc, &Size_hints);
+
+       XSelectInput(Display_p, Win, ExposureMask | KeyPressMask |
+                       KeyReleaseMask | ButtonPressMask | StructureNotifyMask);
+
+       load_font();
+       get_GC(Win);
+       XMapWindow(Display_p, Win);
+
+       /* determine what height we actually got */
+       if (XGetWindowAttributes(Display_p, Win, &attributes) != 0) {
+               Conf_info_p->vlines = Height = attributes.height;
+       }
+               
+       create_image(Width, Height);
+
+       /* it seems we need to wait for an exposure event,(or maybe it's
+        * really MapNotify) before proceeding, or else the "wait" message
+        * doesn't get displayed, so wait for it */
+       XWindowEvent(Display_p, Win, ExposureMask, &event);
+}
+\f
+
+/* create XImage for the display. If one already existed, free it first (which
+ * would happen if window was re-sized */
+
+static void
+create_image(wid, height)
+
+int wid;
+int height;
+
+{
+       char *databuff;
+
+
+       /* if already have one, free that and redo if different size */
+       if (Image_p != (XImage *) 0) {
+               if (Image_p->width == wid && Image_p->height == height) {
+                       /* already have one of correct size */
+                       return;
+               }
+               else {
+                       XDestroyImage(Image_p);
+               }
+       }
+
+       /* create buffer for display image */
+       if ((databuff = (char *) malloc(BYTES_PER_LINE * height)) == (char *) 0) {
+               Exit_errmsg = "Could not allocate memory\n";
+               ( *(Conf_info_p->cleanup) )  (1);
+       }
+
+       Image_p = XCreateImage(Display_p, DefaultVisual(Display_p, Xscreen),
+                       1, XYBitmap, 0, databuff, wid, height,
+                       8, BYTES_PER_LINE);
+       Image_p->bitmap_unit = 8;
+       Image_p->bitmap_bit_order = MSBFirst;
+}
+\f
+
+/* Look up the color resource named. If found, return its value,
+ * otherwise return the default value. */
+
+static unsigned long
+get_color(resource_name, default_value)
+
+char *resource_name;
+unsigned long default_value;
+
+{
+       char *value;
+       XColor color;
+
+       /* First try looking up in command line resource database. */
+       if ((value = get_cmd_resource(resource_name)) != (char *) 0) {
+               if (color_ok(resource_name, value, &color)) {
+                       return(color.pixel);
+               }
+       }
+
+       /* failing that, try looking in the default database */
+       if ((value = XGetDefault(Display_p, Mupdisp, resource_name)) != 0) {
+               if (color_ok(resource_name, value, &color)) {
+                       return(color.pixel);
+               }
+       }
+
+       return(default_value);
+}
+\f
+
+/* look up a value from the command line database. Return it if found, else 0 */
+static char *
+get_cmd_resource(resource_name)
+
+char *resource_name;
+
+{
+       XrmValue rm_value;
+       char *str_type[20];
+       char res_name[100];
+       char class_name[100];
+       int offset;
+
+
+       /* create the resource and class names. Class name has initial caps */
+       sprintf(res_name, "%s.%s", Mupdisp, resource_name);
+       sprintf(class_name, "%s.%s", Mupdisp, resource_name);
+       class_name[0] = toupper(class_name[0]);
+       offset = strlen(Mupdisp) + 1;
+       class_name[offset] = toupper(class_name[offset]);
+
+       /* look it up in command line resource database. */
+       if (XrmGetResource(Resource_db, res_name,
+                       class_name, str_type, &rm_value) == True) {
+               return ((char *) rm_value.addr);
+       }
+       return((char *) 0);
+}
+
+/* Parse a color name and allocate it. If all goes well, fill in the
+ * XColor and return 1. If something goes wrong, return 0. */
+
+static int
+color_ok(resource_name, value, color_p)
+
+char *resource_name;
+char *value;
+XColor *color_p;
+
+{
+       if (XParseColor(Display_p,
+                       DefaultColormapOfScreen(
+                       DefaultScreenOfDisplay(Display_p)),
+                       value, color_p) != 0) {
+               if (XAllocColor(Display_p,
+                               DefaultColormapOfScreen(
+                               DefaultScreenOfDisplay(Display_p)),
+                               color_p) != 0) {
+                       return (1);
+               }
+       }
+       else {
+               fprintf(stderr, "invalid %s color: %s\n",
+                               resource_name, value);
+       }
+       return(0);
+}
+\f
+
+/* get input in X windows mode. Handle all the events, including mouse,
+ * resizing and exposure */
+void
+xterm_user_interf()
+
+{
+       XEvent report;          /* what X event happened */
+       char inpbuff[IBUFSIZ];
+       KeySym keysym;
+       XComposeStatus compose;
+       int window_size = OK;
+       static int control = 0; /* non-zero if control key is pressed */
+
+
+       while (1) {
+
+               /* get an event and take appropriate action */
+               XNextEvent(Display_p, &report);
+
+               switch(report.type) {
+
+               case Expose:
+                       /* repaint screen */
+                       while(XCheckTypedEvent(Display_p, Expose, &report))
+                               ;
+                       if (window_size == SMALL) {
+                               TooSmall(Win);
+                       }
+                       else {
+                               do_cmd('r');
+                       }
+                       break;
+
+               case ConfigureNotify:
+                       /* set up image of proper size */
+                       Width = report.xconfigure.width;
+                       Height = report.xconfigure.height;
+                       if ((Width < Size_hints.min_width) ||
+                                       (Height < Size_hints.min_height)) {
+                               window_size = SMALL;
+                       }
+                       else {
+                               window_size = OK;
+                       }
+                       create_image(Width, Height);
+                       Conf_info_p->vlines = Height;
+                       break;
+
+               case ButtonPress:
+                       /* mouse. left is forward, right is backward scroll */
+                       if (report.xbutton.button == 1) {
+                               do_cmd('f');
+                       }
+                       else if (report.xbutton.button == 3) {
+                               do_cmd('b');
+                       }
+                       break;
+
+               case KeyPress:
+                       /* keyboard input. Do appropriate command */
+                       XLookupString(&(report.xkey), inpbuff, IBUFSIZ, &keysym,
+                                               &compose);
+                       /* the linux version of isascii claims
+                        * that isascii(0xff0d) is true! So I added the
+                        * extra check for < 256 (which isascii should already
+                        * be checking) */
+                       if (keysym < 256 && isascii(keysym)) {
+                               if (control != 0) {
+                                       do_cmd(keysym & 0x1f);
+                               }
+                               else {
+                                       do_cmd(keysym);
+                               }
+                       }
+                       else if (keysym == XK_Return) {
+                               do_cmd('\n');
+                       }
+                       else if (keysym == XK_BackSpace) {
+                               do_cmd('\b');
+                       }
+                       else if (keysym == XK_Up) {
+                               /* use up key as synonym for scrolling back */
+                               do_cmd('b');
+                       }
+                       else if (keysym == XK_Down) {
+                               /* use down key as synonym for scrolling forward */
+                               do_cmd('f');
+                       }
+                       else if (keysym == XK_Prior) {
+                               /* use page up key as synonym for previous page */
+                               do_cmd('p');
+                       }
+                       else if (keysym == XK_Next) {
+                               /* use page down key as synonym for next page */
+                               do_cmd('n');
+                       }
+                       else if (keysym == XK_Control_L || keysym == XK_Control_R) {
+                               control++;
+                       }
+                       break;
+
+               case KeyRelease:
+                       /* just check for control key release */
+                       XLookupString(&(report.xkey), inpbuff, IBUFSIZ, &keysym,
+                                               &compose);
+                       if (keysym == XK_Control_L || keysym == XK_Control_R) {
+                               if (control > 0) {
+                                       control--;
+                               }
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+       }
+}
+\f
+
+/* create graphics context. Basically copy the example in the X book */
+
+static void
+get_GC(win)
+
+Window win;
+
+{
+       unsigned long valuemask = 0;
+       XGCValues values;
+       unsigned int line_width = 6;
+       int line_style = LineOnOffDash;
+       int cap_style = CapRound;
+       int join_style = JoinRound;
+       int dash_offset = 0;
+       static char dash_list[] = { 12, 24 };
+       int list_length = 2;
+
+       gc = XCreateGC(Display_p, Win, valuemask, &values);
+       XSetFont(Display_p, gc, Font_info_p->fid);
+       XSetForeground(Display_p, gc, Foreground);
+       XSetBackground(Display_p, gc, Background);
+       XSetLineAttributes(Display_p, gc, line_width, line_style, cap_style,
+                       join_style);
+       XSetDashes(Display_p, gc, dash_offset, dash_list, list_length);
+}
+\f
+
+/* load a font. Copy example in X book */
+
+static void
+load_font()
+
+{
+       char *fontname = "9x15";
+
+       if ((Font_info_p = XLoadQueryFont(Display_p, fontname)) == NULL) {
+               fprintf(stderr, "can't open 9x15 font\n");
+               generalcleanup(1);
+       }
+}
+
+
+static void
+TooSmall(win)
+
+Window win;
+
+{
+       char *string1 = "Too small";
+
+       XDrawString(Display_p, win, gc, 2, Font_info_p->max_bounds.ascent + 2,
+                       string1, strlen(string1));
+       Exit_errmsg = "Window too small\n";
+       ( *(Conf_info_p->cleanup) )  (1);
+}
+\f
+
+/* X cleanup function */
+
+void
+xterm_cleanup(status)
+
+int status;
+
+{
+       /* free all X resources */
+       XUnloadFont(Display_p, Font_info_p->fid);
+       XFreeGC(Display_p, gc);
+       XCloseDisplay(Display_p);
+
+       /* call non-terminal-type specific cleanup */
+       generalcleanup(status);
+}
+\f
+
+/* draw screen in X mode */
+
+void
+xterm_draw(line, small)
+
+int line;      /* start drawing at this raster line */
+int small;     /* if YES, use small, full-page mode */
+
+{
+       register int i;
+       long offset;                    /* offset into file where page begins */
+       int fd;                         /* file descriptor of bitmap file */
+
+
+       /* make sure we have a valid page */
+       if (Currpage_p == (struct Pginfo *) 0) {
+               ( *(Conf_info_p->error) ) ("page # out of range");
+               return;
+       }
+
+       /* find data in bitmap file */
+       offset = Currpage_p->seqnum * BYTES_PER_PAGE;
+       fd = gen1file(small);
+       lseek(fd, offset + line * BYTES_PER_LINE, SEEK_SET);
+
+       /* copy into memory and display it */
+       for (i = 0; i < Conf_info_p->vlines; i++) {
+               read(fd, Image_p->data + i * BYTES_PER_LINE, BYTES_PER_LINE);
+       }
+       XPutImage(Display_p, Win, gc, Image_p, 0, 0, 0, 0, Width, Height);
+       XFlush(Display_p);
+}
+\f
+
+
+/* Error handler. For now just beep. Maybe eventually pop up an error message */
+
+void
+xterm_error(msg)
+
+char *msg;
+
+{
+       putc('\7', stderr);
+}
+\f
+
+/* draw a raster bitmap, centered on the window */
+
+void
+xterm_raster(bitmap, width, height)
+
+unsigned char *bitmap; /* what to display */
+int width, height;     /* of bitmap, width is in bytes */
+
+{
+       register int b;
+       int x, y;       /* upper left corner of where to put bitmap, x in bytes */
+       XImage *bm_image;
+       char *bmap;
+
+
+       /* figure out how to center on screen */
+       x = (BYTES_PER_LINE - width) / 2;
+       y = (Conf_info_p->vlines - height) / 2;
+
+       /* get space to image, copy, inverting to white on black. Display,
+        * then release the storage */
+       if ((bmap = (char *) malloc(width*height)) == (char *) 0) {
+               Exit_errmsg = "Could not allocate memory\n";
+               ( *(Conf_info_p->cleanup) )  (1);
+       }
+       for (b = width * height - 1; b >= 0; b--) {
+               bmap[b] = bitmap[b] ^ 0xff;
+       }
+       bm_image = XCreateImage(Display_p, DefaultVisual(Display_p, Xscreen),
+                       1, XYBitmap, 0, bmap, width * 8, height,
+                       8, width);
+       bm_image->bitmap_unit = 8;
+       bm_image->bitmap_bit_order = MSBFirst;
+       XPutImage(Display_p, Win, gc, bm_image, 0, 0, x * 8, y, width * 8, height);
+       XDestroyImage(bm_image);
+       XFlush(Display_p);
+}
+
+#else
+
+/* some compilers complain about files that are effectively empty,
+ * so put in something even when entire file is effectively ifdef-ed out */
+static short dummy;
+
+#endif
+
diff --git a/mup/mupmate/Config.C b/mup/mupmate/Config.C
new file mode 100644 (file)
index 0000000..446238a
--- /dev/null
@@ -0,0 +1,1089 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+// Code for the Config menu item on the main toolbar
+
+#include "globals.H"
+#include "Preferences.H"
+#include "Config.H"
+#include "Main.H"
+#include "utils.H"
+#include <FL/fl_ask.H>
+#include <FL/Fl_Tooltip.H>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+
+// Window to ask user where files and tools are located
+
+FileLocations_dialog::FileLocations_dialog(void)
+       : Fl_Double_Window(620, 300, "Mupmate File Locations")
+{
+       mup_documentation_p = new Fl_Input(200, 30, 400, 30, "Mup Documentation Folder");
+       mup_documentation_p->tooltip("Set where Mup documentation\n"
+                               "files are installed on your system.\n"
+                               "This folder must contain the \"uguide\"\n"
+                               "folder that contains the HTML version\n"
+                               "of the Mup User's Guide.");
+
+       mup_program_p = new Fl_Input(200, 65, 400, 30, "Mup Command Path");
+       mup_program_p->tooltip("Set where the Mup program\n"
+                               "is installed on your system.");
+
+       music_files_p = new Fl_Input(200, 100, 400, 30, "Folder for Mup Files");
+       music_files_p->tooltip("Set the default folder for storing\n"
+                               "your Mup files (.mup input files,\n"
+                               "and .ps and .mid output files).");
+
+       muppath_p = new Fl_Input(200, 135, 400, 30, "Folder for Mup include Files");
+       static char include_tip_text[200];
+       (void) sprintf(include_tip_text,
+                       "Set the default folder (or list of folders,\n"
+                       "separated by %c characters) for\n"
+                       "storing your Mup \"include\" files.",
+                       path_separator());
+       muppath_p->tooltip(include_tip_text);
+
+       viewer_p = new Fl_Input(200, 170, 400, 30, "PostScript Viewer Path");
+       viewer_p->tooltip("Set which PostScript viewing program\n"
+                               "to use for displaying Mup output.\n"
+#ifdef OS_LIKE_WIN32
+                               "This is typically GSview32.exe\n"
+                               "which you can obtain from\n"
+                               "http://www.cs.wisc.edu/~ghost/gsview/"
+#else
+                               "The \"gv\" program is a common choice."
+#endif
+                       );
+
+       player_p = new Fl_Input(200, 205, 400, 30, "MIDI Player Path");
+       player_p->tooltip("Set which MIDI player program\n"
+                               "to use for playing Mup MIDI output.\n"
+#ifdef OS_LIKE_WIN32
+                               "This is typically wmplayer.exe"
+#else
+                               "Common choices include xplaymidi or timidity."
+#endif
+                       );
+
+       apply_p = new Fl_Return_Button(50, 255, 100, 30, "Apply");
+       apply_p->when(FL_WHEN_RELEASE);
+       apply_p->callback(Apply_cb, this);
+       
+       cancel_p = new Fl_Button(w() - 150, 255, 100, 30, "Cancel");
+       cancel_p->shortcut(FL_Escape);
+       cancel_p->when(FL_WHEN_RELEASE);
+       cancel_p->callback(Cancel_cb, this);
+
+       // Populate the fields
+       set_current_values();
+
+       // Arrange for destructor to clean up new-ed widgets
+       end();
+
+       // Arrange for window manager closes to do Cancel.
+       callback(Cancel_cb, this);
+       when(FL_WHEN_NEVER);
+}
+
+
+FileLocations_dialog::~FileLocations_dialog()
+{
+}
+
+
+//--- Callback for when user clicks "Apply" on FileLocations dialog.
+// Save values in preferences file.
+
+CALL_BACK(FileLocations_dialog, Apply)
+{
+       bool changes = false;           // if any changes made
+       bool error = false;             // if any errors found
+       char location[FL_PATH_MAX];
+
+       // Documentation location
+       if (mup_documentation_p->size() > 0) {
+               (void) Preferences_p->set(Mup_documentation_location,
+                                               mup_documentation_p->value());
+               changes = true;
+               // Documentation being wrong means User's Guide can't be
+               // shown, which is bad, although not fatal.
+               if ( ! fl_filename_isdir(mup_documentation_p->value()) ) {
+                       fl_alert("Location for Mup documentation is not a valid folder.");
+                       error = true;
+               }
+               else {
+                       if (access(users_guide_index_file(
+                                       mup_documentation_p->value()), F_OK)
+                                       != 0) {
+                               fl_alert("Folder specified for Mup documentation it not correct:\n"
+                                       "it does not contain the Mup User's Guide.");
+                               error = true;
+                       }
+               }
+       }
+
+       // Location of Mup program
+       if (mup_program_p->size() > 0) {
+               if (find_executable(mup_program_p->value(), location)) {
+                       (void) Preferences_p->set(Mup_program_location,
+                                               mup_program_p->value());
+                       changes = true;
+               }
+               else {
+                       fl_alert("Location specified for Mup program is not valid.");
+                       error = true;
+               }
+       }
+
+       // Default folder for Mup input files
+       if (music_files_p->size() > 0) {
+               if (chdir(music_files_p->value()) != 0) {
+                       fl_alert("Value for \"Folder for Mup Files\" is not a valid folder.");
+                       error = true;
+               }
+               else {
+                       (void) Preferences_p->set(Music_files_location,
+                                               music_files_p->value());
+                       changes = true;
+               }
+       }
+
+       // $MUPPATH value
+       if (muppath_p->size() > 0) {
+               (void) Preferences_p->set(MUPPATH_location, muppath_p->value());
+               // Set $MUPPATH
+               set_muppath(muppath_p->value());
+               changes = true;
+               // Setting MUPPATH correctly is only important if user
+               // actually uses it, which many people won't, but if it is set
+               // to something invalid, we give a warning.
+               // Since MUPPATH can be a list, we check each component
+               // in the list.
+               char pathcopy[muppath_p->size() + 1];
+               (void) strcpy(pathcopy, muppath_p->value());
+               char * component_p = pathcopy;
+               char * sep_p;   // where path separator appears in list
+               do {
+                       if ((sep_p = strchr(component_p, path_separator())) != 0) {
+                               *sep_p = '\0';
+                       }
+                       if (strlen(component_p) > 0 &&
+                                       ! fl_filename_isdir(component_p)) {
+                               fl_alert("Location for Mup include files\n"
+                                       "\"%s\"\nis not a valid folder.",
+                                       component_p);
+                               error = true;
+                       }
+                       component_p += strlen(component_p) + 1;
+               } while (sep_p != 0);
+       }
+
+       // PostScript viewer program
+       if (viewer_p->size() > 0) {
+               if (find_executable(viewer_p->value(), location)) {
+                       (void) Preferences_p->set(Viewer_location, viewer_p->value());
+                       changes = true;
+               }
+               else {
+                       fl_alert("Location specified for PostScript viewer is not valid.");
+                       error = true;
+               }
+       }
+
+       // MIDI player
+       if (player_p->size() > 0) {
+               if (find_executable(player_p->value(), location)) {
+                       (void) Preferences_p->set(MIDI_player_location, player_p->value());
+                       changes = true;
+               }
+               else {
+                       fl_alert("Location specified for MIDI player is not valid.");
+                       error =  true;
+               }
+       }
+
+       // If any changes, persist the data.
+       if (changes) {
+               Preferences_p->flush();
+       }
+
+       // If there were errors, leave form up so user can try to correct them.
+       if ( ! error ) {
+               hide();
+       }
+}
+
+
+//--- callback for when user clicks "Cancel" on FileLocations dialog
+
+CALL_BACK(FileLocations_dialog, Cancel)
+{
+       hide();
+       // Put all the original settings back on the form
+       set_current_values();
+}      
+
+
+// Populate form with the current default values from user's preferences.
+
+void
+FileLocations_dialog::set_current_values(void)
+{
+       char * val;
+       (void) Preferences_p->get(Mup_documentation_location, val,
+                                       Default_Mup_documentation_location);
+       mup_documentation_p->value(val);
+
+       (void) Preferences_p->get(Mup_program_location, val,
+                                       Default_Mup_program_location);
+       mup_program_p->value(val);
+
+       (void) Preferences_p->get(Music_files_location, val,
+                                       Default_music_files_location);
+       music_files_p->value(val);
+       (void) Preferences_p->get(MUPPATH_location, val,
+                                       Default_MUPPATH_location);
+       muppath_p->value(val);
+       (void) Preferences_p->get(Viewer_location, val,
+                                       Default_viewer_location);
+       viewer_p->value(val);
+       (void) Preferences_p->get(MIDI_player_location, val,
+                                       Default_MIDI_player_location);
+       player_p->value(val);
+}
+
+
+//-----------------------------------------------------------------
+
+// List of standard FLTK fonts, and info to map name to menu entry.
+static struct Font {
+       const char * name;
+       Fl_Font value;
+       int menu_offset;
+} Fontlist[] = {
+       { "Courier",                    FL_COURIER },
+       { "Courier Bold",               FL_COURIER_BOLD },
+       { "Courier Italic",             FL_COURIER_ITALIC },
+       { "Courier Bold Italic",        FL_COURIER_BOLD_ITALIC },
+       { "Helvetica",                  FL_HELVETICA },
+       { "Helvetica Bold",             FL_HELVETICA_BOLD },
+       { "Helvetica Italic",           FL_HELVETICA_ITALIC },
+       { "Helvetica Bold Italic",      FL_HELVETICA_BOLD_ITALIC },
+       { "Times",                      FL_TIMES },
+       { "Times Bold",                 FL_TIMES_BOLD },
+       { "Times Italic",               FL_TIMES_ITALIC },
+       { "Times Bold Italic",          FL_TIMES_BOLD_ITALIC },
+};
+static const int Fontlistlength = sizeof(Fontlist) / sizeof(Fontlist[0]);
+
+// Window to ask user preferences, like editor font, size, etc.
+
+Preferences_dialog::Preferences_dialog(void)
+       : Fl_Double_Window(400, 280, "Mupmate Preferences")
+{
+       // Make widget for user's editor font choice.
+       font_p = new Fl_Choice(20, 40, 210, 30, "Text Font");
+       font_p->tooltip("Select the font to be used\n"
+                       "in the editor window where you\n"
+                       "type in Mup input. It is also used\n"
+                       "for the Help and error report text.");
+       // Arrange to reset size menu if font selection changes
+       font_p->callback(fontchg_cb, this);
+       font_p->when(FL_WHEN_CHANGED);
+       font_p->align(FL_ALIGN_TOP_LEFT);
+
+       // Make widget for user's editor size choice.
+       size_p = new Fl_Choice(270, 40, 100, 30, "Text Size");
+       size_p->tooltip("Select the text size to be used\n"
+                       "in the editor window where you\n"
+                       "type in Mup input. It is also used\n"
+                       "for the Help and error report text.");
+       size_p->align(FL_ALIGN_TOP_LEFT);
+
+       auto_display_p = new Fl_Check_Button(20, 90, 180, 30,
+                                               "Auto-Display on Save");
+       auto_display_p->tooltip("Set whether your music\n"
+                       "is displayed automatically\n"
+                       "whenever you save your Mup file.");
+
+       auto_save_p = new Fl_Check_Button(w() - 170, 90, 150, 30,
+                                               "Auto-Save on Run");
+       auto_save_p->tooltip("Set whether your music is saved\n"
+                       "automatically whenever you do Display, Play,\n"
+                       "Write PostScript or Write MIDI from the Run menu.");
+
+       tooltips_delay_p = new Fl_Value_Input(150, 155, 100, 30, "Tool Tip Delay");
+       tooltips_delay_p->minimum(0.0);
+       tooltips_delay_p->precision(3);
+       tooltips_delay_p->tooltip("Set how long to delay before showing\n"
+                       "tool tips, in seconds.\n");
+       tooltips_delay_p->align(FL_ALIGN_TOP_LEFT);
+
+       // Create and configure widget for Apply button
+       apply_p = new Fl_Return_Button(60, 215, 100, 30, "Apply");
+       apply_p->when(FL_WHEN_RELEASE);
+       apply_p->callback(Apply_cb, this);
+
+       // Create and configure widget for Cancel button
+       cancel_p = new Fl_Button(w() - 160, 215, 100, 30, "Cancel");
+       cancel_p->shortcut(FL_Escape);
+       cancel_p->when(FL_WHEN_RELEASE);
+       cancel_p->callback(Cancel_cb, this);
+
+       // Populate the fields
+       set_current_values();
+
+       // Arrange for destructor to clean up new-ed widgets
+       end();
+
+       // Arrange for window manager closes to do Cancel.
+       callback(Cancel_cb, this);
+       when(FL_WHEN_NEVER);
+}
+
+Preferences_dialog::~Preferences_dialog()
+{
+}
+
+
+//---- Callback for when user changes font selection.
+// This re-creates the size menu to be what sizes are available
+// for that font, since each font could have a different set of sizes.
+
+CALL_BACK(Preferences_dialog, fontchg)
+{
+       unsigned char size;
+       if (size_p->mvalue() != 0) {
+               size = atoi(size_p->mvalue()->text);
+       }
+       else {
+               // Shouldn't really be possible to get here,
+               // but better to be safe.
+               size = (unsigned char) atoi(Default_editor_size);
+       }
+
+       set_size_list(Config::fontvalue(font_p->mvalue()->text), size);
+}
+
+
+//--- Callback for when user clicks Apply in Preferences
+// Save the new values.
+
+CALL_BACK(Preferences_dialog, Apply)
+{
+       Fl_Font font;
+       int n;
+
+       Preferences_p->set(Auto_display_preference, auto_display_p->value());
+       Preferences_p->set(Auto_save_preference, auto_save_p->value());
+       Preferences_p->set(Tooltips_delay_preference, tooltips_delay_p->value());
+       Fl_Tooltip::delay(tooltips_delay_p->value());
+
+       // Convert font menu selection into font value.
+       for (n = 0; n < Fontlistlength; n++) {
+               if (Fontlist[n].menu_offset == font_p->value()) {
+                       Preferences_p->set(Editor_font_preference, Fontlist[n].name);
+                       font = Fontlist[n].value;
+                       break;
+               }
+       }
+       if (n >= Fontlistlength) {
+               // Selection not valid. Fall back to using the default.
+               char * fontname;
+               (void) Preferences_p->get(Editor_font_preference, fontname,
+                                                       Default_editor_font);
+               font = Config::fontvalue(fontname);
+       }
+
+       // Save size value.
+       unsigned char size;
+       if (size_p->text() != 0) {
+               (void) Preferences_p->set(Editor_size_preference, size_p->text());
+               size = (unsigned char) atoi(size_p->text());
+       }
+       else {
+               size = (unsigned char) atoi(Default_editor_size);
+       }
+
+       // Persist the data.
+       Preferences_p->flush();
+
+       // Actually change the font/size in all relevant windows.
+       // Windows that want to know about these changes register a callback,
+       // so we call them.
+       Font_change_registration::run_callbacks(font, size);
+
+       hide();
+}
+
+//--- callback for when user clicks Cancel in Preferences
+
+CALL_BACK(Preferences_dialog, Cancel)
+{
+       hide();
+       // Put all the original settings back on the form
+       set_current_values();
+}
+
+
+// Populate form with current values from user's preferences
+
+void
+Preferences_dialog::set_current_values(void)
+{
+       int auto_display;
+       (void) Preferences_p->get(Auto_display_preference, auto_display,
+                                               Default_auto_display);
+       auto_display_p->value(auto_display);
+
+       int auto_save;
+       (void) Preferences_p->get(Auto_save_preference, auto_save,
+                                               Default_auto_save);
+       auto_save_p->value(auto_save);
+
+       double tooltips_delay;
+       (void) Preferences_p->get(Tooltips_delay_preference, tooltips_delay,
+                                               Default_tooltips_delay);
+       tooltips_delay_p->value(tooltips_delay);
+
+       char * fontname;
+       (void) Preferences_p->get(Editor_font_preference, fontname,
+                                               Default_editor_font);
+       Fl_Font font = Config::fontvalue(fontname);
+       // Populate font menu
+       font_p->clear();
+       for (int i = 0; i < Fontlistlength; i++) {
+               Fontlist[i].menu_offset =
+                       font_p->add(Fontlist[i].name, 0, 0, 0, 0);
+               // Set the current value
+               if (Fontlist[i].value == font) {
+                       font_p->value(Fontlist[i].menu_offset);
+               }
+       }
+
+       char * sizename;
+       (void) Preferences_p->get(Editor_size_preference, sizename,
+                                               Default_editor_size);
+       unsigned char size = (unsigned char) atoi(sizename);
+       // Populate the size menu
+       set_size_list(font, size);
+}
+
+
+// When font selection changes, re-create the size menu,
+// because each font could have different sizes available.
+
+void
+Preferences_dialog::set_size_list(Fl_Font font, uchar curr_size)
+{
+       // Avoid really tiny sizes, or more importantly, zero, like if an atoi
+       // failed, because otherwise FLTK may try to divide by zero.
+       // Also limit to a maximum size.
+       if (curr_size < Min_size || curr_size > Max_size) {
+               curr_size = (unsigned char) atoi(Default_editor_size);
+       }
+
+       // Clean out the current menu if any
+       size_p->clear();
+       
+       // Populate the menu
+       int * sizelist;
+       int numsizes = Fl::get_font_sizes(font, sizelist);
+       
+       // Set current value to ridiculous value, then find closest
+       int currvalue = 5000;
+
+       int i;  // index through sizelist
+       int menu_index; // index into menu
+       for (i = menu_index = 0; i < numsizes; i++) {
+               if (sizelist[i] == 0) {
+                       // This means font is scaleable 
+                       continue;
+               }
+               if (sizelist[i] > Max_size) {
+                       break;
+               }
+               char num_as_string[4];
+               (void) sprintf(num_as_string, "%d", sizelist[i]);
+               size_p->add(num_as_string, 0, 0, 0, 0);
+               // If this is closest index to desired size, mark as current
+               if ( abs(sizelist[i] - currvalue) > abs(sizelist[i] - curr_size) ) {
+                       currvalue = sizelist[i];
+                       size_p->value(menu_index);
+               }
+               menu_index++;
+       }
+       if (numsizes == 0 || (numsizes == 1 && sizelist[0] == 0)) {
+               // Either no available sizes at all, or only
+               // scaleable, with no special "good" sizes,
+               // so we pick some and hope for the best.
+               size_p->add("10", 0, 0, 0, 0);
+               if (curr_size <= 11) {
+                       size_p->value(0);
+               }
+               size_p->add("12", 0, 0, 0, 0);
+               if (curr_size >= 12 && curr_size <= 13) {
+                       size_p->value(1);
+               }
+               size_p->add("14", 0, 0, 0, 0);
+               if (curr_size >= 14 && curr_size <= 15) {
+                       size_p->value(2);
+               }
+               size_p->add("16", 0, 0, 0, 0);
+               if (curr_size >= 16 && curr_size <= 17) {
+                       size_p->value(3);
+               }
+               size_p->add("18", 0, 0, 0, 0);
+               if (curr_size >= 18) {
+                       size_p->value(4);
+               }
+       }
+}
+
+//----------dialog to let user fill in the Registration form---------------
+
+#define MULTI_OS "Note that if you wish to use Mup\n" \
+       "on multiple machines simultaneously,\n" \
+       "you need to purchase a registration\n" \
+       "for each."
+
+
+RegistrationForm_dialog::RegistrationForm_dialog(void)
+       : Fl_Double_Window(500, 450, "Mup Registration")
+{
+       name_p = new Fl_Input(80, 20, 400, 30, "Name");
+       name_p->tooltip("Enter your name.");
+
+       address_p = new Fl_Input(80, 60, 400, 30, "Address");
+       address_p->tooltip("Enter your street address.");
+
+       city_p = new Fl_Input(80, 100, 180, 30, "City");
+       city_p->tooltip("Enter the name of the city\n"
+                               "in which you live.");
+       state_p = new Fl_Input(380, 100, 100, 30, "State/Province");
+       state_p->tooltip("Enter the state or province (if any)\n"
+                       "in which you live.");
+
+       postal_code_p = new Fl_Input(110, 140, 120, 30, "Postal Code");
+       postal_code_p->tooltip("Enter your zip code or postal code\n"
+                               "as appropriate for your country.");
+
+       country_p = new Fl_Input(320, 140, 160, 30, "Country");
+       country_p->tooltip("Enter the name of the country in which\n"
+                       "you live (optional if in USA).");
+
+       email_p = new Fl_Input(110, 180, 370, 30, "Email address");
+       email_p->tooltip("Enter your email address. This will only be used\n"
+                       "to send you your registration key\n"
+                       "and announcements of future (free) Mup upgrades.");
+
+       how_heard_p = new Fl_Input(20, 240, 460, 30, "Where did you hear about Mup?");
+       how_heard_p->align(FL_ALIGN_TOP_LEFT);
+       how_heard_p->tooltip("Please let us know how you learned about Mup\n"
+                       "(a particular web link, magazine, book, etc.).");
+
+       // Checkboxes for OS types.
+       // If we are compiled for a particular OS,
+       // automatically check that box.
+       Windows_p = new Fl_Check_Button(20, 280, 80, 30, "Windows");
+#ifdef __WIN32
+       Windows_p->value(1);
+#endif
+       Windows_p->tooltip("Check here if you plan to run Mup\n"
+                       "under Microsoft Windows.\n"
+                       MULTI_OS);
+
+       Mac_p = new Fl_Check_Button(110, 280, 50, 30, "Mac");
+       Mac_p->tooltip("Check here if you plan to run Mup\n"
+                       "under Apple Mac OS.\n"
+                       MULTI_OS);
+#ifdef __APPLE__
+       Mac_p->value(1);
+#endif
+
+       Linux_p = new Fl_Check_Button(170, 280, 60, 30, "Linux");
+       Linux_p->tooltip("Check here if you plan to run Mup\n"
+                       "under Linux. "
+                       MULTI_OS);
+#ifdef __linux
+       Linux_p->value(1);
+#endif
+
+       other_p = new Fl_Check_Button(240, 280, 60, 30, "Other");
+       other_p->tooltip("Check here if you plan to run Mup\n"
+                       "under an OS not listed.\n"
+                       MULTI_OS);
+       other_OS_p = new Fl_Input(300, 280, 180, 30, "");
+       other_OS_p->tooltip("If you checked \"Other,\"\n"
+                       "specify the name of the Operating System.\n"
+                       MULTI_OS);
+
+       mailing_list_p = new Fl_Check_Button(100, 320, 350, 30,
+                               "I would like to join the Mup user's mailing list");
+       mailing_list_p->tooltip("There is a email mailing list for registered\n"
+                       "Mup users, for sharing information about Mup.\n"
+                       "Check here if you want to join the list.\n"
+                       "There is no extra charge, and you can always\n"
+                       "subscribe/unsubscribe later if you change your mind.");
+
+       num_regs_p = new Positive_Int_Input(340, 355, 60, 30,
+                                       "Number of Registrations ($29 each)");
+       num_regs_p->value("1");
+       num_regs_p->tooltip("Enter the number of registrations\n"
+                       "you wish to purchase.\n"
+                       MULTI_OS);
+
+       save_form_p = new Fl_Return_Button(40, h() - 50, 120, 30, "Save Form");
+       save_form_p->callback(SaveForm_cb, this);
+       cancel_p = new Fl_Button(w() - 160, h() - 50, 120, 30, "Cancel");
+       cancel_p->shortcut(FL_Escape);
+       cancel_p->when(FL_WHEN_RELEASE);
+       cancel_p->callback(Cancel_cb, this);
+
+       // Arrange for destructor to clean up new-ed widgets
+       end();
+
+       // Arrange for window manager closes to do Cancel.
+       callback(Cancel_cb, this);
+       when(FL_WHEN_NEVER);
+}
+
+
+RegistrationForm_dialog::~RegistrationForm_dialog(void)
+{
+}
+
+
+CALL_BACK(RegistrationForm_dialog, SaveForm)
+{
+       generate_form();
+       hide();
+}
+
+
+CALL_BACK(RegistrationForm_dialog, Cancel)
+{
+       hide();
+}
+
+
+// Generate the registration form with fields filled in.
+
+extern const char * const registration_text;
+static const char * const checkmark = "X";
+static const char * const reg_file_name = "mup-reg.txt";
+
+void
+RegistrationForm_dialog::generate_form()
+{
+       char * text = strdup(registration_text);
+
+       // First find all the fields in the registration form.
+       // Do this before filling anything is to avoid any chance
+       // of being confused by what we fill in.
+       char * name = strstr(text, "Name");
+       char * address = strstr(text, "Address");
+       char * city = strstr(text, "City");
+       char * state = strstr(text, "State");
+       char * postal_code = strstr(text, "Zip code");
+       char * country = strstr(text, "Country");
+       char * email = strstr(text, "Email");
+       char * how_heard = strstr(text, "How did you");
+       char * how_heard_line2 = strstr(how_heard, "\n\n");
+       char * Linux = strstr(text, "Linux");
+       char * Windows = strstr(text, "Windows/MS-DOS");
+       char * Mac = strstr(text, "Mac");
+       char * other = strstr(text, "Other");
+       char * mailing_list = strstr(text, "Yes");
+       char * regs = strstr(text, "Mup Version");
+
+       (void) fill_in(false, name, name_p->value());
+       (void) fill_in(false, address, address_p->value());
+       (void) fill_in(false, city, city_p->value());
+       (void) fill_in(false, state, state_p->value());
+       (void) fill_in(false, postal_code, postal_code_p->value());
+       (void) fill_in(false, country, country_p->value());
+       (void) fill_in(false, email, email_p->value());
+       const char * remaining;
+       if ((remaining = fill_in(false, how_heard, how_heard_p->value()))
+                                                                       != 0) {
+               (void) fill_in(false, how_heard_line2, remaining);
+       }
+
+       if (Windows_p->value()) {
+               (void) fill_in(true, Windows, checkmark);
+       }
+       if (Linux_p->value()) {
+               (void) fill_in(true, Linux, checkmark);
+       }
+       if (Mac_p->value()) {
+               (void) fill_in(true, Mac, checkmark);
+       }
+       if (other_p->value()) {
+               (void) fill_in(true, other, checkmark);
+       }
+       if (other_OS_p->size() > 0) {
+               (void) fill_in(false, other, other_OS_p->value());
+       }
+       (void) fill_in(mailing_list_p->value(), mailing_list, checkmark);
+
+       (void) fill_in(true, regs, num_regs_p->value());
+
+       // write to file
+       FILE * regfile;
+       if ((regfile = fopen(reg_file_name, "w")) == 0) {
+               fl_alert("Unable to write registration form file.");
+       }
+       else {
+               (void) fprintf(regfile, "%s", text);
+               (void) fprintf(regfile, "\n\n\t Total due:  $%.2f\n",
+                       (29.0 + sales_tax()) * atoi(num_regs_p->value()));
+               fclose(regfile);
+               char currdir[FL_PATH_MAX];
+
+               if (getcwd(currdir, sizeof(currdir)) == 0) {
+                       currdir[0] = '\0';
+               }
+               hide();
+               fl_message("Your registration form has been saved in\n"
+                       "%s%c%s.", currdir, dir_separator(), reg_file_name);
+       }
+       free(text);
+}
+
+
+// Fills in value into blank either before or after the given place.
+// Center the string in the blank.
+// If it can't fit the entire value, it returns a pointer to
+// what was left over, otherwise returns zero.
+
+const char *
+RegistrationForm_dialog::fill_in(bool before, char * place, const char * const value)
+{ 
+       if (place == 0 || value == 0) {
+               // Shouldn't happen, but better than core dump.
+               return(value);
+       }
+
+       char * blanks_p;
+       // Find beginning of the blank.
+       if (before) {
+               // back up to beginning of blanks, skipping any spaces
+               for (blanks_p = place - 1; *blanks_p == ' '; blanks_p--)
+                       ;
+               for (   ; *blanks_p == '_'; blanks_p--)
+                       ;
+               blanks_p++;
+       }
+       else {
+               blanks_p = strchr(place, '_');
+       }
+
+       // Figure out how much leading padding to leave
+       int count = strspn(blanks_p, "_");
+       int length = strlen(value);
+
+       // Fill in the blank.
+       int padding;
+       if (length > count) {
+               // Try to split at white space.
+               int used_length;
+               for (used_length = count; used_length > 10; used_length--) {
+                       if (value[used_length] == ' ') {
+                               break;
+                       }
+               }
+               padding = (count - used_length) / 2;
+               strncpy(blanks_p + padding, value, used_length);
+               return(value + used_length + 1);
+       }
+       else {
+               padding = (count - length) / 2;
+               strncpy(blanks_p + padding, value, length);
+               return(0);
+       }
+}
+
+
+// Since Arkkra is based in Illinois, Illinois residents need to pay
+// sales tax. So try to deduce if the address is Illinois.
+// Simple minded--may sometimes guess wrong.
+
+double
+RegistrationForm_dialog::sales_tax(void)
+{
+       const char * pattern;
+
+       if (state_p->size() > 0) {
+               // Skip leading white space
+               for (pattern = state_p->value(); *pattern == ' '; pattern++)
+                       ;
+               if (*pattern == '\0') {
+                       return(0.0);
+               }
+               // Remove any trailing white space.
+               // Can't remove in place, since string is const.
+               // So remove from copy.
+               char state[strlen(pattern) + 1];
+               (void) strcpy(state, pattern);
+               char * p;
+               for (p = state + strlen(pattern) - 1; p > state ; p--) {
+                       if (*p == ' ') {
+                               *p = '\0';
+                       }
+                       else {
+                               break;
+                       }
+               }
+               
+               if (strcmp(state, "IL") == 0
+                               || strcasecmp(state, "Illinois") == 0
+                               || strcasecmp(state, "Ill.") == 0) {
+                       // Sales tax is $2.18 per registration.
+                       return(2.18);
+               }
+       }
+       return(0.0);
+}
+
+
+//----------dialog to let user type in the Registration Key---------------
+
+RegistrationKey_dialog::RegistrationKey_dialog(void)
+       : Fl_Double_Window(250, 100, "Registration Key")
+{
+       key_p = new Fl_Secret_Input(60, 20, 150, 30, "Key:");
+       key_p->tooltip("Enter the registration key\n"
+               "you received from Arkkra Enterprises\n"
+               "after you have paid your registration fee.");
+
+       OK_p = new Fl_Return_Button(25, 60, 80, 30, "OK:");
+       OK_p->when(FL_WHEN_RELEASE);
+       OK_p->callback(OK_cb, this);
+
+       cancel_p = new Fl_Button(120, 60, 90, 30, "Cancel");
+       cancel_p->shortcut(FL_Escape);
+       cancel_p->when(FL_WHEN_RELEASE);
+       cancel_p->callback(Cancel_cb, this);
+
+       // Arrange for destructor to clean up new-ed widgets
+       end();
+
+       // Arrange for window manager closes to do Cancel.
+       callback(Cancel_cb, this);
+       when(FL_WHEN_NEVER);
+}
+
+
+RegistrationKey_dialog::~RegistrationKey_dialog()
+{
+}
+
+CALL_BACK(RegistrationKey_dialog, OK)
+{
+       hide();
+       FILE * keyfile;
+       if ((keyfile = fopen(magic_file(), "w")) == 0) {
+               fl_alert("Unable to open registration key file %s.",
+                                                       magic_file());
+       }
+       else {
+               if (fprintf(keyfile, "%s", key_p->value()) != key_p->size()) {
+                       fl_alert("Unable to save registration key in %s.",
+                                                       magic_file());
+               }
+               fclose(keyfile);
+       }
+
+       // Blank out the field, for if it gets displayed again later.
+       key_p->value("");
+}
+
+
+// If user cancels entering registration key, we just hide the window
+
+CALL_BACK(RegistrationKey_dialog, Cancel)
+{
+       hide();
+}
+
+
+//-------the Config menu item on main toolbar-------------------------------
+
+Config::Config()
+{
+       locations_p = 0;
+       preferences_p = 0;
+       registrationform_p = 0;
+       registrationkey_p = 0;
+}
+
+Config::~Config()
+{
+       if (locations_p != 0) {
+               delete locations_p;
+               locations_p = 0;
+       }
+       if (preferences_p != 0) {
+               delete preferences_p;
+               preferences_p = 0;
+       }
+       if (registrationform_p != 0) {
+               delete registrationform_p;
+               registrationform_p = 0;
+       }
+       if (registrationkey_p != 0) {
+               delete registrationkey_p;
+               registrationkey_p = 0;
+       }
+}
+
+
+// Bring up the dialog for "File Locations" menu item
+
+CALL_BACK(Config, FileLocations)
+{
+       if (locations_p == 0) {
+               // first time, create widget
+               locations_p = new FileLocations_dialog();
+       }
+       locations_p->show();
+}
+
+
+// Bring up the dialog for "Preferences" menu item
+
+CALL_BACK(Config, Preferences)
+{
+       if (preferences_p == 0) {
+               // first time, create widget
+               preferences_p = new Preferences_dialog();
+       }
+       preferences_p->show();
+}
+
+
+// Bring up dialog for filling in Registration Form
+
+CALL_BACK(Config, RegistrationForm)
+{
+       if (registrationform_p == 0) {
+               // first time, create widget
+               registrationform_p = new RegistrationForm_dialog();
+       }
+       registrationform_p->show();
+       fl_message("Note: For fastest service, you can register via\n"
+               "credit card at http://www.arkkra.com/doc/credtcrd.html\n"
+               "rather than filling out and mailing in a paper form.");
+}
+
+
+// Bring up dialog to let user enter their registration key after paying
+
+CALL_BACK(Config, RegistrationKey)
+{
+       if (registrationkey_p == 0) {
+               // first time, create widget
+               registrationkey_p = new RegistrationKey_dialog();
+       }
+       registrationkey_p->show();
+}
+
+
+// Translate font name to FL_Font value.
+
+Fl_Font
+Config::fontvalue(const char * fontname)
+{
+       int n;
+       // Linear search of the list (it is short).
+       for (n = 0; n < Fontlistlength; n++) {
+               if (strcmp(Fontlist[n].name, fontname) == 0) {
+                       return(Fontlist[n].value);
+               }
+       }
+       // Hmmm. Not found. Should not happen. Hunt for default
+       for (n = 0; n < Fontlistlength; n++) {
+               if (strcmp(Fontlist[n].name, Default_editor_font) == 0) {
+                       return(Fontlist[n].value);
+               }
+       }
+       // Wow. Can't find default either. Punt.
+       return(FL_COURIER);
+}
+
+
+//--------------------- class that lets other classes register a callback
+// to be called for changes in font/size
+
+
+// List of callbacks for when font/size change
+Font_change_registration * Font_change_registration::list_p = 0;
+
+Font_change_registration::Font_change_registration(Font_change_callback func, void * arg)
+{
+       // Save callback information.
+       callback = func;
+       callback_arg = arg;
+
+       // Add to list of callbacks.
+       next = list_p;
+       list_p = this;
+
+       // Set the font and size on this newly registered widget.
+       // Look up the current values and call the newly registered callback.
+       char * fontstr;
+       (void) Preferences_p->get(Editor_font_preference, fontstr,
+                                                       Default_editor_font);
+       Fl_Font font = Config::fontvalue(fontstr);
+
+       char * sizestr;
+       (void) Preferences_p->get(Editor_size_preference, sizestr,
+                                                       Default_editor_size);
+       unsigned char size = (unsigned char) atoi(sizestr);
+       if (size < Min_size) {
+               size = (unsigned char) atoi(Default_editor_size);
+       }
+       (*func)(arg, font, size);
+}
+
+Font_change_registration::~Font_change_registration(void)
+{
+       // Remove callback from linked list
+       if (list_p == this) {
+               list_p = next;
+       }
+       else {
+               Font_change_registration * fcr_p;
+               for (fcr_p = list_p; fcr_p != 0; fcr_p = fcr_p->next) {
+                       if (fcr_p->next == this) {
+                               fcr_p->next = next;
+                               return;
+                       }
+               }
+       }
+}
+
+
+// Notify all classes that want to know about font/size changes,
+// by calling the callback function they registered.
+
+void
+Font_change_registration::run_callbacks(Fl_Font font, unsigned char size)
+{
+       // Avoid unreadably small sizes and division by zero if
+       // earlier atoi() of size failed due to bad data
+       // (e.g., user hand-editing the preference file)
+       if (size < Min_size || size > Max_size) {
+               size = (unsigned char) atoi(Default_editor_size);
+       }
+
+       // Walk through list of registered callbacks, calling each.
+       Font_change_registration * fcr_p;
+       for (fcr_p = list_p; fcr_p != 0; fcr_p = fcr_p->next) {
+               (*(fcr_p->callback))(fcr_p->callback_arg, font, size);
+       }
+}
diff --git a/mup/mupmate/Config.H b/mup/mupmate/Config.H
new file mode 100644 (file)
index 0000000..e127a7f
--- /dev/null
@@ -0,0 +1,220 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+
+// Classes for Config menu item off of main toolbar
+
+#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Secret_Input.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Return_Button.H>
+#include <FL/Fl_Check_Button.H>
+#include <FL/Fl_Choice.H>
+#include <FL/Fl_Value_Input.H>
+#include "utils.H"
+
+
+// Class for window that asks user for file locations
+
+class FileLocations_dialog : Fl_Double_Window {
+
+friend class Config;
+
+public:
+       FileLocations_dialog(void);
+       ~FileLocations_dialog();
+
+       // Callbacks
+       static void Apply_cb(Fl_Widget *, void *);
+       static void Cancel_cb(Fl_Widget *, void *);
+
+private:
+       // Callbacks
+       void Apply(void);
+       void Cancel(void);
+
+       // Populuate fields with current values
+       void set_current_values(void);
+
+       // Widgets
+       Fl_Input * mup_program_p;
+       Fl_Input * mup_documentation_p;
+       Fl_Input * music_files_p;
+       Fl_Input * muppath_p;
+       Fl_Input * viewer_p;
+       Fl_Input * player_p;
+       Fl_Return_Button * apply_p;
+       Fl_Button * cancel_p;
+};
+
+
+// Class for window that asks user for preferences, like editor font, size, etc.
+
+class Preferences_dialog : Fl_Double_Window {
+
+friend class Config;
+
+public:
+       Preferences_dialog(void);
+       ~Preferences_dialog();
+
+       // Callbacks
+       static void Apply_cb(Fl_Widget *, void * data);
+       static void Cancel_cb(Fl_Widget *, void * data);
+       static void fontchg_cb(Fl_Widget *, void * data);
+
+private:
+       // Callbacks
+       void fontchg(void);
+       void Apply(void);
+       void Cancel(void);
+
+       // Populate fields with current values
+       void set_current_values(void);
+
+       // Populate size menu as appropriate for the given font
+       void set_size_list(Fl_Font font, uchar curr_size);
+
+       // Widgets
+       Fl_Choice * font_p;
+       Fl_Choice * size_p;
+       Fl_Check_Button * auto_display_p;
+       Fl_Check_Button * auto_save_p;
+       Fl_Value_Input * tooltips_delay_p;
+       Fl_Return_Button * apply_p;
+       Fl_Button * cancel_p;
+};
+
+
+// Class for user to fill out registration form
+
+class RegistrationForm_dialog : public Fl_Double_Window
+{
+public:
+       RegistrationForm_dialog(void);
+       ~RegistrationForm_dialog(void);
+
+       // Callbacks
+       static void SaveForm_cb(Fl_Widget *, void * data);
+       static void Cancel_cb(Fl_Widget *, void * data);
+
+private:
+       // Callbacks
+       void SaveForm(void);
+       void Cancel(void);
+
+       // Fill in the form and write it out for user to mail with payment.
+       void generate_form(void);
+       // Fill in the value in the blank before or after the given place.
+       // If can't fit entire value, returns pointer to how far it got,
+       // otherwise returns zero.
+       const char * fill_in(bool before, char *place, const char * const value);
+       // Calculate sales tax due.
+       double sales_tax(void);
+
+       // Widgets
+       Fl_Input * name_p;
+       Fl_Input * address_p;
+       Fl_Input * city_p;
+       Fl_Input * state_p;
+       Fl_Input * postal_code_p;
+       Fl_Input * country_p;
+       Fl_Input * email_p;
+       Fl_Input * how_heard_p;
+       Fl_Check_Button * Windows_p;
+       Fl_Check_Button * Mac_p;
+       Fl_Check_Button * Linux_p;
+       Fl_Check_Button * other_p;
+       Fl_Input * other_OS_p;
+       Fl_Check_Button * mailing_list_p;
+       Positive_Int_Input  * num_regs_p;
+
+       Fl_Return_Button * save_form_p;
+       Fl_Button * cancel_p;
+};
+
+
+// Class for user to enter registration key after paying.
+
+class RegistrationKey_dialog : public Fl_Double_Window {
+public:
+       RegistrationKey_dialog(void);
+       ~RegistrationKey_dialog();
+
+       // Callbacks
+       static void OK_cb(Fl_Widget *, void *);
+       static void Cancel_cb(Fl_Widget *, void *);
+
+private:
+       // Callbacks
+       void OK(void);
+       void Cancel(void);
+
+       // Widgets
+       Fl_Secret_Input * key_p;
+       Fl_Return_Button * OK_p;
+       Fl_Button * cancel_p;
+};
+
+// Class for the Config menu item on main toolbar
+
+class Config {
+public:
+       Config();
+       ~Config();
+
+       // Callbacks
+       static void FileLocations_cb(Fl_Widget *, void *);
+       static void Preferences_cb(Fl_Widget *, void *);
+       static void RegistrationForm_cb(Fl_Widget *, void *);
+       static void RegistrationKey_cb(Fl_Widget *, void *);
+
+       // Convert font name to Fl_Font value
+       static Fl_Font fontvalue(const char *);
+
+private:
+       // Callbacks
+       void FileLocations(void);
+       void Preferences(void);
+       void RegistrationForm(void);
+       void RegistrationKey(void);
+
+       // Widgets
+       FileLocations_dialog * locations_p;
+       Preferences_dialog * preferences_p;
+       RegistrationForm_dialog * registrationform_p;
+       RegistrationKey_dialog * registrationkey_p;
+};
+
+
+// Any class that wants to be notified of changes in user preference
+// for font and size should register a callback function of this type
+// using the Font_change_registration class. The first arg will be user
+// data the registrant wants to have passed to it. The second argument
+// is the new font, and the third argument is the new size.
+typedef void (*Font_change_callback)(void *, Fl_Font, unsigned char);
+
+// Any class that wants to be notified of changes in user preference
+// in font/size should instantiate an instance of this class.
+class Font_change_registration {
+public:
+       Font_change_registration(Font_change_callback func, void * arg);
+       ~Font_change_registration(void);
+
+       // This runs all the registered callbacks
+       static void run_callbacks(Fl_Font font, unsigned char size);
+
+private:
+       // Linked list of callbacks
+       static Font_change_registration * list_p;
+       Font_change_registration * next;
+
+       // What function to call back, and what to pass it.
+       Font_change_callback callback;
+       void * callback_arg;
+};
+
+#endif
diff --git a/mup/mupmate/Edit.C b/mup/mupmate/Edit.C
new file mode 100644 (file)
index 0000000..f85e632
--- /dev/null
@@ -0,0 +1,640 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+// Code for Edit menu on main toolbar
+
+
+#include "globals.H"
+#include "Edit.H"
+#include "utils.H"
+#include <FL/Enumerations.H>
+#include <FL/fl_ask.H>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+
+//-------------------Find_dialog class--------------------------------
+// This class is for the window that pops up when user does a "Find"
+
+// Constructor creates the window and all the widgets inside it
+
+Find_dialog::Find_dialog(void)
+       : Fl_Double_Window(430, 170, "Find")
+{
+       pattern_p = new Fl_Input(90, 20, 175, 20, "Find what:");
+       // We have ungray the "Find Next" when user enters a pattern,
+       // so set up callback for that
+       pattern_p->callback(Pattern_cb, this);
+       pattern_p->when(FL_WHEN_CHANGED);
+       pattern_p->tooltip("Enter the pattern you want to\n"
+                       "search for in your Mup input.");
+
+       replace_with_p = new Fl_Input(90, 60, 175, 20, "Replace with");
+       replace_with_p->tooltip("Enter the replacement text.");
+       replace_with_p->hide();
+
+       casematch_p = new Fl_Check_Button(10, 85, 100, 20, "Match case");
+       casematch_p->tooltip("If checked, upper/lower case must match.\n"
+                       "If not checked, case is ignored.");
+
+       direction_p = new Fl_Box(FL_ENGRAVED_BOX, 120, 55, 125, 35, "");
+       up_p = new Fl_Round_Button(130, 60, 40, 20, "Up");
+       up_p->type(FL_RADIO_BUTTON);
+       up_p->value(0);
+       up_p->tooltip("Search upward from current place.");
+       up_p->callback(change_cb, this);
+       down_p = new Fl_Round_Button(175, 60, 60, 20, "Down");
+       down_p->type(FL_RADIO_BUTTON);
+       down_p->value(1);
+       down_p->tooltip("Search downward from current place.");
+       down_p->callback(change_cb, this);
+
+       next_p = new Fl_Return_Button(285, 10, 125, 30, "Find Next");
+       next_p->when(FL_WHEN_RELEASE);
+       next_p->callback(FindNext_cb, this);
+       next_p->deactivate();
+
+       replace_p = new Fl_Button(285, 45, 125, 30, "Replace");
+       replace_p->tooltip("Replace the current instance of the pattern\n"
+                       "with the replacement text.");
+       replace_p->callback(Replace_cb, this);
+       replace_p->when(FL_WHEN_RELEASE);
+       replace_p->deactivate();
+       replace_p->hide();
+
+       replace_all_p = new Fl_Button(285, 80, 125, 30, "Replace All");
+       replace_all_p->tooltip("Replace all instances of the pattern\n"
+                       "with the replacement text.");
+       replace_all_p->callback(ReplaceAll_cb, this);
+       replace_all_p->when(FL_WHEN_RELEASE);
+       replace_all_p->deactivate();
+       replace_all_p->hide();
+
+       cancel_p = new Fl_Button(285, 115, 125, 30, "Cancel");
+       cancel_p->shortcut(FL_Escape);
+       cancel_p->when(FL_WHEN_RELEASE);
+       cancel_p->callback(Cancel_cb, this);
+
+       // Arrange for destructor to clean up new-ed widgets
+       end();
+
+       // Arrange for window manager closes to do Cancel.
+       callback(Cancel_cb, this);
+       when(FL_WHEN_NEVER);
+}
+
+Find_dialog::~Find_dialog()
+{
+}
+
+
+// The class can be used for either Find or Replace.
+// These next two methods set which of those two personalities
+// the window has.
+
+void
+Find_dialog::as_Find()
+{
+       label("Find");
+       cancel_p->resize(cancel_p->x(), 55, cancel_p->w(), cancel_p->h());
+       casematch_p->resize(casematch_p->x(), 65, casematch_p->w(), casematch_p->h());
+       resize(x(), y(), w(), 120);
+       direction_p->show();
+       up_p->show();
+       down_p->show();
+       replace_with_p->hide();
+       replace_p->hide();
+       replace_all_p->hide();
+       is_replace = false;
+}
+
+void
+Find_dialog::as_Replace()
+{
+       label("Replace");
+       cancel_p->resize(cancel_p->x(), 115, cancel_p->w(), cancel_p->h());
+       casematch_p->resize(casematch_p->x(), 115, casematch_p->w(), casematch_p->h());
+       resize(x(), y(), w(), 155);
+       direction_p->hide();
+       up_p->hide();
+       down_p->hide();
+       replace_with_p->show();
+       replace_p->show();
+       replace_all_p->show();
+       is_replace = true;
+}
+
+
+// Callback for when user clicks "Find Next" button after filling in
+// the dialog.
+
+CALL_BACK(Find_dialog, FindNext)
+{
+       int start = editor_p->insert_position();
+       bool found;
+       int where;
+       if (down_p->value() == 1 || is_replace) {
+               found = editor_p->buffer()->search_forward(
+                               start + 1, pattern_p->value(),
+                               &where, casematch_p->value());
+       }
+       else {
+               found = editor_p->buffer()->search_backward(
+                               start - 1, pattern_p->value(),
+                               &where, casematch_p->value());
+       }
+
+       if ( ! found ) {
+               // It seems fltk does not find a pattern if it is exactly
+               // at the beginning for an upward search or exactly
+               // at the end for a downward search. That surely can't
+               // be right, so add special checks for that. If fltk
+               // fixes that some day, we'll never hit this case,
+               // so this should still be compatible.
+               int patlength = pattern_p->size();
+               int bufflength = editor_p->buffer()->length();
+               where = (down_p->value() ? bufflength - patlength : 0);
+               // If pattern is longer than buffer, then no match possible.
+               // If already at pattern,
+               // we already found the end one last time.
+               if (patlength <= bufflength &&
+                               where != editor_p->insert_position() - patlength) {
+                       if (casematch_p->value()) {
+                               if (strncmp(pattern_p->value(),
+                                               editor_p->buffer()->text()
+                                               + where, patlength) == 0) {
+                                       found = 1;
+                               }
+                       }
+                       else {
+                               if (strncasecmp(pattern_p->value(),
+                                               editor_p->buffer()->text()
+                                               + where, patlength) == 0) {
+                                       found = 1;
+                               }
+                       }
+               }
+
+               if ( ! found ) {
+                       fl_alert("Cannot find \"%s\"", pattern_p->value());
+                       gray_out();
+
+                       // The main editor window should now
+                       // be made active, rather than the Find window.
+                       editor_p->take_focus();
+               }
+       }
+       if (found) {
+               editor_p->buffer()->highlight(where, where + pattern_p->size());
+               editor_p->insert_position(where + pattern_p->size());
+               editor_p->show_insert_position();
+       }
+}
+
+
+// Callback for when user clicks "Replace"
+
+CALL_BACK(Find_dialog, Replace)
+{
+       // See if we are already at the pattern to replace due to
+       // a previous Replace/Find Next
+       int start, end, isRect, rectStart, rectEnd;
+       bool at_pattern = false;
+       if (editor_p->buffer()->highlight_position(&start, &end, &isRect,
+                                               &rectStart, &rectEnd)) {
+               int place = editor_p->insert_position();
+               if (place == end && (end - start == pattern_p->size())) {
+                       if (casematch_p->value()) {
+                       
+                               at_pattern = (strncmp(pattern_p->value(),
+                                       editor_p->buffer()->text() + start,
+                                       pattern_p->size()) == 0);
+                       }
+                       else {
+                               at_pattern = (strncasecmp(pattern_p->value(),
+                                       editor_p->buffer()->text() + start,
+                                       pattern_p->size()) == 0);
+                       }
+               }
+       }
+
+       if (at_pattern) {
+               editor_p->buffer()->unhighlight();
+               editor_p->buffer()->replace(start, end, replace_with_p->value());
+       }
+
+       FindNext();
+}
+
+
+// Callback for when use clicks "Replace All"
+
+CALL_BACK(Find_dialog, ReplaceAll)
+{
+       // We want to be able to "undo" the entire "Replace All"
+       // so we make a copy of the buffer, make all the changes in the
+       // copy and then replace the original with the altered copy.
+       Fl_Text_Buffer altered_buff;
+       altered_buff.copy(editor_p->buffer(), 0, editor_p->buffer()->length(), 0);
+       int start;      // where to begin each search
+       bool found = true;      // if matching pattern found on current search
+       int where;      // offset into buffer where match occurred
+       int new_cursor_pos;
+       bool replaced_something = false;        // if any matches found at all
+
+       new_cursor_pos = editor_p->insert_position();
+       for (start = 0; found; start = where + replace_with_p->size()) {
+               if ((found = altered_buff.search_forward(
+                                               start, pattern_p->value(),
+                                               &where, casematch_p->value()))
+                                               != 0) {
+                       altered_buff.replace(where, where + pattern_p->size(),
+                                               replace_with_p->value());
+                       new_cursor_pos = where + replace_with_p->size();
+                       replaced_something = true;
+               }
+       }
+       // Kludge because pattern at very end is not found.
+       // See more complete explanation in FindNext().
+       where = altered_buff.length() - pattern_p->size();
+       if (where >= 0) {
+               found = false;
+               if (casematch_p->value()) {
+                       if (strcmp(pattern_p->value(),
+                                       altered_buff.text() + where) == 0) {
+                               found = true;
+                       }
+               }       
+               else {
+                       if (strcasecmp(pattern_p->value(),
+                                       altered_buff.text() + where) == 0) {
+                               found = true;
+                       }
+               }
+               if (found) {
+                       altered_buff.replace(where, where + pattern_p->size(),
+                                               replace_with_p->value());
+                       new_cursor_pos = where + replace_with_p->size();
+                       replaced_something = true;
+               }
+       }
+
+       if (replaced_something) {
+               editor_p->buffer()->replace(0, editor_p->buffer()->length(),
+                                               altered_buff.text());
+               editor_p->insert_position(new_cursor_pos);
+       }
+       else {
+               fl_alert("No instances of pattern to replace.");
+       }
+       replace_all_p->deactivate();
+}
+
+
+// Callback for when user clicks "Cancel" in the "Find" window.
+// Hides the window.
+
+CALL_BACK(Find_dialog, Cancel)
+{
+       editor_p->buffer()->unhighlight();
+       hide();
+}
+
+
+// If user did Find Next until no more instances found,
+// the Find Next and Replace buttons will get grayed out,
+// But if they then change search direction, we need to reactivate them
+// since the pattern might be found in that direction.
+// They must also be ungrayed if the contents of the editor buffer change,
+// since the new text might contain the pattern.
+
+CALL_BACK(Find_dialog, change)
+{
+       next_p->activate();
+       replace_p->activate();
+       replace_all_p->activate();
+}
+
+
+// Callback for when user changes pattern, to know whether to gray or ungray
+// Find Next button or not.
+
+CALL_BACK(Find_dialog, Pattern)
+{
+       if (pattern_p->size() > 0) {
+               next_p->activate();
+               replace_p->activate();
+               replace_all_p->activate();
+       }
+       else {
+               gray_out();
+       }
+}
+
+// Horrible kludge. If the "Find" or "Replace" is grayed out because there
+// are no more instances of the pattern in the current direction,
+// and then user moves the cursor somewhere else, it's possible the pattern
+// may then be findable. But modify_callback does not get called for
+// a change in cursor position. So we poll to see if the cursor position
+// changed since the last check, and if so, ungray.
+// Fortunately, we can limit this to only when the button are grayed,
+// which shouldn't be too often.
+
+void
+Find_dialog::gray_out(void)
+{
+       next_p->deactivate();
+       replace_p->deactivate();
+       replace_all_p->deactivate();
+       // Remember where we are and set up to poll for changes
+       last_cursor_position = editor_p->insert_position();
+       Fl::add_timeout(0.5, cursor_change_check, this);
+}
+
+void
+Find_dialog::cursor_change_check(void * data)
+{
+       Find_dialog * obj_p = (Find_dialog *) data;
+       if (obj_p->editor_p->insert_position() != obj_p->last_cursor_position
+                               && obj_p->pattern_p->size() > 0) {
+               obj_p->change();
+       }
+       else {
+               Fl::repeat_timeout(0.5, cursor_change_check, data);
+       }
+}
+
+
+// Class needs access to the editor; this lets it know which editor
+// instance to use, and which main window it is associated with.
+
+void
+Find_dialog::set_editor(Fl_Text_Editor * ed)
+{
+       editor_p = ed;
+}
+
+
+// Returns the current "Find" pattern entered by user,
+// or "" if they have not yet entered any such pattern
+
+const char *
+Find_dialog::get_pattern()
+{
+       if (pattern_p->value() == 0) {
+               return("");
+       }
+       else {
+               return(pattern_p->value());
+       }
+}
+
+
+//---------------- GoTo class---------------------------------------------
+
+GoTo_dialog::GoTo_dialog(void)
+       : Fl_Double_Window(225, 95, "Goto line")
+{
+       linenum_p = new Positive_Int_Input(115, 10, 60, 30, "Line Number:");
+       linenum_p->tooltip("Enter the line number of the line\n"
+                       "you want to make the current line.");
+
+       ok_p = new Fl_Return_Button(25, 50, 75, 30, "OK");
+       ok_p->when(FL_WHEN_RELEASE);
+       ok_p->callback(OK_cb, this);
+
+       cancel_p = new Fl_Button(125, 50, 75, 30, "Cancel");
+       cancel_p->shortcut(FL_Escape);
+       cancel_p->when(FL_WHEN_RELEASE);
+       cancel_p->callback(Cancel_cb, this);
+
+       // Arrange for destructor to clean up new-ed widgets
+       end();
+
+       // Arrange for window manager closes to do Cancel.
+       callback(Cancel_cb, this);
+       when(FL_WHEN_NEVER);
+}
+
+GoTo_dialog::~GoTo_dialog()
+{
+}
+
+
+// Callback for when user clicks "OK" in GoTo dialog
+
+CALL_BACK(GoTo_dialog, OK)
+{
+       // Find end of valid range
+       int last_line = editor_p->buffer()->count_lines(0,
+                       editor_p->buffer()->length());
+       // FLTK line numbers start at 0, so we have to subtract 1 from
+       // number supplied by user.
+       int desired_line = (int) strtol(linenum_p->value(), 0, 0) - 1;
+       if (desired_line < 0 || desired_line > last_line) {
+               fl_alert("Line number out of range");
+               return;
+       }
+
+       // Find appropriate new cursor position and move cursor there
+       int newposition = editor_p->buffer()->skip_lines(0, desired_line);
+       editor_p->insert_position(newposition);
+       editor_p->show_insert_position();
+       hide();
+}
+
+
+// Callback if user cancel Go To
+
+CALL_BACK(GoTo_dialog, Cancel)
+{
+       hide();
+}
+
+
+// Code that calls constructor should then call this to tell
+// us which editor instance to act upon.
+
+void
+GoTo_dialog::set_editor(Fl_Text_Editor * ed)
+{
+       editor_p = ed;
+}
+
+
+// Initialize contents on GoTo field to the current line number
+
+void
+GoTo_dialog::set_current_line()
+{
+       char num_as_string[16];
+       // fltk numbers lines from 0, so add 1 to get what user expects
+       (void) sprintf(num_as_string, "%d",
+               editor_p->buffer()->count_lines(0, editor_p->insert_position()) + 1);
+       linenum_p->value(num_as_string);
+}
+
+
+//------------------Edit class-----------------------------------------------
+// Implements the items in the Edit menu on the main toolbar
+
+
+Edit::Edit()
+{
+       find_p = 0;
+       goto_p = 0;
+       wrote_to_clipboard = false;
+}
+
+
+Edit::~Edit()
+{
+       if (find_p != 0) {
+               delete find_p;
+               find_p = 0;
+       }
+       if (goto_p != 0) {
+               delete goto_p;
+               goto_p = 0;
+       }
+}
+
+
+//---Undo menu item---------------
+
+CALL_BACK(Edit, Undo)
+{
+       buffer_p->undo();
+}
+
+
+//---Cut menu item---------------
+
+CALL_BACK(Edit, Cut)
+{
+       Fl_Text_Editor::kf_cut('x', editor_p);
+       set_can_paste();
+}
+
+
+//---Copy menu item---------------
+
+CALL_BACK(Edit, Copy)
+{
+       Fl_Text_Editor::kf_copy('c', editor_p);
+       set_can_paste();
+}
+
+
+//---Paste menu item---------------
+
+CALL_BACK(Edit, Paste)
+{
+       Fl_Text_Editor::kf_paste('v', editor_p);
+}
+
+
+//---Delete menu item---------------
+
+CALL_BACK(Edit, Delete)
+{
+       buffer_p->remove_selection();
+       buffer_p->unselect();
+}
+
+
+//---Find menu item---------------
+
+CALL_BACK(Edit, Find)
+{
+       if (find_p == 0) {
+               // First time, create widget
+               find_p = new Find_dialog();
+               find_p->set_editor(editor_p);
+       }
+       find_p->as_Find();
+       find_p->show();
+}
+
+
+//---Find Next menu item---------------
+
+CALL_BACK(Edit, FindNext)
+{
+       if (find_p == 0 || strlen(find_p->get_pattern()) == 0) {
+               // No pattern specified yet; turn into Find
+               Find();
+               return;
+       }
+       find_p->FindNext();
+}
+
+
+//---Replace menu item---------------
+
+CALL_BACK(Edit, Replace)
+{
+       if (find_p == 0) {
+               // First time, create widget
+               find_p = new Find_dialog();
+               find_p->set_editor(editor_p);
+       }
+       find_p->as_Replace();
+       find_p->show();
+}
+
+
+//---Go To menu item---------------
+
+CALL_BACK(Edit, GoTo)
+{
+       if (goto_p == 0) {
+               // First time, create widget
+               goto_p = new GoTo_dialog();
+               goto_p->set_editor(editor_p);
+       }
+       goto_p->set_current_line();
+       goto_p->show();
+}
+
+
+//---Select All menu item---------------
+
+CALL_BACK(Edit, SelectAll)
+{
+       buffer_p->select(0, buffer_p->length());
+}
+
+
+//---- Callback for when editor window is modified.
+// Grayed out find/replace should be ungrayed, because the modified
+// text might now match.
+
+void
+Edit::modify_cb(int, int, int, int, const char *, void * data)
+{
+       if ( ((Edit *)data)->find_p != 0) {
+               ((Edit *)data)->find_p->change();
+       }
+}
+
+
+// Class needs access to the editor; this lets it know which editor
+// instance to use.
+
+void
+Edit::set_editor(Fl_Text_Editor * ed)
+{
+       editor_p = ed;
+       buffer_p = editor_p->buffer();
+}
+
+// Ungray Paste button
+
+void
+Edit::set_can_paste(void)
+{
+       wrote_to_clipboard = true;
+       editor_p->buffer()->call_modify_callbacks();
+}
diff --git a/mup/mupmate/Edit.H b/mup/mupmate/Edit.H
new file mode 100644 (file)
index 0000000..8ab39fe
--- /dev/null
@@ -0,0 +1,171 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+#ifndef _EDIT_H_
+#define _EDIT_H_
+
+// Classes for Edit menu item off of main toolbar
+
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Text_Editor.H>
+#include <FL/Fl_Text_Buffer.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Int_Input.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Round_Button.H>
+#include <FL/Fl_Check_Button.H>
+#include <FL/Fl_Return_Button.H>
+
+
+
+// Class for window that pops up for "Find" or "Replace"
+
+class Find_dialog : public Fl_Double_Window {
+
+friend class Edit;     // so it can call FindNext()
+
+public:
+       Find_dialog(void);
+       ~Find_dialog();
+
+       // Callbacks
+       static void FindNext_cb(Fl_Widget *, void * data);
+       static void Replace_cb(Fl_Widget *, void * data);
+       static void ReplaceAll_cb(Fl_Widget *, void * data);
+       static void Cancel_cb(Fl_Widget *, void * data);
+       static void Pattern_cb(Fl_Widget *, void * data);
+       static void change_cb(Fl_Widget *, void * data);
+       static void cursor_change_check(void * data);
+
+       // Returns current search pattern
+       const char * get_pattern(void);
+
+       // Tells class which edit buffer to search in
+       void set_editor(Fl_Text_Editor *);
+
+       // Class instance can be either a Find or a Replace.
+       // These change the personality.
+       void as_Find(void);
+       void as_Replace(void);
+
+       // when not allowed to search/replace
+       void gray_out(void);
+
+private:
+       // Callbacks
+       void FindNext(void);
+       void Replace(void);
+       void ReplaceAll(void);
+       void Cancel(void);
+       void Pattern(void);
+       void change(void);
+
+       // Widgets
+       Fl_Input * pattern_p;
+       Fl_Input * replace_with_p;
+       Fl_Button * replace_p;
+       Fl_Button * replace_all_p;
+       Fl_Check_Button * casematch_p;
+       Fl_Box * direction_p;
+       Fl_Round_Button * up_p;
+       Fl_Round_Button * down_p;
+       Fl_Return_Button * next_p;
+       Fl_Button * cancel_p;
+
+       // The text editor widget we are editing
+       Fl_Text_Editor * editor_p;
+
+       // true if current personality is "Replace," false if "Find."
+       bool is_replace;
+
+       // Where cursor was at last check
+       int last_cursor_position;
+};
+
+
+// Class for window that pops up for Go To
+
+class GoTo_dialog : Fl_Double_Window {
+
+friend class Edit;
+
+public:
+       GoTo_dialog(void);
+       ~GoTo_dialog();
+
+       // Callbacks
+       static void OK_cb(Fl_Widget *, void * data);
+       static void Cancel_cb(Fl_Widget *, void * data);
+
+       // Tells us which editor instance to use
+       void set_editor(Fl_Text_Editor * ed);
+
+       // Initialize contents on GoTo field to the current line number
+       void set_current_line();
+
+private:
+       // Callbacks
+       void OK(void);
+       void Cancel(void);
+
+       // Widgets
+       Fl_Int_Input * linenum_p;
+       Fl_Return_Button * ok_p;
+       Fl_Button * cancel_p;
+       Fl_Text_Editor * editor_p;
+};
+
+
+// Class for Edit Menu from main toolbar
+
+class Edit {
+public:
+       Edit();
+       ~Edit();
+
+       // Callbacks
+       static void Undo_cb(Fl_Widget *, void * data);
+       static void Cut_cb(Fl_Widget *, void * data);
+       static void Copy_cb(Fl_Widget *, void * data);
+       static void Paste_cb(Fl_Widget *, void * data);
+       static void Delete_cb(Fl_Widget *, void * data);
+       static void Find_cb(Fl_Widget *, void * data);
+       static void FindNext_cb(Fl_Widget *, void * data);
+       static void Replace_cb(Fl_Widget *, void * data);
+       static void GoTo_cb(Fl_Widget *, void * data);
+       static void SelectAll_cb(Fl_Widget *, void * data);
+       static void modify_cb(int, int, int, int, const char *, void * data);
+
+       // Tells us which editor instance to use
+       void set_editor(Fl_Text_Editor * ed);
+
+       // true if there is something in the clipboard that can be pasted
+       bool can_paste()        { return wrote_to_clipboard; }
+       void set_can_paste();
+
+private:
+       // Callbacks
+       void Undo(void);
+       void Cut(void);
+       void Copy(void);
+       void Paste(void);
+       void Delete(void);
+       void Find(void);
+       void FindNext(void);
+       void Replace(void);
+       void GoTo(void);
+       void SelectAll(void);
+
+       // Widgets
+       Fl_Text_Editor * editor_p;
+       Fl_Text_Buffer * buffer_p;
+       Find_dialog * find_p;
+       GoTo_dialog * goto_p;
+
+       // if wrote something to the cut/copy buffer
+       bool wrote_to_clipboard;
+};
+
+#endif
diff --git a/mup/mupmate/File.C b/mup/mupmate/File.C
new file mode 100644 (file)
index 0000000..3c1001a
--- /dev/null
@@ -0,0 +1,608 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+// Code for the File menu off the main toolbar
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <FL/Fl.H>
+#include <FL/fl_ask.H>
+#ifndef OS_LIKE_WIN32
+#include <FL/Fl_File_Icon.H>
+#endif
+#include <FL/Fl_Shared_Image.H>
+#include <FL/Fl_Input.H>
+#include <FL/filename.H>
+#include <FL/Fl_Bitmap.H>
+#include <FL/Fl_File_Chooser.H>
+#include "globals.H"
+#include "File.H"
+#include "Main.H"
+#include "Preferences.H"
+#include "utils.H"
+#include <time.h>
+#ifdef OS_LIKE_WIN32
+#include <FL/x.H>
+#include <commdlg.h>
+#endif
+
+// The file name filters
+#define Mup_filter "*.mup"
+#define All_filter "*.*"
+
+extern char dir_separator();
+extern const char * const template_text;
+
+
+//-----------------Class to implement the File menu off the main menu bar
+
+File::File()
+{
+       filename = 0;
+       unsaved_changes = false;
+}
+
+File::~File()
+{
+       if (filename) {
+               delete filename;
+               filename = 0;
+       }
+}
+
+
+//--- the "New" menu item -------------
+
+CALL_BACK(File, New)
+{
+       // Ask user if they want to save any unsaved change on
+       // current file first.
+       switch (save_changes_check()) {
+       default: // default case should be impossible
+       case Save_confirm_dialog::Cancel:
+               return;
+       case Save_confirm_dialog::No:
+               break;
+       case Save_confirm_dialog::Yes:
+               Save(false);
+               break;
+       }
+
+       // Clear the current edit buffer
+       Fl_Text_Buffer * buffer_p = editor_p->buffer();
+       buffer_p->replace(0, buffer_p->length(), "");
+
+       if (filename) {
+               delete filename;
+               filename = 0;
+       }
+       set_window_label();
+       // Reset state information
+       begin_new_file();
+}
+
+
+// --- the "New From Template" menu item
+
+CALL_BACK(File, NewFromTemplate)
+{
+       New();
+       editor_p->buffer()->append(template_text);
+       unsaved_changes = false;
+}
+
+//--- the "Open" menu item -------------
+
+CALL_BACK(File, Open)
+{
+       // If already editing a file, ask user if they want to
+       // save any unsaved changes first
+       switch (save_changes_check()) {
+       default: // default case should be impossible
+       case Save_confirm_dialog::Cancel:
+               return;
+       case Save_confirm_dialog::No:
+               break;
+       case Save_confirm_dialog::Yes:
+               Save(false);
+               break;
+       }
+
+       // Clear out label to "Untitled" in case the load fails
+       set_window_label();
+
+       // Ask user for filename. If they give one, load it into editor.
+       const char * newfile = open_ask_user();
+       if (newfile != 0 && newfile[0] != '\0') {
+               load_file(newfile);
+       }
+}
+
+
+//--- the "Save" menu item -------------
+
+// Save the current buffer contents.
+// If honor_auto_display is true and user has requested auto display,
+// do the Run>Display action. If the save was due to finishing up an old
+// file to start on a new or due to saving before exiting, we don't do that;
+// it is only done if user did an explicit Save or Save As.
+
+CALL_BACK_A(File, Save, bool honor_auto_display)
+{
+       if (filename == 0) {
+               // No file name given yet, so change into a Save As
+               SaveAs(honor_auto_display);
+       }
+       else {
+               save_file(honor_auto_display);
+       }
+}
+
+
+//--- the "SaveAs" menu item -------------
+
+CALL_BACK_A(File, SaveAs, bool honor_auto_display)
+{
+       // Ask user for name of file to save to
+       const char * newfile = save_as_ask_user();
+       if (newfile != 0 && newfile[0] != '\0') {
+
+               // If user didn't give a suffix, add .mup suffix.
+               // If they used .ps or .mid or .err suffix, don't allow that.
+               const char * suffix = fl_filename_ext(newfile);
+               char * suffixed_filename = 0;
+               if (*suffix == '\0') {
+                       // User did not supply a suffix, so we add .mup
+                       suffixed_filename = new char[strlen(newfile) + 5];
+                       (void) sprintf(suffixed_filename, "%s.mup", newfile);
+                       newfile = suffixed_filename;
+               }
+               else if (strcasecmp(suffix, ".ps") == 0
+                                       || strcasecmp(suffix, ".mid") == 0
+                                       || strcasecmp(suffix, ".err") == 0) {
+                       fl_alert("A filename extension of .ps .mid or .err\n"
+                               "is not allowed for Mup input files,\n"
+                               "since those extensions are used for\n"
+                               "PostScript, MIDI, and error output files.");
+                       return;
+               }
+
+               if (access(newfile, F_OK) == 0) {
+                       const char * ask_replace = " already exists. Do you want to replace it?";
+                       char question[strlen(newfile) + strlen(ask_replace) + 1];
+                       (void) sprintf(question, "%s%s\n", newfile, ask_replace);
+                       switch (Save_confirm_dialog::confirm_save(question)) {
+                       default: // default case should be impossible.
+                       case Save_confirm_dialog::Cancel:
+                       case Save_confirm_dialog::No:
+                               if (suffixed_filename != 0) {
+                                       delete suffixed_filename;
+                               }
+                               return;
+                       case Save_confirm_dialog::Yes:
+                               break;
+                       }
+               }
+
+               // Save the name of the new file
+               if (filename != 0) {
+                       // forget previous file name
+                       delete filename;
+               }
+               if (suffixed_filename != 0) {
+                       filename = suffixed_filename;
+               }
+               else {
+                       filename = new char[strlen(newfile) + 1];
+                       (void) sprintf(filename, newfile);
+               }
+
+               set_window_label();
+               save_file(honor_auto_display);
+       }
+}
+
+
+//--- the "Exit" menu item -------------
+
+CALL_BACK(File, Exit)
+{
+       switch (save_changes_check()) {
+       default: // default case should be impossible
+       case Save_confirm_dialog::Cancel:
+               return;
+       case Save_confirm_dialog::No:
+               break;
+       case Save_confirm_dialog::Yes:
+               Save(false);
+               break;
+       }
+       Main::clean_exit();
+}
+
+//------------------------------------------------------------------------
+
+// This class needs access to editor window, so whoever creates an instance
+// of this class needs to call this function to give it access.
+
+void
+File::set_editor(Fl_Text_Editor * ed)
+{
+       editor_p = ed;
+}
+
+// We need to set parent's label, etc. Save info about parent.
+
+void
+File::set_parent(Main * win_p)
+{
+       parent_window_p = win_p;
+}
+
+// Called when user makes a change in editor window.
+// Let's us know if we need to prompt user about unsaved changes.
+
+void
+File::modify_cb(int, int num_inserted, int num_deleted, int, const char *, void * data)
+{
+       if (num_inserted > 0 || num_deleted > 0) {
+               ((File *)data)->unsaved_changes = true;
+       }
+}
+
+
+// Utility method that does the details of saving the current file
+
+void
+File::save_file(bool honor_auto_display)
+{
+       if (editor_p->buffer()->savefile(filename) != 0) {
+               fl_alert("failed to save file %s", filename);
+       }
+       else {
+               // All unsaved changes have now been saved
+               unsaved_changes = false;
+
+               // If user wants auto-display on save, do that
+               if (honor_auto_display) {
+                       int auto_display;
+                       (void) Preferences_p->get(Auto_display_preference, auto_display,
+                                                       Default_auto_display);
+                       if (auto_display) {
+                               parent_window_p->runmenu_p->Display();
+                       }
+               }
+       }
+}
+
+
+// Utility method to ask user if they want to save changes.
+// Returns:
+//     Cancel  don't do anything
+//     No      do action without saving changes
+//     Yes     save changes before doing action
+// The extra_text argument allows caller to enhance the question
+// asked of the user. The "No" button can be hidden.
+
+Save_confirm_dialog::Answer
+File::save_changes_check(const char * extra_text, bool hide_the_No)
+{
+       if ( ! unsaved_changes ) {
+               return Save_confirm_dialog::No;
+       }
+       const char * name = effective_filename();
+       char question[200 + strlen(name) + strlen(extra_text)];
+       (void) sprintf(question, "The text in the %s file has changed. "
+                       "Do you want to save the changes? %s", name, extra_text);
+       return(Save_confirm_dialog::confirm_save(question, hide_the_No));
+}
+
+
+// Read the given file into the editor window.
+
+void
+File::load_file(const char * name)
+{
+       // Free up existing file name, if any
+       if (filename != 0) {
+               delete filename;
+               filename = 0;
+       }
+
+       // If name supplied doesn't have .mup suffix,
+       // try again with that suffix added.
+       char * newname = 0;
+       if (access(name, F_OK) != 0) {
+               if (strlen(name) < 5 ||
+                               strcasecmp(name + strlen(name) - 4, ".mup") != 0) {
+                       newname = new char[strlen(name) + 5];
+                       (void) sprintf(newname, "%s.mup", name);
+               }
+       }
+       if (newname == 0) {
+               newname = new char[strlen(name) + 1];
+               (void) strcpy(newname, name);
+       }
+
+       // Mup files are typically only a few Kbytes,
+       // so we probably don't need the default 128 K buffer,
+       // but memory is cheap enough these days, so just go with that.
+       if (editor_p->buffer()->loadfile(newname) != 0) {
+               fl_alert("Unable to load file \"%s\"", newname);
+               delete newname;
+       }
+       else {
+               filename = newname;
+       }
+
+       // Reset state information for a new file
+       begin_new_file();
+
+       // add file name to window label
+       set_window_label();
+}
+
+void
+File::set_window_label()
+{
+       if (parent_window_p == 0) {
+               return;
+       }
+       const char * name = effective_filename();
+       char label[strlen(name) + 11];
+       (void) sprintf(label, "%s - Mupmate", name);
+       parent_window_p->copy_label(label);
+}
+
+
+const char *
+File::effective_filename(void)
+{
+       return(filename == 0 ? "Untitled.mup" : filename);
+}
+
+void
+File::begin_new_file(void)
+{
+       parent_window_p->begin_new_file();
+       unsaved_changes = false;
+}
+
+#ifndef OS_LIKE_WIN32
+// Add Icon for Mup files.
+
+// Figure out note polygon one time and just add these offsets for the other...
+#define RIGHT_NOTE_X   5800
+#define RIGHT_NOTE_Y   -1200
+
+static short Mup_icon_data[] = {
+       Fl_File_Icon::COLOR,    0, FL_RED,
+
+       // left stem
+       Fl_File_Icon::POLYGON,
+       Fl_File_Icon::VERTEX, 600, 1200, 
+       Fl_File_Icon::VERTEX, 600, 8200,
+       Fl_File_Icon::VERTEX, 1200, 8200,
+       Fl_File_Icon::VERTEX, 1200, 1200,
+       Fl_File_Icon::VERTEX, 600, 1200,
+       Fl_File_Icon::END,
+
+       // right stem
+       Fl_File_Icon::POLYGON,
+       Fl_File_Icon::VERTEX, 6400, 600, 
+       Fl_File_Icon::VERTEX, 6400, 7000,
+       Fl_File_Icon::VERTEX, 7000, 7000,
+       Fl_File_Icon::VERTEX, 7000, 600,
+       Fl_File_Icon::VERTEX, 6400, 600,
+       Fl_File_Icon::END,
+
+       // beam
+       Fl_File_Icon::POLYGON,
+       Fl_File_Icon::VERTEX, 600, 1200, 
+       Fl_File_Icon::VERTEX, 600, 2700,
+       Fl_File_Icon::VERTEX, 7000, 2100,
+       Fl_File_Icon::VERTEX, 7000, 600,
+       Fl_File_Icon::VERTEX, 600, 2000,
+       Fl_File_Icon::END,
+
+       // left note
+       Fl_File_Icon::POLYGON,
+       Fl_File_Icon::VERTEX, 600, 8200, 
+       Fl_File_Icon::VERTEX, 1600, 9400,
+       Fl_File_Icon::VERTEX, 3200, 9400,
+       Fl_File_Icon::VERTEX, 3800, 8800,
+       Fl_File_Icon::VERTEX, 3800, 8000,
+       Fl_File_Icon::VERTEX, 3000, 7200,
+       Fl_File_Icon::VERTEX, 1600, 7200,
+       Fl_File_Icon::VERTEX, 800, 7900,
+       Fl_File_Icon::VERTEX, 800, 8200,
+       Fl_File_Icon::VERTEX, 500, 9000,
+       Fl_File_Icon::END,
+
+       // right note
+       Fl_File_Icon::POLYGON,
+       Fl_File_Icon::VERTEX, 600 + RIGHT_NOTE_X, 8200 + RIGHT_NOTE_Y, 
+       Fl_File_Icon::VERTEX, 1600 + RIGHT_NOTE_X, 9400 + RIGHT_NOTE_Y,
+       Fl_File_Icon::VERTEX, 3200 + RIGHT_NOTE_X, 9400 + RIGHT_NOTE_Y,
+       Fl_File_Icon::VERTEX, 3800 + RIGHT_NOTE_X, 8800 + RIGHT_NOTE_Y,
+       Fl_File_Icon::VERTEX, 3800 + RIGHT_NOTE_X, 8000 + RIGHT_NOTE_Y,
+       Fl_File_Icon::VERTEX, 3000 + RIGHT_NOTE_X, 7200 + RIGHT_NOTE_Y,
+       Fl_File_Icon::VERTEX, 1600 + RIGHT_NOTE_X, 7200 + RIGHT_NOTE_Y,
+       Fl_File_Icon::VERTEX, 800 + RIGHT_NOTE_X, 7900 + RIGHT_NOTE_Y,
+       Fl_File_Icon::VERTEX, 800 + RIGHT_NOTE_X, 8200 + RIGHT_NOTE_Y,
+       Fl_File_Icon::VERTEX, 500 + RIGHT_NOTE_X, 9000 + RIGHT_NOTE_Y,
+       Fl_File_Icon::END,
+
+       Fl_File_Icon::END
+};
+
+void
+File::add_mup_icon(void)
+{
+       new Fl_File_Icon("*.mup", Fl_File_Icon::PLAIN,
+                       sizeof(Mup_icon_data) / sizeof(Mup_icon_data[0]),
+                       Mup_icon_data);
+}
+#endif
+
+
+
+// Ask user for name of file to open, and return their choice
+
+const char *
+File::open_ask_user(void)
+{
+#ifdef OS_LIKE_WIN32
+       OPENFILENAME openfilename;
+       static CHAR path[FL_PATH_MAX] = "*.mup";
+       CHAR dir[FL_PATH_MAX];
+       memset(&openfilename, 0, sizeof(openfilename));
+       GetCurrentDirectory(sizeof(dir), dir);
+       openfilename.lStructSize = sizeof(openfilename);
+       parent_window_p->make_current();
+       openfilename.hwndOwner = fl_window;
+       openfilename.hInstance = fl_display;
+       openfilename.lpstrFilter = "Mup files (*.mup)\0*.mup\0All files (*.*)\0*.*\0";
+       openfilename.lpstrFile = path;
+       openfilename.nMaxFile = sizeof(path);
+       openfilename.lpstrInitialDir = dir;
+       openfilename.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
+       openfilename.lpstrDefExt = ".mup";
+
+       if (GetOpenFileName(&openfilename)) {
+               return(path);
+       }
+       else {
+               return(0);
+       }
+
+#else
+       fl_file_chooser_ok_label("Open");
+       return (fl_file_chooser("Open Mup file", "Mup files (*.mup)\tAll files (*)", "*.mup"));
+#endif
+}
+
+
+// Ask user for name of file to save to, and return their choice
+
+const char *
+File::save_as_ask_user(void)
+{
+#ifdef OS_LIKE_WIN32
+       OPENFILENAME openfilename;
+       static CHAR path[FL_PATH_MAX] = "*.mup";
+       CHAR dir[FL_PATH_MAX];
+       memset(&openfilename, 0, sizeof(openfilename));
+       GetCurrentDirectory(sizeof(dir), dir);
+       openfilename.lStructSize = sizeof(openfilename);
+       parent_window_p->make_current();
+       openfilename.hwndOwner = fl_window;
+       openfilename.hInstance = fl_display;
+       openfilename.lpstrFilter = "Mup files (*.mup)\0*.mup\0All files (*.*)\0*.*\0";
+       openfilename.lpstrFile = path;
+       openfilename.nMaxFile = sizeof(path);
+       openfilename.lpstrInitialDir = dir;
+       openfilename.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
+       openfilename.lpstrDefExt = ".mup";
+       if (GetSaveFileName(&openfilename)) {
+               return(path);
+       }
+       else {
+               return(0);
+       }
+#else
+       fl_file_chooser_ok_label("Save");
+       return (fl_file_chooser("Save Mup file", "Mup files (*.mup)\tAll files (*)", "*.mup"));
+#endif
+}
+
+
+//---------------------------------------------------------------------
+// The fl_choice function has the middle button as the default,
+// but we want the left button (Yes) to be the default for whether
+// to save before exiting, so we have a special class for it.
+// It is based on the fl_choice code.
+
+Save_confirm_dialog::Save_confirm_dialog(const char * text)
+       : Fl_Double_Window(500, 130, "Confirm")
+{
+       // Make question mark "icon"
+       icon_p = new Fl_Box(10, 10, 50, 50);
+       icon_p->box(FL_THIN_UP_BOX);
+       icon_p->labelfont(FL_TIMES_BOLD);
+       icon_p->labelsize(30);
+       icon_p->color(FL_WHITE);
+       icon_p->labelcolor(FL_BLUE);
+       icon_p->label("?");
+
+       // Print the question
+       message_p = new Fl_Box(90, 20, 400, 40);
+       message_p->label(text);
+       message_p->align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT | FL_ALIGN_WRAP);
+
+       yes_p = new Fl_Return_Button(210, h() - 50, 70, 30, "Yes");
+
+       no_p = new Fl_Button(300, h() - 50, 70, 30, "No");
+
+       cancel_p = new Fl_Button(390, h() - 50, 70, 30, "Cancel");
+       cancel_p->shortcut(FL_Escape);
+       show();
+
+       // Arrange for destructor to free new-ed widgets
+       end();
+}
+
+Save_confirm_dialog::~Save_confirm_dialog()
+{
+}
+
+
+// Method to bring up dialog to ask user if they want to save changes.
+// Returns:
+//     Cancel  don't do anything
+//     No      do action without saving changes
+//     Yes     save changes before doing action
+
+Save_confirm_dialog::Answer
+Save_confirm_dialog::confirm_save(const char * text, bool hide_the_No)
+{
+       // Create dialog window
+       Save_confirm_dialog * confirm_p = new Save_confirm_dialog(text);
+
+       // Only show desired buttons
+       if (hide_the_No) {
+               confirm_p->no_p->hide();
+       }
+
+       // Wait for user to select a button
+       Answer ret;
+       for ( ; ; ) {
+               Fl_Widget *widget_p = Fl::readqueue();
+               if (widget_p == 0) {
+                       Fl::wait();
+               }
+               else if (widget_p == confirm_p->cancel_p ||
+                               widget_p == confirm_p) {
+                       ret = Cancel;
+                       break;
+               }
+               else if (widget_p == confirm_p->no_p) {
+                       ret = No;
+                       break;
+               }
+               else if (widget_p == confirm_p->yes_p) {
+                       ret = Yes;
+                       break;
+               }
+       }
+
+       // Clean up the dialog window
+       confirm_p->hide();
+       delete confirm_p;
+
+       return ret;
+}
diff --git a/mup/mupmate/File.H b/mup/mupmate/File.H
new file mode 100644 (file)
index 0000000..e39bb6d
--- /dev/null
@@ -0,0 +1,122 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+#ifndef _FILE_H_
+#define _FILE_H_
+
+#include <FL/Fl.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Text_Editor.H>
+#include <FL/Fl_File_Browser.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Return_Button.H>
+#include <FL/Fl_Choice.H>
+#include <FL/filename.H>
+
+class Main;
+
+
+// Class used to ask user if they want to save changes.
+// The FLTK fl_choice doesn't do quite what we want, so we make our own...
+
+class Save_confirm_dialog : Fl_Double_Window {
+public:
+       enum Answer { Cancel, No, Yes };
+
+       // This brings up the dialog
+       static Answer confirm_save(const char * text, bool hide_the_No = false);
+
+private:
+       Save_confirm_dialog(const char * text);
+       ~Save_confirm_dialog(void);
+
+       // Widgets
+       Fl_Box * icon_p;
+       Fl_Box * message_p;
+       Fl_Return_Button * yes_p;
+       Fl_Button * no_p;
+       Fl_Button * cancel_p;
+};
+
+
+
+// Class for the items off of "File" on the main menu bar
+
+class File {
+
+friend class Run;
+
+public:
+       File();
+       ~File();
+
+       // Callbacks
+       static void modify_cb(int, int, int, int, const char *, void * data);
+       static void New_cb(Fl_Widget *, void * data);
+       static void NewFromTemplate_cb(Fl_Widget *, void * data);
+       static void Open_cb(Fl_Widget *, void * data);
+       static void Save_cb(Fl_Widget *, void * data);
+       static void SaveAs_cb(Fl_Widget *, void * data);
+       static void Exit_cb(Fl_Widget *, void * data);
+
+       // Load a file into the text editor
+       void load_file(const char * name);
+
+       // Give access to the text editor buffer
+       Fl_Text_Buffer * get_buffer() { return editor_p->buffer(); }
+
+       // Gives real filename, or "Untitled.mup" if there is none
+       const char * effective_filename();
+
+       // This class needs access to Main class and its text editor.
+       // Creator should call these to point to the proper instances 
+       void set_editor(Fl_Text_Editor * ed_p);
+       void set_parent(Main * main_p);
+
+       // These show the dialog and return the file name the user enters.
+       const char * open_ask_user(void);
+       const char * save_as_ask_user(void);
+
+       // Ask user if they want to save the currently unsaved changes.
+       Save_confirm_dialog::Answer save_changes_check(const char * extra_text = "",
+                                               bool hide_the_No = false);
+
+#ifndef OS_LIKE_WIN32
+       // Make icon for Mup files.
+       static void add_mup_icon(void);
+#endif
+
+
+private:
+       // Callbacks
+       void New(void);
+       void Open(void);
+       void NewFromTemplate(void);
+       void Save(bool honor_auto_display = true);
+       void SaveAs(bool honor_auto_display = true);
+       void Exit(void);
+
+       // Write out the current file
+       void save_file(bool honor_auto_display);
+
+       // Put current file name in window label
+       void set_window_label(void);
+
+       // Reset things for starting to edit a different file
+       void begin_new_file(void);
+
+       // The name of file being edited
+       char * filename;
+
+       // If buffer has changed since last being saved
+       bool unsaved_changes;
+
+       // Pointers to other class instances we need
+       Fl_Text_Editor * editor_p;
+       Main * parent_window_p;
+};
+
+#endif
diff --git a/mup/mupmate/Help.C b/mup/mupmate/Help.C
new file mode 100644 (file)
index 0000000..59e8f87
--- /dev/null
@@ -0,0 +1,291 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+// Code for Help menu item from main toolbar
+
+#include "globals.H"
+#include "Preferences.H"
+#include "Config.H"
+#include "Help.H"
+#include <FL/fl_ask.H>
+#include <string.h>
+#include <stdlib.h>
+
+
+// Window for browsing Mup User's Guide
+
+Uguide_browser::Uguide_browser(void)
+       : Fl_Double_Window(0, 0, Default_width, Default_height, "Mup User's Guide")
+{
+       browser_p = new Fl_Help_View(x(), y(), w(), h(), "");
+       // Set font/size and arrange to get notified of changes in them
+       font_change_reg_p = new Font_change_registration(font_change_cb, (void *) this);
+
+       // Haven't loaded the User's Guide yet
+       loaded = false;
+
+       // Allow browser window to be made as big as the user wants
+       size_range(Min_width, Min_height, 0, 0);
+       resizable((Fl_Widget *)browser_p);
+
+       // Fix problem with following relative links properly.
+       browser_p->link(resolve_link);
+
+       // Arrange for destructor to clean up new-ed widgets
+       end();
+}
+
+
+Uguide_browser::~Uguide_browser(void)
+{
+       delete font_change_reg_p;
+       font_change_reg_p = 0;
+}
+
+
+// Load Mup User's Guide into browser, if haven't already done so.
+
+void
+Uguide_browser::load_uguide(void)
+{
+       if (!loaded) {
+               // Entry under File Locations tells the base directory
+               // for Mup documentation. We concatenate the uguide/index.file
+               // to that directory to get top level file for User's Guide.
+               char * base_url;
+               (void) Preferences_p->get(Mup_documentation_location, base_url,
+                               Default_Mup_documentation_location);
+               const char * url = users_guide_index_file(base_url);
+
+               // Fltk has a bug (at least in some versions):
+               // the documentation claims load()
+               // returns -1 on failure, but in fact it always returns 0.
+               // So the strncmp attempts to deduce if it failed.
+               if (browser_p->load(url) != 0 ||
+                               strstr(browser_p->value(), "Mup User's Guide")
+                               == 0) {
+                       fl_alert("Unable to load User's Guide.\n  %s\n"
+                               "Check settings in Config > File Locations", url);
+               }
+               else {
+                       loaded = true;
+               }
+       }
+}
+
+
+// Callback for when user changes font/size
+
+void
+Uguide_browser::font_change_cb(void * data, Fl_Font font, unsigned char size)
+{
+       ((Uguide_browser *)data)->font_change(font, size);
+}
+
+void
+Uguide_browser::font_change(Fl_Font font, unsigned char size)
+{
+       browser_p->textfont(font);
+       browser_p->textsize(size);
+}
+
+// On Windows, Fl_Help_View doesn't seem to properly follow relative
+// URLs (it goes relative to current working directory rather than
+// relative to the file containing the link),
+// so we use the link() callback to prepend the proper directory.
+// On Linux, things work fine without this kludge, but things also
+// work with it, so to keep code common, we do it always.
+
+const char *
+Uguide_browser::resolve_link(Fl_Widget * help_browser_p, const char * uri)
+{
+       static char link_path[FL_PATH_MAX];
+
+       if (strncmp(uri, "http:", 5) == 0) {
+               // Uguide has a few links to arkkra.com.
+               // They won't actually work, because we don't handle
+               // http, but it's better to let them through than to
+               // change the path and really confuse the user.
+               return(uri);
+       }
+
+       char * base_url;
+       (void) Preferences_p->get(Mup_documentation_location, base_url,
+                               Default_Mup_documentation_location);
+       (void) sprintf(link_path, "%s%c%s%c%s", base_url, dir_separator(),
+                               uguide_directory, dir_separator(),
+                               fl_filename_name(uri));
+       return((const char *) link_path);
+}
+
+//---- Hints for user when they use Mupmate for the first time
+// (or they can ask to see it later too)
+
+const char * Welcome_message =
+       "Welcome to Mupmate. Mupmate provides an interface to the\n"
+       "Mup music publication program from Arkkra Enterprises,\n"
+       "making it easy to edit, display, and print musical scores.\n"
+       "\n"
+       "If you have not used Mup before, you should begin by selecting\n"
+       "   Help > Mup User's Guide\n"
+       "for information on how to use Mup.\n"
+       "\n"
+       "You may also want to verify that the settings under\n"
+       "   Config > File Locations   and    Config > Preferences\n"
+       "are what you want, and adjust them if you wish.\n"
+       "\n"
+       "You are welcome to try out Mup for free to decide whether\n"
+       "it meets your needs. If you decide to keep it, select\n"
+       "   Config > Registration Form\n";
+
+StartupHints::StartupHints(void)
+       : Fl_Double_Window(Default_width - 100, Default_height - 100,
+       "Mup Startup Hints")
+{
+       text_p = new Fl_Text_Display(20, 20, w() - 40, h() - 90);
+       resizable((Fl_Widget *) text_p);
+       text_p->buffer( new Fl_Text_Buffer () );
+       font_change_reg_p = new Font_change_registration(font_change_cb, (void *) this);
+       text_p->buffer()->text(Welcome_message);
+       char * doc_dir;
+       (void) Preferences_p->get(Mup_documentation_location, doc_dir,
+                       Default_Mup_documentation_location);
+       text_p->buffer()->append("\nAdditional documentation is available in the folder:\n  ");
+       text_p->buffer()->append(doc_dir);
+
+       OK_p = new Fl_Return_Button(w() / 2 - 50, h() - 50, 100, 30,
+                                                               "OK");
+       OK_p->callback(OK_cb, this);
+       show();
+       end();
+
+       Preferences_p->set(Showed_startup_hints, 1);
+       Preferences_p->flush();
+}
+
+StartupHints::~StartupHints()
+{
+       delete font_change_reg_p;
+       font_change_reg_p = 0;
+}
+
+// Callback for user clicking OK when done reading startup hints
+
+CALL_BACK(StartupHints, OK)
+{
+       hide();
+}
+
+
+// Callback for when user changes font/size
+
+void
+StartupHints::font_change_cb(void * data, Fl_Font font, unsigned char size)
+{
+       ((StartupHints *)data)->font_change(font, size);
+}
+
+void
+StartupHints::font_change(Fl_Font font, unsigned char size)
+{
+       text_p->textfont(font);
+       text_p->textsize(size);
+       text_p->redisplay_range(0, text_p->buffer()->length());
+}
+
+//-----the "About" window-----------------------------------------------
+
+About_dialog::About_dialog(void)
+       : Fl_Double_Window(270, 200, "About Mupmate")
+{
+       message_p = new Fl_Multiline_Output(20, 20, w() - 40, 120, "");
+       message_p->value("\n   Mupmate is a user interface\n"
+                       "   for the Mup music publisher\n"
+                       "   program from www.arkkra.com\n"
+                       "\n"
+                       "     This is Version 5.3");
+       // Hide the cursor by making same color as background
+       message_p->cursor_color(message_p->color());
+
+       ok_p = new Fl_Return_Button((w() - 100) / 2, 155, 100, 30, "OK");
+       ok_p->callback(OK_cb, this);
+
+       // Arrange for destructor to clean up new-ed widgets
+       end();
+}
+
+About_dialog::~About_dialog(void)
+{
+}
+
+
+CALL_BACK(About_dialog, OK)
+{
+       hide();
+}
+
+//------the Help menu item from main toolbar-----------------------------
+
+Help::Help(void)
+{
+       uguide_p = 0;
+       startup_hints_p = 0;
+       about_p = 0;
+}
+
+Help::~Help(void)
+{
+       if (about_p != 0) {
+               delete about_p;
+               about_p = 0;
+       }
+       if (startup_hints_p != 0) {
+               delete startup_hints_p;
+               startup_hints_p = 0;
+       }
+       if (uguide_p != 0) {
+               delete uguide_p;
+               uguide_p = 0;
+       }
+}
+
+
+// Callback for when user requests viewing the Mup User's Guide
+
+CALL_BACK(Help, Uguide)
+{
+       if (uguide_p == 0) {
+               // first time, create widget
+               uguide_p = new Uguide_browser();
+       }
+       // Always attempt to load in case URL was bad last time but okay now.
+       // If already loaded, this will be a no-op.
+       uguide_p->load_uguide();
+       uguide_p->show();
+}
+
+
+// Callback for when user clicks "Startup Hints" button
+
+CALL_BACK(Help, Startup_Hints)
+{
+       // We delete any existing instance and start over,
+       // just in case the path to the documentation has changed.
+       if (startup_hints_p != 0) {
+               delete startup_hints_p;
+       }
+       startup_hints_p = new StartupHints();
+       startup_hints_p->show();
+}
+
+
+// Callback for when user clicks "About" button
+
+CALL_BACK(Help, About)
+{
+       if (about_p == 0) {
+               // first time, create widget
+               about_p = new About_dialog();
+       }
+       about_p->show();
+}
diff --git a/mup/mupmate/Help.H b/mup/mupmate/Help.H
new file mode 100644 (file)
index 0000000..bf92110
--- /dev/null
@@ -0,0 +1,113 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+#ifndef _HELP_H_
+#define _HELP_H_
+
+// Classes for Help menu item off of main toolbar
+
+#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Multiline_Output.H>
+#include <FL/Fl_Help_View.H>
+#include <FL/Fl_Return_Button.H>
+#include <FL/Fl_Text_Display.H>
+#include <FL/filename.H>
+#include "Config.H"
+
+
+// Class for window to let user browse the HTML version of Mup User's Guide
+
+class Uguide_browser : Fl_Double_Window {
+
+friend class Help;
+
+public:
+       Uguide_browser(void);
+       ~Uguide_browser(void);
+
+       // User can change font/size preference. This callback notifies
+       // of such changes, so we can adjust the output accordingly 
+       static void font_change_cb(void * data, Fl_Font font, unsigned char size);
+
+       // Load the User's Guide top level index.html file
+       void load_uguide(void);
+
+private:
+       void font_change(Fl_Font font, unsigned char size);
+
+       // On Windows, Fl_Help_View doesn't seem to properly follow relative
+       // URLs, so we use the link() callback to prepend the proper directory.
+       static const char * resolve_link(Fl_Widget *, const char * uri);
+
+       Fl_Help_View *browser_p;
+       Font_change_registration * font_change_reg_p;
+       bool loaded;
+};
+
+
+// Class to give first time user some hints.
+
+class StartupHints : Fl_Double_Window {
+
+friend class Help;
+
+public:
+       StartupHints(void);
+       ~StartupHints(void);
+
+       static void OK_cb(Fl_Widget *, void * data);
+       // User can change font/size preference. This callback notifies
+       // of such changes, so we can adjust the output accordingly 
+       static void font_change_cb(void * data, Fl_Font font, unsigned char size);
+private:
+       void OK(void);
+       void font_change(Fl_Font font, unsigned char size);
+
+       Font_change_registration * font_change_reg_p;
+       Fl_Text_Display * text_p;       // The text of the hints
+       Fl_Return_Button * OK_p;
+};
+
+
+// Class for "About" window
+
+class About_dialog : Fl_Double_Window {
+
+friend class Help;
+
+public:
+       About_dialog(void);
+       ~About_dialog(void);
+
+       static void OK_cb(Fl_Widget *, void * data);
+
+private:
+       void OK(void);
+
+       Fl_Multiline_Output * message_p;
+       Fl_Return_Button * ok_p;
+};
+
+
+// Class for Help menu item from main toolbar
+
+class Help {
+public:
+       Help(void);
+       ~Help(void);
+
+       static void Uguide_cb(Fl_Widget *, void * data);
+       static void Startup_Hints_cb(Fl_Widget *, void * data);
+       static void About_cb(Fl_Widget *, void * data);
+
+private:
+       void Uguide(void);
+       void Startup_Hints(void);
+       void About(void);
+
+       About_dialog * about_p;
+       StartupHints * startup_hints_p;
+       Uguide_browser * uguide_p;
+};
+
+#endif
diff --git a/mup/mupmate/Main.C b/mup/mupmate/Main.C
new file mode 100644 (file)
index 0000000..906f6d4
--- /dev/null
@@ -0,0 +1,724 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+// Code for the main window for Mupmate, a front end program for
+// the Mup music publisher program from Arkkra Enterprises.
+// It uses the FLTK toolkit for OS independence.
+
+// This file contains code for the toolbar and editor window,
+// as well as general startup and showing the license.
+
+// We only support editing a single file at a time, so most classes
+// as really effectively singletons, but the code is written to be
+// able to support multiple instances, in case we ever want to do that.
+// That means callback functions are always passed a pointer to
+// a class instance as their second argument, and all they do is cast 
+// that to the appropriate type, and call the corresponding class method.
+
+// For the most part, widgets are only allocated when needed, but then
+// stay around for the life of the process, in case they are needed again.
+
+// Callbacks are named with _cb suffix.
+// Pointers are named with _p suffix, except for (char *) types
+// that are pointing to text strings, which don't have any special suffix.
+
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#include <FL/Fl.H>
+#include <FL/fl_ask.H>
+#include <FL/Fl_Tooltip.H>
+
+#include "globals.H"
+#include "Main.H"
+#include "Preferences.H"
+#include "utils.H"
+
+#include <FL/x.H>
+#ifdef OS_LIKE_WIN32
+#include "resource.h"
+#else
+#include <FL/Fl_File_Icon.H>
+#ifdef OS_LIKE_UNIX
+#include <X11/xpm.h>
+#include "mup32.xpm"
+#endif
+#endif
+
+// Height of the tool bar on the main window
+#define TOOLBAR_HEIGHT 30
+
+// How often to blink the cursor.
+#define BLINK_RATE 0.5
+
+// If file indicating user has agreed to license terms doesn't exist,
+// we ask them to agree. This is the text of the license.
+extern const char * const license_text;
+
+//----------------------------------------------------------------------
+
+// Define the toolbar and its submenus.
+//  Indented lines indicate the submenus.
+// The & indicates shortcut key
+
+const char * File_label = "&File";
+ const char * New_label = "&New";
+ const char * NewFromTemplate_label = "New From &Template";
+ const char * Open_label = "&Open...";
+ const char * Save_label = "&Save";
+ const char * SaveAs_label = "Save &As...";
+ const char * Exit_label = "E&xit";
+const char * Edit_label = "&Edit";
+ const char * Undo_label = "&Undo";
+ const char * Cut_label = "Cu&t";
+ const char * Copy_label = "&Copy";
+ const char * Paste_label = "&Paste";
+ const char * Delete_label = "&Delete";
+ const char * Find_label = "&Find...";
+ const char * FindNext_label = "Find &Next";
+ const char * Replace_label = "&Replace...";
+ const char * GoTo_label = "&Go To...";
+ const char * SelectAll_label = "&Select All";
+const char * Run_label = "&Run";
+ const char * Display_label = "&Display";
+ const char * Play_label = "&Play";
+ const char * WritePostScript_label = "&Write PostScript File";
+ const char * WriteMIDI_label = "Write &MIDI File";
+ const char * Options_label = "&Set Options...";
+const char * Config_label = "&Config";
+ const char * FileLocations_label = "&File Locations...";
+ const char * Preferences_label = "&Preferences...";
+ const char * RegistrationForm_label = "&Registration Form...";
+ const char * RegistrationKey_label = "Registration &Key...";
+const char * Help_label = "&Help";
+ const char * UserGuide_label = "Mup &User's Guide";
+ const char * StartupHints_label = "&Startup Hints";
+ const char * AboutMupmate_label = "&About Mupmate";
+
+Fl_Menu_Item Toolbar_menu[] = {
+       { File_label,   0,      0,      0,      FL_SUBMENU },
+               { New_label,    FL_CTRL + 'n',  File::New_cb },
+               { NewFromTemplate_label,        FL_CTRL + 't', File::NewFromTemplate_cb },
+               { Open_label,   FL_CTRL + 'o',  File::Open_cb },
+               { Save_label,   FL_CTRL + 's',  File::Save_cb },
+               { SaveAs_label,         0,      File::SaveAs_cb,        0,      FL_MENU_DIVIDER },
+               { Exit_label,   0,      File::Exit_cb },
+               { 0 },
+       { Edit_label,   0,      0,      0,      FL_SUBMENU },
+               { Undo_label,   FL_CTRL + 'z',  Edit::Undo_cb,  0,      FL_MENU_INACTIVE | FL_MENU_DIVIDER },
+               { Cut_label,    FL_CTRL + 'x',  Edit::Cut_cb,   0,      FL_MENU_INACTIVE },
+               { Copy_label,   FL_CTRL + 'c',  Edit::Copy_cb,  0,      FL_MENU_INACTIVE },
+               { Paste_label,  FL_CTRL + 'v',  Edit::Paste_cb, 0,      FL_MENU_INACTIVE },
+               { Delete_label, FL_Delete,      Edit::Delete_cb,        0,      FL_MENU_INACTIVE | FL_MENU_DIVIDER },
+               { Find_label,   FL_CTRL + 'f',  Edit::Find_cb,  0,      FL_MENU_INACTIVE },
+               { FindNext_label,       FL_F + 3,       Edit::FindNext_cb,      0,      FL_MENU_INACTIVE },
+               { Replace_label,        FL_CTRL + 'h',  Edit::Replace_cb,       0,      FL_MENU_INACTIVE },
+               { GoTo_label,   FL_CTRL + 'g',  Edit::GoTo_cb,  0,      FL_MENU_DIVIDER },
+               { SelectAll_label,      FL_CTRL + 'a',  Edit::SelectAll_cb,     0, FL_MENU_INACTIVE },
+               { 0 },
+       { Run_label,    0,      0,      0,      FL_SUBMENU },
+               { Display_label,                        0,      Run::Display_cb,        0,      FL_MENU_INACTIVE },
+               { Play_label,                   0,      Run::Play_cb,   0,      FL_MENU_INACTIVE },
+               { WritePostScript_label,        0,      Run::WritePostScript_cb,        0, FL_MENU_INACTIVE },
+               { WriteMIDI_label,              0,      Run::WriteMIDI_cb,      0,       FL_MENU_DIVIDER | FL_MENU_INACTIVE },
+               { Options_label,                0,      Run::Options_cb },
+               { 0 },
+       { Config_label, 0,      0,      0,      FL_SUBMENU },
+               { FileLocations_label,          0,      Config::FileLocations_cb },
+               { Preferences_label,            0,      Config::Preferences_cb, 0,      FL_MENU_DIVIDER },
+               { RegistrationForm_label,       0,      Config::RegistrationForm_cb },
+               { RegistrationKey_label,        0,      Config::RegistrationKey_cb },
+               { 0 },
+       { Help_label,   0,      0,      0,      FL_SUBMENU },
+               { UserGuide_label,              0,      Help::Uguide_cb },
+               { StartupHints_label,           0,      Help::Startup_Hints_cb },
+               { AboutMupmate_label,           0,      Help::About_cb },
+               { 0 },
+       { 0 }
+};
+
+
+//----------------------------------------------------------------------
+
+// Linked list of main windows, in case we ever support more than one
+// at a time. (Currently we don't, because we're not sure if it
+// might be more confusing than useful.)
+Main * Main::list_p;
+
+
+// Constructor for main window. It contains toolbar and editor window.
+
+Main::Main(const char * title)
+       : Fl_Double_Window(Default_width, Default_height, title)
+{
+       xclass("mup");
+#ifdef OS_LIKE_WIN32
+       icon((char *)LoadIcon(fl_display, MAKEINTRESOURCE(IDI_ICON)));
+#else
+#ifdef OS_LIKE_UNIX
+       fl_open_display();
+       Pixmap p, mask;
+       XpmCreatePixmapFromData(fl_display, DefaultRootWindow(fl_display),
+                                 mup32_xpm, &p, &mask, NULL);
+       icon((char *)p);
+#endif
+#endif
+       // Try to use user's default foreground/background
+       Fl::get_system_colors();
+
+       void * data = 0;
+
+       // Create class instances for each toolbar item
+       filemenu_p = new File();
+       editmenu_p = new Edit();
+       configmenu_p = new Config();
+       helpmenu_p = new Help();
+       runmenu_p = new Run();
+
+       // Add to list of windows 
+       next = list_p;
+       list_p = this;
+
+       // Create the toolbar and populate its menu items
+       toolbar_p = new Fl_Menu_Bar(0, 0, w(), TOOLBAR_HEIGHT);
+       int numitems = sizeof(Toolbar_menu) / sizeof(Toolbar_menu[0]);
+       for (int i = 0; i < numitems; i++) {
+               if (Toolbar_menu[i].text != 0) {
+                       // As we move to each top-level menu item,
+                       // keep a pointer to that item, which is then
+                       // used as the argument to callback functions,
+                       // so they know what object to act on.
+                       if (strcmp(Toolbar_menu[i].text, File_label) == 0) {
+                               data = (void *) filemenu_p;
+                       }
+                       else if (strcmp(Toolbar_menu[i].text, Edit_label) == 0) {
+                               data = (void *) editmenu_p;
+                       }
+                       else if (strcmp(Toolbar_menu[i].text, Config_label) == 0) {
+                               data = (void *) configmenu_p;
+                       }
+                       else if (strcmp(Toolbar_menu[i].text, Run_label) == 0) {
+                               data = (void *) runmenu_p;
+                       }
+                       else if (strcmp(Toolbar_menu[i].text, Help_label) == 0) {
+                               data = (void *) helpmenu_p;
+                       }
+               }
+               Toolbar_menu[i].user_data(data);
+       }
+       toolbar_p->copy(Toolbar_menu);
+
+       // Create and configure the editor window
+       editor_p = new Fl_Text_Editor(0, TOOLBAR_HEIGHT, w(),
+                                       h() - TOOLBAR_HEIGHT, "");
+       editor_p->buffer( new Fl_Text_Buffer );
+
+       // Set font/size and arrange to be notified of changes in them
+       font_change_reg_p = new Font_change_registration(font_change_cb,
+                                                               (void *) this);
+
+       // Several objects need to be notified of changes in the
+       // editor window, so they can do things like gray-ungray menu items.
+       editor_p->buffer()->add_modify_callback(modify_cb, (void*) this);
+       editor_p->buffer()->add_modify_callback(File::modify_cb,
+                                       (void*) filemenu_p);
+       editor_p->buffer()->add_modify_callback(Edit::modify_cb,
+                                       (void*) editmenu_p);
+
+       // Initialize state information.
+       have_selection = false;
+       can_paste = false;
+       prev_bufflength = 0;
+       // Undo is inactive until user does something that can be undone.
+       undo_active = false;
+       undo_active_on_next_change = true;
+
+       // Arrange to make cursor blink
+       Fl::add_timeout(BLINK_RATE, blinker, this);
+       cursor_state = 1;
+
+       // Let editor take as much space as is available
+       // if the user resizes the main window. 
+       size_range(Min_width, Min_height, 0, 0);
+       resizable((Fl_Widget *) editor_p);
+
+       // Other classes need to have access to editor and such
+       filemenu_p->set_editor(editor_p);
+       filemenu_p->set_parent(this);
+       editmenu_p->set_editor(editor_p);
+       runmenu_p->set_file(filemenu_p);
+
+       // Arrange for destructor to free the new-ed child widgets
+       end();
+
+       show();
+
+       // Arrange for window manager closes to do Exit.
+       callback(atclose_cb, this);
+       when(FL_WHEN_NEVER);
+
+#ifdef OS_LIKE_UNIX
+       // Arrange for icon to be associated with window
+       XWMHints hints;
+       hints.flags = IconPixmapHint | IconMaskHint ;
+       hints.icon_pixmap = p;
+       hints.icon_mask = mask;
+       XSetWMHints(fl_display, fl_xid((Fl_Window *)this), &hints);
+#endif
+}
+
+
+// Destructor for main window
+
+Main::~Main()
+{
+       delete font_change_reg_p;
+       font_change_reg_p = 0;
+       Fl::remove_timeout(blinker, this);
+       // Remove from list of Main windows 
+       if (list_p == this) {
+               list_p = next;
+       }
+       else {
+               for (Main * m = list_p; m != 0; m = m->next) {
+                       if (m->next == this) {
+                               m->next = this->next;
+                               break;
+                       }
+               }
+       }
+       delete filemenu_p;
+       filemenu_p = 0;
+       delete editmenu_p;
+       editmenu_p = 0;
+       delete configmenu_p;
+       configmenu_p = 0;
+       delete helpmenu_p;
+       helpmenu_p = 0;
+       delete runmenu_p;
+       runmenu_p = 0;
+}
+
+
+// Callback for when user changes font/size
+
+void
+Main::font_change_cb(void * data, Fl_Font font, unsigned char size)
+{
+       ((Main *)data)->font_change(font, size);
+}
+
+
+void
+Main::font_change(Fl_Font font, unsigned char size)
+{
+       // Get shorter name for buffer, as we'll be using it a lot.
+       Fl_Text_Buffer * buffer_p = editor_p->buffer();
+
+       // Don't want this change to count as something that can be undone
+       buffer_p->canUndo(false);
+
+       // We want to change the entire text buffer, so need to
+       // select its whole contents. If there was already a selection,
+       // save that and put it back when we are done
+       int sel_start, sel_end;
+       int had_selection;
+       int cursorplace = editor_p->insert_position();
+       if ((had_selection = buffer_p->selected()) != 0) {
+               buffer_p->selection_position(&sel_start, &sel_end);
+               buffer_p->unselect();
+       }
+
+       // set new font and size
+       buffer_p->select(0, editor_p->buffer()->length() - 1);
+       editor_p->textfont(font);
+       editor_p->textsize(size);
+       buffer_p->unselect();
+
+       // Put selection and cursor back as they were before font change
+       if (had_selection) {
+               buffer_p->select(sel_start, sel_end);
+       }
+       editor_p->insert_position(cursorplace);
+       buffer_p->canUndo(true);
+}
+
+
+// Callback for when editor window changes.
+// This arranges to gray/ungray toolbar menu items.
+
+void
+Main::modify_cb(int, int, int, int, const char *, void * data)
+{
+       ((Main *)data)->modify();
+}
+
+void
+Main::modify()
+{
+       int bufflength = editor_p->buffer()->length();
+       // See if what changed is something we might care about.
+       if (editor_p->buffer()->selected() != have_selection ||
+                       editmenu_p->can_paste() != can_paste
+                       || undo_active != undo_active_on_next_change
+                       || bufflength < 2 || prev_bufflength == 0) {
+
+               // Something changed, and we may need to
+               // gray or ungray menu items in response.
+               have_selection = editor_p->buffer()->selected();
+               const Fl_Menu_Item * menu_p = toolbar_p->menu();
+               Fl_Menu_Item * item_p;
+               // Walk through toolbar and submenus, checking
+               // if anything needs to be grayed/ungrayed.
+               for (int i = 0; i < toolbar_p->size(); i++) {
+                       const char * mtext = toolbar_p->text(i);
+                       if (mtext == 0) {
+                               continue;
+                       }
+                       // Can only Copy, Cut, and Delete if something
+                       // is selected.
+                       if (strcmp(mtext, Copy_label) == 0 ||
+                                       strcmp(mtext, Cut_label) == 0 ||
+                                       strcmp(mtext, Delete_label) == 0) {
+                               // have to un-const so we can (de)activate
+                               item_p = (Fl_Menu_Item *) &(menu_p[i]);
+                               if (have_selection) {
+                                       item_p->activate();
+                               }
+                               else {
+                                       item_p->deactivate();
+                               }
+                       }
+
+                       // Paste is different. It becomes active when there
+                       // is something in clipboard, and never again becomes
+                       // inactive.
+                       if (strcmp(mtext, Paste_label) == 0 &&
+                                               editmenu_p->can_paste()) {
+                               ((Fl_Menu_Item *)&(menu_p[i]))->activate();
+                               can_paste = true;
+                       }
+
+                       // Undo is also different. On first change of any
+                       // kind it become active, and stays that way,
+                       // except it gets reset on new file.
+                       if (strcmp(mtext, Undo_label) == 0) {
+                               if (undo_active && ! undo_active_on_next_change) {
+                                       ((Fl_Menu_Item *)&(menu_p[i]))->deactivate();
+                                       undo_active = false;
+                                       undo_active_on_next_change = true;
+                               }
+                               else if ( ! undo_active && undo_active_on_next_change) {
+                                       ((Fl_Menu_Item *)&(menu_p[i]))->activate();
+                                       undo_active = true;
+                               }
+                       }
+
+                       // Find and FindNext are inactive when file is empty,
+                       // because obviously there is nothing to find.
+                       // Similar for Replace and Select All.
+                       // Also for all the Run things
+                       if (strcmp(mtext, Find_label) == 0 ||
+                                       strcmp(mtext, FindNext_label) == 0 ||
+                                       strcmp(mtext, Replace_label) == 0 ||
+                                       strcmp(mtext, SelectAll_label) == 0 ||
+                                       strcmp(mtext, Display_label) == 0 ||
+                                       strcmp(mtext, Play_label) == 0 ||
+                                       strcmp(mtext, WritePostScript_label) == 0 ||
+                                       strcmp(mtext, WriteMIDI_label) == 0) {
+                               if (bufflength == 0) {
+                                       ((Fl_Menu_Item *)&(menu_p[i]))->deactivate();
+                               }
+                               else {
+                                       ((Fl_Menu_Item *)&(menu_p[i]))->activate();
+                               }
+                       }
+               }
+       }
+       prev_bufflength = bufflength;
+}
+
+
+// This method gets called when user starts working on a new file.
+// It sets state information so we can know how to gray menu items properly.
+
+void
+Main::begin_new_file()
+{
+       // transition Undo-ability state from true to false
+       undo_active = true;
+       undo_active_on_next_change = false;
+       editor_p->buffer()->call_modify_callbacks();
+       runmenu_p->clean_up();
+}
+
+
+// Handle some special cases.
+// 1. By default fltk will exit the main window upon getting escape.
+// That seems bad, since a vi user will be used to hitting escape all the
+// time when editing, because that is always a "safe" thing to do,
+// and if they did it here by mistake, they would lose all
+// their text entry since the last save. So we ignore the escape in this window.
+// I suppose we could ask if they really want to quit...
+// 2. If user does cut or copy via keyboard accelerator, the normal code
+// for ungraying the Paste button doesn't get called, so we catch that case
+// here and ungray it.
+
+int
+Main::handle_events(int e)
+{
+       // If escape is received while on main window,
+       // return 1 to show that we consumed the event.
+       if (e == FL_SHORTCUT && Fl::event_key() == FL_Escape) {
+               for (Main * m_p = list_p; m_p != 0; m_p = m_p->next) {
+                       if (Fl::first_window() == m_p) {
+                               return(1);
+                       }
+               }
+       }
+
+       // If user did cut or copy via cntl-c or cntl-x,
+       // arrange to ungray Paste.
+       if (e == FL_KEYUP && (Fl::event_state() & FL_CTRL)  &&
+                       (Fl::event_key() == 'v' || Fl::event_key() == 'x')) {
+               for (Main * m_p = list_p; m_p != 0; m_p = m_p->next) {
+                       if (Fl::first_window() == m_p) {
+                               m_p->editmenu_p->set_can_paste();
+                               break;
+                       }
+               }
+       }
+
+       return(0);
+}
+
+
+// If user tries to close the main window via the window manager
+// while having unsaved changes, we ask user if they want to save
+// the changes first. 
+
+CALL_BACK(Main, atclose)
+{
+       File::Exit_cb(0, filemenu_p);
+}
+
+
+// Blink the cursor. It can be hard to see if next to selected text if not
+// blinking. We could potentially optimize to only do this while
+// the window has focus, but it doesn't seem worth the complication...
+
+void
+Main::blinker(void * data)
+{
+       Main * obj_p = (Main *) data;
+       // Put cursor into opposite of its current state
+       obj_p->cursor_state ^= 1;
+       obj_p->editor_p->show_cursor(obj_p->cursor_state);
+       // Reset timer to call ourselves again.
+       Fl::repeat_timeout(BLINK_RATE, blinker, data);
+}
+
+
+// Give user hints if we haven't already done that before.
+
+void
+Main::hints(void)
+{
+       int did_startup;
+       (void) Preferences_p->get(Showed_startup_hints, did_startup,
+                                       Default_startup_hints_flag);
+       if ( ! did_startup) { 
+               Help::Startup_Hints_cb(0, (void *) helpmenu_p);
+       }
+}
+
+//----------------------------------------------------------------------
+
+int
+main(int argc, char **argv, const char **arge)
+{
+       // The arge value may get changed when we set new environment
+       // variables, so look up PATH first thing.
+       get_path(arge);
+
+       // Uguide browser needs to show images
+       fl_register_images();
+
+#ifndef OS_LIKE_WIN32
+       // On Windows we use the native Open/Save As dialogs.
+       // On other platforms we use FLTK's, but add icon for Mup files.
+       Fl_File_Icon::load_system_icons();
+       File::add_mup_icon();
+#endif
+
+       // Try to get best hardware support for graphics
+       Fl::visual(FL_DOUBLE|FL_INDEX);
+
+       // Get the user's preferences that persists across sessions
+       Preferences_p = new Fl_Preferences(Fl_Preferences::USER,
+                                       "arkkra.com", "mupmate");
+
+       // Enable tips when user hovers their mouse over a widget.
+       // If user doesn't like them, they can set delay to huge value.
+       Fl_Tooltip::enable();
+       double tooltips_delay;
+       (void) Preferences_p->get(Tooltips_delay_preference, tooltips_delay,
+                                       Default_tooltips_delay);
+       Fl_Tooltip::delay(tooltips_delay);
+
+       // Set $MUPPATH
+       char * val;
+       (void) Preferences_p->get(MUPPATH_location, val,
+                                               Default_MUPPATH_location);
+       set_muppath(val);
+
+       // Tell Mup that it is being run via mupmate,
+       // so it can give more appropriate error messages.
+       putenv("MUPMATE=1");
+
+       // Create main window
+       Main *main_p = new Main("Mupmate");
+
+       // Ensure "escape" key doesn't kill main window,
+       // and make sure Paste ungraying works
+       Fl::add_handler(Main::handle_events);
+
+       // Try to find some reasonable defaults for configuration items
+       // that aren't already set.
+       deduce_helper_locations();
+
+       // If magic file indicating license agreement isn't there,
+       // ask user to agree to Mup license.
+       if (access(magic_file(argv[0]), F_OK) != 0) {
+               // Show the license and get agreement before continuing
+               new License(main_p, magic_file(argv[0]));
+       }
+       else {
+               // Display the main window.
+               main_p->show(1, argv);
+
+               // The first time, we show user some hints.
+               main_p->hints();
+       }
+
+       // Go to where user said they want to store their Mup files by default.
+       // Need to wait to do this until after we have deduced locations
+       // of executable, in case they were in current directory.
+       char * mup_dir;
+       (void) Preferences_p->get(Music_files_location, mup_dir,
+                                               Default_music_files_location);
+       if (strcmp(mup_dir, ".") != 0) {
+               if (chdir(mup_dir) != 0) {
+                       char curr_dir[FL_PATH_MAX] = "current";
+                       char message[2 * FL_PATH_MAX + 100];
+                       (void *) getcwd(curr_dir, sizeof(curr_dir));
+                       sprintf(message, "Unable to change to folder\n"
+                               "\"%s.\"\nStaying in \"%s\" folder.\n"
+                               "Fix setting of \"Folder for Mup Files\"\n"
+                               "in Config->File Locations.",
+                               mup_dir, curr_dir);
+                       fl_alert(message);
+               }
+       }
+
+       // Expect 0 or 1 args. If 1, should be name of file to load
+       if (argc > 1) {
+               main_p->filemenu_p->load_file(argv[1]);
+       }
+       if (argc > 2) {
+               fl_alert("Only expecting one file; extra arguments are being ignored.");
+       }
+
+       // Go into main event-handler loop
+       int exitvalue = Fl::run();
+       Main::clean_exit(exitvalue);
+       /*NOTREACHED*/
+       return(exitvalue);
+}
+
+
+// Clean up all the windows and their children and exit.
+
+void
+Main::clean_exit(int exitval)
+{
+       Main * m_p;
+       Main * nextwin_p;
+
+       for (m_p = list_p; m_p != 0; m_p = nextwin_p) {
+               nextwin_p = m_p->next;
+               delete m_p;
+       }
+       exit(exitval);
+}
+
+//---------- class to show Mup license and get user's agreement
+
+
+License::License(Main *m_p, const char * magic)
+       : Fl_Double_Window(Default_width, Default_height, "Mup License")
+{
+       // save passed-in info in object data
+       main_p = m_p;
+       magic_file_name = magic;
+
+       // widget for displaying the license text
+       text_p = new Fl_Text_Display(20, 20, w() - 40, h() - 90);
+       resizable((Fl_Widget *) text_p);
+       text_p->buffer( new Fl_Text_Buffer () );
+       text_p->textsize(18);
+       text_p->buffer()->text(license_text);
+
+       i_agree_p = new Fl_Return_Button(100, h() - 50, 100, 30, "I Agree");
+       i_agree_p->callback(IAgree_cb, this);
+
+       cancel_p = new Fl_Button(w() - 200, h() - 50, 100, 30, "Cancel");
+       cancel_p->callback(Cancel_cb, this);
+       cancel_p->shortcut(FL_Escape);
+
+       show();
+
+       // Arrange for destructor to free the new-ed child widgets
+       end();
+
+       // Arrange for window manager closes to do Cancel.
+       callback(Cancel_cb, this);
+       when(FL_WHEN_NEVER);
+}
+
+
+License::~License()
+{
+}
+
+
+// Callback for when user clicks that they agree to the license.
+
+CALL_BACK(License, IAgree)
+{
+       // Create the magic file
+       int fd;
+       if ((fd = open(magic_file_name, O_WRONLY | O_CREAT, 0644)) < 0) {
+               fl_alert("Unable to create file indicating license agreement.");
+       }
+       else {
+               close(fd);
+       }
+
+       hide();
+
+       // Bring up the normal main window
+       main_p->show();
+       main_p->hints();
+}
+
+// Callback if user refuses to accept license. We just exit if they refuse.
+
+CALL_BACK(License, Cancel)
+{
+       exit(0);
+}
diff --git a/mup/mupmate/Main.H b/mup/mupmate/Main.H
new file mode 100644 (file)
index 0000000..fc1e6f9
--- /dev/null
@@ -0,0 +1,133 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+#ifndef _MAIN_H_
+#define _MAIN_H_
+
+// Header file for the main Mupmate window, containing toolbar and editor.
+
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Menu_Bar.H>
+#include <FL/Fl_Menu_Item.H>
+#include <FL/Fl_Text_Buffer.H>
+#include <FL/Fl_Text_Editor.H>
+
+#include "File.H"
+#include "Edit.H"
+#include "Run.H"
+#include "Config.H"
+#include "Help.H"
+
+class Main;
+
+//---------- class to show Mup license and get user's agreement
+
+class License : public Fl_Double_Window {
+public:
+       License(Main * m_p, const char * magic);
+       ~License(void);
+
+       // Callbacks
+       static void IAgree_cb(Fl_Widget *, void * data);
+       static void Cancel_cb(Fl_Widget *, void * data);
+       static void Continue_cb(Fl_Widget *, void * data);
+
+private:
+       // Callbacks
+       void IAgree(void);
+       void Cancel(void);
+       void Continue(void);
+
+       // Widgets
+       Fl_Text_Display * text_p;       // The text of the license
+       Fl_Return_Button * i_agree_p;
+       Fl_Button * cancel_p;
+
+       // Name of file that tells us if user has agreed to license
+       const char * magic_file_name;
+
+       // The main window
+       Main * main_p;
+};
+
+
+
+// Class for main window, with editor and toolbar
+
+class Main : public Fl_Double_Window {
+
+friend class License;
+
+public:
+       Main(const char * title);
+       ~Main();
+
+       // Callbacks
+       static void modify_cb(int, int, int, int, const char *, void * data);
+       static void font_change_cb(void * data, Fl_Font font, unsigned char size);
+       static void atclose_cb(Fl_Widget *, void * data);
+
+       // We don't want Escape to cause main window to close,
+       // and need to handle Paste ungraying specially.
+       // This event handler takes care of those things.
+       static int handle_events(int);
+
+       // Show user hints the first time they bring up Mupmate
+       void hints(void);
+
+       // Reset state information when user opens a new file.
+       void begin_new_file();
+
+       // Pointers to the classes for each toolbar menu item widgets
+       File * filemenu_p;
+       Edit * editmenu_p;
+       Config * configmenu_p;
+       Help * helpmenu_p;
+       Run * runmenu_p;
+
+       // Clean up all windows 
+       static void clean_exit(int exitval = 0);
+
+private:
+       // called when input text is modified
+       void modify(void);
+
+       // Sets font/size of editor
+       void font_change(Fl_Font font, unsigned char size);
+
+       // Make window manager close like Exit
+       void atclose(void);
+
+       // Cursor blinker
+       static void blinker(void *);
+
+       // Ponters to the top level widgets
+       Fl_Menu_Bar * toolbar_p;
+       Fl_Text_Editor * editor_p;
+
+       // For font/size change notification
+       Font_change_registration * font_change_reg_p;
+
+       // True if there is a selected area in editor window
+       bool have_selection;
+
+       // True if something in clipboard
+       bool can_paste;
+
+       // For knowing when to gray out Undo menu item
+       bool undo_active;
+       bool undo_active_on_next_change;
+       int prev_bufflength;
+
+       // Current cursor on/off state, for blinker
+       int cursor_state;
+
+       // We currently only have one main window, but code is
+       // general to allow multiple windows. We keep a linked list
+       // of all the windows.
+       static Main * list_p;
+       Main * next;
+};
+
+#endif
diff --git a/mup/mupmate/Preferences.C b/mup/mupmate/Preferences.C
new file mode 100644 (file)
index 0000000..23aba11
--- /dev/null
@@ -0,0 +1,317 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+// This file contains code for defining and using things
+// related to user configuration settings and preferences.
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "globals.H"
+#include "utils.H"
+#include "Preferences.H"
+#include <FL/filename.H>
+
+// Access to the user preferences file
+Fl_Preferences * Preferences_p;
+
+// Preference names and default values
+const char * const Editor_font_preference = "editor_font";
+const char * const Default_editor_font = "Courier";
+
+const char * const Editor_size_preference = "editor_size";
+const char * const Default_editor_size = "12";
+
+const char * const Auto_display_preference = "auto_display";
+const int Default_auto_display = 0;
+
+const char * const Auto_save_preference = "auto_save";
+const int Default_auto_save = 1;
+
+const char * const Tooltips_delay_preference = "tooltips_delay";
+const double Default_tooltips_delay = 1.0;
+
+const char * const Mup_program_location = "Mup_program";
+const char * const Default_Mup_program_location = "mup";
+
+const char * const Mup_documentation_location = "Mup_documentation";
+#if defined(__WIN32)
+const char * const Default_Mup_documentation_location = "c:\\Program Files\\mupmate";
+#else
+const char * const Default_Mup_documentation_location = "/usr/share/doc/packages/mup";
+#endif
+
+const char * const Music_files_location = "Music_folder";
+const char * const Default_music_files_location = ".";
+
+const char * const MUPPATH_location = "MUPPATH";
+const char * const Default_MUPPATH_location = ".";
+
+const char * const Viewer_location = "Viewer";
+#if defined(__WIN32)
+const char * const Default_viewer_location = "c:\\Program Files\\Ghostgum\\gsview\\gsview32.exe";
+#else
+const char * const Default_viewer_location = "gv";
+#endif
+
+const char * const MIDI_player_location = "MIDI_player";
+#if defined(__WIN32)
+const char * const Default_MIDI_player_location = "c:\\Program Files\\Windows Media Player\\wmplayer.exe";
+#else
+const char * const Default_MIDI_player_location = "xplaymidi";
+#endif
+
+const char * const Showed_startup_hints = "showed_startup_hints";
+const int Default_startup_hints_flag = 0;
+
+// Name of User's Guide directory and index file
+// relative to Mup documentation directory.
+const char * uguide_directory = "uguide";
+#ifdef OS_LIKE_WIN32
+const char * uguide_filename = "index.htm";
+#else
+const char * uguide_filename = "index.html";
+#endif
+
+// Don't use un-readable tiny font, but especially avoid size of zero,
+// which could happen if preferences file contains a bad number, so that
+// atoi() returns zero. Keep max small enough to fit reasonable number
+// of characters in a window.
+const unsigned char Min_size = 5;
+const unsigned char Max_size = 30;
+
+// Minimum and default sizes for Main and Help browser windows.
+const int Min_width = 600;
+const int Default_width = 720;
+const int Min_height = 400;
+const int Default_height = 480;
+
+
+// If user hasn't specified any program yet to use for PostScript viewer
+// and/or MIDI file player, we try to deduce what they have available
+// that could be used, and set one of those as the default.
+
+// List of likely programs to use as PostScript viewers
+static const char * const viewer_candidates[] = {
+#if defined(__WIN32)
+       "GSview32",
+       "GSview",
+#else
+#ifdef OS_LIKE_UNIX
+       "gv",
+       "ghostview",
+#endif
+#endif
+       0
+};
+
+// List of likely programs to use as MIDI file players
+static const char * const player_candidates[] = {
+#if defined(__WIN32)
+       "wmplayer",
+       "mplayer",
+#else
+#ifdef OS_LIKE_UNIX
+       "xplaymidi",
+       "timidity",
+       "pmidi",
+       "playmidi",
+#endif
+#endif
+       0
+};
+
+
+// If the default preference value for a program location is no good,
+// try to find where it is.
+// pgm_location = the preference name of the program of interest
+// default_location = the default path to the program
+// file_suffix = .ps or .mod or .mup
+// Returns true if the preference value was updated.
+
+static bool
+deduce_location(const char * pgm_location, const char * default_location,
+                       const char * file_suffix, const char * const * candidates)
+{
+       char * place;                   // a path to try for finding the pgm
+       char location[FL_PATH_MAX];     // full path to pgm when it is found
+
+       if (Preferences_p->get(pgm_location, place, default_location) != 0) {
+               // There was a value already set. Make sure it is good.
+               if (find_executable(place, location)) {
+                       if (strcmp(place, location) != 0) {
+                               // Must have started as relative path
+                               // and now we know the full path.
+                               (void) Preferences_p->set(pgm_location, location);
+                               return(true);
+                       }
+                       else {
+                               // Existing setting was okay as is.
+                               return(false);
+                       }
+               }
+       }
+
+#ifdef OS_LIKE_WIN32
+       // Try looking in the registry for what to use for
+       // files of this type.
+       if ((place = lookup_pgm_for_file_suffix(file_suffix)) != 0) {
+               (void) Preferences_p->set(place, default_location);
+               return(true);
+       }
+#endif
+
+       // If there had been nothing set, see if the default location is good.
+       if (find_executable(default_location, location)) {
+               (void) Preferences_p->set(pgm_location, location);
+               return(true);
+       }
+
+       // Try looking in the various educated guess locations.
+       if (candidates != 0) {
+               int i;
+               for (i = 0; candidates[i] != 0; i++) {
+                       if (find_executable(candidates[i], location)) {
+                               (void) Preferences_p->set(pgm_location, location);
+                               return(true);
+                       }
+               }
+       }
+
+       return(false);
+}
+
+
+// Returns true is the Mup User's Guide can be found at the given location.
+
+static bool
+doc_found(const char * location)
+{
+       return(access(users_guide_index_file(location), F_OK) == 0);
+}
+
+
+// Try to deduce where the Mup documentation is.
+// Returns true if updated the Preferences to point to new location.
+
+static bool
+deduce_documentation_location(const char * doc_location, const char * default_doc_location)
+{
+       char * place;
+       // First try the stored location, if any
+       if (Preferences_p->get(doc_location, place, default_doc_location) != 0) {
+               if (doc_found(place)) {
+                       // Existing preference is good. No update needed.
+                       return(false);
+               }
+       }
+
+       // Try default location 
+       if (doc_found(default_doc_location)) {
+               Preferences_p->set(doc_location, default_doc_location);
+               return(true);
+       }
+
+       // Try relative to where Mup executable is.
+       char *muploc;
+       (void) Preferences_p->get(Mup_program_location, muploc,
+                                       Default_Mup_program_location);
+       char * basename_p;
+       if ((basename_p = strrchr(muploc, dir_separator())) != 0) {
+               int len = basename_p - muploc;
+               char mupdir[len + 1];
+               (void) strncpy(mupdir, muploc, len);
+               mupdir[len] = '\0';
+               if (doc_found(mupdir)) {
+                       Preferences_p->set(doc_location, mupdir);
+                       return(true);
+               }
+
+               // Try at ../docs from where mup executable was,
+               // since it could be there from unpacking tar file.
+               char * parentdir_p;
+               if ((parentdir_p = strrchr(mupdir, dir_separator())) != 0) {
+                       len = parentdir_p - mupdir + 1;
+                       // Add room for doc and terminator
+                       char mupdocdir[len + 5];
+                       (void) strncpy(mupdocdir, muploc, len);
+                       (void) strcpy(mupdocdir + len, "docs");
+                       if (doc_found(mupdocdir)) {
+                               Preferences_p->set(doc_location, mupdocdir);
+                               return(true);
+                       }
+               }
+       }
+       return(false);
+}
+
+
+// This function attempts to find the locations of what we need,
+// like a PostScript viewer and MIDI player.
+
+void
+deduce_helper_locations(void)
+{
+       bool updated = false;
+
+       // First try to find a PostScript viewer
+       if (deduce_location(Viewer_location, Default_viewer_location, ".ps",
+                                       viewer_candidates)) {
+               updated = true;
+       }
+
+       // Next do MIDI player
+       if (deduce_location(MIDI_player_location, Default_MIDI_player_location,
+                               ".mid", player_candidates)) {
+               updated = true;
+       }
+
+       // Find the Mup command itself
+       if (deduce_location(Mup_program_location, Default_Mup_program_location, ".mup", 0)) {
+               updated = true;
+       }
+
+       if (deduce_documentation_location(Mup_documentation_location,
+                               Default_Mup_documentation_location)) {
+               updated = true;
+       }
+
+#ifdef OS_LIKE_WIN32
+       // Try to guess a good default place for Mup input files.
+       char * place;
+       if (Preferences_p->get(Music_files_location, place,
+                                       Default_music_files_location) == 0) {
+               if ((place = find_music_folder()) != 0) {
+                       Preferences_p->set(Music_files_location, place);
+                       updated = true;
+               }
+       }
+       // The same place is probably a good guess for Mup include files.
+       if (Preferences_p->get(MUPPATH_location, place,
+                                       Default_MUPPATH_location) == 0) {
+               if ((place = find_music_folder()) != 0) {
+                       Preferences_p->set(MUPPATH_location, place);
+                       updated = true;
+               }
+       }
+#endif
+
+       // If at least one better choice was found, update the persistent data.
+       if (updated) {
+               Preferences_p->flush();
+       }
+}
+
+
+// Given a path to Mup's documentation directory,
+// add on the name of the User's Guide index file.
+// Return that in a static area.
+
+const char *
+users_guide_index_file(const char * const doc_dir)
+{
+       static char file_path[FL_PATH_MAX];
+       (void) sprintf(file_path, "%s%c%s%c%s", doc_dir, dir_separator(),
+                       uguide_directory, dir_separator(), uguide_filename);
+       return((const char *) file_path);
+}
diff --git a/mup/mupmate/Preferences.H b/mup/mupmate/Preferences.H
new file mode 100644 (file)
index 0000000..374f574
--- /dev/null
@@ -0,0 +1,64 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+#ifndef _PREFERENCES_H_
+#define _PREFERENCES_H_
+
+// This file contains things related to user configuration options
+// and preferences.
+
+#include <FL/Fl_Preferences.H>
+
+// Names and default values for things stored in preferences file
+extern const char * const Mup_program_location;
+extern const char * const Mup_documentation_location;
+extern const char * const Music_files_location;
+extern const char * const MUPPATH_location;
+extern const char * const Viewer_location;
+extern const char * const MIDI_player_location;
+extern const char * const Editor_font_preference;
+extern const char * const Editor_size_preference;
+extern const char * const Auto_display_preference;
+extern const char * const Auto_save_preference;
+extern const char * const Tooltips_delay_preference;
+extern const char * const Showed_startup_hints;
+
+extern const char * const Default_Mup_program_location;
+extern const char * const Default_Mup_documentation_location;
+extern const char * const Default_music_files_location;
+extern const char * const Default_MUPPATH_location;
+extern const char * const Default_viewer_location;
+extern const char * const Default_MIDI_player_location;
+extern const char * const Default_editor_font;
+extern const char * const Default_editor_size;
+extern const int Default_auto_display;
+extern const int Default_auto_save;
+extern const double Default_tooltips_delay;
+extern const int Default_startup_hints_flag;
+
+// This lets us access user preferences that persist across sessions
+extern Fl_Preferences * Preferences_p;
+
+// Minimum and maximum font size we use
+extern const unsigned char Min_size;
+extern const unsigned char Max_size;
+
+// Default and minimum sizes of Main and Help browser windows
+extern const int Min_width;
+extern const int Default_width;
+extern const int Min_height;
+extern const int Default_height;
+
+// The directory containing User's Guide, relative to top of
+// documentation tree
+extern const char * uguide_directory;
+
+// Given a path to Mup's documentation directory,
+// add on the name of the User's Guide index file.
+// Return that in a static area.
+extern const char * users_guide_index_file(const char * const doc_dir);
+
+// This tries to find reasonable default applications for viewing and playing
+extern void deduce_helper_locations(void);
+
+#endif
diff --git a/mup/mupmate/Run.C b/mup/mupmate/Run.C
new file mode 100644 (file)
index 0000000..de95228
--- /dev/null
@@ -0,0 +1,1371 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+// This file includes methods related to the "Run" menu on the main toolbar.
+
+#include "Run.H"
+#include "Preferences.H"
+#include "globals.H"
+#include "Config.H"
+#include "defines.h"
+#include <FL/fl_ask.H>
+#include <FL/filename.H>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#ifdef OS_LIKE_UNIX
+#include <sys/wait.h>
+#include <errno.h>
+#endif
+
+// Message for when Mup fails, but we can't figure out why.
+const char * Unknown_Mup_failure = "Mup failed. Reason unknown.";
+
+// Describe use of numbers passed to -x option
+#define EXTRACT_NUM_DESCRIPTION "0 is used for pickup measure.\n" \
+               "Negative numbers are used to specify\n" \
+               "number of measures from the end.\n"
+
+// Tooltip is the same for all macro entries
+const char * macro_definition_tip =
+       "Your Mup input can use macros to vary characteristics\n"
+       "of the output for different runs.\n"
+       "Enter the name of a macro you want to define,\n"
+       "optionally followed by an equals sign and macro definition.\n"
+       "Macro names must consist of upper case letters,\n"
+       "numbers, and underscores, starting with an upper case letter.";
+
+//------ Class for user to set parameters to pass to Mup
+
+Run_parameters_dialog::Run_parameters_dialog(void)
+               : Fl_Double_Window(0, 0, 700, 350, "Mup Options")
+{
+       enable_combine_p = new Fl_Check_Button(20, 20, 165, 30,
+                                               "Enable Auto Multirest");
+       enable_combine_p->tooltip("Set whether to automatically combine\n"
+                       "consecutive measures of rests into a multirest.");
+       enable_combine_p->callback(combine_cb, this);
+       enable_combine_p->when(FL_WHEN_CHANGED);
+
+       rest_combine_p = new Positive_Int_Input(370, 20, 40, 30,
+                                               "Min Measures to Combine");
+       rest_combine_p->tooltip("Minimum number of consecutive measures\n"
+                       "of rest that will be combined into a multirest.");
+       // Only becomes active if auto-multirest combine becomes active
+       rest_combine_p->deactivate();
+
+       // -p firstpage
+       first_page_p = new Positive_Int_Input(300, 60, 50, 30, "First Page's Page Number");
+       first_page_p->tooltip("Set the page number to use\n"
+                       "for the first page of music output.");
+
+       // -o pagelist
+       pages_p = new Fl_Group(30, 100, 380, 70, "Pages to Display");
+       pages_p->box(FL_ENGRAVED_BOX);
+       pages_p->align(FL_ALIGN_TOP_LEFT | FL_ALIGN_INSIDE);
+
+       all_p = new Fl_Check_Button(170, 105, 55, 20, "All");
+       all_p->type(FL_RADIO_BUTTON);
+       all_p->tooltip("You can restrict to displaying only a subset\n"
+                       "of the pages of music, but this shows all pages.");
+       all_p->callback(selected_pages_cb, this);
+       all_p->when(FL_WHEN_CHANGED);
+
+       odd_p = new Fl_Check_Button(245, 105, 60, 20, "Odd");
+       odd_p->type(FL_RADIO_BUTTON);
+       odd_p->tooltip("This restricts to displaying only\n"
+                       "odd numbered pages. This is generally\n"
+                       "most useful for printing to a\n"
+                       "single-sided printer.");
+       odd_p->callback(selected_pages_cb, this);
+       odd_p->when(FL_WHEN_CHANGED);
+
+       even_p = new Fl_Check_Button(320, 105, 70, 20, "Even");
+       even_p->type(FL_RADIO_BUTTON);
+       even_p->tooltip("This restricts to displaying only\n"
+                       "even numbered pages. This is generally\n"
+                       "most useful for printing to a\n"
+                       "single-sided printer.");
+       even_p->callback(selected_pages_cb, this);
+       even_p->when(FL_WHEN_CHANGED);
+
+       selected_p = new Fl_Check_Button(50, 135, 85, 20, "Selected:");
+       selected_p->tooltip("This restricts to displaying only\n"
+                       "the pages you list in the blank to the right.");
+       selected_p->type(FL_RADIO_BUTTON);
+       selected_p->callback(selected_pages_cb, this);
+       selected_p->when(FL_WHEN_CHANGED);
+
+       page_list_p = new Fl_Input(150, 130, 230, 30, "");
+       page_list_p->tooltip("List the specific pages you want displayed.\n"
+                       "You can list individual pages separated by commas,\n"
+                       "and/or ranges of pages separated by dashes.\n"
+                       "Pages may be listed more than once and in any order.");
+       page_list_p->deactivate();
+       saved_page_list = 0;
+       pages_p->end();
+
+       // -s stafflist
+       staff_list_p = new Fl_Input(150, 180, 260, 30, "Staffs to Display/Play");
+       staff_list_p->tooltip("If you wish to display or play only a subset\n"
+                       "of the staffs, or voices on a staff, list them here.\n"
+                       "Staffs are specified by comma-separated numbers\n"
+                       "or ranges, like 1,4 or 1-3,5-6. Staff numbers can be\n"
+                       "followed by v1, v2, or v3 to limit to a single voice.\n");
+       saved_staff_list = 0;
+
+       // -x extract list
+       extract_begin_p = new Int_Input(150, 220, 95, 30, "Extract Measures");
+       extract_begin_p->tooltip("If you wish to display or play only selected\n"
+                       "measures, enter the starting measure here.\n"
+                       EXTRACT_NUM_DESCRIPTION);
+       extract_begin_p->callback(extract_cb, this);
+       extract_begin_p->when(FL_WHEN_CHANGED);
+       extract_end_p = new Int_Input(315, 220, 95, 30, "through");
+       extract_end_p->tooltip("If you wish to display or play only selected\n"
+                       "measures, enter the ending measure here.\n"
+                       EXTRACT_NUM_DESCRIPTION);
+       extract_end_p->deactivate();
+
+       // Macros
+       macros_group_p = new Fl_Group(430, 20, 250, 40 + MAX_MACROS * 40, "Macro Definitions");
+       macros_group_p->box(FL_ENGRAVED_BOX);
+       macros_group_p->align(FL_ALIGN_TOP | FL_ALIGN_INSIDE);
+       int m;
+       for (m = 0; m < MAX_MACROS; m++) {
+
+               macro_definitions_p[m] = new Fl_Input(450, 50 + m * 40, 210, 30, "");
+               macro_definitions_p[m]->tooltip(macro_definition_tip);
+
+               saved_macro_definitions[m] = 0;
+       }
+       macros_group_p->end();
+
+       save_p = new Fl_Return_Button(100, h() - 50, 80, 30, "Save");
+       save_p->callback(Save_cb, this);
+       save_p->when(FL_WHEN_RELEASE);
+
+       clear_form_p = new Fl_Button((w() - 150) / 2, h() - 50, 150, 30,
+                                                               "Clear Options");
+       clear_form_p->callback(clear_form_cb, this);
+       clear_form_p->when(FL_WHEN_RELEASE);
+
+       cancel_p = new Fl_Button(w() - 180, h() - 50, 80, 30, "Cancel");
+       cancel_p->shortcut(FL_Escape);
+       cancel_p->callback(Cancel_cb, this);
+       cancel_p->when(FL_WHEN_RELEASE);
+
+       // Set everything to default values
+       clear_form();
+       
+       // Arrange to clean up all the new-ed widgets in destructor.
+       end();
+
+       // Arrange for window manager closes to do Cancel.
+       callback(Cancel_cb, this);
+       when(FL_WHEN_NEVER);
+}
+
+
+Run_parameters_dialog::~Run_parameters_dialog(void)
+{
+       int m;
+       for (m = 0; m < MAX_MACROS; m++) {
+               if (saved_macro_definitions[m] != 0) {
+                       delete saved_macro_definitions[m];
+               }
+       }
+}
+
+
+//---- Callback for when user changes enablement of rest combining,
+// to gray or ungray the field for how many measures to combine.
+
+CALL_BACK(Run_parameters_dialog, combine)
+{
+       if (enable_combine_p->value()) {
+               rest_combine_p->activate();
+       }
+       else {
+               rest_combine_p->value("");
+               rest_combine_p->deactivate();
+       }
+}
+
+
+//---- Callback for when user changes setting of start of measure extraction,
+// to gray or ungray the field for ending measure of extraction.
+
+CALL_BACK(Run_parameters_dialog, extract)
+{
+       if (extract_begin_p->size() > 0) {
+               extract_end_p->activate();
+       }
+       else {
+               extract_end_p->value("");
+               extract_end_p->deactivate();
+       }
+}
+
+//---- Callback for when user changes setting of page selection,
+// to gray or ungray the field for listing the specific pages to display
+
+CALL_BACK(Run_parameters_dialog, selected_pages)
+{
+       page_list_p->value("");
+       if (selected_p->value() == 1) {
+               page_list_p->activate();
+       }
+       else {
+               page_list_p->deactivate();
+       }
+}
+
+
+//----Callback for button for clearing the form
+
+CALL_BACK(Run_parameters_dialog, clear_form)
+{
+       // Set everything to default values
+       saved_enable_combine = false;
+       enable_combine_p->value(saved_enable_combine);
+
+       (void) sprintf(saved_combine_measures, "");
+       rest_combine_p->value(saved_combine_measures);
+
+       (void) sprintf(saved_first_page, "%d", MINFIRSTPAGE);
+       first_page_p->value(saved_first_page);
+
+       if (saved_page_list != 0) {
+               delete saved_page_list;
+       }
+       saved_page_list = new char[1];
+       saved_page_list[0] = '\0';
+       page_list_p->value(saved_page_list);
+       all_p->value(1);
+       saved_pages = ALL_PAGES;
+
+       if (saved_staff_list != 0) {
+               delete saved_staff_list;
+       }
+       saved_staff_list = new char[1];
+       saved_staff_list[0] = '\0';
+       staff_list_p->value(saved_staff_list);
+
+       saved_extract_begin[0] = '\0';
+       extract_begin_p->value(saved_extract_begin);
+       saved_extract_end[0] = '\0';
+       extract_end_p->value(saved_extract_end);
+
+       int m;
+       for (m = 0; m < MAX_MACROS; m++) {
+               macro_definitions_p[m]->value("");
+               if (saved_macro_definitions[m] != 0) {
+                       delete saved_macro_definitions[m];
+                       saved_macro_definitions[m] = 0;
+               }
+       }
+}
+
+
+//---- callback for when user clicks "Save" on Set Options form
+
+CALL_BACK(Run_parameters_dialog, Save)
+{
+       // -c rest combine option
+       bool error = false;
+       saved_enable_combine = enable_combine_p->value();
+       int num_meas = (int) atoi(rest_combine_p->value());
+       if (saved_enable_combine && (num_meas < MINRESTCOMBINE || num_meas > MAXRESTCOMBINE)) {
+               fl_alert("\"Min Measures to Combine\" must be between\n"
+                       "%d and %d.", MINRESTCOMBINE, MAXRESTCOMBINE);
+               error = true;
+       }
+       else {
+               (void) strcpy(saved_combine_measures, rest_combine_p->value());
+       }
+
+       // -p first page option
+       int page_num = (int) atoi(first_page_p->value());
+       if (page_num < MINFIRSTPAGE || page_num > MAXFIRSTPAGE) {
+               fl_alert("\"First Page\" number must be between\n"
+               "%d and %d.", MINFIRSTPAGE, MAXFIRSTPAGE);
+               error = true;
+       }
+       else {
+               (void) strcpy(saved_first_page, first_page_p->value());
+       }
+
+       // We don't really fully parse and error check the -o argument,
+       // but make sure it at least is made up of only valid characters.
+       if (page_list_p->size() > 0) {
+               if (strspn(page_list_p->value(), "0123456789,- \t")
+                                       != page_list_p->size()) {
+                       fl_alert("\"Pages to Display\" value is not valid.");
+                       error = true;
+               }
+               else {
+                       // Free existing, if any, and save new value.
+                       if (saved_page_list != 0) {
+                               delete saved_page_list;
+                       }
+                       saved_page_list = new char[page_list_p->size() + 1];
+                       strcpy(saved_page_list, page_list_p->value());
+               }
+       }
+       else if (saved_page_list[0] != '\0') {
+               // Had a list before but not anymore.
+               // Null out the existing list.
+               delete saved_page_list;
+               saved_page_list = new char[1];
+               saved_page_list[0] = '\0';
+       }
+       if (all_p->value() == 1) {
+               saved_pages = ALL_PAGES;
+       }
+       if (odd_p->value() == 1) {
+               saved_pages = ODD_PAGES;
+       }
+       if (even_p->value() == 1) {
+               saved_pages = EVEN_PAGES;
+       }
+       if (selected_p->value() == 1) {
+               saved_pages = SELECTED_PAGES;
+       }
+       if (saved_pages == SELECTED_PAGES && page_list_p->size() == 0) {
+               fl_alert("You did not list which selected pages you want.");
+               error = true;
+       }
+
+       // Similar for staff list (-s option)
+       if (staff_list_p->size() > 0) {
+               if (strspn(staff_list_p->value(), "0123456789,-v \t")
+                                       != staff_list_p->size()) {
+                       fl_alert("\"Staffs to Display/Play\" is not valid");
+                       error = true;
+               }
+               else {
+                       if (saved_staff_list != 0) {
+                               delete saved_staff_list;
+                       }
+                       saved_staff_list = new char[staff_list_p->size() + 1];
+                       strcpy(saved_staff_list, staff_list_p->value());
+               }
+       }
+       else if (saved_staff_list[0] != '\0') {
+               delete saved_staff_list;
+               saved_staff_list = new char[1];
+               saved_staff_list[0] = '\0';
+       }
+
+       // We can't really error check -x option values.
+       // Widget will have already constrained to integer,
+       // and we have no way to know what range is valid,
+       // since we don't know how many measures the song has.
+       // However, to keep things simple, we have fixed-size array of 8 bytes
+       // for saving value, so can only allow up to 6 digits plus sign.
+       if (abs(atoi(extract_begin_p->value())) >= 1000000) {
+               fl_alert("\"Extract Measures\" start value is out of range.");
+               error = true;
+       }
+       else {
+               (void) strcpy(saved_extract_begin, extract_begin_p->value());
+       }
+       if (abs(atoi(extract_end_p->value())) >= 1000000) {
+               fl_alert("\"Extract Measures\" end value is out of range.");
+               error = true;
+       }
+       else {
+               (void) strcpy(saved_extract_end, extract_end_p->value());
+       }
+
+       // Macros
+       int m;
+       int macsize;
+       bool changed;
+       for (m = 0; m < MAX_MACROS; m++) {
+               changed = false;
+               if ((macsize = macro_definitions_p[m]->size()) > 0) {
+                       if (macro_error(macro_definitions_p[m]->value())) {
+                               fl_alert("Macro %d has invalid format.", m + 1);
+                               error = true;
+                       }
+                       else if (saved_macro_definitions[m] == 0) {
+                               // no macro before, but is one now
+                               changed = true;
+                       }
+                       else if (strcmp(macro_definitions_p[m]->value(),
+                                       saved_macro_definitions[m]) != 0) {
+                               // A different macro value than before
+                               delete saved_macro_definitions[m];
+                               changed = true;
+                       }
+                       if (changed) {
+                               saved_macro_definitions[m] = new char[macsize + 1];
+                               (void) strcpy(saved_macro_definitions[m],
+                                       macro_definitions_p[m]->value());
+                       }
+               }
+               else if (macsize == 0 && saved_macro_definitions[m] != 0) {
+                       // Used to be a macro value, but not anymore
+                       delete saved_macro_definitions[m];
+                       saved_macro_definitions[m] = 0;
+               }
+       }
+
+
+       // If there were user errors, we leave the window up for user to
+       // correct the errors. User can, of course, cancel without correcting,
+       // in which case if they try to run, Mup will complain about the
+       // bad arguments.
+       if ( ! error ) {
+               hide();
+       }
+}
+
+
+//---- Callback for when user clicks "Cancel" on Set Options form
+
+CALL_BACK(Run_parameters_dialog, Cancel)
+{
+       // Put back all the previous values
+       enable_combine_p->value(saved_enable_combine);
+       rest_combine_p->value(saved_combine_measures);
+       first_page_p->value(saved_first_page);
+
+       // It seems setting a radio button via value(1) doesn't reset the
+       // others, so clear all, then set the one we want
+       all_p->value(0);
+       odd_p->value(0);
+       even_p->value(0);
+       selected_p->value(0);
+       switch (saved_pages) {
+       default:        // default should be impossible
+       case ALL_PAGES:
+               all_p->value(1);
+               break;
+       case ODD_PAGES:
+               odd_p->value(1);
+               break;
+       case EVEN_PAGES:
+               even_p->value(1);
+               break;
+       case SELECTED_PAGES:
+               selected_p->value(1);
+               break;
+       }
+       page_list_p->value(saved_page_list);
+       staff_list_p->value(saved_staff_list);
+       extract_begin_p->value(saved_extract_begin);
+       extract_end_p->value(saved_extract_end);
+
+       int m;
+       for (m = 0; m < MAX_MACROS; m++) {
+               macro_definitions_p[m]->value( saved_macro_definitions[m] == 0
+                                       ? "" : saved_macro_definitions[m]);
+       }
+       hide();
+}
+
+// Return true if check of macro finds an error.
+
+bool
+Run_parameters_dialog::macro_error(const char * macro)
+{
+       // First character must be an upper case letter.
+       if ( ! isupper(macro[0])) {
+               return(true);
+       }
+       // Everything up to = or end of string, whichever comes first,
+       // must be upper case letter, digit, or underscore.
+       const char * m_p;
+       for (m_p = macro; *m_p != '\0' && *m_p != '='; m_p++) {
+               if ( ! isupper(*m_p) && ! isdigit(*m_p) && *m_p != '_') {
+                       return(true);
+               }
+       }
+       return(false);
+}
+
+
+//--------class for Run menu -----------------------------------------------
+
+Run::Run()
+{
+       parameters_p = 0;
+       report_p = 0;
+#ifdef OS_LIKE_WIN32
+       display_child.hProcess = 0;
+       display_child.dwProcessId = 0;
+       MIDI_child.hProcess = 0;
+       MIDI_child.dwProcessId = 0;
+#else
+       display_child = 0;
+       MIDI_child = 0;
+#endif
+}
+
+Run::~Run()
+{
+       if (parameters_p != 0) {
+               delete parameters_p;
+               parameters_p = 0;
+       }
+       if (report_p != 0) {
+               delete report_p;
+               report_p = 0;
+       }
+       // Kill off any child processes
+       clean_up();
+}
+
+
+
+//------------callback for Display menu item
+
+CALL_BACK(Run, Display)
+{
+       Run_Mup(false, true);
+}
+
+
+//-----Callback for menu item to play MIDI file
+
+CALL_BACK(Run, Play)
+{
+       Run_Mup(true, true);
+}
+
+
+//---------callback for menu item for writing PostScript output
+
+CALL_BACK(Run, WritePostScript)
+{
+       Run_Mup(false, false);
+}
+
+//---------callback for menu item for writing MIDI output
+
+CALL_BACK(Run, WriteMIDI)
+{
+       Run_Mup(true, false);
+}
+
+//---- callback for menu item to collect Mup command line parameters from user
+
+CALL_BACK(Run, Options)
+{
+       if (parameters_p == 0) {
+               parameters_p = new Run_parameters_dialog();
+       }
+       parameters_p->show();
+}
+
+
+//--------- This lets Run class know the file name and editor buffer,
+// which it needs access to, so it can run Mup on its contents.
+
+void
+Run::set_file(File * file_info_p)
+{
+       file_p = file_info_p;
+}
+
+
+// Run Mup commands with user's parameters on the current file
+
+void
+Run::Run_Mup(bool midi, bool show_or_play)
+{
+
+       const char * mup_input = file_p->effective_filename();
+       // Make sure file has been written.
+       // The fiilename == 0 will be hit in the case where
+       // user did New From Template but made no changes.
+       if (file_p->unsaved_changes || file_p->filename == 0) {
+               int auto_save;
+               (void) Preferences_p->get(Auto_save_preference, auto_save,
+                                                       Default_auto_save);
+               if (auto_save) {
+                       file_p->Save(false);
+                       if (file_p->unsaved_changes || file_p->filename == 0) {
+                               // User probably canceled a Save that got
+                               // turned into a SaveAs,
+                               // or maybe Save failed. If not properly
+                               // saved, we shouldn't try to process it.
+                               return;
+                       }
+               }
+               else {
+                       bool hide_the_No;
+                       const char * extra_text;
+                       // If there is a previous version of the file,
+                       // allow user to select "No," which means use that
+                       // previous version rather than writing out current.
+                       if (access(mup_input, F_OK) == 0) {
+                               hide_the_No = false;
+                               extra_text = "(If you select \"No,\" "
+                                       "the most recently saved version "
+                                       "of the Mup input file will be used.)";
+                       }
+                       else {
+                               // No previous version
+                               hide_the_No = true;
+                               extra_text = "";
+                       }
+                       switch (file_p->save_changes_check(extra_text, hide_the_No)) {
+                       default:        // default case should be impossible
+                       case Save_confirm_dialog::Cancel:
+                               return;
+                       case Save_confirm_dialog::No:
+                               break;
+                       case Save_confirm_dialog::Yes:
+                               file_p->Save(false);
+                               if (file_p->unsaved_changes
+                                               || file_p->filename == 0) {
+                                       // User probably canceled the Save,
+                                       // or maybe it failed. If not properly
+                                       // saved, we shouldn't try to process it.
+                                       return;
+                               }
+                               break;
+                       }
+               }
+               // If was "Untitled" before, it is now saved under a good
+               // name, so get what that is.
+               mup_input = file_p->effective_filename();
+       }
+
+       // Get length of file name without the extension
+       int base_length = strlen(mup_input)
+                                       - strlen(fl_filename_ext(mup_input));
+
+       // Create output file name
+       char mup_output[base_length + (midi ? 5 : 4)];
+       strncpy(mup_output, mup_input, base_length);
+       strcpy(mup_output + base_length, (midi ? ".mid" : ".ps"));
+
+       // Create error file name
+       char mup_error[base_length + 5];
+       strncpy(mup_error, mup_input, base_length);
+       strcpy(mup_error + base_length, ".err");
+
+       // Get Mup command to use.
+       char * mup_command;
+       (void) Preferences_p->get(Mup_program_location, mup_command,
+                                       Default_Mup_program_location);
+       char full_location[FL_PATH_MAX];
+       if ( ! find_executable(mup_command, full_location)) {
+               fl_alert("Mup command not found.\n"
+                               "Check Config > File Locations setting.");
+               return;
+       }
+
+       if (parameters_p == 0) {
+               // User hasn't set any parameters, so we will use all
+               // defaults. Creating the instance lets us deference it
+               // below, so we don't have to care whether user ever
+               // went to the Set Options page or not.
+               parameters_p = new Run_parameters_dialog();
+       }
+
+       // Build up list of arguments.
+       // array slots needed for args:
+       //      1 for Mup command itself
+       //      2 for -e and arg
+       //      2 for -f or -m and arg
+       //      2 for -c and arg
+       //      2 for -p and arg
+       //      2 for -o and arg
+       //      2 for -s and arg
+       //      2 for -x and arg
+       //      1 for Mup input file name
+       //      2 for each -D and its macro definition arg
+       //      1 for null terminator
+       const char * command[17 + 2 * MAX_MACROS];
+       command[0] = full_location;
+       command[1] = "-e";
+       command[2] = mup_error;
+       command[3] = (midi ? "-m" : "-f");
+       command[4] = mup_output;
+       int arg_offset = 5;
+
+       // rest combine
+       if (parameters_p->enable_combine_p->value() &&
+                       parameters_p->rest_combine_p->size() > 0) {
+               command[arg_offset++] = "-c";
+               command[arg_offset++] = parameters_p->rest_combine_p->value();
+       }
+
+       // first page
+       if (parameters_p->first_page_p->size() > 0) {
+               command[arg_offset++] = "-p";
+               command[arg_offset++] = parameters_p->first_page_p->value();
+       }
+
+       // page list
+       switch (parameters_p->saved_pages) {
+       default:        // default should be impossible
+       case Run_parameters_dialog::ALL_PAGES:
+               break;
+       case Run_parameters_dialog::ODD_PAGES:
+               command[arg_offset++] = "-o";
+               command[arg_offset++] = "odd";
+               break;
+       case Run_parameters_dialog::EVEN_PAGES:
+               command[arg_offset++] = "-o";
+               command[arg_offset++] = "even";
+       case Run_parameters_dialog::SELECTED_PAGES:
+               if (parameters_p->page_list_p->size() > 0) {
+                       command[arg_offset++] = "-o";
+                       command[arg_offset++] = parameters_p->page_list_p->value();
+               }
+               // Else they said selected, but then didn't list
+               // any particular pages. We treat like ALL_PAGES,
+               // since no pages is useless.
+               // We would have already given error message,
+               // but they must have ignored it.
+               break;
+       }
+
+       // staff list
+       if (parameters_p->staff_list_p->size() > 0) {
+               command[arg_offset++] = "-s";
+               command[arg_offset++] = parameters_p->staff_list_p->value();
+       }
+
+       // extract list
+       char xoption[parameters_p->extract_begin_p->size()
+                               + parameters_p->extract_end_p->size() + 2];
+       if (parameters_p->extract_begin_p->size() > 0) {
+               command[arg_offset++] = "-x";
+               (void) strcpy(xoption, parameters_p->extract_begin_p->value());
+               if (parameters_p->extract_end_p->size() > 0) {
+                       (void) strcat(xoption, ",");
+                       (void) strcat(xoption, parameters_p->extract_end_p->value());
+               }
+               command[arg_offset++] = xoption;
+       }
+
+       // -D options
+       int m;
+       for (m = 0; m < MAX_MACROS; m++) {
+               if (parameters_p->saved_macro_definitions[m] != 0) {
+                       command[arg_offset++] = "-D";
+                       command[arg_offset++] = parameters_p->saved_macro_definitions[m];
+               }
+       }
+
+       // Mup input file name and null terminator
+       command[arg_offset++] = mup_input;
+       command[arg_offset++] = 0;
+
+       static bool set_mupquiet = false;
+       if ( ! set_mupquiet ) {
+               putenv("MUPQUIET=1");
+               set_mupquiet = true;
+       }
+
+       // Look up the right (dis)player program to use.
+       // On Windows we need this even if we are only writing the file,
+       // not actually (dis)playing. To keep the code simpler,
+       // we just always look it up.
+       char * player_command;
+       if (midi) {
+               (void) Preferences_p->get(MIDI_player_location,
+                       player_command,
+                       Default_MIDI_player_location);
+       }
+       else {
+               (void) Preferences_p->get(Viewer_location,
+                       player_command,
+                       Default_viewer_location);
+       }
+#ifdef OS_LIKE_WIN32
+       // Media player locks the file it plays, so if we had
+       // run it before, we have to make it release the lock 
+       // before we run Mup. Also, if it was playing a different file
+       // before, it doesn't seem to want to play ours.
+       // So if the MIDI player of choice is the media player,
+       // we first try to make it close somewhat gracefully,
+       // and wait a second for that to complete.
+       // In any case we try to kill off any child MIDI players we
+       // know of. If the graceful close already worked,
+       // it should find the child already dead.
+       // If they are using some other MIDI player,
+       // we don't know what to do, so we'll just kill any child
+       // MIDI player we know spawned previously, if any.
+       // Would be nice to be able to do something less drastic than
+       // kill the process, but we're not sure what else would be effective.
+       if (midi) {
+               if (is_mplayer(player_command)) {
+                       HWND window_handle;
+                       if ((window_handle = FindWindow(0, "Windows Media Player")) != 0) {
+                               SendMessage(window_handle, WM_CLOSE, 0, 0);
+                       }
+                       _sleep(1000);
+               }
+               if (has_MIDI_child()) {
+                       kill_process(&MIDI_child, "MIDI player");
+               }
+       }
+       // Somewhat similarly, we kill off any prior displayer, unless
+       // the displayer is GSview, which we know we can pass -e argument
+       // to make it reuse existing instance, if any.
+       else if ( ! is_gsview(player_command) && has_display_child()) {
+               kill_process(&display_child, "display");
+       }
+#endif
+
+       // Run the command.
+       int ret = execute_command(command, 0, true);
+
+       // Report the errors, if any.
+       struct stat info;
+       if (stat(mup_error, &info) == 0) {
+               if (info.st_size > 0) {
+                       if (report_p == 0) {
+                               report_p = new Error_report();
+                       }
+                       report_p->loadfile(mup_error);
+                       report_p->show();
+               }
+               unlink(mup_error);
+       }
+       else if (ret != 0) {
+               // Exited with error, but left no error file.
+               // Must have died badly (core dumped, execvp failed, etc)
+#if defined(WIFEXITED) && defined(WIFSIGNALED)
+               if (WIFEXITED(ret)) {
+                       // Did exit(), so most likely exec failed
+                       // due to bad path to Mup program,
+                       // although we should have caught that above.
+                       fl_alert("Mup exited with return code %d but no error output.\n"
+                               "Check Config > File Locations setting.",
+                               WEXITSTATUS(ret));
+               }
+               else if (WIFSIGNALED(ret)) {
+                       // Probably core dump :-(
+                       fl_alert("Mup exited due to signal %d.", WTERMSIG(ret));
+               } else {
+                       fl_alert(Unknown_Mup_failure);
+               }
+#else // WIF... macros not defined
+               if (ret == -1) {
+#ifdef OS_LIKE_WIN32
+                       // Look up the error reason to include in message.
+                       DWORD format_retval;
+                       LPVOID error_string = 0;
+                       if (FormatMessage(
+                                       FORMAT_MESSAGE_ALLOCATE_BUFFER
+                                       | FORMAT_MESSAGE_FROM_SYSTEM
+                                       | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+                                       0, GetLastError(),
+                                       LANG_NEUTRAL, (LPTSTR)&error_string,
+                                       0, 0)) {
+                               fl_alert("Failed to execute Mup program:\n%s"
+                                       "Check settings in Config > File Locations.",
+                                       (char *) error_string);
+                               LocalFree((HLOCAL)error_string);
+                       }
+                       else {
+                               fl_alert(Unknown_Mup_failure);
+                       }
+               }
+#else  // not Windows
+                       fl_alert(Unknown_Mup_failure);
+               }
+#endif
+               else {
+                       fl_alert(Unknown_Mup_failure);
+               }
+#endif // WIF... macros
+       }
+
+       if (ret != 0) {
+               // Something went wrong. We should not go on to
+               // display/play even if user had asked for that.
+               return;
+       }
+
+       // We wrote the output file successfully.
+       // Hide any previous error window and
+       // check if we need to (dis)play the results.
+       if (report_p != 0) {
+               report_p->hide();
+       }
+       if ( ! show_or_play ) {
+               // User just asked to generate a file, not (dis)play it.
+               fl_message("%s output file\n\n     %s\n\n"
+                       "has been successfully created.",
+                       (midi ? "MIDI" : "PostScript"), mup_output);
+               return;
+       }
+
+
+       if ( ! find_executable(player_command, full_location)) {
+               fl_alert("Unable to run %s command.\n"
+                       "Check Config > File Locations setting.",
+                       player_command);
+               return;
+       }
+
+#ifdef OS_LIKE_UNIX
+       // For MIDI, we try to kill the previous player
+       // if any, since we'll probably need the same
+       // sound card. Note that for Windows, we did this
+       // even before running Mup, since the player may lock
+       // the file so Mup would be unable to write it.
+       if (midi) {
+               kill_process(&MIDI_child, "MIDI player");
+       }
+
+       // If using gv as displayer and one already running on
+       // this file, it would be nice to get send it SIGHUP
+       // to make it re-read the file
+       // rather than starting a new one.
+       // But for other displayers, we don't know what signal
+       // might work, if any. And even with gv, if we send
+       // the signal, we have no way of knowing whether it
+       // actually worked. And there are lots of cases to
+       // consider. Suppose the displayer was gv,
+       //  and they brought up an instance,
+       // then they changed to some other displayer,
+       // and then back to gv. Should we have killed off
+       // the first gv when bringing up the other viewer,
+       // of should we keep it up and reuse it after they
+       // change back?  What if they kill the current
+       // instance just after we decided to re-use it?
+       // So just keep things simple for now. Always
+       // kill off any existing viewer we know of and
+       // start up a new one.
+       else {    // displaying
+               kill_process(&display_child, "display");
+       }
+#endif
+
+       // Fill in the argv array for displayer/player
+       command[0] = full_location;
+#ifdef OS_LIKE_WIN32
+       // Media player appears to ignore its argument
+       // if it isn't a full path name, including drive.
+       // So ensure we have everything.
+       char fullpath[FL_PATH_MAX];
+       if (mup_output[1] != ':' ) {
+               // We don't have complete path.
+               // Get current directory including drive.
+               if (getcwd(fullpath, sizeof(fullpath)) == 0) {
+                       fl_alert("Unable to determine current folder.");
+                       return;
+               }
+               if (mup_output[0] != dir_separator()) {
+                       // Relative path
+                       (void) sprintf(fullpath + strlen(fullpath),
+                               "%c%s", dir_separator(),
+                               mup_output);
+               }
+               else {
+                       // Was full path except for drive.
+                       (void) strcpy(fullpath + 2, mup_output);
+               }
+       }
+       else {
+               // Can use existing path as is.
+               (void) strcpy(fullpath, mup_output);
+       }
+
+       if ( ! midi && is_gsview(player_command)) {
+               // For gsview, use -e to make it use
+               // existing instance if any.
+               command[1] = "-e";
+               command[2] = fullpath;
+               command[3] = '\0';
+       }
+       else {
+               command[1] = fullpath;
+               command[2] = '\0';
+               
+       }
+#else
+       command[1] = mup_output;
+       command[2] = '\0';
+#endif
+
+       if (execute_command(command,
+                       (midi ? &MIDI_child : &display_child)) != 0) {
+               fl_alert("Unable to run %s command.\n"
+                       "Check settings under Config > File Locations.",
+                       command[0]);
+       }
+}
+
+
+// Execute given command with the given argv.
+// If proc_info_p is zero, wait for the process to complete,
+// otherwise save information about the spawned process in what it points to,
+// so that the caller can keep track of it while it runs independently.
+// The hide_window parameter is only used for Windows and causes the
+// spawned process to be created with flags to not create a window,
+// This lets us use a console mode version of Mup, so traditional users
+// can continue to run Mup in a console without mupmate, but we can
+// run the same .exe without the annoyance of a console popping up.
+// Returns 0 on success, -1 on failure to create process,
+// or what the process returned if it had non-zero exit code,
+// and was waited for.
+
+int
+Run::execute_command(const char ** argv, Proc_Info *proc_info_p, bool hide_window)
+{
+       int ret = -1;
+
+#ifdef OS_LIKE_UNIX
+       pid_t child;
+       switch (child = fork()) {
+       case 0:
+               execvp(argv[0], (char * const *)argv);
+               // If here, the exec failed. Child must die.
+               exit(1);
+       case -1:
+               // failed
+               if (proc_info_p != 0) {
+                       *proc_info_p = 0;
+               }
+               break;
+       default:
+               if (proc_info_p == 0) {
+                       // wait for child to complete
+                       if (waitpid(child, &ret, 0) < 0) {
+                               ret = -1;
+                       }
+               }
+               else {
+                       *proc_info_p = child;
+                       ret = 0;
+               }
+               break;
+       }
+#else
+
+#ifdef OS_LIKE_WIN32
+
+       // Convert the argv array into a string with each argument quoted.
+       // First calculate how much space is needed.
+       int a;
+       int length = 0;
+       bool has_quote = false;         // to optimize normal case
+       for (a = 0; argv[a] != 0; a++) {
+               length += strlen(argv[a]);
+               // A quoted argv[0] won't work; just quote the other args.
+               if (a > 0) {
+                       // Add space before the arg and quotes on each end.
+                       length += 3;
+                       const char * s;
+                       // If embedded quote, add space for escaping it
+                       for (s = argv[a]; *s != '\0'; s++) {
+                               if (*s == '"') {
+                                       length++;
+                                       has_quote = true;
+                               }
+                       }
+               }
+       }
+
+       // Get space and fill in all the arguments, properly quoted.
+       char command[length + 1];
+       (void) strcpy(command, argv[0]);
+       char * dest = command + strlen(command);
+       for (a = 1; argv[a] != 0; a++) {
+               *dest++ = ' ';
+               *dest++ = '"';
+               if (has_quote) {
+                       int i;
+                       for (i = 0; argv[a][i] != '\0'; i++) {
+                               if (argv[a][i] == '"') {
+                                       *dest++ = '\\';
+                               }
+                               *dest++ = argv[a][i];
+                       }
+               }
+               else {
+                       (void) strcpy(dest, argv[a]);
+                       dest += strlen(dest);
+               }
+               *dest++ = '"';
+       }
+       *dest = '\0';
+
+       // Fill in information for starting up the process
+       PROCESS_INFORMATION process_info;
+       STARTUPINFO         startup_info;
+       memset( &startup_info, 0, sizeof(startup_info));
+       startup_info.cb = sizeof(startup_info);
+       DWORD create_flags;     // flags to control creation aspects
+       if (hide_window) {
+               startup_info.dwFlags = STARTF_USESHOWWINDOW;
+               startup_info.wShowWindow = SW_HIDE;
+               create_flags = CREATE_NO_WINDOW;
+       }
+       else {
+               create_flags = 0;
+       }
+
+       // Run the process
+       BOOL proc = CreateProcess(NULL, command, NULL, NULL, 
+                       TRUE, create_flags, NULL, NULL,
+                       &startup_info, &process_info);
+
+       if (proc) {
+               // It was successfully created.
+               if (proc_info_p == 0) {
+                       // wait for child to complete
+                       DWORD result = WaitForSingleObject(
+                                       process_info.hProcess, INFINITE);
+                       switch (result) {
+                       case WAIT_FAILED:
+                       case WAIT_ABANDONED:
+                       case WAIT_TIMEOUT:
+                               ret = -1;
+                               break;
+                       default:
+                               GetExitCodeProcess(process_info.hProcess, &result);
+                               ret = (int) result;
+                       }
+               }
+               else {
+                       *proc_info_p = process_info;
+                       ret = 0;
+               }
+       }
+       else {
+               proc_info_p->hProcess = 0;
+               proc_info_p->dwProcessId = 0;
+               ret = -1;
+       }
+
+#else
+       fl_alert("Process execution only implemented\n"
+               "for Linux (and similar) and Windows so far...");
+       ret = -1;
+#endif
+
+#endif
+       return(ret);
+}
+
+
+// Kill the specified process, if it exists.
+// The description is used in error messages
+
+void
+Run::kill_process(const Proc_Info * const proc_info_p, const char * const description)
+{
+#ifdef OS_LIKE_UNIX
+       int exitstatus;
+       if (*proc_info_p == 0 || waitpid(*proc_info_p, &exitstatus, WNOHANG)
+                                                       == *proc_info_p) {
+               // No process spawned or the one we had already died
+               return;
+       }
+       // Not clear how hard to try to kill process.
+       // SIGTERM should usually work, and is preferable if it works.
+       // We wait a little while and try SIGKILL if it hasn't died yet.
+       // We don't check for errors, because the
+       // only errors that should be possible are bad signal (should be
+       // impossible, since we hard-code SIGTERM), process doesn't exist
+       // (already dead, so no need to kill it), or bad permission (we
+       // spawned it ourself, so ought to have permission to kill it).
+       (void) kill(*proc_info_p, SIGTERM);
+       // Wait for up to 3 seconds for it to die
+       int w;
+       int ret;
+       for (w = 0; w < 3; w++) {
+               if ((ret = waitpid(*proc_info_p, &exitstatus, WNOHANG))
+                                                       == *proc_info_p) {
+                       // It died.
+                       // *** Especially in the case of MIDI, there is a
+                       // chance the player has already written stuff out
+                       // to the device driver that it won't clear out when
+                       // it dies, so that if we try to start a new one,
+                       // the device will still be busy. But we have no way
+                       // to know how long to wait, if at all, and don't
+                       // want to always sleep a long time just to cover
+                       // the case of trying to play again while in the middle
+                       // of playing.
+                       return;
+               }
+               if (ret == -1 && errno == ECHILD) {
+                       // Child doesn't exist, so nothing to kill
+                       return;
+               }
+               sleep(1);
+       }
+       // Okay. Resort to SIGKILL and wait 1 more second to let it die.
+       kill(*proc_info_p, SIGKILL);
+       sleep(1);
+#endif
+#ifdef OS_LIKE_WIN32
+       if (proc_info_p->hProcess == 0 || WaitForSingleObject(
+                               proc_info_p->hProcess, 0) != WAIT_TIMEOUT) {
+               // No process spawned or the one we had must have already died.
+               return;
+       }
+       HANDLE handle;
+       if ( (handle = OpenProcess(PROCESS_TERMINATE,
+                       FALSE, proc_info_p->dwProcessId)) == 0 ||
+                       TerminateProcess(handle, 0) == 0) {
+               // Warn user we were unable to kill the old child.
+               DWORD format_retval;
+               LPVOID error_string = 0;
+               if (FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
+                                       | FORMAT_MESSAGE_FROM_SYSTEM
+                                       | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+                                       0, GetLastError(),
+                                       LANG_NEUTRAL, (LPTSTR)&error_string,
+                                       0, 0)) {
+                       fl_alert("Unable to terminate %s process.\n%s",
+                                       description, (char *) error_string);
+                       LocalFree((HLOCAL)error_string);
+               }
+       }
+       if (handle != 0) {
+               CloseHandle(handle);
+       }
+#endif
+}
+
+
+#ifdef OS_LIKE_WIN32
+// Return true if the given command is for Windows Media Player.
+
+bool
+Run::is_mplayer(const char * command)
+{
+       int length = strlen(command);
+       if (strcasecmp(command + length - 12, "wmplayer.exe") == 0 ||
+                       strcasecmp(command + length - 11, "mplayer.exe") == 0 ||
+                       strcasecmp(command + length - 8, "wmplayer") == 0 ||
+                       strcasecmp(command + length - 7, "mplayer") == 0) {
+               return(true);
+       }
+       return(false);
+}
+
+
+// Return true if the given command is for GSview.
+
+bool
+Run::is_gsview(const char * command)
+{
+       int length = strlen(command);
+       if (strcasecmp(command + length - 12, "gsview32.exe") == 0 ||
+                       strcasecmp(command + length - 10, "gsview.exe") == 0 ||
+                       strcasecmp(command + length - 8, "gsview32") == 0 ||
+                       strcasecmp(command + length - 6, "gsview") == 0) {
+               return(true);
+       }
+       return(false);
+}
+#endif
+
+
+// Called when user begins a new file, or when exiting,
+// to kill off child proceses that were spawned.
+// We start new processes for new file,
+// even if one already up for current file.
+// Not sure if that's what user wants, but...
+
+void
+Run::clean_up(void)
+{
+       kill_process(&display_child, "display");
+       kill_process(&MIDI_child, "MIDI player");
+}
+
+
+// Report whether we spawned a display child and think it is still alive.
+
+bool
+Run::has_display_child(void)
+{
+#ifdef OS_LIKE_WIN32
+       return(display_child.hProcess != 0);
+#else
+       return(display_child != 0);
+#endif
+}
+
+
+// Report whether we spawned a MIDI child and think it is still alive.
+
+bool
+Run::has_MIDI_child(void)
+{
+#ifdef OS_LIKE_WIN32
+       return(MIDI_child.hProcess != 0);
+#else
+       return(MIDI_child != 0);
+#endif
+}
+
+
+//------------ Class for displaying errors from Mup
+
+Error_report::Error_report(void)
+       : Fl_Double_Window(Default_width, Default_height, "Error report")
+{
+       text_p = new Fl_Text_Display(20, 20, w() - 40, h() - 90);
+       resizable((Fl_Widget *) text_p);
+       text_p->buffer( new Fl_Text_Buffer() );
+
+       // Set font/size and arrange to get notified of changes in them
+       font_change_reg_p = new Font_change_registration(
+                                       font_change_cb, (void *) this);
+
+       ok_p = new Fl_Return_Button(w() / 2 - 40, h() - 50, 80, 30, "OK");
+       ok_p->callback(OK_cb, this); 
+       show();
+
+       // Arrange to clean up new-ed widgets in destructor.
+       end();
+}
+
+Error_report::~Error_report()
+{
+}
+
+
+// Load the error file (from -e of Mup) into window to show user.
+
+int
+Error_report::loadfile(const char * filename)
+{
+       return text_p->buffer()->loadfile(filename);
+}
+
+
+// Callback for when user clicks OK after reading Mup error report
+
+CALL_BACK(Error_report, OK)
+{
+       hide();
+}
+
+
+// Callback for change in font/size
+
+void
+Error_report::font_change_cb(void * data, Fl_Font font, unsigned char size)
+{
+       ((Error_report *)data)->font_change(font, size);
+}
+
+void
+Error_report::font_change(Fl_Font font, unsigned char size)
+{
+       text_p->textfont(font);
+       text_p->textsize(size);
+       text_p->redisplay_range(0, text_p->buffer()->length());
+}
diff --git a/mup/mupmate/Run.H b/mup/mupmate/Run.H
new file mode 100644 (file)
index 0000000..9e6356e
--- /dev/null
@@ -0,0 +1,209 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+#ifndef _RUN_H_
+#define _RUN_H_
+
+// Classes for Run menu off of main toolbar
+
+#include <FL/Fl.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Text_Editor.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Return_Button.H>
+#include <FL/Fl_Check_Button.H>
+#include <FL/Fl_Value_Input.H>
+#include "globals.H"
+#include "File.H"
+#include "Config.H"
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef OS_LIKE_UNIX
+#include <signal.h>
+#endif
+#ifdef OS_LIKE_WIN32
+#include <windef.h>
+#include <winbase.h>
+#include <winnt.h>
+#include <process.h>
+#endif
+
+// Information about a non-waited-for process
+#ifdef OS_LIKE_WIN32
+typedef PROCESS_INFORMATION Proc_Info;
+#else
+typedef pid_t Proc_Info;
+#endif
+
+// We limit the number of macros user can define,
+// to fit in a reasonably small dialog window.
+#define MAX_MACROS     5
+
+
+// Class for asking user what arguments to pass to Mup when running it
+
+class Run_parameters_dialog : Fl_Double_Window {
+
+friend class Run;
+
+public:
+       Run_parameters_dialog(void);
+       ~Run_parameters_dialog(void);
+
+       // Callbacks
+       static void combine_cb(Fl_Widget *, void * data);
+       static void extract_cb(Fl_Widget *, void * data);
+       static void selected_pages_cb(Fl_Widget *, void * data);
+       static void clear_form_cb(Fl_Widget *, void * data);
+       static void Macros_cb(Fl_Widget *, void * data);
+       static void Save_cb(Fl_Widget *, void * data);
+       static void Cancel_cb(Fl_Widget *, void * data);
+
+       // Returns true if macro definition is invalid.
+       static bool macro_error(const char * macro);
+
+private:
+       // Callbacks
+       void combine(void);
+       void extract(void);
+       void selected_pages(void);
+       void clear_form(void);
+       void Macros(void);
+       void Save(void);
+       void Cancel(void);
+
+       // Widgets
+       Fl_Check_Button * enable_combine_p;
+       Positive_Int_Input * rest_combine_p;
+       Positive_Int_Input * first_page_p;
+       Fl_Group * pages_p;
+         Fl_Check_Button * all_p;
+         Fl_Check_Button * odd_p;
+         Fl_Check_Button * even_p;
+         Fl_Check_Button * selected_p;
+         Fl_Input * page_list_p;
+       Fl_Input * staff_list_p;
+       Int_Input * extract_begin_p;
+       Int_Input * extract_end_p;
+       Fl_Group * macros_group_p;
+         Fl_Input * macro_definitions_p[MAX_MACROS];
+       Fl_Return_Button * save_p;
+       Fl_Button * clear_form_p;
+       Fl_Button * cancel_p;
+
+       // Saved values for run parameters
+       bool saved_enable_combine;
+       char saved_combine_measures[8];
+       char saved_first_page[8];
+       enum { ALL_PAGES, ODD_PAGES, EVEN_PAGES, SELECTED_PAGES } saved_pages;
+       char * saved_page_list;
+       char * saved_staff_list;
+       char saved_extract_begin[8];
+       char saved_extract_end[8];
+       char * saved_macro_definitions[MAX_MACROS];
+};
+
+
+// Class for displaying stderr output from Mup to user
+
+class Error_report : public Fl_Double_Window
+{
+public:
+       Error_report(void);
+       ~Error_report(void);
+
+       // Reads the file where stderr was saved
+       int loadfile(const char * filename);
+
+       // Callbacks
+       static void OK_cb(Fl_Widget *, void *);
+       static void font_change_cb(void * data, Fl_Font font, unsigned char size);
+
+private:
+       // Callbacks
+       void font_change(Fl_Font font, unsigned char size);
+       void OK(void);
+
+       // Widgets
+       Fl_Text_Display * text_p;
+       Font_change_registration * font_change_reg_p;
+       Fl_Return_Button * ok_p;
+};
+
+
+
+// Class for the Run menu on the main menu bar
+
+class Run {
+
+friend class File;     // For auto-display
+
+public:
+       Run(void);
+       ~Run(void);
+
+       // To know which file to run Mup on
+       void set_file(File * file);
+       // Kill off child processes
+       void clean_up(void);
+
+       // Callbacks
+       static void Display_cb(Fl_Widget *, void * data);
+       static void Play_cb(Fl_Widget *, void * data);
+       static void WritePostScript_cb(Fl_Widget *, void * data);
+       static void WriteMIDI_cb(Fl_Widget *, void * data);
+       static void Options_cb(Fl_Widget *, void * data);
+
+private:
+       // Callbacks
+       void Display(void);
+       void Play(void);
+       void WritePostScript(void);
+       void WriteMIDI(void);
+       void Options(void);
+
+       // This runs Mup and maybe viewer/player
+       void Run_Mup(bool midi, bool show_or_play);
+
+       // Execute the command with given argv.
+       // If proc_info_p is zero, wait for the process to complete,
+       // otherwise fill it in with information about the spawned process,
+       // so that the caller can keep track of it while it runs independently.
+       // The hide_window parameter is only used for Windows and causes the
+       // spawned process to be created with flags to not create a window,
+       // This lets us use a console mode version of Mup, so traditional users
+       // can continue to run Mup in a console without mupmate, but we can
+       // run the same .exe without the annoyance of a console popping up.
+       // Returns 0 on success, -1 on failure to create process,
+       // or what the process returned if it had non-zero exit code
+       // and was waited for. If a not-waited-for process returns 0,
+       // proc_info_p will contain handle or pid information.
+       int execute_command(const char **argv, Proc_Info * proc_info_p,
+                                               bool hide_window = false);
+
+       // kill off a previously spawned child process
+       void kill_process(const Proc_Info * const proc_info_p,
+                                       const char * const description);
+
+       // Report if we have running helper programs
+       bool has_MIDI_child(void);
+       bool has_display_child(void);
+
+#ifdef OS_LIKE_WIN32
+       // To check if using displayer/player we know how to handle specially
+       static bool is_gsview(const char * command);
+       static bool is_mplayer(const char * command);
+#endif
+
+       // Widgets
+       Run_parameters_dialog * parameters_p;
+       Error_report * report_p;
+       File * file_p;
+
+       // Handles for child processes
+       Proc_Info display_child;
+       Proc_Info MIDI_child;
+};
+
+#endif
diff --git a/mup/mupmate/globals.H b/mup/mupmate/globals.H
new file mode 100644 (file)
index 0000000..71492d8
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _GLOBALS_H
+#define _GLOBALS_H
+
+// Try to consolidate OS-specific ifdef complicated clauses to this
+// header file, so code can use descriptive ifdefs
+#if defined(__WIN32) && ! defined(__CYGWIN__)
+#define OS_LIKE_WIN32
+#endif
+
+#if defined(__linux) || defined(unix)
+#define OS_LIKE_UNIX
+#endif
+
+
+// We use a class static method for callbacks which cast their "void * data"
+// argument to an instance of the class, and call the class method.
+// So we use these macros to enforce consistent usage of that technique. 
+// Most places will use CALL_BACK. The CALL_BACK_A is only needed in code
+// when the object method takes an argument.
+// Can't use CALLBACK as single word since under mingw that is already
+// defined as something completely different.
+#define CALL_BACK_A(classname, cb_name, arg) \
+       void \
+       classname::cb_name##_cb(Fl_Widget *, void * data) \
+       { \
+               ((classname *)data)->cb_name(); \
+       } \
+       void \
+       classname::cb_name(arg)
+#define CALL_BACK(classname, cb_name) CALL_BACK_A(classname, cb_name, void)
+
+#endif
diff --git a/mup/mupmate/license.C b/mup/mupmate/license.C
new file mode 100644 (file)
index 0000000..3bba4e9
--- /dev/null
@@ -0,0 +1,69 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+extern const char * const license_text =
+"\n\
+At Arkkra Enterprises, we'd like all our customers to be delighted with our\n\
+products. To ensure that Mup and any other products or services we provide\n\
+are readily available at the lowest possible cost to you, we need to\n\
+establish licensing terms.\n\
+\n\
+While there are other music publication programs on the market, we believe\n\
+Mup has unique features that you may find very useful. Since different\n\
+people may want different things in a music publication program, you do not\n\
+have to pay for Mup until after you've had a chance to try it out and\n\
+evaluate it for yourself. If you have problems with Mup, let us know and we\n\
+will try to resolve them. If you have paid your registration fee and we\n\
+cannot resolve problems to your satisfaction, we will gladly refund your\n\
+money.\n\
+\n\
+          Mup License\n\
+\n\
+Arkkra Enterprises disclaims all warranties relating to this software,\n\
+whether expressed or implied, including but not limited to any implied\n\
+warranties of merchantability and fitness for a particular purpose, and all\n\
+such warranties are expressly and specifically disclaimed. Neither Arkkra\n\
+Enterprises nor anyone else who has been involved in the creation,\n\
+production, or delivery of this software shall be liable for any indirect,\n\
+consequential, or incidental damages arising out of the use of or inability\n\
+to use such software even if Arkkra Enterprises has been advised of the\n\
+possibility of such damages of claims. In no event shall Arkkra Enterprises'\n\
+liability for any damages ever exceed the price paid for the license to use\n\
+the software, regardless of the form of the claim. The person using the\n\
+software bears all risk as to the quality and performance of the software.\n\
+\n\
+Some states do not allow the exclusion of the limit of liability for\n\
+consequential damages, so the above limitation may not apply to you.\n\
+\n\
+This agreement shall be governed by the laws of the state of Illinois and\n\
+shall inure to the benefit of Arkkra Enterprises, and any successors,\n\
+administrators, heirs and assigns. Any action or proceeding brought by\n\
+either party against the other arising out of or related to this agreement\n\
+shall be brought only in the state or federal court of competent\n\
+jurisdiction located in DuPage County, Illinois. The parties hereby consent\n\
+to in personam jurisdiction of said courts.\n\
+\n\
+This software is licensed to you, for your own use. This is copyrighted\n\
+software. You are not obtaining title to the software or any copyright\n\
+rights. You may not sublicense, rent, lease, convey, modify, or translate\n\
+this software for any purpose.\n\
+\n\
+You may make as many copies as you need for back-up purposes. You may use\n\
+this software on more than one computer, provided there is no chance it will\n\
+be used simultaneously on more than one computer. If you need to use this\n\
+software on more than one computer simultaneously, you will need to obtain a\n\
+license for each copy or a site license.\n\
+\n\
+You may make copies of this software for other parties under the following\n\
+terms:\n\
+\n\
+    * The copy must be an exact copy as would be obtained directly from\n\
+      Arkkra Enterprises, including this license. It must clearly state that\n\
+      it is a copy, and must give the address of Arkkra Enterprises.\n\
+\n\
+    * The copy must be used by the obtaining party only for the purpose of\n\
+      trialing the software. If after trialing the software, the receiving\n\
+      party wishes to continue to use the software, they must submit their\n\
+      license fee.\n\
+\n\
+    * All limitations and disclaimers of this license apply to the copy.";
diff --git a/mup/mupmate/mup16.xpm b/mup/mupmate/mup16.xpm
new file mode 100644 (file)
index 0000000..d66f8eb
--- /dev/null
@@ -0,0 +1,23 @@
+/* XPM */
+static char * mup16_xpm[] = {
+"16 16 4 1",
+"      c None",
+".     c white",
+"X     c #ff2222",
+"o     c #ff9999",
+" ......         ",
+"..XXXo.         ",
+".XXXXX.   ......",
+".XXXXX.  ..XXXo.",
+".XoXX..  .XXXXX.",
+".X....   .XXXXX.",
+".X.      .XoXX..",
+".X.      .X.... ",
+".X.      .X.    ",
+".X.      .X.    ",
+".X....   .X.    ",
+".XXXo.....X.    ",
+".XXXXXXX..X.    ",
+".XXXXXXXXXX.    ",
+".....oXXXXX.    ",
+"    ........    "};
diff --git a/mup/mupmate/mup32.xpm b/mup/mupmate/mup32.xpm
new file mode 100644 (file)
index 0000000..8557e9c
--- /dev/null
@@ -0,0 +1,42 @@
+/* XPM */
+static char * mup32_xpm[] = {
+/* width height ncolors chars_per_pixel */
+"32 32 4 1",
+/* colors */
+"      c None",
+".     c white",
+"X     c #FF2222",
+"o     c #FF9999",
+/* pixels */
+"      ......                    ",
+"    .........                   ",
+"   ...XXXXo..                   ",
+"  ..XXXXXXXo..                  ",
+" ..XXXXXXXXXo..         .....   ",
+" ..XXXXXXXXXo..       ......... ",
+"..XXXXXXXXXX..       ...XXXXo.. ",
+"..XXXXXXXXXo..      ..XXXXXXXo..",
+"..XXoXXXXXX..      ..XXXXXXXXXo.",
+"..XX.oXXXX..       ..XXXXXXXXXo.",
+"..XX.......       ..XXXXXXXXXX..",
+"..XX......        ..XXXXXXXXXo..",
+"..XX..            ..XXoXXXXXX.. ",
+"..XX..            ..XX.oXXXX..  ",
+"..XX..            ..XX.......   ",
+"..XX..            ..XX......    ",
+"..XX..            ..XX..        ",
+"..XX..            ..XX..        ",
+"..XX..            ..XX..        ",
+"..XX..            ..XX..        ",
+"..XX..            ..XX..        ",
+"..XX....          ..XX..        ",
+"..XX.........     ..XX..        ",
+"..XXXXXo............XX..        ",
+"..XXXXXXXXXXo.......XX..        ",
+"..XXXXXXXXXXXXXXXo..XX..        ",
+"..XXXXXXXXXXXXXXXXXXXX..        ",
+"..XXXXXXXXXXXXXXXXXXXX..        ",
+".......oXXXXXXXXXXXXXX..        ",
+"............oXXXXXXXXX..        ",
+"       .................        ",
+"            ............        "};
diff --git a/mup/mupmate/mup48.xpm b/mup/mupmate/mup48.xpm
new file mode 100644 (file)
index 0000000..5e18ad2
--- /dev/null
@@ -0,0 +1,58 @@
+/* XPM */
+static char * mup48_xpm[] = {
+/* width height ncolors chars_per_pixel */
+"48 48 4 1",
+/* colors */
+"      c None",
+".     c white",
+"X     c #FF9999",
+"o     c #FF2222",
+/* pixels */
+"        .........                               ",
+"       ...........                              ",
+"      .............                             ",
+"     ..XooooooooX...                            ",
+"    ..XooooooooooX....                          ",
+"   ..XooooooooooooX...                          ",
+"  ..Xoooooooooooooo...             ..........   ",
+" ...ooooooooooooooo...            ...........   ",
+" ...ooooooooooooooo...           .............. ",
+"...oooooooooooooooo...          ..XooooooooX... ",
+"...oooooooooooooooX..          ..XooooooooooX...",
+"...ooooooooooooooX..          ..XooooooooooooX..",
+"...oooXoooooooooX..          ..Xoooooooooooooo..",
+"...ooo.XooooooX...          ...ooooooooooooooo..",
+"...ooo...........           ...ooooooooooooooo..",
+"...ooo..........           ...oooooooooooooooo..",
+"...ooo.........            ...oooooooooooooooX..",
+"...ooo...                  ...ooooooooooooooX.. ",
+"...ooo...                  ...oooXoooooooooX..  ",
+"...ooo...                  ...ooo.XoooooooX..   ",
+"...ooo...                  ...ooo...........    ",
+"...ooo...                  ...ooo..........     ",
+"...ooo...                  ...ooo.........      ",
+"...ooo...                  ...ooo...            ",
+"...ooo...                  ...ooo...            ",
+"...ooo...                  ...ooo...            ",
+"...ooo...                  ...ooo...            ",
+"...ooo...                  ...ooo...            ",
+"...ooo...                  ...ooo...            ",
+"...ooo...                  ...ooo...            ",
+"...ooo...                  ...ooo...            ",
+"...ooo...                  ...ooo...            ",
+"...ooo....                 ...ooo...            ",
+"...ooo.........            ...ooo...            ",
+"...ooo...............      ...ooo...            ",
+"...oooooooooX.................ooo...            ",
+"...oooooooooooooooX...........ooo...            ",
+"...ooooooooooooooooooooX......ooo...            ",
+"...ooooooooooooooooooooooooooXooo...            ",
+"...oooooooooooooooooooooooooooooo...            ",
+"...oooooooooooooooooooooooooooooo...            ",
+"...oooooooooooooooooooooooooooooo...            ",
+"............Xoooooooooooooooooooo...            ",
+"..................Xoooooooooooooo...            ",
+".......................Xooooooooo...            ",
+"           .........................            ",
+"                 ...................            ",
+"                     ...............            "};
diff --git a/mup/mupmate/mupicons.ico b/mup/mupmate/mupicons.ico
new file mode 100644 (file)
index 0000000..3523250
Binary files /dev/null and b/mup/mupmate/mupicons.ico differ
diff --git a/mup/mupmate/mupmate.rc b/mup/mupmate/mupmate.rc
new file mode 100644 (file)
index 0000000..c008169
--- /dev/null
@@ -0,0 +1,2 @@
+#include "resource.h"
+IDI_ICON               ICON    DISCARDABLE     "mupicons.ico"
diff --git a/mup/mupmate/regform.C b/mup/mupmate/regform.C
new file mode 100644 (file)
index 0000000..fde93ce
--- /dev/null
@@ -0,0 +1,32 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+extern const char * const registration_text =
+"Mup is SHAREWARE.  You can try out a copy for free, but if you decide\n\
+to keep and use it, you must register by filling out the form below\n\
+and sending the form and cash, check, or money order to:\n\
+             Arkkra Enterprises\n\
+             P. O. Box 315\n\
+             Warrenville, IL  60555    USA\n\
+\n\
+Name______________________________________________________________\n\
+\n\
+Address___________________________________________________________\n\
+\n\
+City_____________________________ State/Province__________________\n\
+\n\
+Zip code/Postal code_____________________ Country_________________\n\
+\n\
+Email address (please print clearly)______________________________\n\
+\n\
+How did you find out about Mup?___________________________________\n\
+\n\
+__________________________________________________________________\n\
+\n\
+___Linux  ___ Windows/MS-DOS  ___Mac  ___Other____________________\n\
+\n\
+Would you like to join the Mup users mailing list? ___ Yes  ___ No\n\
+\n\
+___ Mup Version 5.3 Registrations.........................$29 each\n\
+                       (Illinois residents, add $2.18 sales tax)\n\
+(For credit card payment, see http://www.arkkra.com/doc/credtcrd.html)";
diff --git a/mup/mupmate/resource.h b/mup/mupmate/resource.h
new file mode 100644 (file)
index 0000000..b9dd4e0
--- /dev/null
@@ -0,0 +1,3 @@
+#ifndef IDI_ICON
+#define IDI_ICON 101
+#endif
diff --git a/mup/mupmate/template.C b/mup/mupmate/template.C
new file mode 100644 (file)
index 0000000..5ca4513
--- /dev/null
@@ -0,0 +1,148 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+/* We build the template into Mupmate so we do not have to depend on the
+ * template file existing at run time. */
+extern const char * const template_text =
+"//!Mup-Arkkra\n\
+// This is a Mup input file template.\n\
+// Lines starting with // are \"comments\" that are here for your benefit.\n\
+// You can remove them without affecting the output.\n\
+\n\
+/////////////////////////////////////////////////////////////////////////\n\
+//             things to go on the top of the first page\n\
+top\n\
+\n\
+       //               centered title.\n\
+       // The number in parentheses is the text point size.\n\
+       // Make it bigger if you want a bigger title or smaller if you\n\
+       // want a smaller title\n\
+       title (18) \"Replace this with the title of your song\"\n\
+\n\
+       //              subtitle\n\
+       // If you want a subtitle, remove the // from the beginning\n\
+       // of the next line and fill in the appropriate subtitle text\n\
+       // title (14) \"Replace this with the subtitle\"\n\
+\n\
+       //              composer info\n\
+       // The first pair of double quotes enclose what to left justify,\n\
+       // the second encloses what to right justify.\n\
+       // If you want more than one line, add similar lines of input\n\
+       title   \"\"   \"Replace this with composer info\"\n\
+\n\
+\n\
+/////////////////////////////////////////////////////////////////////////\n\
+//             things to go on the bottom on the first page\n\
+bottom\n\
+       // If you want a copyright notice, remove the //\n\
+       // from the next line and edit in the appropriate information\n\
+       // title \"\\(copyright) Copyright  Replace this with year and name\"\n\
+\n\
+\n\
+/////////////////////////////////////////////////////////////////////////\n\
+//             things to go on the top of pages other than the first\n\
+top2\n\
+       // This example will give a centered page number between dashes.\n\
+       // You can customize as you wish.\n\
+       title \"- \\% -\"\n\
+\n\
+\n\
+/////////////////////////////////////////////////////////////////////////\n\
+//             things to go at the bottom of pages other than the first\n\
+bottom2\n\
+       // if you want things printed at the bottom of pages of than\n\
+       // the first page, place them here\n\
+\n\
+\n\
+/////////////////////////////////////////////////////////////////////////\n\
+//             score-wide parameters\n\
+//\n\
+// You may or may not need to change some items in this section\n\
+//\n\
+// The values given as examples are the default values that Mup uses\n\
+// if you don't specify anything for them\n\
+score\n\
+       //      time signature. Can be cut, com,\n\
+       //      or two numbers with a / between them\n\
+       time = 4/4\n\
+\n\
+       //      key signature. Value is a number from 0 to 7\n\
+       //      followed by # or & for number of sharps or flats.\n\
+       key = 0#\n\
+\n\
+       //      how many staffs. Can be a number from 1 to 40\n\
+       staffs = 1\n\
+\n\
+       //      clef. Can be treble, treble8, 8treble, frenchviolin,\n\
+       //      soprano, mezzosoprano, alto, tenor, baritone, or bass\n\
+       clef = treble\n\
+\n\
+       // Note: there are many more parameters that can be set,\n\
+       // but they are not included in this simple template.\n\
+       // There are parameters to set margins, control how things\n\
+       // are laid out on the page, transpositions value, font and size\n\
+       // for text and lyrics, etc\n\
+\n\
+\n\
+/////////////////////////////////////////////////////////////////////////\n\
+//     You can set some parameters for specific staffs,\n\
+//     to override the score-wide parameters. For example,\n\
+//     if you specify staffs = 2 in the score-wide parameters above,\n\
+//     and want to use bass clef on staff 2, even though the score-wide\n\
+//     clef parameter is set to treble, you can do\n\
+//             staff 2\n\
+//                     clef = bass\n\
+\n\
+\n\
+/////////////////////////////////////////////////////////////////////////\n\
+//             music input starts here\n\
+music\n\
+\n\
+\n\
+// For each measure, you enter one line of input for each staff,\n\
+// then indicate what kind of barline to print.\n\
+// The following specifies that staff 1 contains a measure of rest\n\
+// and that an ordinary bar line is to be used at the end of the measure.\n\
+\n\
+1: mr;\n\
+bar\n\
+\n\
+// Usually, a measure of input for one staff consists of one or more chords\n\
+// Each chord is specified by\n\
+//     time_value notes ;\n\
+// where time_value is something like\n\
+//     4       for a quarter note\n\
+//     8       for an eighth note\n\
+//     4.      for a dotted-quarter note\n\
+// etc and notes is a list of one or more notes, specified as a pitch from\n\
+// a to g, optionally followed by an accidental (#, &, x, &&, or n for sharp,\n\
+// flat, double sharp, double flat, or natural respectively).\n\
+// Examples:\n\
+//     4c;\n\
+//     2. ceg;\n\
+//     16 f#;\n\
+//     1 d b&;\n\
+// (Spaces are optional, you can put them in if you want, but don't have to)\n\
+//\n\
+// So a complete measure might look something like:\n\
+//     1: 4e; 4d; 2c;\n\
+//     bar\n\
+//\n\
+// If you want a note in a different octave than the default octave\n\
+// (the octave from middle-C up for treble clef,\n\
+// or the octave below middle-C for bass clef),\n\
+// you can add a + for each octave to go up or - for each octave to go down.\n\
+// For example:\n\
+//     1: c+; gc+e+; a&-; f#---;\n\
+//\n\
+// There are many other things you can specify, such as ties, slurs, grace\n\
+// notes, etc, and there are also many shortcuts you can use to save typing.\n\
+// Consult the Mup documentation for more details.\n\
+\n\
+// Other bar types you may want to use are\n\
+//     repeatstart\n\
+//     repeatend\n\
+//     repeatboth\n\
+//     dblbar\n\
+//     endbar\n\
+//     invisbar";
diff --git a/mup/mupmate/utils.C b/mup/mupmate/utils.C
new file mode 100644 (file)
index 0000000..ff4cda1
--- /dev/null
@@ -0,0 +1,573 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+// This file contains code for miscellaneous things that don't seem to really
+// belong with any particular menu.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "globals.H"
+#include "utils.H"
+#include <FL/fl_ask.H>
+#include <FL/filename.H>
+#ifdef OS_LIKE_WIN32
+#include <windef.h>
+#include <winbase.h>
+#include <winreg.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#endif
+
+
+// The FLTK Fl_Int_Input is almost what we want, but it allows
+// octal and hex input via leading 0 and 0x respectively.
+// So the Int_Input derived class intercepts the input and throws away
+// characters from the set [xX] and leading zeros.
+// Sometimes we also want to restrict to positive numbers,
+// so the Positive_Int_Input class discards the - character as well.
+
+Int_Input::Int_Input(int x, int y, int w, int h, const char * label)
+       : Fl_Int_Input(x, y, w, h, label)
+{
+       allow_negative = true;
+}
+
+
+Positive_Int_Input::Positive_Int_Input(int x, int y, int w, int h, const char * label)
+       : Int_Input(x, y, w, h, label)
+{
+       allow_negative = false;
+}
+
+int
+Int_Input::handle(int event)
+{
+       if (event == FL_KEYBOARD) {
+               int key = Fl::event_key();
+               if (key == 'x' || key == 'X') {
+                       return(1);
+               }
+               if (key == '0' && position() == 0) {
+                       return(1);
+               }
+               if (key == '-' && ! allow_negative) {
+                       return(1);
+               }
+       }
+       return(Fl_Int_Input::handle(event));
+}
+
+
+
+// Character used to separate items in $PATH and to separate directory names
+#ifdef OS_LIKE_WIN32
+       static const char path_sep = ';';
+       static const char dir_sep = '\\';
+#else
+       static const char path_sep = ':';
+       static const char dir_sep = '/';
+#endif
+
+
+// Return the native OS's directory separator character
+
+char
+dir_separator(void)
+{
+       return(dir_sep);
+}
+
+// Return the native OS's path separator character
+char
+path_separator(void)
+{
+       return(path_sep);
+}
+
+// Set the value of $MUPPATH. We "new" space for it and save a static
+// pointer to that space.
+// If it had been set before, we delete the old space.
+
+void
+set_muppath(const char * new_muppath)
+{
+       static char * muppath = 0;
+
+       if (muppath != 0) {
+               // The +8 is to skip past the MUPPATH= part
+               if (strcmp(muppath + 8, new_muppath) == 0) {
+                       // Setting to existing value, so nothing to do
+                       return;
+               }
+               delete muppath;
+       }
+       muppath = new char [strlen(new_muppath) + 9];
+       (void) sprintf(muppath, "MUPPATH=%s", new_muppath);
+       (void) putenv(muppath);
+}
+
+
+
+// Given a path to a file in "location", and the length of that path,
+// and a suffix, see if the location with the suffix added is an
+// executable file. If so, return true, with the suffixed name left
+// in location. Otherwise return false with location as it came in.
+// Could also return false if path would be longer than FL_PATH_MAX,
+// and therefore will not fit. (Better to fail than core dump.)
+
+static bool
+access_with_suffix(char * location, int length, const char * suffix)
+{
+       if (length + strlen(suffix) + 1 > FL_PATH_MAX) {
+               // Too long to store
+               return(false);
+       }
+
+       // Add suffix and see if it is an executable file
+       (void) strcpy(location + length, suffix);
+       if(access(location, X_OK) == 0) {
+               return(true);
+       }
+       else {
+               // This suffix didn't work. Remove it before returning
+               location[length] = '\0';
+               return(false);
+       }
+}
+
+
+// Given a file location, see if it exists as an executable file,
+// taking into account the DOS/Windows strangeness of implicit suffixes.
+
+static bool
+check_access(char * location)
+{
+       int len = strlen(location);
+#ifdef __WIN32
+       // If doesn't have a suffix, try with .com, .exe, and .bat suffix
+       if (len < 5 || strchr(location + len - 4, '.') == 0) {
+               // This is the precedence order for executable suffixes
+               if (access_with_suffix(location, len, ".com")) {
+                       return(true);
+               }
+               if (access_with_suffix(location, len, ".exe")) {
+                       return(true);
+               }
+               if (access_with_suffix(location, len, ".bat")) {
+                       return(true);
+               }
+               return(false);
+       }
+       // If did have a suffix, go ahead and try name as is
+#endif
+       return access_with_suffix(location, len, "");
+}
+
+
+// Find the value of PATH. First try in third arg of main()
+// since that seems more reliable on some OSs. Failing that, try getenv().
+
+// We cache the value so we only have to search for it one time.
+// This also rescues us in case env_p becomes invalid due to setting
+// new environment variable values.
+
+static const char * Path = 0;
+
+void
+get_path(const char ** const env_p)
+{
+       if (Path != 0) {
+               // Already did it before
+               return;
+       }
+
+       if (env_p != 0) {
+               // Find $PATH in the environment variable list
+               int e;
+               for (e = 0; env_p[e] != 0; e++) {
+                       if (strncmp(env_p[e], "PATH=", 5) == 0) {
+                               Path = strdup(env_p[e] + 5);
+                               break;
+                       }
+               }
+       }
+       if (Path == 0) {
+               // Not found in the arge, so try looking up directly
+               Path = getenv("PATH");
+       }
+}
+
+
+// Return true if given path is an absoluate path
+
+bool
+is_absolute(const char * const path)
+{
+#ifdef OS_LIKE_WIN32
+       if ((path[0] != '\0' && path[1] == ':') || path[0] == dir_sep) {
+#else
+       if (path[0] == dir_sep) {
+#endif
+               return(true);
+       }
+       return(false);
+}
+
+
+// Given the name of a executable program, find the directory from
+// which it comes, and put the full path into "location,"
+// which is expected to be at least FL_PATH_MAX bytes long.
+// The incoming pgm_name is expected to be no more than FL_PATH_MAX long.
+// It uses the components of PATH to try to find the executable.
+// For Windows, if the program name doesn't have a suffix,
+// it tries to find a .com, .exe, or .bat file with the pgm_name.
+// It returns true on success. On failure, it returns false,
+// and the contents of location are not defined.
+
+bool
+find_executable(const char * const pgm_name, char * location)
+{
+       // If pgm_name is already absolute path,
+       // just check if it exists and is executable
+       if (is_absolute(pgm_name)) {
+               (void) strcpy(location, pgm_name);
+               return (check_access(location));
+       }
+
+       if (Path == 0) {
+               // Should have already looked up $PATH,
+               // but make another attempt, just in case...
+               get_path(0);
+               if (Path == 0) {
+                       return(false);
+               }
+       }
+
+       // We'll try the program name added to each PATH component
+       // until we find it or have to give up.
+#ifdef OS_LIKE_WIN32
+       // DOS/Windows implicitly adds current working directory first
+       bool add_implicit_cwd = true;
+#else
+       bool add_implicit_cwd = false;
+#endif
+       const char * component;         // current component of PATH
+       const char * next_component;    // next component of PATH
+       const char * sep_p;             // location of PATH separator
+       int len;                        // length of component
+       for (component = Path; *component != '\0'; component = next_component) {
+               if (add_implicit_cwd) {
+                       // DOS/Windows implicitly adds current directory
+                       // as first PATH component.
+                       len = 0;
+                       next_component = component;
+                       add_implicit_cwd = false;
+               }
+
+               else if ((sep_p = strchr(component, path_sep)) != 0) {
+                       // Not the last component in the PATH
+                       len = sep_p - component;
+                       next_component = sep_p + 1;
+               }
+               else {
+                       // Is the last component in the PATH
+                       len = strlen(component);
+                       next_component = component + len;
+               }
+
+               if (len == 0) {
+                       // Empty path component means current directory.
+                       // Allow enough room for directory separator,
+                       // pgm_name, suffix, and null terminator
+                       if (getcwd(location, FL_PATH_MAX
+                                       - strlen(pgm_name) - 6) == 0) {
+                               // Current directory unobtainable or too long
+                               return(false);
+                       }
+                       len = strlen(location);
+               }
+               else {
+                       strncpy(location, component, len);
+               }
+
+               // If PATH component didn't already add a directory
+               // separator, we add one. In some OSs it doesn't hurt
+               // to add another, but no reason to use an extra byte.
+               if (location[len-1] != dir_sep) {
+                       location[len++] = dir_sep;
+               }
+
+               // Now add the progam name itself and see if it exists.
+               // The check_access() will add implied suffix if necessary.
+               (void) strcpy(location + len, pgm_name);
+               if (check_access(location)) {
+                       return(true);
+               }
+       }
+       return(false);
+}
+
+
+// Returns location of magic file that lets us know user agreed
+// to the license. The value is saved so subsequent calls can just return
+// the saved value. If something goes wrong, a null string is returned.
+
+#ifdef OS_LIKE_WIN32
+  #define MAGIC_FILE_NAME "mup.ok"
+#else
+  #if defined(OS_LIKE_UNIX) || defined(VMS) || defined(AMIGA) || defined(EMX)
+    #define MAGIC_FILE_NAME ".mup"
+  #else
+    #ifdef Mac_BBEdit
+      #define MAGIC_FILE_NAME (char *)(MupRegFileName + 1)
+    #endif
+  #endif
+#endif
+
+#ifndef MAGIC_FILE_NAME
+#error OS not supported
+#endif
+
+const char *
+magic_file(const char * pname, const char ** env_p)
+{
+       char * home;
+       char * fname = MAGIC_FILE_NAME;
+       static char * magicpath = 0;    // Path is saved here
+
+       if (magicpath != 0) {
+               // Must have figured it out on previous call
+               return(magicpath);
+       }
+
+       // First check current directory. This will only work
+       // for the case where user has already created the file,
+       // and is of somewhat questionable use, since if the user
+       // changes directories to somewhere without the magic file,
+       // Mup will print the watermark.
+       if (access(fname, F_OK) == 0) {
+               magicpath = new char[strlen(fname) + 1];
+               strcpy(magicpath, fname);
+               return(magicpath);
+       }
+
+#ifdef OS_LIKE_WIN32
+       // Construct pathname to magic file in the directory where
+       // mup.exe came from
+       if (pname == 0) {
+               // Shouldn't happen; We should get called once with valid
+               // pname, and return cached value after that
+               fl_alert("Unable to determine magic file name.");
+               return("");
+       }
+       char location[FL_PATH_MAX];
+       if (find_executable(pname, location)) {
+               int baselength = strlen(location)
+                                       - strlen(fl_filename_name(location));
+               magicpath = new char[baselength + strlen(fname) + 1];
+               // Copy pname up to last backslash
+               (void) strncpy(magicpath, location, baselength);
+               // add magic file name
+               (void) strcpy(magicpath + baselength, fname);
+       }
+#else
+       // Construct pathname to magic file if it is in $HOME
+       if ((home = getenv("HOME")) != (char *) 0) {
+               magicpath = new char[strlen(home) + strlen(fname) + 2];
+#ifdef VMS
+               (void) sprintf(magicpath, "%s%s", home, fname);
+#else
+               (void) sprintf(magicpath, "%s/%s", home, fname);
+#endif
+       }
+
+#endif
+#ifdef Mac_BBEdit
+#pragma unused(pname)
+       // Check for file in Preferences folder inside System folder
+       magicpath = 0;
+       home = 0;
+       {
+               short vRefNum;
+               long dirID;
+               FSSpec fsSpec;
+               
+               if (FindFolder(kOnSystemDisk, kPreferencesFolderType, false,
+                                               &vRefNum, &dirID) == noErr) {
+                       // Preferences folder exists
+                       if (FSMakeFSSpec(vRefNum, dirID,
+                                       (StringPtr) MupRegFileName, &fsSpec)
+                                       == noErr) {
+                               // File exists
+                               short old_vRefNum;
+                               long old_dirID;
+                               if (HGetVol((StringPtr) 0, &old_vRefNum,
+                                                       &old_dirID) != noErr) {
+                                        return;
+                               }
+
+                               if (HSetVol((StringPtr) 0, vRefNum, dirID)
+                                                               != noErr) {
+                                        return;
+                               }
+                               HSetVol((StringPtr) 0, old_vRefNum, old_dirID);
+                               magicpath = new char[strlen(MAGIC_FILE_NAME) + 1];
+                               (void) sprintf(magicpath, MAGIC_FILE_NAME);
+                       }
+               }
+       }
+#endif
+
+       if (magicpath == 0) {
+               // Not sure what to really do here... Punt.
+               fl_alert("Unable to find magic file path.");
+               magicpath = "";
+       }
+
+       return(magicpath);
+}
+
+
+#ifdef OS_LIKE_WIN32
+
+// On Windows, we read the registry to try to determine the proper
+// program to use for a given file type, like .mid or .ps files.
+// This function will return the path to the appropriate file,
+// if found, in a static area that may get overwritten on next call,
+// so caller needs to make its own copy. If program is not found,
+// returns null.
+
+
+char *
+lookup_pgm_for_file_suffix(const char * file_suffix)
+{
+       static char data[512];
+       char name[512]; 
+       long len = sizeof(data);
+       // First find entry for file suffix mapping to a class
+       (void) sprintf(name, "Software\\Classes\\%s", file_suffix);
+       HRESULT result = RegQueryValue(HKEY_LOCAL_MACHINE, name, data, &len);
+       if (result != ERROR_SUCCESS) {
+               return(0);
+       }
+
+       // Next look up the program associated with that class
+       (void) sprintf(name, "Software\\Classes\\%s\\shell\\open\\command", data);
+       len = sizeof(data);
+       result = RegQueryValue(HKEY_LOCAL_MACHINE, name, data, &len);
+       if (result != ERROR_SUCCESS) {
+               return(0);
+       }
+
+       // We might get multiple strings back,
+       // giving the program itself plus arguments.
+       // We only want the program itself. So if the first string is quoted,
+       // strip the quotes and anything after it.
+       char * d;
+       if (*data == '"') {
+               for (d = data + 1; *d != '\0'; d++) {
+                       if (*d == '"') {
+                               *(d-1) = '\0';
+                               break;
+                       }
+                       *(d-1) = *d;
+               }
+       }
+       if (access(data, X_OK) == 0) {
+               return(data);
+       }
+       return(0);
+}
+
+
+// Look up the given name in the CURRENT_USER area of registry
+// and if found, fill in the data and return true, except return false.
+
+static bool
+reg_dir_found(char * name, char * data, DWORD len)
+{
+       HRESULT result = RegQueryValueEx(HKEY_CURRENT_USER, name, 0, 0,
+                                       (LPBYTE)data, &len);
+       if (result == ERROR_SUCCESS) {
+               struct stat info;
+               if (stat(data, &info) == 0 && (info.st_mode & S_IFDIR)) {
+                       return(true);
+               }
+       }
+       return(false);
+}
+
+
+// Look for likely default folder for Mup files.
+// Use the current user's "My Music" folder if there is one,
+// otherwise try their "Personal" folder.
+// Returns path in static area or null on failure.
+
+char *
+find_music_folder(void)
+{
+       static char best_value[FL_PATH_MAX];
+
+       // Get the registry info about folders
+       HKEY key = 0;
+       // Win'98 uses "User Shell Folders" but newer versions use just
+       // "Shell Folders," so we check for both, newer first, since that
+       // is probably more likely to work.
+       if ((RegOpenKeyEx(HKEY_CURRENT_USER,
+                       "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
+                       0, KEY_READ, &key) == ERROR_SUCCESS) ||
+                       (RegOpenKeyEx(HKEY_CURRENT_USER,
+                       "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
+                       0, KEY_READ, &key) == ERROR_SUCCESS)) {
+               DWORD max_key_length;
+               DWORD count;
+               DWORD max_name_length;
+               DWORD max_value_length;
+               // Find out how many subkeys there are, and max lengths.
+               if (RegQueryInfoKey(key, 0, 0, 0, 0, &max_key_length, 0, &count,
+                               &max_name_length, &max_value_length, 0, 0)
+                               == ERROR_SUCCESS) {
+                       TCHAR name[max_name_length + 1];
+                       DWORD name_length;
+                       DWORD value_type;
+                       BYTE value[max_value_length + 1];
+                       DWORD value_length;
+                       int i;
+                       best_value[0] = '\0';
+                       // Look for "My Music" and "Personal" subkeys.
+                       // There's probably a better way to query for specific
+                       // subkey than linear search, but this works...
+                       for (i = 0; i < count; i++) {
+                               name_length = sizeof(name);
+                               value_length = sizeof(value);
+                               if (RegEnumValue(key, i, name, &name_length, 0,
+                                               &value_type, value,
+                                               &value_length)
+                                               == ERROR_SUCCESS) {
+                                       if (value_type != REG_SZ) {
+                                               continue;
+                                       }
+                                       if (strcasecmp(name, "My Music") == 0) {
+                                               // Found the ones we want.
+                                               strcpy(best_value, (char *) value);
+                                               break;
+                                       }
+                                       if (strcasecmp(name, "Personal") == 0) {
+                                               // This is our second choice.
+                                               // Save as best so far.
+                                               strcpy(best_value, (char *) value);
+                                       }
+                               }
+                       }
+               }
+       }
+       if (key != 0) {
+               RegCloseKey(key);
+       }
+       return(best_value[0] == '\0' ? 0 : best_value);
+}
+
+#endif
diff --git a/mup/mupmate/utils.H b/mup/mupmate/utils.H
new file mode 100644 (file)
index 0000000..dee6435
--- /dev/null
@@ -0,0 +1,86 @@
+/* Copyright (c) 2006 by Arkkra Enterprises */
+/* All rights reserved */
+
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+// This file defines miscellaneous things that don't seem to really
+// belong with any particular menu.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Int_Input.H>
+
+#ifdef OS_LIKE_WIN32
+// For some reason mingw doesn't seem to properly define va_list anywhere.
+// I guess it needs a compiler-specific header file.
+// We don't actually use any functions that use va_list,
+// so just need to try to keep the compiler happy.
+#ifndef va_list
+#define va_list __VALIST
+#endif
+#endif
+
+// The FLTK Fl_Int_Input is almost what we want, but it allows
+// octal and hex input via leading 0 and 0x respectively.
+// So the Int_Input derived class intercepts the input and throws away
+// characters from the set [xX] and leading zeros.
+// Sometimes we also want to restrict to positive numbers,
+// so the Positive_Int_Input class discards the - character as well.
+
+class Int_Input : public Fl_Int_Input {
+public:
+       Int_Input(int x, int y, int w, int h, const char * label);
+       int handle(int event);
+protected:
+       bool allow_negative;
+};
+
+class Positive_Int_Input : public Int_Input {
+public:
+       Positive_Int_Input(int x, int y, int w, int h, const char * label);
+};
+
+
+// Return the native OS's directory separator character
+char dir_separator(void);
+// Return the native OS's path separator character
+char path_separator(void);
+
+// Set the $MUPPATH value
+extern void set_muppath(const char * new_muppath);
+
+// Get value of PATH from third argument to main(), or failing that,
+// from getenv(), and save it.
+extern void get_path(const char ** const env_p);
+
+// Return true if given path is an absoluate path
+extern bool is_absolute(const char * const path);
+
+// Find full path to an executable.
+// If found, true is returned and full path is filled into location,
+// which must be at least FL_PATH_MAX bytes long.
+// If executable is not found, false is returned, and the contents of
+// location is not defined.
+extern bool find_executable(const char * const pgm_name, char * location);
+
+// Returns path to magic file saying user agrees to license
+extern const char * magic_file(const char * pname = 0, const char ** env_p = 0);
+
+#ifdef OS_LIKE_WIN32
+// On Windows, we read the registry to try to determine the proper
+// program to use for a given file type, like .mid or .ps files.
+// This function will return the path to the appropriate file,
+// if found, in a static area that may get overwritten on next call,
+// so caller needs to make its own copy. If program is not found,
+// returns null.
+extern char * lookup_pgm_for_file_suffix(const char * file_suffix);
+
+// Look for likely default directory for Mup files.
+// Use the current user's "My Music" place if there is one,
+// otherwise try their "My Documents" folder.
+// Returns path in static area or null on failure.
+extern char * find_music_folder(void);
+
+#endif
+
+#endif
diff --git a/mup/mupprnt b/mup/mupprnt
new file mode 100755 (executable)
index 0000000..a5a08b0
--- /dev/null
@@ -0,0 +1,57 @@
+# UNIX shell script for printing Mup output
+
+# **** NOTE: The GS_DEVICE shell variable needs to be set to the
+#              proper value for your printer type.
+#      Different versions of ghostscript may support different
+#      printer types, so execute ghostscript with the -h option
+#      to see what your version supports.
+#
+#      PRINTERTYPE             printer
+#      ------------------------------------------------------------------
+#      bj10e     Canon BubbleJet BJ10e
+#      cdeskjet  H-P DeskJet 500C with 1 bit/pixel color
+#      cdjcolor  H-P DeskJet 500C with 24 bit/pixel color and
+#                   high-quality color (Floyd-Steinberg) dithering
+#      cdjmono   H-P DeskJet 500C printing black only
+#      deskjet   H-P DeskJet and DeskJet Plus
+#      dfaxhigh  DigiBoard, Inc.'s DigiFAX software format (high resolution)
+#      dfaxlow   DigiFAX low (normal) resolution
+#      djet500   H-P DeskJet 500
+#      djet500c  H-P DeskJet 500C
+#      epson     Epson-compatible dot matrix printers (9- or 24-pin)
+#      eps9high  Epson-compatible 9-pin, interleaved lines
+#                   (triple resolution)
+#      epsonc    Epson LQ-2550 and Fujitsu 3400/2400/1200 color printers
+#      laserjet  H-P LaserJet
+#      la50      DEC LA50 printer
+#      la75      DEC LA75 printer
+#      lbp8      Canon LBP-8II laser printer
+#      ln03      DEC LN03 printer
+#      lj250     DEC LJ250 Companion color printer
+#      ljet2p    H-P LaserJet IId/IIp/III* with TIFF compression
+#      ljet3     H-P LaserJet III* with Delta Row compression
+#      ljetplus  H-P LaserJet Plus
+#      necp6     NEC P6/P6+/P60 printers at 360 x 360 DPI resolution
+#      paintjet  H-P PaintJet color printer
+#      pjetxl    H-P PaintJet XL color printer
+#      r4081     Ricoh 4081 laser printer
+#      tek4696   Tektronix 4695/4696 inkjet plotter
+
+echo "Mupprnt - Version 5.3" >&2
+
+# if environment variable COPIES is set, use that as number of copies to print
+if [ "$COPIES" != "" ]
+then
+       _Mup_copies=-n$COPIES
+fi
+
+muptmp=/usr/tmp/mtmp$$
+trap 'rm -f $muptmp' 0 1 2 15
+mup $* | gs -dNOPAUSE -sOutputFile=$muptmp -
+
+
+if [ $? -eq 0 -a -s "$muptmp" ]
+then
+       # use -c option to copy file to spool area, so we can remove tmp file
+       lp -c $_Mup_copies $muptmp
+fi
diff --git a/mup_5.3.orig.tar.gz b/mup_5.3.orig.tar.gz
new file mode 100644 (file)
index 0000000..03d04ce
Binary files /dev/null and b/mup_5.3.orig.tar.gz differ